Why does /bin/sh behave differently to /bin/bash even if one points to the other?
Solution 1:
bash
looks at the value of $argv[0]
(bash is implemented in C) to determine how it was invoked.
Its behavior when invoked as sh
is documented in the manual:
If Bash is invoked with the name
sh
, it tries to mimic the startup behavior of historical versions ofsh
as closely as possible, while conforming to the POSIX standard as well.When invoked as an interactive login shell, or as a non-interactive shell with the
-login
option, it first attempts to read and execute commands from/etc/profile
and~/.profile
, in that order. The--noprofile
option may be used to inhibit this behavior. When invoked as an interactive shell with the namesh
, Bash looks for the variableENV
, expands its value if it is defined, and uses the expanded value as the name of a file to read and execute. Since a shell invoked assh
does not attempt to read and execute commands from any other startup files, the--rcfile
option has no effect. A non-interactive shell invoked with the namesh
does not attempt to read any other startup files.When invoked as
sh
, Bash enters POSIX mode after the startup files are read
There's a long list (currently 46 items) of things that change when bash
is in POSIX mode, documented here.
(POSIX mode is probably useful mostly as a way to test scripts for portability to non-bash
shells.)
Incidentally, programs that change their behavior depending on the name under which they were invoked are fairly common. Some versions of grep
, fgrep
, and egrep
are implemented as a single executable (though GNU grep
doesn't do this). view
is typically a symbolic link to vi
or vim
; invoking it as view
causes to open in read-only mode. The Busybox system includes a number of individual commands that are all symlinks to the master busybox
executable.
Solution 2:
Invoking bash as sh
causes it to enter posix mode after reading the startup files it would normally read (as opposed to the startup files a POSIX sh would read.) Bash has many different invocation modes. You can find out about these modes from the INVOCATION
section of the manual. Here is some detail about the POSIX mode.
POSIX mode
This mode means bash will try, in various degrees, to conform to POSIX expectations. As explained here, bash has a few different invocations for this mode, with slightly different implications:
-
sh
: Bash enters POSIX mode after reading startup files. -
bash --posix
: Bash enters POSIX mode before reading startup files. -
set -o posix
: Bash switches to POSIX mode. -
POSIXLY_CORRECT
: If this variable is in the environment when bash starts, the shell enters posix mode before reading the startup files, likebash --posix
. If it is set while bash is running, likeset -o posix
.
Solution 3:
From the Bash Reference Manual:
If Bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well.
Solution 4:
Because the bash
binary checks how it was invoked (via argv[0]
) and enters a compatibility mode if it's being run as sh
.