Back up and restore user crontabs
Export a user’s schedule safely, capture system jobs separately, and restore without accidentally replacing the wrong table.
Use crontab -l to export the current user's installed table. Restore it with crontab filename after reviewing the file. A restore replaces the account's entire table, so preserve newer jobs before loading an older backup.
Backing up only a user's crontab does not capture every scheduled task on a machine.
Make a guarded backup
This script creates a private backup directory and publishes a dated file only after a successful export:
#!/bin/sh
set -eu
umask 077
backup_dir="$HOME/.local/state/crontab-backups"
mkdir -p "$backup_dir"
tmp=$(mktemp "$backup_dir/.pending.XXXXXX")
trap 'rm -f "$tmp"' EXIT
trap 'exit 1' HUP INT TERM
if crontab -l > "$tmp"; then
destination="$backup_dir/crontab-$(date +%Y%m%d-%H%M%S)-$$.txt"
mv "$tmp" "$destination"
printf 'Saved %s\n' "$destination"
else
printf 'Export failed; inspect the crontab error above.\n' >&2
exit 1
fi
The exit trap removes the temporary file; the signal traps exit rather than allowing the script to continue after an interruption. Signals such as SIGKILL cannot be trapped, so abrupt termination can still leave an unpublished temporary file.
The export runs as the script's account. To back up another user's table, an administrator can use sudo crontab -u appuser -l, with the same guarded-file approach. Do not interpret every failed export as “no jobs”: permissions and account lookup can also fail.
Include the other scheduling layers
Inventory /etc/crontab, /etc/cron.d/, the periodic-script directories such as /etc/cron.daily/, and /etc/anacrontab when present. Also record systemd service/timer units and application or Kubernetes schedules if those are in scope.
For multiple users, enumerate the relevant account directory, for example with getent passwd on Linux, and export each selected account using crontab -u username -l. Preserve errors in the backup report. A loop over /etc/passwd alone can miss centrally managed accounts; copying /var/spool/cron/* is not a portable replacement for exports because spool layouts and permissions differ.
Back up the invoked scripts, dependencies, configuration, permissions and required secret references as well. A schedule alone cannot reconstruct a working backup job or data pipeline. Keep credentials out of broadly readable archives and repositories.
Schedule the backup
Save the guarded script as /home/appuser/bin/backup-crontab.sh and make it executable. Its user-crontab entry can be:
0 4 * * * /home/appuser/bin/backup-crontab.sh
Date formatting inside the script uses ordinary % characters. When a date expression appears directly in a crontab command, escape each percent sign as \%. Store backups outside the host too if they must survive its loss. Version control is useful for reviewed schedule configuration, provided the repository's access and contents are appropriate.
Restore deliberately
Inspect the saved file and compare it with the current table, then restore to the intended account:
crontab /path/to/reviewed-crontab.txt
crontab -l
For a different account:
sudo crontab -u appuser /path/to/reviewed-crontab.txt
sudo crontab -u appuser -l
System-format files containing username fields belong in their system locations, not in a user-crontab import. After restoration, verify timezone, paths, account permissions, output and the next run. Ordinary crontab changes do not require a daemon restart.
Common questions
Does importing append the backup? No. Merge wanted jobs into a reviewed candidate before installation.
Can I keep the backup in Git? Yes for suitable configuration, but inspect it for tokens, addresses and embedded secrets, and control repository access.
Why did a restored job fail? Check the account, environment, scripts and dependencies on the new host. Restoring text does not restore its runtime.
References
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan