stdin: is not a tty
Closed this issue ยท 51 comments
Hello
I run Vagrant version 1.2.2 on Mac OS 10.8.3.
When I set up a multi VM environment with lucid64 boxes, which I provision either with shell or puppet, I always get the following error when provisionning
stdin: is not a tty
Example :
dhcp-10-0-89-123:devops-test-deploy geoffroy$ vagrant up test
Bringing machine 'test' up with 'virtualbox' provider...
[test] Importing base box 'precise64'...
[test] Matching MAC address for NAT networking...
[test] Setting the name of the VM...
[test] Clearing any previously set forwarded ports...
[test] Creating shared folders metadata...
[test] Clearing any previously set network interfaces...
[test] Preparing network interfaces based on configuration...
[test] Forwarding ports...
[test] -- 22 => 2250 (adapter 1)
[test] -- 80 => 4567 (adapter 1)
[test] Running any VM customizations...
[test] Booting VM...
[test] Waiting for VM to boot. This can take a few minutes.
[test] VM booted and ready for use!
[test] Setting hostname...
[test] Configuring and enabling network interfaces...
[test] Mounting shared folders...
[test] -- /vagrant
[test] -- /etc/puppet
[test] -- /tmp/vagrant-puppet/manifests
[test] Running provisioner: shell...
[test] Running: /var/folders/6m/twgys53s1cn326fz4tlrchjr0000gn/T/vagrant-shell20130430-3314-ejk9pk
stdin: is not a tty
Thanks
Geoffroy
Yeah this is a known "thing." It is not really a problem because it doesn't really cause a problem. Actually, the reason this error message even appears is due to a bug in Ubuntu not checking whether stdin is a TTY, and just assuming it is.
thanks for your quick reply ! I won't bother then :)
Is there any workaround possible to avoid this warning? For some reason it annoys me unnaturally ๐
Yea, along with occasional dpkg-preconfigure: unable to re-open stdin: No such file or directory
is making me nervous
Is this also something to not worry about? dpkg-preconfigure: unable to re-open stdin: No such file or directory
For those looking for a fix, see https://bugs.launchpad.net/ubuntu/+source/xen-3.1/+bug/1167281. I recently built my own box using veewee and replaced:
msg n
With:
tty -s && mesg n
In file /root/.profile
.
Adding this to a shell provisioner should fix it:
sed -i 's/^mesg n$/tty -s \&\& mesg n/g' /root/.profile
@johnraz that worked for me too on one host machine but on another host machine I now get:
tty: extra operand 'mesg'
It's really a nasty hack anyway and I only tried it against ubuntu 12.04 ... Guess you will have to adapt it to whatever distro / version you are using.
I did say earlier this bug "annoys me unnaturally".. I decided today I wouldn't stop until I understood why this happens. ๐ Unfortunately this entire situation with shells and configuration files (.bashrc
/.profile
/etc). is really worse than I thought. It's obvious the current situation evolved "organically" and it really sucks to work with.
Vagrant defaults its SSH shell command to bash -l
. This command is used for Vagrant's internal SSH communicator (which is used to execute commands in shell provisioners and plugins). The -l
flag forces this to be a login shell. For a non-interactive login shell like this one, bash will source /etc/profile
, followed by the first existing file out of ~/.bash_profile, ~/.bash_login, and ~/.profile. Since Vagrant runs most of its commands as root, it will source /etc/profile
, then /root/.profile
.
On Ubuntu, /root/.profile
contains the command mesg n
. This command is used to prevent other users on the machine writing to your current terminal device -- this is a good thing, it stops other users on the machine from writing to root terminals (I couldn't find much on the security implications, but a discussion of the potential reasons for this is available in [1, pp. 270]). However, this command doesn't even make sense when running commands as Vagrant does, because there is no terminal device at all (which is obvious, once you realise what mesg
is for).
So it's true that Ubuntu's default /root/.profile
doesn't check whether a terminal device is present before running mesg
(as @mitchellh said initially), and that's why this problem is fixed when changing the relevant line to read tty -s && mesg -n
as suggested by @andyshinn (it only runs mesg -n
if tty
reports that stdin is a terminal).
However, I don't think the onus is on Ubuntu to implement this change as @mitchellh suggests. Their /root/.profile
assumes that all login shells are interactive -- but that's because they usually are. Login shells are usually started by the login
process (or ssh
when logging in interactively), and in those instances the shell would also be interactive. It's fairly unusual to have a login shell that's also non-interactive (the condition which triggers this problem).
A better way to fix this would be to avoid using a login shell. I think the only reason Vagrant chooses to use a login shell is so that /etc/profile
is sourced before the command is run. On the base Ubuntu boxes provided by Vagrant, that executes /etc/profile.d/vagrantruby.sh
, which adds /opt/ruby/bin
into $PATH
. So if you changed the Vagrant setting config.ssh.shell
to bash
(without the -l
), it would fix this issue, but you would have to give the full path to Ruby because it wouldn't be in the $PATH
. So I think to fix this problem "correctly", we need to find another way to get /opt/ruby/bin
into the $PATH
.
Honestly, I think there are some problems with the way the base box is built, specifically what happens in postinstall.sh
. I'd open a pull request with some suggested changes, but I can't find that hosted anywhere official to do so. Here's my recommendations:
- Remove the trailing slash from the
$PATH
(currently/etc/profile.d/vagrantruby.sh
containsPATH=$PATH:/opt/ruby/bin/
, the trailing slash can cause problems, a trivial example beingwhich ruby
giving/opt/ruby/bin//ruby
with two slashes). - Actually
export
the change to$PATH
(the current assignment to$PATH
won't affect any sub-processes, which can be confusing) - The main problem, however: we need to find another way to get
/opt/ruby/bin
into the$PATH
. I really like the way OS X has/etc/paths.d
(that would fix this problem awesomely) but unfortunately nothing like that is in Ubuntu yet. If you really really want to make extra double sure that Ruby is always available, why not chuck it into/etc/environment
? This is sourced bylogin
/sshd
itself when logging in, no matter how you log in really.
tl;dr: Environment variables and shell configurations are FUBAR. @mitchellh (I believe?) should maybe adjust postinstall.sh
used to build the official Vagrant Ubuntu base boxes -- don't use /etc/profile.d/vagrantruby.sh
to add /opt/ruby/bin
into the $PATH
, let's modify /etc/environment
instead. Citations. I have no life.
[1] B. Toxen, Real World Linux Security: Intrusion Prevention, Detection, and Recovery. Upper Saddle River, NJ: Prentice Hall, 2003. http://goo.gl/kmKryu
Oh, one more thing: for the time being, I'm fixing this by adding this line to my Vagrantfile:
config.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'"
This starts bash as a non-login shell, but also tells it to source /etc/profile
, which I hypothesised to be the only reason to use a login shell by default. Works for me with the stock precise64
Vagrant box.
Some other ways to fix the issue:
- Previous suggestions to change
mesg n
totty -s && mesg n
in/root/.profile
- Remove the
mesg n
line from/root/.profile
completely, if you don't care about the security/denial of service implications, or will only have trusted users on the virtual machine (passwordless sudo is enabled on the base boxes already anyway...) - Put a script named
mesg
in root's$PATH
which only executes the realmesg
if stdin is a tty (tested usingtty -s
or the preferredtest -t 0
) - Disable login shell for the SSH command in your Vagrantfile:
config.ssh.shell = 'bash'
-- you'll also have to use full paths to binaries in all of your provisioners, asruby
won't be found in$PATH
(probably only feasible if only using shell provisioners)
@bradfeehan : Very interesting findings. Thanks for taking the time to dig this and share it with us.
@bradfeehan thank you so much for writing this up! I tried config.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'"
and it worked :)
@bradfeehan Wow, thanks! This bothered me to no end. I was about to go in for the deep dive to sort this out.
@bradfeehan this worked for me! thanks.
There's a problem with this workaround that means you don't get ~/.bash_profile
sourced when logging in interactively via vagrant ssh
. I guess this problem really is so complex that there's no right answer.
I'm going to put up with the message, and solve it a different way when it annoys me too much again.
If anybody get this error:
[2014-01-20T08:11:08-05:00] INFO: Chef Run complete in 67.290072613 seconds
[2014-01-20T08:11:08-05:00] INFO: Running report handlers
[2014-01-20T08:11:08-05:00] INFO: Report handlers complete
[2014-01-20T13:10:00+00:00] INFO: Forking chef instance to converge...
[2014-01-20T13:10:00+00:00] DEBUG: Fork successful. Waiting for new chef pid: 5680
[2014-01-20T08:11:08-05:00] DEBUG: Forked instance successfully reaped (pid: 5680)
[2014-01-20T08:11:08-05:00] DEBUG: Exiting
Or their vagrant box runs out of memory, remove the config.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'"
hack. For me, it was causing problem with the rbenv cookbook (https://github.com/RiotGames/rbenv-cookbook)
@phirschybar I was also getting that error message: " tty: extra operand 'mesg' "
It's because you have to double-escape the ampersands in @andyshinn's command. So the command would look like:
config.vm.provision :shell,
:inline => "sed -i 's/^mesg n$/tty -s \\&\\& mesg n/g' /root/.profile"
Note the double-backslashes before the ampersand. If you don't do that, you end up writing unintended text into /root/.profile, leading to that error message in subsequent provisions.
This command is almost perfect, but you still get that 'stdin is not a tty' on your very first provision. To reassure my colleagues when provisioning a box for the first time, I now add the following to my Vagrantfile:
#This next bit fixes the 'stdin is not a tty' error when shell provisioning Ubuntu boxes
config.vm.provision :shell,
#if there a line that only consists of 'mesg n' in /root/.profile, replace it with 'tty -s && mesg n'
:inline => "(grep -q -E '^mesg n$' /root/.profile && sed -i 's/^mesg n$/tty -s \\&\\& mesg n/g' /root/.profile && echo 'Ignore the previous error about stdin not being a tty. Fixing it now...') || exit 0;"
That prints a reassuring green message right after the scary red 'stdin is not a tty' upon the very first provision.
(The only thing I don't like about it is that I used a redundant grep to determine if sed was going to do any work. You can use sed's 'q' command to determine if it did any work, but I'm already in over my Unix head, and couldn't get it to work.)
I have the same problem, and for me it's an actual problem.
Why is there no option to have a TTY during provisioning?
The only answer I could imagine is "But provisioning should not be interactive". However, I always run provisioning on a terminal and watch the output.
There exist commands which require a TTY, even when they do not actually need to interact with the user โ in my case, it was "agda-mode setup" from Agda starting Emacs, mostly just to find it (I'm sure you didn't hear of Agda).
Debian package installation also requires a TTY, though that's actually interactive; however, upon finding no TTY, in my setup it still tries to use ncurses and ends up corrupting the terminal settings, requiring to run reset
in the host terminal.
I'm working this around by provisioning with vagrant ssh -c /vagrant/myscript.sh, but that seems to half-defeat the point of having provisioning.
@Blaisorblade There is: config.ssh.pty = true
(min Vagrant 1.4.0)
Thanks! But shouldn't it be documented under both of
http://docs.vagrantup.com/v2/vagrantfile/ssh_settings.html
http://docs.vagrantup.com/v2/provisioning/shell.html
(so that one can find it from both places), while it isn't documented in either page?
Also, while this setting solves my problem, provisioning does not terminate if I actually use "agda-mode setup", which does use the terminal in strange ways. It's still better, but not perfect. (Also, the same script works fine inside ssh โ and enabling keep_color does not help).
In addition, with config.ssh.pty the default shared folder is mounted under logout
(meaning /home/vagrant/logout
) instead of /vagrant
. I guess some command is happy to see a TTY and is producing output which Vagrant doesn't expect, but usually login/logout scripts are supposed to not produce output with non-interactive shells.
I also tried adding :binary => true to the provisioning configuration, but it didn't help.
I experienced the same as @Blaisorblade, seems like a bug to me. Breaks a lot things like provisioning that requires mounted folders in a known /tmp location.
I haven't seen this bit of trivia mentioned yet, so...
I only see "stdin: is not a tty" when running a privileged shell provisioner. If I set "privileged: false", the message doesn't appear.
If you are running Centos/REHL then config.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'"
wont work. You need to comment out Defaults requiretty
in /etc/sudoers.
Gist of a --debug stderr/stdout log, with a link to the Vagrantfile in the description available here: https://gist.github.com/momer/270b875f376b44883d1e
Update
I had added DOCKER_OPTS='-H tcp://0.0.0.0:4243 ...'
as I was using the command on another VM set up. Removing that opt allowed Vagrant to set up and start Docker correctly.
I am also running into the same issue as @Blaisorblade and @andyshinn when setting
config.ssh.pty = true
on precise64.box.
@bradfeehan thanks
Cheers to @bradfeehan going hard on this. We should reopen this and figure it out ๐
@bradfeehan : Thanks from me as well. I agree with your analysis, but for two minor nitpickings:
Remove the trailing slash from the $PATH (currently /etc/profile.d/vagrantruby.sh contains PATH=$PATH:/opt/ruby/bin/, the trailing slash can cause problems, a trivial example being which ruby giving /opt/ruby/bin//ruby with two slashes).
That path is just as valid, and I don't think there can be any "problems" (except if some script does something weird), but I agree that's ugly and should be fixed.
Actually export the change to $PATH (the current assignment to $PATH won't affect any sub-processes, which can be confusing)
Nope: changing a variable doesn't mean you need to reexport it. To be clear, after:
PATH=/bin:/usr/bin
export PATH
PATH=/other/path:$PATH
subprocesses will see the new value of PATH. That's because export (conceptually) sets a flag for the variable name, not for its content.
There is an unexpected and trivial solution on stack overflow : http://serverfault.com/questions/500764/dpkg-reconfigure-unable-to-re-open-stdin-no-file-or-directory
export LANGUAGE=en_US.UTF-8
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
locale-gen en_US.UTF-8
dpkg-reconfigure locales
it just works.
I also received a similar error message (but with a different root cause), and my issue was solved in #5753. I'm posting for search-engine visibility.
LOL!
In addition, with config.ssh.pty the default shared folder is mounted under logout (meaning /home/vagrant/logout) instead of /vagrant. I guess some command is happy to see a TTY and is producing output which Vagrant doesn't expect, but usually login/logout scripts are supposed to not produce output with non-interactive shells.
Should reproduce that again; my analysis was wrong, because the provisioning shell is indeed interactive (as discussed by others).
Note that the workaround based on overriding the shell breaks vagrant ssh -c COMMAND
. I have yet to find a way to quiet the error while keeping this feature.
Im using Ubuntu 14.04.
I found that using
config.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'"
as @bradfeehan suggests, breaks the vagrant ssh -c COMMAND
as @warrenseine mentioned.
But using
config.vm.provision "fix-no-tty", type: "shell" do |s|
s.privileged = false
s.inline = "sudo sed -i '/tty/!s/mesg n/tty -s \\&\\& mesg n/' /root/.profile"
end
as @johnraz suggests, works fine.
I didnt test the @Offirmo suggestion, but my box already had the locales set as he suggests:
$ locale
LANG=en_US.UTF-8
LANGUAGE=en_US:
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=en_US.UTF-8
getting this when running vagrant up on a windows 7 pro x64 host ... attempting to generate a ubuntu vm ... suggestions on fix? I have tried updating my vagrantfile many ways, no luck so far...
default:
default: Guest Additions Version: 4.3.10
default: VirtualBox Version: 5.0
==> default: Mounting shared folders...
default: /vagrant => C:/HashiCorp/Vagrant/projects/docker
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!
chown id -u vagrant
:id -g vagrant
/vagrant
Stdout from the command:
Stderr from the command:
chown: changing ownership of `/vagrant': Not a directory
c:\HashiCorp\Vagrant\projects\docker>
I didn't understand, how is this closed if I have still the same issue? Is the workaround a kind configuration? Is there documentation?
ubuntu 14.10 as guest,
windows 10 as host
vagrant 1.8.1
vb-guest 0.11.1
The workaround of @johnraz works:
config.vm.provision "fix-no-tty", type: "shell" do |s|
s.privileged = false
s.inline = "sudo sed -i '/tty/!s/mesg n/tty -s \\&\\& mesg n/' /root/.profile"
end
I'm getting the issue on:
Vagrant 1.8.5
VirtualBox 5.0.26
bento/ubuntu-16.04 version 20160805.0.0
default: Running: /var/folders/fv/4bgskv153wz93tdmbvmfb9fh0000gn/T/vagrant-shell20160807-7353-126ogg7.sh ==> default: mesg: ==> default: ttyname failed ==> default: : ==> default: Inappropriate ioctl for device
I re-wrote the /root/.profile editing snippet because it was broken for me:
(grep -q -E '^(mesg n \|\| true)$' /root/.profile && sed -ri 's/^(mesg n \|\| true)$/tty -s \&\& mesg n/' /root/.profile && echo 'Ignore the previous error about stdin not being a tty. Fixing it now...')
The error only occurs once while provisioning now.
@liquidice That's probably a different issue. See #7155
@Ajedi32 As I said, I run that code I provided above on initial provision, and the problem only happens once on initial provision now, instead of every time.
This is happening for me as well. I have attached the log file: vagrant.log.tar.gz.
Here are the annoying messages that appear when I run vagrant up
:
$ vagrant up
.
.
.
==> acs: mesg:
==> acs: ttyname failed
==> acs: :
==> acs: Inappropriate ioctl for device
.
.
.
==> acs: dpkg-preconfigure: unable to re-open stdin: No such file or directory
Vagrantfile:
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
# ansible control center
config.vm.define "acs" do |acs|
acs.vm.box = "boxcutter/ubuntu1604"
acs.vm.hostname = "acs"
acs.vm.network "private_network", ip: "192.168.33.10"
acs.vm.provision "shell", inline: "sed -i 's/us.archive.ubuntu/au.archive.ubuntu/g' /etc/apt/sources.list && apt-get update && apt-get install ansible -y"
end
end
Host OS: Ubuntu 16.04
VirtualBox version: 5.0.24_Ubuntur108355
CC: @mitchellh
mount -t devtmpfs none /home/chroot/dev
mount -t devpts none /home/chroot/dev/pts
I'm running into an issue with apt-get update if I use the fix-no-tty solution. Essentially, apt-get just stalls and does nothing.
Edit: It might just be apt-get hanging...
@berdon You sure apt-get isn't waiting for console input? Then it might do different things on a terminal or not (even failing on a non-terminal). That's surprising for apt-get update
, but if a program isn't using input at all it shouldn't notice...
I believe the issue was unrelated to Vagrant and more likely related to IPv6 issues and apt-get. I ran across a StackExchange post suggesting disabling IPv6 for updates and upgrades. This seems to have fixed the issue:
Pre-Config shell script:
echo "Disabling IPv6"
sudo cp /etc/sysctl.conf /etc/sysctl.conf.bak
echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.default.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.lo.disable_ipv6 = 1" >> /etc/sysctl.conf
sudo sysctl -p
Post-Config shell script:
# sudo apt-get -qq -y update
echo "Resetting IPv6"
mv /etc/sysctl.conf.bak /etc/sysctl.conf
I'm going to lock this issue because it has been closed for 30 days โณ. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.