Introduction
A useful backup is more than an archive command. You must know what it contains, verify that it can be read, restore the file you need, and make unattended runs observable.
In this lab, you will back up a small application workspace from a manifest, restore one selected file, turn the workflow into a timestamped script, and install a Cron schedule. Every automated path is absolute so the job does not depend on an interactive shell's current directory.
Define the Backup Scope with a Manifest
In this step, you will create a manifest: a plain-text list of paths that makes the backup scope visible and reviewable.
Enter the workspace:
cd /home/labex/project/backup-lab
Create a manifest containing paths relative to the data directory:
cat > backup-manifest.txt <<'EOF'
config/app.conf
documents/runbook.txt
EOF
Number the entries so they are easy to review:
nl -ba backup-manifest.txt
Confirm that every listed source exists with a while loop. Read its structure before running it:
IFS=prevents the shell from trimming whitespace at the start or end of a line;read -r itemreads one complete line intoitemwithout treating backslashes specially;do ... doneencloses the command repeated for each line;< backup-manifest.txtsupplies the manifest as the loop's input;test -fchecks that the corresponding path is a regular file, and&&printsreadyonly when that check succeeds.
while IFS= read -r item; do
test -f "data/$item" && echo "ready: $item"
done < backup-manifest.txt
The unlisted documents/scratch.txt file is intentionally outside this managed backup.
Create an Archive from the Manifest
In this step, you will use tar -T to read filenames from the manifest. The -C data option makes the archive use short relative paths.
tar -czf backups/manual-backup.tar.gz -C data -T backup-manifest.txt
The options mean:
-c: create an archive;-z: compress it with gzip;-f: use the following archive filename;-C data: operate relative todata;-T backup-manifest.txt: read the backup members from the manifest.
Inspect the resulting file:
ls -lh backups/manual-backup.tar.gz
Compare its timestamp and size with the source files:
stat -c '%n size=%s modified=%y' backups/manual-backup.tar.gz data/config/app.conf data/documents/runbook.txt
Verify the Archive without Extracting It
In this step, you will test the archive before relying on it. First test the gzip stream:
gzip -t backups/manual-backup.tar.gz
No output means the compressed stream passed its integrity check. Now list the tar members without extracting them:
tar -tzf backups/manual-backup.tar.gz | tee archive-contents.txt
Compare the saved listing with the manifest:
diff -u backup-manifest.txt archive-contents.txt
The command should show no differences. Confirm that the unmanaged scratch file is absent:
if tar -tzf backups/manual-backup.tar.gz | grep -qx 'documents/scratch.txt'; then
echo "Unexpected scratch file found"
else
echo "Archive scope is correct"
fi
Restore One Selected File
In this step, you will restore only one selected file so unrelated data is not overwritten. Simulate accidental deletion of the configuration:
rm data/config/app.conf
test -e data/config/app.conf || echo "app.conf is missing"
Extract only config/app.conf into the separate restore directory:
rm -rf restore/*
tar -xzf backups/manual-backup.tar.gz -C restore config/app.conf
Inspect the recovered file, then copy it back to its working location:
cat restore/config/app.conf
cp restore/config/app.conf data/config/app.conf
cmp -s restore/config/app.conf data/config/app.conf && echo "Configuration restored"
Only the requested archive member was extracted.
Build a Timestamped Backup Script
In this step, you will build a timestamped backup script. Cron starts jobs with a limited environment, so use absolute paths inside unattended scripts.
Create backup.sh:
cat > backup.sh <<'EOF'
#!/bin/bash
source_dir=/home/labex/project/backup-lab/data
manifest=/home/labex/project/backup-lab/backup-manifest.txt
backup_dir=/home/labex/project/backup-lab/backups
timestamp=$(date +%Y%m%d-%H%M%S)
archive="$backup_dir/backup-$timestamp.tar.gz"
mkdir -p "$backup_dir"
if [ ! -d "$source_dir" ] || [ ! -f "$manifest" ]; then
echo "Backup source or manifest is missing" >&2
exit 1
fi
/bin/tar -czf "$archive" -C "$source_dir" -T "$manifest" || exit 1
/bin/tar -tzf "$archive" > "$archive.contents" || exit 1
echo "Created $archive"
exit 0
EOF
Make the script executable and test it now instead of waiting for Cron:
chmod u+x backup.sh
./backup.sh | tee last-backup.txt
ls -1 backups
The timestamp gives each run a unique filename. The companion .contents file records exactly what the archive contains.
Install and Inspect a Cron Schedule
In this step, you will install and inspect a personal Cron schedule. A crontab line begins with five scheduling fields, followed by the command:
| Position | Field | Usual range |
|---|---|---|
| 1 | minute | 0–59 |
| 2 | hour | 0–23 |
| 3 | day of month | 1–31 |
| 4 | month | 1–12 |
| 5 | day of week | 0–7, where Sunday is 0 or 7 |
An asterisk * means every allowed value. A step such as */5 means every five units in that field.
minute hour day-of-month month day-of-week command
For example, */5 * * * * means every five minutes. 0 2 * * * means 02:00 every day.
crontab -e opens your personal crontab in an editor. A reliable workflow is to prepare and install a known-good entry first, then make a small interactive edit. Create one entry that uses absolute paths and captures both standard output and standard error:
cat > backup.crontab <<'EOF'
*/5 * * * * /home/labex/project/backup-lab/backup.sh >> /home/labex/project/backup-lab/logs/backup.log 2>&1
EOF
Review and install it:
cat backup.crontab
crontab backup.crontab
Now open the installed crontab in Nano:
EDITOR=nano crontab -e
Add this comment on the line above the schedule:
## LabEx managed backup schedule
Press Ctrl+O, then Enter to save. Press Ctrl+X to leave Nano and return to the shell. Use crontab -l to confirm exactly what Cron will read and save that output:
crontab -l | tee installed-crontab.txt
The output should contain the comment followed by the every-five-minutes entry. Inspecting the installed result catches editor mistakes before you depend on the schedule.
Test Logging and Understand Percent Escaping
In this step, you will test backup logging and learn Cron's special handling of percent signs. First run the scheduled command manually:
/home/labex/project/backup-lab/backup.sh >> /home/labex/project/backup-lab/logs/backup.log 2>&1
tail -n 5 logs/backup.log
find backups -maxdepth 1 -type f -name 'backup-*.tar.gz' -printf '%f\n' | sort
The timestamp is created inside backup.sh, where ordinary % characters are safe. Cron treats an unescaped % in a crontab command specially, however. If you place date directly in a crontab line, escape each percent sign with a backslash.
Save a correctly escaped example for reference:
cat > cron-date-example.txt <<'EOF'
0 2 * * * /bin/echo "backup-$(/bin/date +\%Y\%m\%d-\%H\%M\%S)" >> /home/labex/project/backup-lab/logs/date-example.log 2>&1
EOF
cat cron-date-example.txt
Your installed job remains the simpler script-based entry. It uses absolute paths, gives every archive a timestamp, and leaves a log that can be inspected after unattended runs.
Summary
You defined a backup scope in a manifest, created an archive with tar -T, verified it without extraction, and recovered one selected file. You then wrote a timestamped backup script with absolute paths, installed and inspected a Cron schedule, redirected unattended output to a log, and learned why percent signs must be escaped when date appears directly in a crontab command.



