1. Overview
The cron daemon schedules jobs according to time patterns stored in crontabs. We can change this configuration with the crontab command. However, careless use of it may cause loss of all entries.
In this tutorial, we’ll learn how to prevent such a scenario or recover cron jobs when it happens.
2. The crontab Command
With the crontab command, we can edit, list, and remove the cron jobs with -e, -l, and -r switches, respectively:
$ crontab { -e | -l | -r }
The problem with these one-letter commands is that we can easily confuse them with each other. It’s particularly hurtful if we type r instead of e, as crontab would irreversibly remove all entries without warning.
3. Managing crontab Files
By default, the crontab files are named after the user and stored in the /var/spool/cron folder. All changes made by the -e command go right there. So, for user joe, crontab is located in the file:
$ sudo ls -all /var/spool/cron/joe
-rw-------. 1 joe joe 257 Jul 16 17:06 /var/spool/cron/joe
Because the system manages this file, we shouldn’t edit it directly. Moreover, with the traditional partition scheme, this folder is in the */ (*root) partition. So, the reinstallation of the system erases its whole content.
However, we can put the file with the configuration in the home folder. Thus, let’s create the crontab file .crontab_conf in joe’s home folder:
$ ls -all .crontab_conf
-rw-r--r--. 1 joe joe 257 Aug 31 17:11 .crontab_conf
After filling the file with desired entries, let’s install the crontab with:
$ crontab ~/.crontab_conf
Now, we can apply all recommended safety measures to this file, in order to avoid its loss.
4. Backup to Save the Day
If we’re going to ad hoc edit the cron jobs with -e anyway, we can at least back up the configuration. So, let’s dump the crontab to the .crontab_dump file:
$ crontab -l > ~/.crontab_dump
To restore jobs from the file, all we need is:
$ crontab ~/.crontab_dump
Moreover, we can use crontab itself to automate the backup update, every day at midnight:
0 0 * * * crontab -l /home/joe/.crontab_dump
5. Getting Warned
With the -i option combined with -r, crontab asks for confirmation before removing the entries:
$ crontab -i -r
crontab: really delete joe's crontab? (y/n)
Using -i with other options has no effect, but it can save us from a mistake while issuing -r by accident. To prevent this potential mistake from happening, let’s provide an alias containing -i:
$ alias crontab="crontab -i"
We can then add the alias in the user’s .bashrc file for permanent effect.
Now, we can execute all of crontab‘s commands as before, but in the -r case, we receive a warning.
6. The Forensic Job
Without a backup, we’re forced to rely on searching for cron job traces in logs. By default, in the case of systemd distributions, we can use journalctl. In other systems, cron usually logs to /var/log/syslog.
As an example, let’s search journalctl output:
$ journalctl | grep CROND
# ...
Aug 31 16:36:01 192.168.1.14 CROND[3233]: (joe) CMD ($WORKDIR/./rscript1 >> $WORKDIR/jobs_log1.txt)
# ...
Aug 31 17:00:01 192.168.1.14 CROND[4176]: (joe) CMD ($WORKDIR/./rscript2 >> $WORKDIR/jobs_log2.txt)
# ...
Aug 31 17:06:01 192.168.1.14 CROND[4277]: (joe) CMD ($WORKDIR/./rscript1 >> $WORKDIR/jobs_log1.txt)
# ...
We can see that we had two cron jobs, executing rscript1 and rscript2. However, the log doesn’t contain the cron time expressions. So, we can only try to reconstruct them from the logged time pattern. The problem with this approach is that we can’t see the values of variables, such as the WORKDIR crontab variable above.
7. Conclusion
In this article, we learned how to avoid accidentally deleting entries with the crontab command. We studied various measures to enhance the safety of crontab data. First, we moved the configuration file from the system-wide location to the home folder. Next, we made a backup of the crontab file and enabled the warning before removing the configuration. Finally, we learned how hard it is to reconstruct the jobs from system logs only, as we’ll lose valuable information such as time expressions and crontab variables.