Hacker News new | past | comments | ask | show | jobs | submit login
Cron Jobs on Linux – Comprehensive Guide with Examples (ittavern.com)
88 points by todsacerdoti 33 days ago | hide | past | favorite | 50 comments



The uncertainty of "did this edit to the crontab file get seen by the daemon".

The distinction between original Unix cron, anacron, and the at function.

What PATH applies.

Which POSIX are you on? Linux or BSD or SysV derived Unix differs in cron

Is cron even running by default? Containerised Unix may not do what you think

One syntax for /etc/cron.d (user to run as) and another for crontab -u <user> -e

The variation in which file it logs to in /var/log

Systemd and launchd and systemctl and launchctl and journalctl... (persisting daemons which run things according to the clock)

Daylight savings and ritualised habits about cronojbs at midnight

(Yes, I read the article. It's a great practical introduction to cron on most Linux situations people will find themselves in for the first time)


Good list!

I have covered many of these topics here (see developer questions section)

https://cronitor.io/guides


Most of your list is detailed in the manpages.


Not everybody will like it (and nobody needs to use it), but: systemd timers do very similar things, are well integrated into the systemd ecosystem, have a nice syntax, allow all nice systemd features, and are quite nice imho.


Useful things to consider when using Cron:

* Do you know where it's going to send any output? If you're not certain then add a MAILTO entry at the start of the crontab to make it explicit

* Do your jobs require additional environment variables configuring?

* How noisy is your job's output? Any thing sent to STDOUT or STDERR will get emailed to either the recipients in the MAILTO option or the user that the crontab is for - initially you'll want a lot of output so you can check that it's working as expected, but once you're happy with it then you don't want all the information just any errors. There are many ways to achieve this like using --quiet options on commands to suppress output, or redirecting STDOUT to /dev/null or a file on disk (as errors should end up in STDERR).


Is 'mail' broken in the default Ubuntu desktop install? Cron errors (if not redirecting output to a file) fail to deliver with:

  Sep  6 02:20:01 ThinkPad-L560 CRON[3748665]: (root) CMD (/bin/bash /root/bin/backup.rsync /.git)
  Sep  6 02:20:01 ThinkPad-L560 cron[3748668]: sendmail: fatal: open /etc/postfix/main.cf: No such file or directory
  Sep  6 02:20:01 ThinkPad-L560 postfix/sendmail[3748668]: fatal: open /etc/postfix/main.cf: No such file or directory
  Sep  6 02:20:01 ThinkPad-L560 CRON[3748664]: (root) MAIL (mailed 291 bytes of output but got status 0x004b from MTA#012)
 ...


Cronitor solves the errors/output collection for you. Made by indie developers, launched here 10 years ago, nice free plan.


Nice overview. UX wise systemd timers are far superior.


Are they though? Last time I played with them I had to create/edit two text files instead of one (service file and timer file), figure out if I needed to enable and start them both, figure out what to do if I want to temporarily disable the timer (systemctl stop? disable?), etc.


Which is much easier than fiddling around with crontab, in my experience.

Yes, you need a systemd service file and a systemd timer file. Creating both is a matter of ~30m. Then, you do `systemctl start` and you're good... As a great benefit, you can see the status of each timer, which is great for debugging quick problems, like permission issues/runtime errors/... when setting the timer up.


> Creating both is a matter of ~30m.

I can write a cron entry in a minute or two, depending on the complexity.


Well, it takes 30m the first time, when learning from scratch. When learning the arcane cron entry system, I'd guess it takes even longer than 30m, unless you have a simple time in mind (like "every minute" or something similar - "every second Monday" is definitely more complex to reason about in cron). Again, comparing not knowing systemd timer vs not knowing cron.


Sure, not saying you can just sit down and do it straight away. But the additional complexity of systemd, I think, makes it even more daunting. It’s much like how modern frontend has a million components. I understand there are or were reasons for all of it, but not everyone needs it, and it’s intimidating to a newcomer.

In comparison, cron (and *nix tooling in general) asks you to learn a small bit of that tool’s syntax, and that’s it. You can add complexity if you’d like – read the man pages – but for the most part, you can be productive very quickly.


start and enable, or they won't come up after reboot or target change


Handy shortcut:

   systemctl enable foo.timer --now
To enable and start the unit in one command.


That’s true. But once you get it set up, you can check the status, see when it last ran, when it will run next, the logs from the last run, if it failed last time, why, etc. You can stop it, start it, restart it, disable it.

Simeone just needs to write some CLI for making really simple timers.


Don't forget one of the best reasons timers are great: they won't cause long-running jobs to overlap. I can't tell you how many systems I've had to unbreak because a job took too long and spiraled out of control.


> Simeone just needs to write some CLI for making really simple timers.

That's a post-it or a simple-systemd-timers.txt though. Don't bother Simeone with that :).


lol. I must have been on mobile.


Open a terminal and then in bash:

    while true; do
        date;
        ./doit.sh;
        sleep 300;
    done | tee doit.log
if you want to get fancy, you can do:

    date "+%Y.%M.%dT%H:%m:%s-%Z`./doit.sh`"
to get it all on one line.


For doing things like this I like using the "watch" command.


Yeah, it is almost at feature parity. The following bloat is not needed at all:

1. Ensure commands are ran after you close the terminal you just opened.

2. Trigger actions when the process did fail (OnFailure=)

3. ensure the scheduling job survives system restarts

4. have proper scheduling, and handling of missed schedule doe to downtime (eg. for notebooks)

5. run the process in cgoups, under other user's context, or in a chroot, etc.

6. apply randomized jitter to the schedule to avoid crating overload and cascading failures resulting from that

7. Timing out tasks

8. Handle service dependencies...

just to name few from the top of my head...

cron is great, and systemd timers are also good, and even more refined solution to the task scheduling problem. Your propsal does not solve even the basics (configurable schedule). As other comment notes your script is more like the watch command.


Yes if you actually engage and stop playing helpless. The system established things one shouldn't have had to do for decades.


Can't agree more ! Having multiple files is almost never good for these types of things.


Yeah. You get as a bonus a lot of generic tools that work with systemd like journald and other systemd-family utilities. This allows you to log, group jobs, investigate failures, all with better ergonomics and easily transform it into production-grade automation, if necessary.

There's really no reason to use cron today if you have systemd.


I feel like I’m taking crazy pills. “A lot of other generic tools?” You mean like how every *nix tool works for crons, because they’re text files, and *nix tooling operates on text files?

There’s a huge reason to use cron: it’s dead simple, doesn’t require a ton of complexity around it to function, and the syntax hasn’t changed in decades.


No, I don't mean like how every *nix tool works. I mean tools that are specifically designed to work with the data generated and stored by systemd. To give some examples: stdout from the process ran by systemd is automatically collected, timestamped, rotated and interactively paged by journald. journald in turn allows various filtering of the stored logs. On top of this, systemd can be configured to aggregate logs over networks of computers. It has exporters into popular log databases that allow for easy integration with other data collection tools.

In a sense, you could say that Unix shell, or other tools like pipes or redirects constitute an interface that allows generic cooperation between tools written without knowledge of the other tools. So, you aren't too far off. However, the tradeoff here is that with very few very generic tools you must give up more complex things. Eg. you have to concede that everything is a string. When you can confine the interfaces to a smaller group of tools, you can take better advantage of the data they communicate (eg. compared to passing data through pipes, where you have to serialize to string and parse from string data that isn't inherently a string, you can work with structured data with many useful types).

> There’s a huge reason to use cron: it’s dead simple

systemd timers are still simpler. I.e. cron isn't complicated, but it has too many tools all over the place, many arbitrary conventions, its failures are difficult to diagnose. And it's OK. It was written at the time nobody even thought about systemd, so, they had to do some of that work themselves. Today, it's just an anachronism ;)


+100 if I could. Reasons why I generally don't cron:

    * I don't want to rewrite log or dependency management
    * I *really* don't want to troubleshoot when it fails to function, presumably the work was important
    * I barely want to set the job up at all! What service is deficient to beget this babysitting?
Most of my automated jobs do work that depends on other things. Services, mounts, or even the novel idea of a functional network. Things managed and exposed by the manager, systemd.

Go forth and recreate 'After=' and 'Requires=' for your cronjob and make it equally visible and robust, if you want, I guess. A command pipeline of all the right things and intimate knowledge/trust in their return codes will do. I'll go do something more productive or at least rewarding.

Embrace the two files, template them and never mind it again. I promise it can be worth it. I'd argue the Unix Philosophy is paradoxical, if not simply just argued in uncooperative/unproductive ways. Idealistic and impractical if lived truly.

Doing 'one thing' and doing it well actually requires doing the thing and telling others how it went... so really it's two things conflated, if not more! Enter 'systemd does too much': it's for our benefit, truly.

It's not a complete endorsement, of course. There are plenty of things I think are underdeveloped or out of bounds: spare the sniping


Grandstanding:

Pit me against some legacy holdout. Give us both a set of services and complex work to do in a real-world, representative, environment. I don't care what it is.

I guarantee my setup using "timers" will be delivered earlier and prove to be more robust; it's already been written and battle tested. It's ready as soon as I can SSH or clone my repository.

I just hear a bunch of self-selecting [read: made up] surface level complaints. Why is anyone editing these jobs so much to care if it's one file or two? Why not zero? Around two decades after 'cron' the concept of 'Configuration Management' was established.

What's more, interfacing to disable/stop on the regular isn't required with dependencies or relationships defined; the result is implicit. I didn't even mention 'PartOf=' or 'OnFailure=', more settings that allow for handling external influence.

The system will work for you, let it. I've soared through the ranks with this one simple trick: adaptation. The work isn't as unique as it is presented.


Maybe if everyone on your team naturally uses systemd timers, but if they instinctively reach for cron then it's UX will be far superior for them.


https://crontab.guru/ is a great web site to help you write schedules for your cron jobs.


I'm no expert but this seems like a pretty good crash course to me. One thing I still tend to use a lot when fiddling with cron jobs is crontab guru [1], which is very helpful for figuring out scheduling.

[1] https://crontab.guru/


Another great resource, especially when you have a lot of cron jobs, is https://cronheatmap.com which shows an hour-by-minute grid of one day, and how hot each of those minutes is for your given cron schedules.


Every few years, I try to set up a cron job. I carefully follow the instructions. It never runs.


Most of the time, it's because cron jobs are using a different environment (i.e PATH and other variables) than you'd expect. What I sometimes do is to put a "screen -dm" command to run from cron (e.g. if you set it to run each minute and then remove it once it's run). Then, connect to the screen session and you can examine and test what's going on with the environment.


Always explicitly set the path to whatever it is in your shell, it's usually something to do with this.


Yep. Time honored tradition, every cron is edited at least twice. Once to put it there, again to fix PATH.

Everyone who does this enough knows it, everyone else [hopefully] rediscovers. Honest to goodness decades-long cargo culture.

I prefer not having this problem, using "systemd timers" instead. The job and any forked work have a reasonable default path, and observability is worlds better.

Did the last run succeed? When is the next? One command with timers, a guess with cron.


Literally the only issue I’ve had with cron was a bug [0] for an absurd edge case that I found and fixed.

[0]: https://bugs-devel.debian.org/1019716


Congratulations, myself and several dozens of people I know/mentor have repeated the history I mentioned


One main reason for me is that it's not possible to run the job manually. You have to wait for it to run.


Can you post an example?

To where are you expecting to output to go? Does cron have permissions for that?


PSA the Jenkins also has a builtin scheduler.

It also makes seeing the status of jobs and finding logs related to those jobs much easier.

Good overview is here: https://www.panozzaj.com/blog/2014/05/02/replace-local-cron-...


Yes ! that is what I do for personal use for years ! (mainly for backups)

Sadly Jenkins is nowadays less and less popular and I'm concerned that it will become an abandon-ware at some point.

If anyone knows good open source alternative it would be great.


They are still actively committing to the project!

https://github.com/jenkinsci/jenkins/graphs/commit-activity


I have a soft spot for cron jobs. But if you use them, I highly recommend you also use the open source runitor tool:

https://github.com/bdd/runitor

... which lets you quickly integrate any cron job with the https://healthchecks.io service. So darn handy. And you're supporting an indie startup that regularly shows up on HN.


I like setting up cron jobs with task spooler so they can run one after another and I don’t have to guess about potential overlap times.


'chronic' ("runs a command quietly unless it fails") is quite useful.


I put all of my customization in the @reboot entry (usually for root).


cron in 2024? could it be an anachronism?


That's "anacron" job! :-)

Description (from its manpage): "Anacron can be used to execute commands periodically, with a frequency specified in days. Unlike cron(8), it does not assume that the machine is running continuously. Hence, it can be used on machines that aren't running 24 hours a day, to control daily, weekly, and monthly jobs that are usually controlled by cron."




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: