Automating Stuff the 'Easy' Way With anacron

cron is a wonderful tool for running tasks on a schedule. Set it once, and then forevermore on your schedule, cron will handle repeatedly doing the thing.
Unless your computer is off! cron was originally designed for mainframes that never are turned off. If you have a task scheduled to run every day at midnight but your laptop is closed every night, cron will never run the task.1
I recently learned about anacron , which solves this problem by running things at a “scheduled-ish” time. Instead of specifying a time, you specify a frequency (hourly, daily, weekly, etc). When anacron starts (when your computer wakes from sleep/etc) if it’s been more than the specified time since it last ran, it runs. Simple, right?
Eh, not so much. Possibly because I had some complicated things I wanted to set up, getting everything aligned and working took almost a week (admittedly because I was waiting for anacron to run and wasn’t interested in force-scheduling it).
My main problem was that I wanted anacron to run as me, rather than as root. By default, unlike cron, anacron only runs as root.
I wanted to set up urlwatch to keep an eye on some websites, using headless Chrome. Automatically hitting a website as root seems like not a great idea? So running as a non-superuser seemed like the way to go.
Here’s what I did:
Setup
First, get anacron. If you have a Red Hat system, you already have it as part of cronie. On Ubuntu-based distros, you may have to install it. On a Mac, there is no official support for anacron and you are recommended to use launchd. On the other hand, there’s this Macports option with all of 12 installs 😬 which I probably will not be trying.
Then, I followed the steps in this Opensource.com article to configure anacron to run as my user. To summarize that article in my own words:
-
Create a test script to practice on. My example script looked like this:
#!/bin/bash echo $(whoami) >> ~/dontyouknowwhoiam.txtThis should prove that anacron is running as me (which I still wasn’t 100% confident of until testing it).
-
Create local directories that we’ll point
anacronto instead of the system directories:mkdir -p ~/.local/etc/cron.daily ~/.var/spool/anacron -
Create a local configuration file at
/.local/etc/anacrontab:SHELL=/bin/sh PATH=/sbin:/bin:/usr/sbin:/usr/bin #replace with your full $PATH. anacron doesn't have access to system environment variables set in, say, ~/.profile. 1 0 cron.mine run-parts /home/{user}/.local/etc/cron.daily/This will run everything in the
~/.local/etc/cron.dailyfolder every 1 day, waiting 0 minutes after the computer starts up. The buffer can be helpful if you’re running heavy scripts, I assume. Themineis an arbitrary string to distinguish fromcron.dailyorcron.weeklyetc.As an aside,
anacrontabis a perfectly logical name for the scheduling file belonging toanacron.cronhas acrontab(short for cron table), and soanacronhas ananacrontab. But for an elder millennial like myself, this was inevitable:
I’m so sorry. (Not really)
-
Tell our computer to run
anacronon a schedule. The article suggests adding this line to your~/.bash_profile:anacron -t /home/{user}/.local/etc/anacrontab -S /home/{user}/.var/spool/anacronThis manually triggers
anacronwith the local anacrontab, and use your local spool file (which is whatanacronuses to keep track of the last time it ran). Putting it in your ~/.bash_profile means thatanacronwill check for new jobs every time you restart your computer.Putting it in ~/.bashrc (or sourcing the profile file from rc) will run it when you open a new terminal window. Finally, putting it in your
crontab:0 0 * * * anacron -t /home/rachel/.local/etc/anacrontab -S /home/rachel/.var/spool/anacronmeans
anacronwill also check for new jobs at midnight, in case your computer hasn’t been off. I used all three options, because what’s the harm. Worst case, anacron decides that it hasn’t been long enough since it last ran and goes back to sleep.
Those are the basic steps. That said, I ran into at least one bump on the road to better automation.
It’s not stated anywhere but the man page, butrun-parts has fairly specific naming requirements for executables, for it to run them. In default mode, according to the man page,
the names must consist entirely of ASCII upper- and lower-case letters, ASCII digits, ASCII underscores, and ASCII minus-hyphens.
You can check that run-parts is happy with run-parts --test /home/{user}/.local/etc/cron.daily.
Then I had to get urlwatch up and running. I’m going to save that for a separate post, because (as usual) I’ve gotten a little verbose. Up next (eventually): how to configure urlwatch to check for changes to websites on a schedule!
-
Unless your laptop is like mine and “forgets” to sleep when the lid is closed, which is a whole other hilarious problem. ↩