Let me pick up the POP3 example you recently mentioned in a comment. It is a good example, because POP3 can not notify the arrival of new mail. (For IMAP access I would not use a timer solution, because IMAP actually can notify!)
-e stands for edit. Caution: launching without options does not give help, but flushes all your existing cron jobs if you do not manage to get out of the editor without saving.—And that definitively means to lose work if you had existing jobs.
So, in the edit mode, add a line:
30 14,21 * * * mpop --quiet
mpop 2:30pm and 9:30pm.
In theory you could also have edited
/var/spool/cron/crontabs/username, but most crons would not notice and the directory permissions often do not allow direct access to the file.
Cron jobs are less joy to debug. More often than not you end up scheduling it every minute until you trust it and then set the frequency correctly.
Otherwise it is a pretty quick interface for job repetition.
These days, don’t be surprised when you have no cron daemon running. Package
systemd-cron (at least on Debian) serves you systemd timers with a cron user interface: it translates the crontab line transparently for you and the command line tools are the same.—The other way around will probably never exist.
has to be run once (and never again). It makes sure that the user mode systemd is launched on boot. Otherwise the first login would launch it.
systemctl --user edit --full --force mpop.service
You can also run just
systemctl edit mpop.service to get successive errors and hints guiding you to the correct command line with options:
No files found for mpop.service.
Run 'systemctl edit --force --full mpop.service' to create a new unit.
Running the suggested command would reveal permission problems with writing the file and ask for a password to reload the system daemon.—At this point you should remember to add
--user to talk to the user systemd instance. Note: you could also go for the system instance, but I’m not describing that here. It is similar.
Unlike with cron, you could really go directly for the file
~/.config/systemd/user/mpop.service, but you have to remember the path yourself. And in some cases
systemd --user daemon-reload is needed. E.g. if the file is actually existing and loaded.
systemd --user edit ... does a daemon-reload in any case so you don’t have to.
So, in the
mpop.service file you add:
You can test run this with
systemctl --user start mpop.
mpop is short for
Check details with
systemctl --user status mpop or the full output of past runs with
journalctl --user -u mpop (
-u is short for
With systemd, the timer is another unit which triggers the service unit.
Create one with:
systemctl --user edit --full --force mpop.timer
And save the following in the editor:
OnCalendar= can be written shorter. As the
Unit= to active is not written explicitly, the service by the same name will be triggered.
Like the service (short lived), the timer (long living) will initially be off. The service is activated by the timer, so no worries here.
But what activates the timer?—This is where the
[Install] section comes into play. It is related to the
systemctl --user enable/disable ... and they all have very unfortunate names.
The section should be called
[Hooks] and the commands
... hook/unhook .... Reasons:
- the timer is already installed with the existence of the
- would reveal the relationship between the section and the commands
enable command might not enable the unit if it is hooked to a siding unit or a non-existing one (you get a warning for the latter, though), but it will show as “enabled”.
mpop.service unit has no
[Install] section and
enable/disable do nothing on it, it is shown as “static”, even though it is as “enabled” as it gets
Having that said, you can see that the
WantedBy= hook mentions a well-known target, one which is started in normal circumstances and the one supposed to be used for timers.
systemctl --user list-dependencies default.target now and after the following steps to see what happens around
systemctl --user enable mpop.timer # hooks it into the timers.target
systemctl --user start timers.target # this or reboot
I consider executing
timers.target instead of
mpop.timer (both work) better practice. It helps detecting spelling mistakes in the
[Install] section of the timer unit and follows closer the execution path on reboots.