docker container exec -it <container name or id> /bin/sh
docker container exec -it <container name or id> /bin/bash
OCI runtime exec failed: exec failed: container_linux.go:345: starting container process caused "exec: \"/bin/bash\": stat /bin/bash: no such file or directory": unknown
What is sh
sh (or the Shell Command Language) is a programming language described by the POSIX standard. It has many implementations (
bash can also be considered an implementation of
sh (see below).
sh is a specification, not an implementation,
/bin/sh is a symlink (or a hard link) to an actual implementation on most POSIX systems.
What is bash
bash started as an
sh-compatible implementation (although it predates the POSIX standard by a few years), but as time passed it has acquired many extensions. Many of these extensions may change the behavior of valid POSIX shell scripts, so by itself
bash is not a valid POSIX shell. Rather, it is a dialect of the POSIX shell language.
bash supports a
--posix switch, which makes it more POSIX-compliant. It also tries to mimic POSIX if invoked as
sh = bash?
For a long time,
/bin/sh used to point to
/bin/bash on most GNU/Linux systems. As a result, it had almost become safe to ignore the difference between the two. But that started to change recently.
Some popular examples of systems where
/bin/sh does not point to
/bin/bash (and on some of which
/bin/bash may not even exist) are:
- Modern Debian and Ubuntu systems, which symlink
dash by default;
- Busybox, which is usually run during the Linux system boot time as part of
initramfs. It uses the
ash shell implementation.
- BSDs, and in general any non-Linux systems. OpenBSD uses
pdksh, a descendant of the Korn shell. FreeBSD’s
sh is a descendant of the original UNIX Bourne shell. Solaris has its own
sh which for a long time was not POSIX-compliant; a free implementation is available from the Heirloom project.
How can you find out what
/bin/sh points to on your system?
The complication is that
/bin/sh could be a symbolic link or a hard link. If it’s a symbolic link, a portable way to resolve it is:
% file -h /bin/sh
/bin/sh: symbolic link to bash
If it’s a hard link, try
% find -L /bin -samefile /bin/sh
In fact, the
-L flag covers both symlinks and hardlinks, but the disadvantage of this method is that it is not portable — POSIX does not require
find to support the
-samefile option, although both GNU find and FreeBSD find support it.
Ultimately, it’s up to you to decide which one to use, by writing the «shebang» line.
sh (and whatever that happens to point to),
/bin/bash if it’s available (and fail with an error message if it’s not). Of course, you can also specify another implementation, e.g.
Which one to use
For my own scripts, I prefer
sh for the following reasons:
- it is standardized
- it is much simpler and easier to learn
- it is portable across POSIX systems — even if they happen not to have
bash, they are required to have
There are advantages to using
bash as well. Its features make programming more convenient and similar to programming in other modern programming languages. These include things like scoped local variables and arrays. Plain
sh is a very minimalistic programming language.