A backup pipeline.
tar, rsync, scp, and the trailing-slash trap.
logadmin1’s backup script broke when the last admin left. Rebuild it: a daily gzip archive of /etc, a weekly bzip2 snapshot of a home directory, and a continuous rsync mirror of /var/log.
The ticket: logadmin1 lost their backup script when the previous admin left. Three things to rebuild. A daily compressed tarball of /etc, a weekly bzip2 snapshot of /home/dev1 for better compression on source code, and a continuous rsync mirror of /var/log that excludes already-rotated .gz files and removes anything from the mirror that is gone from the source. Also test scp by copying one archive locally.
The real problem: two traps live here. The trailing slash in rsync changes what gets copied, and the —delete flag is unforgiving. Both deserve a dry run.
What we are doing: tar in every compression flavor, rsync with delete and exclude, and scp.
The ticket
id logadmin1 ls /srv/backups 2>/dev/null || sudo mkdir -p /srv/backups which tar rsync scp
Concept review. tar flags and compression.
man tar rsync scp
c create x extract t list v verbose f filename (always right before the archive name) z gzip (.tar.gz) j bzip2 (.tar.bz2) J xz (.tar.xz) -C change to a directory before extracting --exclude skip a pattern
The three compressors trade speed for ratio. gzip is fast and moderate, good for daily backups. bzip2 is slower but compresses text and source better. xz is slowest and smallest, for long-term storage.
Set up the backup directory
sudo mkdir -p /srv/backups/logs sudo chown admin:logadmins /srv/backups sudo chmod 770 /srv/backups ls -ld /srv/backups
Daily archive of /etc
Put the date in the filename so daily runs do not overwrite each other. c z v f means create, gzip, verbose, filename. Always verify the archive after.
DATE=$(date +%Y%m%d)
sudo tar -czvf /srv/backups/etc-${DATE}.tar.gz /etc/ 2>/dev/null
ls -lh /srv/backups/etc-*.tar.gz
tar -tzvf /srv/backups/etc-${DATE}.tar.gz | head -10 # list without extractingWeekly bzip2 snapshot
Same idea, bzip2 this time with j for better compression on source code.
DATE=$(date +%Y%m%d)
sudo tar -cjvf /srv/backups/dev1-${DATE}.tar.bz2 /home/dev1/ 2>/dev/null
ls -lh /srv/backups/dev1-*.tar.bz2The rsync mirror and the trailing slash
The trailing slash on the source is the whole game. A trailing slash copies the contents of the directory. No trailing slash copies the directory itself into the destination. Because —delete removes anything in the destination that is not in the source, always dry run first.
# the difference, in words: # rsync -av /src/ /dst/ copies the CONTENTS of src into dst # rsync -av /src /dst/ creates /dst/src/ # dry run first, always, with --delete sudo rsync -av --dry-run --delete --exclude='*.gz' /var/log/ /srv/backups/logs/ # looks safe? run it for real sudo rsync -av --delete --exclude='*.gz' /var/log/ /srv/backups/logs/ du -sh /srv/backups/logs/
Copy an archive with scp
mkdir -p /tmp/scp_landing
DATE=$(date +%Y%m%d)
scp /srv/backups/etc-${DATE}.tar.gz localhost:/tmp/scp_landing/
ls -lh /tmp/scp_landing/
# recursive directory copy
scp -r /srv/backups/logs localhost:/tmp/scp_landing/Extracting, including a single file
Restores matter as much as backups. You can extract everything, or pull one file out by naming its path inside the archive.
DATE=$(date +%Y%m%d)
# extract everything to a new directory
mkdir -p /tmp/restore_test
sudo tar -xzvf /srv/backups/etc-${DATE}.tar.gz -C /tmp/restore_test/
# extract only one file
mkdir -p /tmp/restore_one
sudo tar -xzvf /srv/backups/etc-${DATE}.tar.gz -C /tmp/restore_one/ etc/hostname
ls -la /tmp/restore_one/etc/
sudo rm -rf /tmp/restore_test /tmp/restore_oneExam questions
Write the command first.
Q1. Create a gzip tar archive of /etc at /tmp/etc_backup.tar.gz, then list its contents without extracting.
Q2. Extract only /etc/hostname from that archive into /tmp/restored/.
Q3. rsync /var/log to /backup/logs, excluding all .gz files, deleting anything in the destination no longer in the source. Show the dry run first.
Answers.
# A1 sudo tar -czvf /tmp/etc_backup.tar.gz /etc/ 2>/dev/null tar -tzvf /tmp/etc_backup.tar.gz | head -20 # A2 mkdir -p /tmp/restored sudo tar -xzvf /tmp/etc_backup.tar.gz -C /tmp/restored/ etc/hostname # A3 sudo mkdir -p /backup/logs sudo rsync -av --dry-run --delete --exclude='*.gz' /var/log/ /backup/logs/ sudo rsync -av --delete --exclude='*.gz' /var/log/ /backup/logs/
Final checklist: confirm everything works
If every check passes, the ticket is done.
# 1. daily /etc gzip archive exists ls /srv/backups/etc-*.tar.gz # 2. weekly bzip2 home snapshot exists ls /srv/backups/dev1-*.tar.bz2 # 3. /var/log mirror excludes .gz and honors --delete ls /srv/backups/logs/ | head # 4. --delete tested with --dry-run first # 5. all three exam commands written from scratch # 6. tracker entry checked off
Reply to logadmin1: daily gzip archives of /etc and weekly bzip2 snapshots of /home/dev1 in /srv/backups/. Continuous /var/log rsync mirror at /srv/backups/logs/ with —delete and —exclude=*.gz. Ready to wire into cron.