Class 25 of 55 • Linux Shells & Terminal

Bourne Shell (sh) Architecture & Scripting Masterclass

 1. What is the Bourne Shell (sh)?

 The Bourne Shell (binary command name sh) is the historic, foundational command-line interpreter and script execution environment designed for the Unix operating system. Developed by computer scientist Stephen Bourne at AT&T Bell Laboratories in Murray Hill, New Jersey, it was officially released in 1979 with Version 7 Unix (V7).

 Before the Bourne Shell, early Unix systems used Ken Thompson's rudimentary "Thompson Shell" (1971), which had no programmatic control flow (loops or conditionals) and required external utility calls for almost every logical operation. Stephen Bourne revolutionized systems programming by creating a shell that was simultaneously a responsive interactive command interpreter and a full-fledged, structured, algorithmic scripting language.

 2. The Architectural Role of a Shell in Linux

 In Linux architecture, the Kernel sits at the core managing CPU scheduling, RAM allocation, hardware drivers, and raw filesystem access. The user never communicates directly with the kernel; instead, the Shell acts as an outer protective layer (hence the name "shell") wrapping around the kernel:

Operating Mode Description & Behavior
Interactive Mode The shell reads commands entered directly by the human user at the command line prompt ($ for standard users, # for root), parses arguments, forks child processes to execute them, and displays results to standard output.
Non-Interactive (Batch) Mode The shell reads a file containing a sequential list of commands (a shell script) and executes them line-by-line automatically, providing exit status codes ($?) upon completion.

 3. Groundbreaking Inventions of the Bourne Shell

 Stephen Bourne introduced syntax rules that became the universal standard codified in the POSIX (Portable Operating System Interface) specification:

Feature Concept Syntax / Notation Architectural Purpose
Environment Variables export VAR="val" Allows variables defined in the current shell process to be inherited by all child processes executed from it (e.g., $PATH, $USER).
I/O Redirection >, >>, <, 2> Redirecting standard output to overwrite (>) or append (>>) files, reading standard input (<), and isolating standard error streams (2>).
UNIX Pipelines cmd1 | cmd2 Pipes the standard output of cmd1 directly into the standard input of cmd2 without intermediate temporary disk files.
Command Substitution `date` or $(date) Executes a sub-command and replaces the command string with its evaluated standard output text.
Control Flow Blocks if...fi, case...esac Structured branching constructs borrowed from Algol 68. Notice the closing keywords are mirror reversals of the opening tags!
Signal Trapping trap 'clean_up' EXIT Enables catching system signals (such as Ctrl+C SIGINT or script exit) to clean up temporary files cleanly.

 4. The Modern Linux Reality: /bin/sh vs. Bash & Dash

 On modern Linux computers, the original proprietary Bell Labs Bourne Shell is rarely installed. Instead, /bin/sh is a standardized symbolic link pointing to a modern, open-source POSIX-compliant implementation:

  • On Ubuntu & Debian: /bin/sh points to Dash (Debian Almquist Shell). Dash is a tiny, blazing-fast POSIX shell (~150 KB) that boots the operating system and runs system scripts with minimal RAM and CPU overhead.
  • On RHEL, Fedora & Rocky Linux: /bin/sh points directly to Bash (GNU Bourne Again Shell). When invoked as sh, Bash automatically turns on its strict POSIX-compliance compatibility mode.
Beware of "Bashisms": If your script starts with the shebang #!/bin/sh, you must avoid Bash-only syntax such as double brackets [[ $a == $b ]], indexed arrays, or the source keyword. Strict POSIX compliance uses single brackets [ "$a" = "$b" ] and the dot operator . ./file.sh.

 5. Practical Lab: Writing a Portable POSIX Bourne Script

 Let us create, inspect, and execute a 100% portable Bourne shell script:

Step 1: Inspecting Your Active /bin/sh

# Check where /bin/sh points on your system:
ls -l /bin/sh
# On Ubuntu/Debian: /bin/sh -> dash
# On Fedora/RHEL:    /bin/sh -> bash

# Check your current login shell:
echo $SHELL

Step 2: Writing a Portable Script

Create a file named backup_check.sh using your text editor:

#!/bin/sh
# Portable Bourne / POSIX Shell Script

# 1. Variables (No spaces around '=')
BACKUP_DIR="/tmp/student_backup"
TARGET_FILE="/etc/hosts"

# 2. Conditionals using standard test '[' operator
if [ ! -d "$BACKUP_DIR" ]; then
    echo "Creating backup directory: $BACKUP_DIR"
    mkdir -p "$BACKUP_DIR"
fi

# 3. Copying and logging
echo "Backing up $TARGET_FILE..."
cp "$TARGET_FILE" "$BACKUP_DIR/"

# 4. Check Exit Status ($?)
if [ $? -eq 0 ]; then
    echo "Backup completed successfully!"
    ls -l "$BACKUP_DIR"
else
    echo "Error: Backup failed!" 1>&2
    exit 1
fi

Step 3: Making Executable & Debugging

# Grant execute permissions:
chmod +x backup_check.sh

# Run the script normally:
./backup_check.sh

# Run the script in trace debugging mode (prints each command executed):
sh -x ./backup_check.sh

 6. Essential Positional Parameters Reference

Special Variable Description
$0 The name of the script itself as invoked.
$1 – $9 The 1st through 9th command-line arguments passed to the script.
$# The total count of command-line arguments passed.
$* All arguments as a single concatenated string: "$1 $2 $3".
$@ All arguments individually quoted: "$1" "$2" "$3" (safest for loop iteration).
$? Exit status of the most recently executed command (0 = success, non-zero = failure).
$$ The Process ID (PID) of the currently running shell script.

 7. Student Q&A and Viva Preparation

The Bourne Shell was created by computer scientist Stephen Bourne at AT&T Bell Laboratories and officially released in 1979 with Version 7 Unix (V7). It served as the default standard Unix shell, replacing the earlier Thompson shell.
The executable binary is named sh and is located at /bin/sh. In modern Linux distributions, /bin/sh is typically a symbolic link pointing to a lightweight POSIX-compliant shell like Dash (on Debian/Ubuntu) or Bash (in POSIX compatibility mode on RHEL/Fedora).
Stephen Bourne introduced environment variables (export), structured algorithmic control flow (if/then/else/fi, for/in/do/done, while/do/done, case/esac), input/output file redirection (<, >, >>), standard error separation (2>), here documents (<<), subshell grouping with parentheses, and signal trap handling.
Writing scripts targeting standard /bin/sh (without Bashisms) guarantees 100% portability across all Unix-like operating systems—including Linux distributions, FreeBSD, OpenBSD, macOS, Solaris, and lightweight embedded Alpine Linux containers that lack full Bash.
For regular unprivileged users, the default command prompt character is the dollar sign ($), while for the root administrative user, the prompt switches to the hash sign (#).

 8. Summary & Next Steps

 The Bourne Shell established the syntax and execution model upon which modern cloud automation and DevOps scripts rely. In the next tutorial, we examine the shell created for C programmers at UC Berkeley: Class 26: The C Shell (csh / tcsh).

Share Share on Facebook Share on Twitter Share on LinkedIn Pin on Pinterest Share on Stumbleupon Share on Tumblr Share on Reddit Share on Diggit

You may also like this!