
Bash Functions Explained
Bash functions let you write a block of code once, give it a name, and reuse it whenever your script needs it. They help turn one long script into cleaner, safer, easier-to-maintain automation.
What is a Bash function?
A Bash function is a reusable block of shell commands. Instead of copying the same lines again and again, you define the function once and call it by name.
Functions are useful when your script has repeated tasks such as checking a service, printing a status message, validating arguments, logging output, checking disk usage or testing a website.
Basic Bash function syntax
The most common syntax is:
function_name() {
command
command
}
Example:
say_hello() {
echo "Hello from Bash"
}
You may also see this style:
function say_hello {
echo "Hello from Bash"
}
The first style, name() { ... }, is widely used and portable across normal Bash scripts.
Calling a Bash function
Defining a function does not run it. You call it by writing the function name later in the script.
#!/usr/bin/env bash
say_hello() {
echo "Hello from Bash"
}
say_hello
Hello from BashThe function must normally be defined before you call it. Bash reads the script from top to bottom, so calling a function before it exists can fail.
Passing arguments to Bash functions
Function arguments work much like script arguments. Inside a function, $1 is the first argument passed to the function, $2 is the second, and $@ means all function arguments.
#!/usr/bin/env bash
greet_user() {
echo "Hello, $1"
}
greet_user "Robbie"
greet_user "Linux Admin"
Hello, Robbie
Hello, Linux AdminUse quotes when passing values that may contain spaces. Without quotes, "Linux Admin" becomes two separate words. Bash is helpful like that, in the same way a cat is helpful when walking across your keyboard.
Using multiple arguments
#!/usr/bin/env bash
show_user() {
echo "Username: $1"
echo "Role: $2"
}
show_user "alice" "developer"
Username: alice
Role: developerFor script-level arguments, see Bash script arguments explained.
Create a usage function
A usage function is one of the most useful functions in beginner scripts. It prints a short help message when the user runs the script incorrectly.
#!/usr/bin/env bash
usage() {
echo "Usage: $0 <domain>"
echo "Example: $0 example.com"
}
if [ "$#" -ne 1 ]; then
usage
exit 1
fi
domain="$1"
echo "Checking domain: $domain"
Usage: check-domain.sh <domain>
Example: check-domain.sh example.comChecking domain: commandlinequiz.comThis keeps the help text in one place. If you change the script later, you only update the usage function.
Use local variables inside functions
By default, Bash variables are global. That means a variable created inside a function can affect the rest of the script. Use local for variables that should only exist inside the function.
#!/usr/bin/env bash
server="production"
show_server() {
local server="staging"
echo "Inside function: $server"
}
show_server
echo "Outside function: $server"
Inside function: staging
Outside function: productionUsing local helps prevent accidental variable clashes as your scripts grow.
Return success or failure from a function
In Bash, return is normally used for exit codes, not for returning text. A return code of 0 means success. Non-zero means failure.
#!/usr/bin/env bash
check_file() {
local file="$1"
if [ -f "$file" ]; then
return 0
else
return 1
fi
}
if check_file "/etc/passwd"; then
echo "File exists"
else
echo "File is missing"
fi
File existsThis pattern is clean because the function can be used directly inside an if statement. For more condition examples, read Bash operators explained.
Checking the return code manually
check_file "/tmp/example.txt"
result=$?
echo "Function returned: $result"
Return text using echo and command substitution
If you want a function to give back text, print it with echo and capture it with command substitution.
#!/usr/bin/env bash
get_date_stamp() {
date "+%Y-%m-%d"
}
stamp=$(get_date_stamp)
echo "Backup date: $stamp"
Backup date: 2026-05-05return for success or failure. Use echo when you want to capture text output.Practical Bash function examples
1. Disk usage checker function
This function checks a mount point and warns if disk usage is above a threshold.
#!/usr/bin/env bash
check_disk_usage() {
local mount_point="$1"
local warning_level="$2"
local usage
usage=$(df -P "$mount_point" | awk 'NR==2 {gsub("%", "", $5); print $5}')
if [ "$usage" -ge "$warning_level" ]; then
echo "[WARN] $mount_point is $usage% full"
return 1
else
echo "[OK] $mount_point is $usage% full"
return 0
fi
}
check_disk_usage "/" 80
check_disk_usage "/home" 85
[OK] / is 42% full
[WARN] /home is 91% fullThis fits naturally with the Linux high disk usage troubleshooting guide.
2. Service status checker function
This function checks whether a systemd service is running.
#!/usr/bin/env bash
check_service() {
local service="$1"
if systemctl is-active --quiet "$service"; then
echo "[OK] $service is running"
return 0
else
echo "[WARN] $service is not running"
return 1
fi
}
check_service "sshd"
check_service "crond"
check_service "httpd"
[OK] sshd is running
[OK] crond is running
[WARN] httpd is not runningIf you want to understand the service commands used here, read the systemd services guide.
3. Website status checker function
This function checks a URL and reports the HTTP status code and response time.
#!/usr/bin/env bash
check_website() {
local url="$1"
local result status time_total
result=$(curl -o /dev/null -s -w "%{http_code} %{time_total}" "$url")
status=$(echo "$result" | awk '{print $1}')
time_total=$(echo "$result" | awk '{print $2}')
if [ "$status" = "200" ]; then
echo "[OK] $url returned $status in ${time_total}s"
return 0
else
echo "[WARN] $url returned $status in ${time_total}s"
return 1
fi
}
check_website "https://example.com"
check_website "https://commandlinequiz.com"
[OK] https://example.com returned 200 in 0.147221s
[OK] https://commandlinequiz.com returned 200 in 0.208456sFor a full monitoring script, see the Bash website uptime monitor guide.
4. Logging function
A simple logging function keeps output consistent across a script.
#!/usr/bin/env bash
log_msg() {
local level="$1"
local message="$2"
local timestamp
timestamp=$(date "+%Y-%m-%d %H:%M:%S")
echo "[$timestamp] [$level] $message"
}
log_msg "INFO" "Starting backup"
log_msg "WARN" "Disk usage is high"
log_msg "INFO" "Backup complete"
[2026-05-05 11:20:00] [INFO] Starting backup
[2026-05-05 11:20:01] [WARN] Disk usage is high
[2026-05-05 11:20:04] [INFO] Backup completePut functions in a separate file
As scripts grow, you may want to keep common functions in one file and load them from other scripts.
Create functions.sh:
log_msg() {
local level="$1"
local message="$2"
echo "[$level] $message"
}
Then source it from another script:
#!/usr/bin/env bash
source ./functions.sh
log_msg "INFO" "Loaded shared functions"
[INFO] Loaded shared functionsCommon Bash function mistakes
| Mistake | Problem | Better option |
|---|---|---|
| Calling a function before it is defined | Bash may not know the function exists yet. | Define functions near the top of the script, then call them later. |
Using return "text" | return expects a numeric exit code. | Use echo and command substitution for text output. |
| Not quoting arguments | Values with spaces can split into multiple words. | Use "$1", "$file" and "$@". |
| Using global variables everywhere | Functions can accidentally overwrite values used later. | Use local inside functions. |
| Functions that do too much | Huge functions become hard to test and reuse. | Keep each function focused on one clear task. |
Practice exercises
Create a greeting function
Write a function that accepts a name and prints a personalised greeting.
Create a file checker
Write a function that checks whether a path exists, then returns success or failure.
Create a service checker
Write a function that accepts a service name and checks it with systemctl.
Create a logging function
Write a function that prints timestamps and log levels for your scripts.
What should you learn next?
Once you understand Bash functions, you can combine them with arguments, user input, loops and tests to build cleaner admin scripts. This is where Bash starts becoming a proper toolkit rather than a pile of one-liners wearing a trench coat.