The proper and easiest way to set cron jobs — Docker version
In my first article on cron and crontab I explained the basics of setting a cron job up and debugging. In this one I’ll explain advanced things such as setting cron jobs from a text file and having a working docker container with cron running.
But I will not be straightforward. A lot of people are doing those things wrongly and I have to adress that too.
Finally, if you’re not familiar with linux environment like me, you are bound to encounter troublesome yet trivial errors. I will have words for those.
Set cron jobs from a cron file — the wrong way
As per the cron documentation :
Cron checks these files and directories:
/etc/crontab
system crontab. Nowadays the file is empty by default.
Originally it was usually used to run daily, weekly,
monthly jobs. By default these jobs are now run through
anacron which reads /etc/anacrontab configuration file.
See anacrontab(5) for more details.
/etc/cron.d/
directory that contains system cronjobs stored for
different users.
/var/spool/cron
directory that contains user crontables created by the
crontab command.
Note that the crontab(1) command updates the modtime of the spool directory whenever it changes a crontab.
Under the hood, when using crontab -e command, the cron file generated is found at /var/spool/cron/ such as : /var/spool/cron/crontabs/<username>.
So you will see a lot of developpers toying around those directories in order to set their cron jobs. After all if my cron file is already at the right place, cron will find and execute it, right ?
They’ll encounter several problems. In order for a cron job to be executed, it needs to know 2 pieces of information : “are the permissions correct ?” “is the user identified ?”
permissions attribution :
Their cron file won’t have the right rwx (read, write, execute) permissions to act correctly, resulting in a cron job correctly set but which won’t work. Their workaround is to modify the rights of their file so that it mimics those that would be provided to the file created by the crontab -e command.
“anonymous” cron file :
This case is encountered for docker developper — like me. Naively the plan is simple : copy the cron file in our local directory directly into the right directory of the container. Either /var/spool/cron for the less dirty ones or /etc/crontab for the fools (don’t toy with /etc/crontab, you’re not supposed to).
So our docker container is running, our file is at the right place, the rights attributed are correct, the script is still not working. Even though everything is at its place, our system don’t know who or what set this file and thus cron is unable to decide for who this file is supposed to run.
I guess that people trying so hard to make things work wrongly would set a user in their dockerfile just for that or I don’t know what. This approach is a dead-end.
Set cron jobs from a cron file — the right way
crontab -u <username> /path/to/<file>
This way you edit through the crontab command — which will create a cron file with the right permissions with an explicitly specified user.
As per the crontab documentation :
-u
Specifies the name of the user whose crontab is to be
modified. If this option is not used, crontab examines
"your" crontab, i.e., the crontab of the person executing
the command. If no crontab exists for a particular user,
it is created for them the first time the crontab -u
command is used under their username.
Set cron jobs from a cron file for a docker container in a windows environment — what could go wrong
Wrong spacing
cron.txt:1: bad minute
Windows and Linux are not using the same spacing for character, respectively CRLF and LF.
Our cron.txt was made on Windows, with CRLF spacing. We need to switch to LF spacing. You can look for that option in your IDE, but VS code has a shortcut for this feature.
Warning : if you have several files on your window, make sure to edit the right one and do not forget to save !
Wrong end of line
new crontab file is missing newline before EOF
A linux file must end with a spacing at the end.
In spite of everything, it’s not running ! Yet everything went fine manually.
If you followed my article explaining the basics of cron, you should have the line ENTRYPOINT [“/bin/bash”].
By having such a container, we need to initialize cron manually. It would be more convenient to have cron executed when the container is started.
To do so, we need to remove ENTRYPOINT [“/bin/bash”] and add CMD [“cron”, “-f”].
But now, our script.sh looks like this :
It can no longer work without the previous entrypoint. So we need to specify which bash use at the beginning.