6

I have a CentOS VM to which I log in using SSH. I appended the following line to .bashrc

echo "from ~/.bashrc: (pid $$)"

and the following line to .bash_profile

echo "from ~/.bash_profile"

When I log into the VM and run ps I get the following output

user@laptop:~ $ ssh vmcentos
Last login: Sun May 17 04:48:24 2020 from 192.168.122.1
from ~/.bashrc: (pid 1821)
from ~/.bash_profile
[admin@localhost ~]$ ps -H -o pid,command
  PID COMMAND
 1821 -bash
 1844   ps -H -o pid,command
[admin@localhost ~]$

This output is what I expect since the shell I log into is an interactive login shell and thus the .bash_profile file is sourced which in turn sources the .bashrc file.

Now I log out from the VM and execute the following command

user@laptop:~ $ ssh vmcentos 'sleep 60; echo $-'
from ~/.bashrc: (pid 1901)
hBc
user@laptop:~ $

then I log into another ssh session on the VM and inspect the process table

[admin@localhost ~]$ ps -eH -o pid,command
  PID COMMAND
(... more output here...)
 1900       sshd: admin@notty
 1901         bash -c sleep 60; echo $-
 1914           sleep 60
(... more output here...)

As far as I understand the shell that ssh executes (process 1901) is non-interactive (because of the -c option and also because the $- variable contains no i character) and non-login (because ARGV0 is not -bash and no --login option is provided). Thus neither .bashrc nor .bash_profile should be sourced. Yet the output of the command clearly shows that .bashrc was sourced. Why?

I used a standard CentOS installation with the standard openssh configuration.

2
  • Related: unix.stackexchange.com/questions/332531/…
    – Kusalananda
    Commented May 17, 2020 at 10:20
  • 1
    Side note: if you test stuff like that, remember that unconditionally printing stuff from the shell init files can break programs like scp and anything else that might try to do something automatically and interpret the output.
    – ilkkachu
    Commented May 17, 2020 at 13:07

1 Answer 1

9

According to the manual, it's supposed to do that:

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 daemon sshd. If Bash determines it is being run in this fashion, it reads and executes commands from ~/.bashrc, if that file exists and is readable.

Bash's startup files are weird.

3
  • Note that it's only if someone uncommented the /* #define SSH_SOURCE_BASHRC */ line in config-top.h in the source code of bash before compiling bash. Commented May 31, 2023 at 6:30
  • @StéphaneChazelas, hmm, it's mentioned as a fact in the manual, though. Looking at the code it looks like SSH_SOURCE_BASHRC controls another test that checks for SSH's envvars, while the test for stdin being a network connection is unconditional, a couple of lines later. (Didn't check changes over versions, there's some suspicious #if 1 lines there) git.savannah.gnu.org/cgit/bash.git/tree/…
    – ilkkachu
    Commented May 31, 2023 at 6:45
  • Yes, that's a very controversial feature, and there's been a lot of back and forth over the years, including at various distros which enabled or not that feature, at times with patches over upstreams IIRC. Note that with ssh, stdin is a pipe (or tty in rlogin mode or with -t), stdin being a socket was with rshd which nobody uses any longer these days. Commented May 31, 2023 at 7:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .