Discussion:
[Help-bash] The execution of /etc/bash.bashrc and ~/.bashrc for non interactive shells
Cristian Zoicas
2017-03-30 14:21:07 UTC
Permalink
Hello all

Can somebody explain the reasons behind the decision to allow
bash to execute the files /etc/bash.bashrc and ~/.bashrc
if it is started remotely and non interactively? For example
the command

ssh ***@somemachine echo "this is a test"

triggers the execution of the above mentioned files.

Thank you
Cristian
Nicholas Chambers
2017-03-30 14:30:34 UTC
Permalink
Post by Cristian Zoicas
Hello all
Can somebody explain the reasons behind the decision to allow
bash to execute the files /etc/bash.bashrc and ~/.bashrc
~/.bashrc is a part of bash. If I recall correctly, /etc/bash.bashrc is
not a part of bash. Instead, operating systems like Ubuntu modify the
system bash so that rc file is sourced. If you build bash from source
does it still happen?
Post by Cristian Zoicas
if it is started remotely and non interactively? For example
the command
triggers the execution of the above mentioned files.
Thank you
Cristian
--
Nicholas Chambers
Technical Support Specialist
***@lightspeedsystems.com
1.800.444.9267
www.lightspeedsystems.com
Greg Wooledge
2017-03-30 14:34:20 UTC
Permalink
Post by Cristian Zoicas
Can somebody explain the reasons behind the decision to allow
bash to execute the files /etc/bash.bashrc and ~/.bashrc
if it is started remotely and non interactively? For example
the command
triggers the execution of the above mentioned files.
First of all, /etc/bash.bashrc (or similarly named files) are not used
by a default upstream bash. There's a compile-time option to enable the
use of a system-wide bashrc file, and many Linux distributions turn
this on. So I'm betting you're using a Linux distribution's build of
bash.

The decision to use bashrc (etc.) when bash is invoked interactively by
ssh goes back many years. Here are some past threads talking about it:

https://lists.gnu.org/archive/html/bug-bash/2007-12/msg00000.html
https://lists.gnu.org/archive/html/bug-bash/2008-10/msg00051.html

And here is a comment from variables.c:

/*
* 24 October 2001
*
* I'm tired of the arguing and bug reports. Bash now leaves SSH_CLIENT
* and SSH2_CLIENT alone. I'm going to rely on the shell_level check in
* isnetconn() to avoid running the startup files more often than wanted.
* That will, of course, only work if the user's login shell is bash, so
* I've made that behavior conditional on SSH_SOURCE_BASHRC being defined
* in config-top.h.
*/

I don't have any references older than this, to figure out where/when
the behavior originally started. Maybe Chet remembers.
Chet Ramey
2017-03-30 15:26:30 UTC
Permalink
Post by Greg Wooledge
The decision to use bashrc (etc.) when bash is invoked interactively by
(We're not talking about interactive shells here.)
Post by Greg Wooledge
https://lists.gnu.org/archive/html/bug-bash/2007-12/msg00000.html
https://lists.gnu.org/archive/html/bug-bash/2008-10/msg00051.html
The discussions and bug reports go back years before that, to the late
1990s. The original request was for bash to run the startup files when
invoked by ssh because that was the only way to, for example, set PATH,
and bash had supported that when using rsh for many years. (Using
something like ssh's .environment was deemed inconvenient.) The first
complaint I found about that dates from 1997. Someone contributed a
patch that used SSH_CLIENT to detect whether or not bash was being run
by ssh, so it got changed.

There were a bunch of startup files that produced output on stdout,
which messed up scp, but people got past that.

Bash used the presence of the SSH_CLIENT or SSH2_CLIENT variables to
detect whether or not it was being run by ssh. However, leaving those
in the environment meant that other non-interactive shells run as part
of the session would see them and run the startup files (like the `bash
-c' jobs run by `make'), so bash made them local.

That led to a firestorm of complaints about modifying the environment,
including golden comments characterizing the bash behavior as "pathetic",
Post by Greg Wooledge
/*
* 24 October 2001
*
* I'm tired of the arguing and bug reports. Bash now leaves SSH_CLIENT
* and SSH2_CLIENT alone. I'm going to rely on the shell_level check in
* isnetconn() to avoid running the startup files more often than wanted.
* That will, of course, only work if the user's login shell is bash, so
* I've made that behavior conditional on SSH_SOURCE_BASHRC being defined
* in config-top.h.
*/
And so here we are. Bash uses the shell_level check and makes sure that
it's 1 before running the startup files when using `bash -c'. I'm sure
you can see the problem with this: it really works well only when a user's
login shell is bash. If someone logs into a machine using ssh, their login
shell is not bash, and they eventually at some point run `bash -c command',
the bash startup files, including /etc/bash.bashrc, will be executed. As
the comment says, that's why the behavior has to be specifically enabled.

There were still plenty of complaints about bash not behaving "as
documented" when SSH_SOURCE_BASHRC is not defined, like in the threads
Greg posted.

Chet
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU ***@case.edu http://cnswww.cns.cwru.edu/~chet/
Cristian Zoicas
2017-04-06 07:30:59 UTC
Permalink
Thank you Chet for shedding some light on this matter. Now it is
understandable that due to a request that dates back to the late 1990s was
decided that bash has to execute .basrc when it is started remotely and
non-interactively, but I still have the feeling that I am missing something.
Please let me explain may doubts.

1) When logging into a virtual console bash executes the system/user profiles (/etc/profile and ~/.profile)
2) When running "su - <username>" bash executes the system/user profiles (/etc/profile and ~/.profile)
3) When running "su - <username> -c ls -l" bash executes the system/user profile (/etc/profile and ~/.profile)
4) When running "bash" at the command prompt bash executes .bashrc (and eventually bash.bashrc)
5) When running "bash -c 'echo "Hello World!"' " bash DOES NOT execute .bashrc (and eventually bash.bashrc)

In all these cases above bash behaves very well and in my opinion as expected
by most users.

Now let's analize what happens under ssh.

I) When running "ssh ***@someshot" bash executes the system/user profiles (/etc/profile and ~/.profile)
II) When running "ssh ***@someshot ls -l" the system/user profiles are not executed but .bashrc is executed.

In case I) when the user logs on the system/user profiles are executed. This
is consistent with all the behavior presented so far.

But in the second case the things are very surprising:

a) although the user is authenticated the system/user profiles are not
executed, and

b) to make the things even more confusing, although the shell is not
interactive .bashrc is executed.

All this behavior is documented in the man pages of ssh and bash, but I simply
cannot understand why was not possibile to start a login shell and
consequently to have bash loading the system/user profiles instead of starting
a non-interactive shell that loads .bashrc. This is also in contrast with the
purpose of the .bashrc files that must prepare the shell for an interactive
session (which does not occur in the case II).

Why the request of loading .bashrc and the impossibility of starting a login shell (when a login is performed)?

Cristian
Chet Ramey
2017-04-08 01:57:51 UTC
Permalink
Post by Cristian Zoicas
Now let's analize what happens under ssh.
(/etc/profile and ~/.profile)
executed but .bashrc is executed.
In case I) when the user logs on the system/user profiles are executed. This
is consistent with all the behavior presented so far.
a) although the user is authenticated the system/user profiles are not
executed, and
b) to make the things even more confusing, although the shell is not
interactive .bashrc is executed.
In case II, what ends up actually being executed is `bash -c "ls -l"'. This
is how sshd invokes the shell to run the requested command. It's not a
login shell, so no login shell startup files. The fact that .bashrc is
read and executed is exactly what we're discussing here: it was added as
an optional feature due to user requests.
Post by Cristian Zoicas
All this behavior is documented in the man pages of ssh and bash, but I simply
cannot understand why was not possibile to start a login shell and
consequently to have bash loading the system/user profiles instead of starting
a non-interactive shell that loads .bashrc. This is also in contrast with the
purpose of the .bashrc files that must prepare the shell for an interactive
session (which does not occur in the case II).
Why the request of loading .bashrc and the impossibility of starting a
login shell (when a login is performed)?
I explained, in my previous message, exactly why bash reads .bashrc when
it's invoked by ssh, and the reasons users requested it.

If you want sshd to start a login shell for every command that it receives,
you'll have to request that feature with the ssh developers.
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU ***@case.edu http://cnswww.cns.cwru.edu/~chet/
Loading...