Introduction#
Hello! Today I’ll explain the set command.
The set command configures options that control shell behavior. Super useful when you want to debug scripts or change error handling behavior.
What is the set Command?#
The set command is a Bash built-in for enabling/disabling shell options and setting positional parameters.
Use it when you want “scripts to stop on errors” or “errors on undefined variables”. Essential for writing serious scripts.
Basic Syntax#
1
2
3
4
5
6
7
8
|
# Enable options
set -option
# Disable options
set +option
# Set positional parameters
set value1 value2 value3...
|
Main Options#
| Option |
Description |
-e |
Exit script if command returns error |
-u |
Error on undefined variables |
-x |
Display commands before execution (debug) |
-o pipefail |
Detect errors in pipelines |
-n |
Check syntax only, don’t execute |
-v |
Display commands before execution |
Usage Examples#
1
2
3
4
5
6
|
#!/bin/bash
set -e
echo "Process 1"
false # Error command
echo "Process 2" # Not executed
|
Output:
The false command errors out and stops the script. Without set -e, it would ignore the error and continue.
Example 2: Error on Undefined Variables (-u)#
1
2
3
4
5
6
|
#!/bin/bash
set -u
NAME="John"
echo $NAME
echo $AGE # Error on undefined variable
|
Output:
1
2
|
John
bash: AGE: unbound variable
|
Prevents bugs from typos.
Example 3: Debug Mode (-x)#
1
2
3
4
5
6
|
#!/bin/bash
set -x
name="John"
age=30
echo "Name: $name, Age: $age"
|
Output:
1
2
3
4
|
+ name=John
+ age=30
+ echo 'Name: John, Age: 30'
Name: John, Age: 30
|
Executed commands are shown with +. Super handy.
Example 4: Detect Pipeline Errors#
1
2
3
4
5
6
|
#!/bin/bash
set -o pipefail
# Error in middle of pipeline
cat nonexistent.txt | grep "test" | wc -l
echo "Exit code: $?"
|
Output:
1
2
|
cat: nonexistent.txt: No such file or directory
Exit code: 1
|
Without set -o pipefail, the exit code would be 0 since wc -l succeeds.
Example 5: Combining Multiple Options#
1
2
3
4
5
|
#!/bin/bash
# Common combination
set -euo pipefail
echo "Safe script execution"
|
or
1
2
3
4
5
|
#!/bin/bash
set -eux
set -o pipefail
echo "Strict mode + debug"
|
Example 6: Setting Positional Parameters#
1
2
3
4
5
6
7
8
9
10
|
# Display current positional parameters
echo "$@"
# Set new values
set apple banana orange
echo "Arg 1: $1"
echo "Arg 2: $2"
echo "Arg 3: $3"
echo "All args: $@"
|
Output:
1
2
3
4
|
Arg 1: apple
Arg 2: banana
Arg 3: orange
All args: apple banana orange
|
Example 7: Disabling Options#
1
2
3
4
5
6
7
8
|
#!/bin/bash
set -x # Enable debug
echo "Debugging"
set +x # Disable debug
echo "Normal execution"
|
Output:
1
2
3
|
+ echo Debugging
Debugging
Normal execution
|
Use + to disable.
Tips & Notes#
set -e Gotchas#
set -e is useful but gets disabled inside conditionals.
1
2
3
4
5
6
7
8
|
#!/bin/bash
set -e
if false; then
echo "Not executed"
fi
echo "This executes" # Doesn't stop on error!
|
If you don’t want this behavior, check explicitly.
1
2
3
4
5
6
7
|
#!/bin/bash
set -e
if ! some_command; then
echo "Command failed" >&2
exit 1
fi
|
Check Current Options#
1
2
|
# Display enabled options
set -o
|
or
Write at Script Top#
Recommended to write set options at script top.
1
2
3
4
5
6
|
#!/bin/bash
# Recommended script header
set -euo pipefail
IFS=$'\n\t'
# Main processing starts here
|
Temporarily Change Options#
1
2
3
4
5
6
7
8
9
10
11
12
|
#!/bin/bash
set -e
# Temporarily disable -e
set +e
might_fail_command
result=$?
set -e
if [ $result -ne 0 ]; then
echo "Command failed"
fi
|
Practical Usage#
Production Scripts#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#!/bin/bash
# Exit immediately on error
set -euo pipefail
# Log file
LOG_FILE="/var/log/myapp.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "Backup started"
tar -czf backup.tar.gz /data
log "Backup completed"
|
Debug Scripts#
1
2
3
4
5
6
7
8
9
|
#!/bin/bash
# Debug mode detection
if [ "${DEBUG:-}" = "1" ]; then
set -x
fi
set -euo pipefail
# Processing...
|
Run with:
1
2
3
4
5
|
# Normal
./script.sh
# Debug
DEBUG=1 ./script.sh
|
Error Handling#
1
2
3
4
5
6
7
8
9
|
#!/bin/bash
set -euo pipefail
# Error handler
trap 'echo "Error occurred: line $LINENO" >&2' ERR
echo "Process 1"
false # Error
echo "Process 2"
|
Output:
1
2
|
Process 1
Error occurred: line 7
|
File Processing#
1
2
3
4
5
6
7
8
9
10
|
#!/bin/bash
set -euo pipefail
# Read from file and set positional parameters
set -- $(cat files.txt)
for file in "$@"; do
echo "Processing: $file"
process_file "$file"
done
|
Environment Variable Defaults#
1
2
3
4
5
6
7
8
|
#!/bin/bash
set -euo pipefail
# Error on undefined but allow defaults
DATABASE_HOST="${DATABASE_HOST:-localhost}"
DATABASE_PORT="${DATABASE_PORT:-5432}"
echo "Connecting to: $DATABASE_HOST:$DATABASE_PORT"
|
Common set Option Combinations#
Strict Mode#
1
2
3
|
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
|
This is Bash script best practice.
-e: Exit on error
-u: Error on undefined variables
-o pipefail: Detect pipeline errors
IFS=$'\n\t': Safe delimiter settings
Debug Mode#
1
2
|
#!/bin/bash
set -xeuo pipefail
|
or conditional:
1
2
3
|
#!/bin/bash
[ "${DEBUG:-0}" = "1" ] && set -x
set -euo pipefail
|
Summary#
Key points about the set command:
- -e: Exit immediately on error (recommended)
- -u: Error on undefined variables (recommended)
- -x: Display commands for debugging
- -o pipefail: Detect pipeline errors (recommended)
- to enable, + to disable
- Best practice:
set -euo pipefail at script top
For serious scripts, you should at least include set -e!