== How Bash decides it's being invoked through sshd and sources your .bashrc Under normal circumstances, Bash only sources your _.bashrc_ when it's run as an interactive non-login shell; for example, this is what [[the Bash manual says about startup files https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html]]. Well, it is most of what the manual says, because there is an important exception, which the Bash manual describes as 'Invoked by remote shell daemon': > 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_, [...] (You can tell how old this paragraph of the manual is because of how much prominence it gives to [[rshd BSDRcmdsAndPrivPorts]]. Also, note that this specific phrasing about standard input presages [[my discovery of when bash doesn't do this BashrcWithPtySsh]].) As the result of [[recent events https://twitter.com/thatcks/status/1141076688606040066]], I became interested in discovering exactly how Bash decides that it's being run in the form of '_ssh host command_' and sources your _.bashrc_. There turn out to be two parts to this answer, but the summary is that ~~if this is enabled at all, Bash will always source your _.bashrc_ for non-interactive commands if you've logged in to a machine via SSH~~. First, this feature may not even be enabled in your version of Bash, because it's a non-default configuration setting (and has been since Bash 2.05a, which is [[pretty old https://ftp.gnu.org/gnu/bash/]]). Debian and thus Ubuntu turn this feature on, as does Fedora, but the FreeBSD machine I have access to doesn't in the version of Bash that's in its ports. Unsurprisingly, OmniOS doesn't seem to either. If you compile Bash yourself without manually changing [[the relevant bit of config-top.h https://git.savannah.gnu.org/cgit/bash.git/tree/config-top.h#n102]], you'll get a version without this. (Based on some digging, I think that [[Arch Linux https://www.archlinux.org/]] also builds Bash without enabling this, since they don't seem to patch config-top.h. I will leave it to energetic people to check other Linuxes and other *BSDs.) Second, how it works is actually very simple. In practice, a non-interactive Bash decides that it is being invoked by SSHD if either (($SSH_CLIENT)) or (($SSH2_CLIENT)) are defined in the environment. In [[a robotic sense UnixAnnoyance]] this is perfectly correct, since OpenSSH's _sshd_ puts (($SSH_CLIENT)) in the environment when you do '_ssh host command_'. In practice it is wrong, because ~~OpenSSH sets (($SSH_CLIENT)) all the time, including for logins~~. So if you use SSH to log in somewhere, (($SSH_CLIENT)) will be set in your shell environment, and then any non-interactive Bash will decide that it should source _~/.bashrc_. This includes, [[for example https://twitter.com/thatcks/status/1141365253558681600]], the Bash that is run (as '_bash -c ..._') to execute commands when you have a Makefile that has explicitly set '_SHELL=/bin/bash_', as Makefiles that are created by the GNU autoconfigure system tend to do. As a result, if you have [[ancient historical things AncientHOMEPerils]] in a _.bashrc_, for example [[clearing the screen on exit https://twitter.com/thatcks/status/1141203140055883777]], then surprise, those things will happen for every command that _make_ runs. This may not make you happy. For situations like Makefiles that explicitly set '_SHELL=/bin/bash_', this can happen even if you don't use Bash as your login shell and haven't had anything to do with it for years. (Of course it also happens if you have perfectly modern things there and expect that they won't get invoked for non-interactive shells, and you do use Bash as your login shell. But if you use Bash as your login shell, you're more likely to notice this issue, because routine ordinary activities like '_ssh host command_' or '_rsync host:/something ._' are more likely to fail, or at least do additional odd things.) PS: [[This October 2001 comment in _variables.c_ https://git.savannah.gnu.org/cgit/bash.git/tree/variables.c#n627]] sort of suggests why support for this feature is now an opt-in thing. PPS: If you want to see if your version of Bash has this enabled, the simple way to tell is to run _strings_ on the binary and see if the embedded strings include '((SSH_CLIENT))'. Eg: > ; /etc/fedora-release > Fedora release 29 (Twenty Nine) > ; strings -a /usr/bin/bash | fgrep SSH_CLIENT > SSH_CLIENT So the Fedora 29 version does have this somewhat dubious feature enabled. Perhaps Debian and Fedora feel stuck with it due to very long-going backwards compatibility, where people would be upset if Bash stopped doing this in some new Debian or Fedora release. === Sidebar: The actual code involved The code for this can currently be found in [[((run_startup_files)) in _shell.c_ https://git.savannah.gnu.org/cgit/bash.git/tree/shell.c#n1083]]: .pn prewrap on /* get the rshd/sshd case out of the way first. */ if (interactive_shell == 0 && no_rc == 0 && login_shell == 0 && act_like_sh == 0 && command_execution_string) { #ifdef SSH_SOURCE_BASHRC run_by_ssh = (find_variable ("SSH_CLIENT") != (SHELL_VAR *)0) || (find_variable ("SSH2_CLIENT") != (SHELL_VAR *)0); #else run_by_ssh = 0; #endif [...] Here we can see that the current Bash source code is entirely aware that no one uses rshd any more, among other things.