Linux Apps & tools

Bash scripting basics

Practical Linux guide: bash scripting basics without the usual guesswork.

10 min read Beginner Updated 9 Jun 2026

Step-by-step guide

Work through each section in order. Stop when your issue is resolved — you do not need every step for every situation.

What you will achieve

Write maintainable Bash scripts on Linux with strict error handling, sane quoting, and arguments — the baseline for cron and systemd oneshot services.

1) Shebang and strict mode

#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'

2) Variables and quoting

name="server1"
echo "Backup ${name} at $(date -Iseconds)"
paths=("/etc" "/var/www")

Always quote expansions: "$var" prevents word splitting.

3) Conditionals and loops

if [[ -f /etc/os-release ]]; then
    source /etc/os-release
    echo "Running on $ID"
fi

for dir in "${paths[@]}"; do
    tar -czf "/backup/$(basename "$dir").tar.gz" "$dir"
done

4) Functions and exit codes

log() { echo "[$(date -Iseconds)] $*"; }
trap 'log "Failed at line $LINENO"' ERR

Verify

shellcheck script.sh
bash -n script.sh

5) Arguments and usage

usage() { echo "Usage: $0 <host>"; exit 1; }
[[ $# -eq 1 ]] || usage
host=$1

6) Reading files safely

while IFS= read -r line; do
    printf '%s\n' "$line"
done < "$file"

7) Temporary files

tmp=$(mktemp) || exit 1
trap 'rm -f "$tmp"' EXIT

Testing scripts

Use shellcheck and run with bash -x script.sh during development. For production cron jobs, log stdout/stderr to journald or a rotated log file.

8) set -x only in debug

[[ "${DEBUG:-}" == 1 ]] && set -x

Prerequisites

bash 4+ (check bash --version). Executable bit (chmod +x script.sh). Editor and shellcheck optional but recommended. Know difference between #!/bin/bash and #!/bin/sh on Debian (dash).

Cron environment minimalism

Cron jobs should use absolute paths and set PATH explicitly — #!/usr/bin/env bash scripts fail in cron if they assume interactive shell PATH.

read -r safety

read -r line < file

-r disables backslash escape eating — prevents subtle input corruption in scripts reading user data.

errexit pitfalls

set -e does not trigger in pipelines unless set -o pipefailcurl | grep can hide curl failure. Always combine both in production scripts. Subshells and if conditions exempt some failures — read bash manual before assuming errexit catches everything.

shellcheck in CI

Add shellcheck step to GitHub Actions or git pre-commit — catches unquoted vars before deploy script runs as root at 2am via cron.

log with timestamp function

log() { printf '[%s] %s\n' "$(date -Iseconds)" "$*"; }

Structured logs from cron jobs grep easier than bare echo without context.

printf over echo

printf '%s\n' "$var" portable — echo -e behaviour varies between bash and dash. Debian /bin/sh is dash — scripts targeting sh must avoid bashisms or use bash shebang explicitly.

Related guides

bash basics linux scripting