Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mesg: ttyname failed: Inappropriate ioctl for device #46

Closed
gingerlime opened this issue Jul 23, 2020 · 9 comments · Fixed by #48
Closed

mesg: ttyname failed: Inappropriate ioctl for device #46

gingerlime opened this issue Jul 23, 2020 · 9 comments · Fixed by #48

Comments

@gingerlime
Copy link

gingerlime commented Jul 23, 2020

Sorry for the delay reporting it. We ended up reverting back to fabric 1.14.1 to resolve this, and I didn't get a chance to test again.

Using fab-classic 1.18.0 with python 2.x I'm getting this error message when I launch fab commands over a remote SSH, e.g.

$ ssh root@remote.host "fab run_command -H root@another.host"

[root@another.host] ... some output
[root@another.host] out: mesg: ttyname failed: Inappropriate ioctl for device

This doesn't happen with fabric 1.14.1

In most cases, the error is harmless, but some commands seem to not execute correctly when this happens (still not 100% sure what fails)

running the fab command locally rather than via ssh works ok.

@ploxiln
Copy link
Owner

ploxiln commented Jul 24, 2020

The difference is related to the shell, and whether it is considered a "login shell". It's from a shell init file similar to this one, which I grabbed from a server running ubuntu-16.04:

root@graph03:~# cat /root/.profile 
# ~/.profile: executed by Bourne-compatible login shells.

if [ "$BASH" ]; then
  if [ -f ~/.bashrc ]; then
    . ~/.bashrc
  fi
fi

mesg n || true

"mesg n" is a command to "disallow messages" on the terminal from other terminal users ... it's a really old esoteric unix thing, and this is making sure it is disabled. But it emits that error message if it can't access the terminal it is running in (the TTY). But it's probably irrelevant for your case either way, and if you can tolerate that message being printed out, you can just ignore it, everything should work the same.

I think that the shell option to fabric might be a way to avoid this. Something like:

from fabric.api import env

env.shell = "/bin/bash -c"  # default is "/bin/bash -l -c"

but the default is the same for Fabric-1.14.1 and fab-classic-1.18.0, so I'm not sure how that changes things ... still, I would check the value of env.shell and whether you use the shell=False kwarg to your run() calls and see if there is any difference somehow. If the -l argument to bash is removed, that may avoid that shell init file with that mesg n command.


When you run fab locally, you're in a real terminal. But when you run fab like:

ssh root@remote.host "fab run_command -H root@another.host"

then ssh by default does not create a "pty" for the command on the remote server. ssh does create a pty by default if you just start a shell like ssh root@remote.host, but it does not if you specify a command to run instead of an interactive shell. So, another way to work-around this problem is to tell ssh to still create that pty, with the -t argument:

ssh -t root@remote.host "fab run_command -H root@another.host"

but again, I'm not sure why the difference between Fabric-1.14.1 and fab-classic-1.18.0, you would have to experiment and figure out the difference you are running into, and I would be interested to find out.

But you re-enable it with the -t option, like:

@gingerlime
Copy link
Author

Hey @ploxiln 👋 thanks again for the prompt and detailed response.

But it's probably irrelevant for your case either way, and if you can tolerate that message being printed out, you can just ignore it, everything should work the same.

Unfortunately it seems to break some stuff. I might need more time to figure out exactly what, but our deploy fab command failed with fab-classic over ssh and works with fabric, and the only noticeable difference were these messages (it is possible that the problem was different, I'm not sure).

So, another way to work-around this problem is to tell ssh to still create that pty, with the -t argument:

This seems to remove the warning messages and resolves the deploy issue as well, so that's a good workaround! I'm still curious (and hope you are too) to understand why it's not needed with fabric 1.14.1 and is needed with fab-classic 1.18.0

@gingerlime
Copy link
Author

I tested it more specifically to see which fab commands fail in connection with the error message. Most commands do indeed execute just fine (but with an extra warning), but others fail.

I was able to narrow down the failure to a command that pulls code from github on the remote host. (e.g. runs sudo("git fetch --all")). The remote host itself runs keychain to load SSH keys into memory, but this command is run only when there's a tty available, the .bashrc on the remote server looks like this

tty -s && [ -f ~/.ssh/id_rsa ] && eval `keychain -q --eval $HOME/.ssh/id_rsa`

So this explains the specific failure due to the missing tty I suppose?

The question still remains why fabric works and fab-classic doesn't. I checked my fab scripts and couldn't find any custom env.shell set up, and I'm using the exact same fab scripts with both versions.

@ploxiln
Copy link
Owner

ploxiln commented Jul 24, 2020

I think that fabric-1.14.1 must be creating/simulating a tty/pty when it runs on the remote server over ssh, even though it is itself not provided with a tty/pty by ssh ... and fab-classic doesn't seem to do that.

@gingerlime
Copy link
Author

I'm obviously biased, but It seems like a sensible default thing to do to me? are there any downsides to doing it?

@ploxiln
Copy link
Owner

ploxiln commented Jul 24, 2020

Yes, there are downsides. A real TTY can behave subtly differently, and for some logic it may be important to know if it has a real TTY or not. But, this change was not exactly intentional. I think this might have been the change that affects your use case: 20fdcd8

That was between fab-classic-1.16.0 and fab-classic-1.17.0, so you could try to go back to fab-classic-1.16.0 and see if that works for your case.

@gingerlime
Copy link
Author

gingerlime commented Jul 24, 2020

Thanks again @ploxiln. Yes, I can confirm that it works with fab-classic 1.16.0 and breaks again with 1.17.0+

Is this something you're willing to roll back? It's hard for me to say what the implications are, besides our use case unfortunately. Again, I'm biased, but somehow feels like a less error-prone default to fake the tty when one isn't there?

@ploxiln
Copy link
Owner

ploxiln commented Jul 26, 2020

I think I've got a decent short-term fix in #48

@gingerlime
Copy link
Author

That's awesome @ploxiln. Thanks so much. I tested it and it seems to work great! Looking forward to the new version when it's out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants