I have a shell script which, when run as root, performs various tasks to prepare a Debian (9/stretch) server for running a web application. Amongst the tasks that the script does is append cronjob lines to the crontab files for root and www-data (in /var/spool/cron/crontabs/), using cat and heredoc text.

Each cronjob that is added to the file is enclosed by marker comments, so that when using the uninstall function of the script, these cronjobs can be found and removed from the crontab files using sed.

This seems to be working OK, although I have now noticed that when reviewing each of the crontabs via crontab -l the first 3 lines of the crontab do not appear, although they do still exist when checking the actual crontab file directly. Some research has revealed that this is a side-effect of an intentional feature in Debian's crontab implementation, which hides the first 3 lines of a crontab as it expects those lines to be a 3 line "DO NOT EDIT THIS FILE" header.

However, if I am appending to a previously non-existent crontab file, this header does not exist and so does not get created, which is why the real first 3 lines of the crontab are hidden instead.

I am probably not doing the right thing by writing to a crontab file directly in any case. How can I update my script so that it can automatically add to and remove from crontabs in a way which keeps the system happy?

(I see from the man page that there is a CRONTAB_NOHEADER which can be set to N in order to not hide the 3 lines.)

  • this seems to be limited to Debian, when I do this on CentOS boxes I see all the lines.
    – slm
    Commented Jul 31, 2018 at 13:57

1 Answer 1


Rather than manipulate a individual crontab I'd opt to drop snippets of crontab functionality in /etc/cron* directories based.

This seems easier to manage in the sense that all that's required is the creation/deletion of files from whatever /etc/cron* directory you need/want the snippet to run under:

$ ls -ld /etc/cron*
-rw-------. 1 root root    0 May  2 10:54 /etc/cron.allow
drwxr-xr-x. 2 root root 4096 Jul 28 14:56 /etc/cron.d
drw-------. 2 root root 4096 Jul 28 14:56 /etc/cron.daily
-rw-------  1 root root    0 Apr 10 21:48 /etc/cron.deny
drw-------. 2 root root 4096 Jul 28 14:55 /etc/cron.hourly
drw-------. 2 root root 4096 Jun  9  2014 /etc/cron.monthly
-rw-------. 1 root root  451 Jun  9  2014 /etc/crontab
drw-------. 2 root root 4096 Jun  9  2014 /etc/cron.weekly
  • 1
    Right, this is much better, especially /etc/cron.d since the crontabs there have the user field (so even the jobs for www-data can be represented without resorting to su). Commented Jul 31, 2018 at 14:08
  • Thanks, is there documentation about how to use the cron.* folders? It looks as though the files in cron.d are crontab files (with the field for the user to run as, as you say), but how do these get run (there does not seem to be a corresponding entry in /etc/crontab)? (Also, the cron.daily (etc) folders don't appear to be particularly useful for me as they would seem to kick off all the jobs in the folder at the same time, if I'm understanding correctly?)
    – dave559
    Commented Jul 31, 2018 at 15:31
  • 1
    @dave559 - nothing official that I've ever seen. The /etc/cron.d is meant for self contained crontab entries (1 per file - or more) that you want to run at whatever time they specify. The `/etc/cron.{daily, hourly, weekly} can be just self contained shell scripts and do not require any crontab details. There's already a crontab entry that oversees these directories and will run whatever is there at the specified times (hourly, daily, weekly).
    – slm
    Commented Jul 31, 2018 at 16:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .