Bash Logging
A log is a written diary of what a script did. Each line records an event with its time. When a scheduled job fails at night, the log explains what happened. Good logging turns a mystery into a quick fix.
The Flight Recorder Analogy
Airplanes carry a recorder that stores every important event during a flight. Investigators read it after a problem. A script log serves the same purpose for your automation.
Script runs
|
+--> INFO Backup started
+--> INFO Copied 42 files
+--> WARN Disk 85% full
+--> ERROR Upload failed
|
v
backup.log (read later to find the cause)
Simple Logging With echo
#!/bin/bash
log_file="job.log"
echo "Job started" >> "$log_file"
echo "Job finished" >> "$log_file"The double arrow appends a line. A single arrow would replace the whole file each time.
Add Timestamps
echo "$(date '+%Y-%m-%d %H:%M:%S') Job started" >> job.logLog line:
2026-10-16 14:30:45 Job startedBuild a Reusable Log Function
#!/bin/bash
log_file="app.log"
log() {
local level="$1"
shift
echo "$(date '+%Y-%m-%d %H:%M:%S') [$level] $*" >> "$log_file"
}
log INFO "Script started"
log WARN "Disk space is low"
log ERROR "Upload failed"Content of app.log:
2026-10-16 14:30:45 [INFO] Script started
2026-10-16 14:30:45 [WARN] Disk space is low
2026-10-16 14:30:45 [ERROR] Upload failedThe function stays in one place, so any format change applies to every message at once.
Standard Output and Standard Error
Programs write to two streams. Normal results use stream 1. Error messages use stream 2.
| Redirect | Effect |
|---|---|
| > file | Save normal output, replace the file |
| >> file | Save normal output, append to the file |
| 2> file | Save only errors |
| > file 2>&1 | Save both streams in one file |
| &> file | Short form for both streams in Bash |
Capture Everything From a Script
The exec command redirects all later output of the script into a file:
#!/bin/bash
exec >> run.log 2>&1
echo "This line goes to the log"
ls /missing_folder
echo "So does the error above"Show Output and Save It Too
The tee command copies output to the screen and to a file:
./backup.sh 2>&1 | tee -a backup.logThe -a option appends instead of replacing.
Send Errors to the Error Stream
error() {
echo "ERROR: $*" >&2
}
error "File not found"Separate streams let users hide normal output but still see problems.
Use the System Logger
The logger command writes into the system log, which collects messages from many programs:
logger -t mybackup "Backup finished"
logger -p user.error -t mybackup "Backup failed"View entries with journalctl -t mybackup or by reading /var/log/syslog on many Linux systems.
Read Logs Quickly
tail -n 20 app.log # last 20 lines
tail -f app.log # follow new lines live
grep "ERROR" app.log # only errors
grep -c "WARN" app.log # count warningsKeep Logs From Growing Forever
Remove old logs on a schedule:
find /var/log/myapp -name "*.log" -mtime +30 -deleteThe logrotate tool automates renaming, compressing, and deleting logs on many Linux systems.
Avoid Sensitive Data
Never write passwords, access keys, or private personal details into a log. Log files often get shared during troubleshooting, so keep them free of secrets.
Key Takeaways
- Append with
>>and add a timestamp to every line. - A
logfunction keeps the format consistent. - Stream 1 holds normal output and stream 2 holds errors.
teeshows and saves output together.loggersends messages to the system log.- Rotate old logs and keep secrets out of them.
