In my reading of the bash manpage, .bashrc should only be executed when the shell is run interactively. The manpage defines interactive as:
An interactive shell is one started without non-option arguments and without the -c option whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the -i option. PS1 is set and $- includes i if bash is interactive, allowing a shell script or a startup file to test this state.
Yet, executing a command with ssh also causes .bashrc to be run, contrary to what I would expect, given that the command is not run interactively. So, this behavior seems like a bug, but it also seems pervasive on all the versions of Red Hat and bash that I've tried. Can someone explain why this behavior is correct?
One additional point: even though .bashrc is run, $-
and $PS
are set as if the shell is non-interactive (as I would expect).
$ grep USER /etc/passwd
USER:x:UID:GID:UNAME:/home/USER:/bin/bash
$ cat ~/.bashrc
echo bashrc:$-,$PS1
$ bash -c 'echo $-'
hBc
$ ssh localhost 'echo $-' </dev/null 2>/dev/null
USER@localhost's password:
bashrc:hBc,
hBc
$ ssh localhost 'ps -ef | grep $$' </dev/null 2>/dev/null
USER@localhost's password:
bashrc:hBc,
USER 28296 28295 0 10:04 ? 00:00:00 bash -c ps -ef | grep $$
USER 28297 28296 0 10:04 ? 00:00:00 ps -ef
USER 28298 28296 0 10:04 ? 00:00:00 grep 28296
I am currently working around this by testing [[ $- = *i* ]]
in .bashrc, but it seems as if I shouldn't have to do that.
One example server, containing no other files in my home directory than .bashrc (and .ssh) has this configuration:
$ cat /etc/redhat-release
Red Hat Enterprise Linux Server release 5.7 (Tikanga)
$ bash --version
GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.
Versions of bash that I've tried this on: 3.00.15, 3.1.17, 3.2.25, 4.1.2 (the latter on Red Hat 6.3).
From the Bash manual:
Bash attempts to determine when it is being run with its standard input connected to a network connection, as when executed by the remote shell daemon, usually
rshd
, or the secure shell daemonsshd
. If Bash determines it is being run in this fashion, it reads and executes commands from~/.bashrc
, if that file exists and is readable. It will not do this if invoked as sh. The--norc
option may be used to inhibit this behavior, and the--rcfile
option may be used to force another file to be read, butrshd
does not generally invoke the shell with those options or allow them to be specified.
The workaround in the default Debian bashrc
skeleton is to put the following at the top of .bashrc
:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With