I’ve been using scp — part of the OpenSSH package — on a daily basis for several years now. In recent months my .bashrc files have become more complex, and at some point I started getting an annoying error message during my remote copies:
stderr is not a tty – where are you?
However charming this error message might be, I’m a little sick of seeing it. I decided to squash this one tonight, and browsing through the bash manpage and Googling did the trick.
Bash reads a wide array of configuration files on startup: ~/.bashrc is read when starting an interactive but non-login shell, ie. running bash or opening an xterm. It reads ~/.bash_profile (among others) when starting an interactive login shell, ie. logging in to a TTY in runlevel 3 or ssh’ing into a host.
To add a level of complexity to the setup, the bash run by scp runs .bashrc, though I’m not sure why. Commands in my ~/.bashrc expect stdin, stdout, and stderr to be available, but it’s obvious things aren’t working 100% as expected. After some searching, it turns out it’s fairly simple to alter .bashrc to cooperate with scp:
# only run if we have an interactive shell
if [ $(expr index "$-" i) -eq 0 ]; then
return
fi
bash gets an environment variable “$-” that contains all its startup flags. If $- contains “i”, the shell is interactive. Our if checks for this flag; if the flag is not found, execution of .bashrc stops. I’ve put this at the top of my .bashrc for now, but at some point I will reorganize so important and non-harmful settings are still executed. (For example, $CVSROOT.)
Works great. Thanks for the help.
Wow, makes enough sense. It fixed my problem with scp too… thanks.
I think I’ve come up with a complete fix thanks to your hack. The message “stderr is not a tty – where are you?” is caused by biff, so by moving biff to the end of /etc/profile just after the snippet you came up with, like so:
if [ $(expr index "$-" i) -eq 0 ]; then
return
fi
if [ -x /usr/bin/biff ]; then
biff y
fi
and it appears to be permanently solved. You can now source /etc/profile without any problems. The stderr message bugged me for a loooong time and it always appeared in .xsession-errors when using display managers like kdm. Thanks to you, it’s now gone. Finally it’s gone!
Thanks.
What a life saver! I tried using:
if [ "$TERM" = "su" ] || [ "$TERM" = "dumb" ] ; then
exit 0;
fi
…which was causing “Remote server terminated connection” HA!
Actually I had problems with:
if [ $(expr index "$-" i) -eq 0 ]; then
I kept getting:
expr: syntax error
bash: [: -eq: unary operator expected
So I changed it to:
if [ -z "$PS1" ]; then
Which is also unique to interactive shells.
This pointed me in the right direction to fix a similar problem I was having with rsync. Thanks!
Indeed, winbiff was causing this issue here too!
Removing it from /etc/profile (on the remote computer) did the trick!
Thanx!
Thanks.
You saved me from annoyings.
Thanks for the post… this solved my problem too.
My .bashrc outputs text (e.g. uname -a, uptime) and this prevented scp from working. Adding that check at the top solved the problem.