DevOps Peach

Linux · Bash Scripting · Lesson 1 of 5

Shells, your first script, and I/O

Understand how Bash reads scripts and connects data streams.

Practice interactively →

How Bash runs a script

A shell receives commands, expands syntax, and asks the kernel to run programs. Bash is the default on most servers; sh is a smaller POSIX shell (Dash on Ubuntu), so Bash-only syntax can fail when a script runs under sh. A Bash script commonly starts with #!/usr/bin/env bash; the shebang matters when the file is executed directly as ./hello.sh. Running bash hello.sh explicitly invokes the interpreter and does not require the script's execute bit, though the file must remain readable.

#!/usr/bin/env bash
set -euo pipefail          # stop on errors, unset variables, failed pipes
# Lines starting with # are comments
name="${1:-World}"
echo "Hello, $name"

./ is needed because the current directory is not in PATH, the list of directories Bash searches for commands. source script.sh (or . script.sh) runs the file inside the current shell instead of a child process, so variables it sets remain afterwards; that is how ~/.bashrc changes are reloaded.

flowchart LR
  F["hello.sh<br/>starts with a shebang"] -- "chmod +x" --> X["./hello.sh"]
  IN["stdin 0<br/>keyboard or a file"] --> X
  X --> OUT["stdout 1<br/>normal output"]
  X --> ERR["stderr 2<br/>error messages"]
  X --> RC["exit status $?<br/>0 = success"]
  %% step F: The shebang line tells the kernel which interpreter runs the file.
  %% step X: chmod +x makes it executable; ./ runs it from the current directory.
  %% step IN: Input arrives on stdin, from the keyboard or a redirected file.
  %% step OUT: Normal output goes to stdout, which > or | can redirect.
  %% step ERR: Errors go to stderr so they stay visible when stdout is redirected.
  %% step RC: Every command returns an exit status; 0 means success.

Streams and redirection

Every process has three standard streams: stdin (0), stdout (1), and stderr (2). Errors go to stderr, so > alone does not capture them.

Syntax Effect
chmod u+x hello.sh Add execute for the owner
bash -n hello.sh Check syntax without executing
date > today.txt Replace a file with stdout
who >> today.txt Append stdout to a file
cmd 2> err.log Send stderr to a file
cmd > all.log 2>&1 Send stdout and stderr to one file
cmd > /dev/null Discard output
ls | sort Feed ls stdout to sort stdin

A here-document feeds several lines to stdin: cat <<EOF > note.txt writes everything up to a line containing only EOF.

Input, variables, and exit status

read -r answer reads one line without treating backslashes specially. Assign variables without spaces around =: name="John" assigns, whereas name = "John" asks Bash to run a command named name.

Every command returns an exit status: 0 for success, anything else for failure. echo $? shows the last one, and exit 1 ends a script with failure so that cron or a CI pipeline notices.

> truncates before writing; use >> to preserve old content. A “Permission denied” error during direct execution often means the execute bit is missing. bash -x hello.sh prints each command as it runs, which is the quickest way to debug.

Practice interactively →