Bash Scripting: Automating Repetitive Tasks
Your First Bash Script: Shebang and Execution
A Bash script is a text file containing commands that the shell executes automatically. Create check_system.sh:
#!/bin/bash
set -euo pipefail
echo "=== System Health ==="
echo "Date: $(date)"
echo "Host: $(hostname)"
echo "Uptime: $(uptime -p)"
df -h / | tail -1
The #!/bin/bash shebang tells Linux which interpreter to use. set -euo pipefail exits on errors, treats unset variables as errors, and fails pipelines properly.
chmod +x check_system.sh && ./check_system.sh
Variables and Command-Line Arguments
SENSOR_DIR="/opt/scada/data"
MAX_TEMP=95
SERVER=$(hostname)
echo "Collecting on $SERVER from ${SENSOR_DIR}"
No spaces around =. Use ${VAR} adjacent to text. Arguments come from $1, $2, etc.
| Variable | Meaning |
|---|---|
$0 |
Script name |
$1-$9 |
Positional arguments |
$# |
Number of arguments |
$@ |
All arguments |
$? |
Exit code of last command |
Conditions: if, test, and [[ ]]
TEMP=97
if [[ $TEMP -gt 95 ]]; then
echo "WARNING: Temperature exceeds threshold!"
elif [[ $TEMP -gt 80 ]]; then
echo "NORMAL: Within range."
else
echo "LOW: Below expected."
fi
Numeric: -eq, -ne, -gt, -lt, -ge, -le. Strings: ==, !=.
[[ -f "$FILE" ]] # File exists
[[ -d "$DIR" ]] # Directory exists
[[ -s "$FILE" ]] # File not empty
[[ -x "$FILE" ]] # File executable
Loops: for, while, and until
for sensor in sensor_01 sensor_02 sensor_03; do
ping -c 1 "${sensor}.factory.local" > /dev/null 2>&1 \
&& echo "$sensor: OK" || echo "$sensor: DOWN"
done
for file in /opt/scada/data/*.csv; do
echo "$(wc -l < "$file") lines in $file"
done
while IFS=',' read -r ts sensor val status; do
[[ "$status" == "ALARM" ]] && echo "ALARM: $sensor=$val at $ts"
done < /var/log/sensors/today.csv
until curl -s http://localhost:8080/health > /dev/null 2>&1; do
echo "Waiting for SCADA server..."; sleep 2
done
Functions: Reusing Code
#!/bin/bash
set -euo pipefail
log_msg() {
local level="$1" msg="$2"
echo "$(date '+%Y-%m-%d %H:%M:%S') [$level] $msg"
}
check_sensor() {
local ip="$1" name="$2"
if ping -c 1 -W 2 "$ip" > /dev/null 2>&1; then
log_msg "INFO" "$name ($ip) online"; return 0
else
log_msg "ERROR" "$name ($ip) UNREACHABLE"; return 1
fi
}
check_sensor "192.168.1.101" "Temp Sensor A"
check_sensor "192.168.1.102" "Pressure Sensor B"
Use local for function-scoped variables. return 0 = success; non-zero = failure.
Practical Example: A Script That Collects Sensor Data Every 5 Minutes and Sends a Report
#!/bin/bash
set -euo pipefail
SENSOR_DIR="/opt/scada/data"
REPORT="/var/log/sensors/report_$(date +%Y%m%d).csv"
collect() {
local sensor="$1"
local val=$(cat "${SENSOR_DIR}/${sensor}/current_value" 2>/dev/null || echo "N/A")
echo "$(date '+%Y-%m-%dT%H:%M:%S'),$sensor,$val"
}
while true; do
ALERTS=0
for dir in "${SENSOR_DIR}"/sensor_*; do
sensor=$(basename "$dir")
reading=$(collect "$sensor")
echo "$reading" >> "$REPORT"
val=$(echo "$reading" | cut -d',' -f3)
if [[ "$val" != "N/A" ]] && [[ "$val" -gt 95 ]]; then
echo "ALERT: $sensor = $val"
ALERTS=$((ALERTS + 1))
fi
done
[[ $ALERTS -gt 0 ]] && tail -20 "$REPORT" | \
mail -s "Sensor Alert" engineer@factory.local 2>/dev/null || true
sleep 300
done
This reads sensors in a loop, logs to CSV, checks thresholds, and emails alerts.
Summary
In this lesson you learned Bash scripting foundations:
- Scripts use
#!/bin/bashandset -euo pipefailfor safety. - Variables store values;
$1,$2provide command-line arguments. if [[ ]]handles numeric, string, and file conditions.for,while, anduntilloops automate repetitive tasks.- Functions organize code with
localvariables and return codes. - Industrial scripts combine these to collect data, check thresholds, and send alerts.
In the next lesson, you will learn networking commands for diagnosing PLC and SCADA communication problems.