Notes on shell scripting with Bash and other UNIX shells.
The Shebang Line: /bin/sh and /bin/bash
Start your shell scripts with the shebang sh, unless you have a specific reason to require another shell. Linux and other UNIX-like systems all include a symbolic link for /bin/sh that points to the default shell for the operating system.
If you use the sh shebang, shells will detect this, and interpret your script using the syntax of the Bourne shell, without any extra features. This means that the script should run correctly in all of the shells that supports the Bourne syntax.
The shebang line for sh is:
Most Linux systems use Bash for shell scripts. Current versions of macOS also provide Bash, but macOS Catalina uses Z shell by default. Debian-based systems use the Dash shell for sh scripts, and Bash for interactive shells. Alpine Linux uses Busybox.
If you need to use features that are specific to Bash, use the bash shebang. This means that the script will be run by Bash, rather than the default shell.
This Stack Overflow answer on bash vs .sh provides more details.
Debian-based systems, such as Ubuntu, provide the checkbashisms tool for you to be able to test scripts for portability.
Enabling Better Error Handling with set
Always use a set command at the start of your scripts, immediately after the shebang line:
Bash and some other shells provide the -o pipefail option, but it is not part of the POSIX standard.
set -euo pipefail
In addition, add the -E option to ensure that ERR traps catch errors from functions and subshells:
set -Eeuo pipefail
To print each command that the shell runs as it executes, add the -x option:
set -xeuo pipefail
Use ShellCheck to Validate Your Scripts
The ShellCheck utility will spot common mistakes and issues in your shell scripts. Always use this tool, because it will enable you to avoid whole classes of problem. For example, ShellCheck considers unquoted strings to be an issue, because of the risk of wordsplitting.
Use sh to Format Your Shell Scripts
The sh utility will format your shell scripts to be consistent.
Each UNIX shell runs a specific set of scripts each time that starts. Use these default scripts to set environment variables.
Bash Startup Scripts
Bash runs different scripts, depending on how is started:
- Started as an interactive non-login shell, it runs the .bashrc scripts. The terminal windows on a Linux graphical desktop are non-login shells.
- Started as an interactive login shell, it runs .bash_profile, .bash_login, and .profile (in that order).
- Started as a non-interactive, non-login shell, it runs the script specified by the BASH_ENV environment variable.
- Started with sh, it runs /etc/profile and ~/.profile scripts.
The global system copy of each default script will be in the /etc directory, and there may be a second script with the same name in the home directory of the current user. Both of these scripts will run.
For convenience, operating system vendors provide default scripts that call other scripts.
Standard Environment Variables on Linux
The Debian Wiki page lists these standard environment variables:
- PATH Colon separated list of directories to search for commands.
- HOME Current user’s home directory.
- LOGNAME Current user’s name.
- SHELL The user’s preferred shell.
- EDITOR The user’s preferred text editor.
- MAIL The user’s email inbox location.
Running Commands on Remote Systems with SSH
To run a single command, use the ssh utility:
ssh email@example.com "command"
To run multiple commands, use a HERE-doc:
ssh firstname.lastname@example.org << HERE command1 command2 HERE
To run a script on a remote system, use SSH to send the contents of the script file to a script interpreter on the remote system. This example uses the bash shell:
ssh email@example.com '/bin/bash -s' < scriptfile.sh
The -s option means that the bash shell will run what is sent to it from the standard input.
ssh exits with either the exit status of the remote command, or with status number 255 if an error occurred.
Using the Command-line
- The Art of Command Line - A guide to mastering the command-line
- Explainshell - enter a command-line on this site to see the help text that matches each argument