The Almquist shell (ash) was written by Kenneth Almquist in 1989 as a small, BSD-licensed replacement for the Bourne shell. Its descendants are everywhere: NetBSD and FreeBSD sh, dash on Debian, and the BusyBox shell. When people say "ash" on Linux today they almost always mean BusyBox ash.
BusyBox ash¶
BusyBox bundles hundreds of trimmed-down utilities into one binary, and its shell is another ash descendant. It is /bin/sh in Alpine, the busybox image, many embedded systems, and initramfs environments. If you docker exec into an Alpine-based container, this is what you get.
BusyBox is compiled with optional bash-compatibility features, so it usually accepts [[ ]], source, ${var//a/b}, and ${var:offset:length}. Arrays are not supported. Because exactly which extras are available depends on the build, don't rely on them.
docker run --rm -it alpine sh # BusyBox ash
busybox --list # every applet in this busybox build
apk add bash # Alpine: install real bash when a script needs it
The classic gotcha: a script with #!/bin/bash in an Alpine image fails with not found, even though the script file exists. The missing file is the interpreter named on the shebang line, not the script. Install bash or change the shebang.
The coreutils replacements are trimmed too. Long options and less common flags of ls, grep, sed, date, and find may be missing, so a script can fail on Alpine because of a utility, not the shell.
Further reading¶
- BusyBox documentation
- sh for portable scripting that works under ash