Bash Tips: SCP Compatibility
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.)