Functions & Exit Codes
Functions group reusable commands; exit codes report whether a command succeeded.
Syntax
name() { commands; }
echo $? # last exit codeAs scripts grow, functions keep them tidy by naming a block of commands you can call repeatedly.
Defining a function
greet() {
echo "Hello, $1"
}
greet AliceFunctions receive arguments just like scripts do, via $1, $2 and so on.
Exit codes
Every command returns an exit code: 0 means success, anything else means failure. The special variable $? holds the last command's code. This is what if actually tests, and it lets you chain commands:
cmd1 && cmd2— run cmd2 only if cmd1 succeeded.cmd1 || cmd2— run cmd2 only if cmd1 failed.
Example
#!/bin/bash
log() {
echo "[$(date +%T)] $1"
}
log "Starting backup"
if tar -czf backup.tar.gz ./data; then
log "Backup succeeded"
else
log "Backup FAILED with code $?"
fi
# Chain on success / failure
mkdir build && echo "Folder created"When to use it
- A deployment script defines a 'log()' function to prefix all messages with a timestamp, keeping output format consistent.
- A sysadmin script uses a 'check_root()' function called at the start to exit immediately if not running as root.
- A library script defines reusable 'backup_db()' and 'rotate_logs()' functions that are sourced and called from multiple other scripts.
More examples
Define and call a function
Defines a log() function using $* to accept any arguments and prefix them with a timestamp.
#!/bin/bash
log() {
echo "[$(date +%H:%M:%S)] $*"
}
log "Starting deployment"
log "Copying files..."
log "Done"Function with return value
Uses 'local' for scoped variables and returns nc's exit code so the caller can test success with if.
#!/bin/bash
is_port_open() {
local host=$1
local port=$2
nc -z "$host" "$port" &>/dev/null
return $? # 0 = success, non-zero = failure
}
if is_port_open localhost 5432; then
echo "PostgreSQL is reachable"
else
echo "Cannot reach PostgreSQL"
fiSource a shared function library
Sources an external file to load shared functions, enabling code reuse across multiple scripts.
#!/bin/bash
# lib/functions.sh defines shared helpers
source /opt/scripts/lib/functions.sh
# or: . /opt/scripts/lib/functions.sh
# Now use functions defined in the library
check_root
log "Root check passed"
backup_db "mydb"
Discussion