When we write a lot of scripts we will eventually want to automate some tasks like saving Database backups, scrap a website periodically, do POST or GET requests to an API, etc. In all these cases we will need a task scheduler. On a Linux systems, our easiest and best option is Crontbab and while it is a great option for quickly creating a scheduled task both on Linux and Mac, Apple deprecated it in favor of launchd. This does not mean that we can’t use Crontab
on Mac but the downside of Crontab
is that is assumes your machine is awake and therefor will skip the task until the next time if this is not the case. On the other hand, launchd
will not run while your Mac is asleep BUT once you wake it up again, it will run.
Nonetheless, both are great and thus we will cover them both. These are the main reasons we would want to use Crontab
over launchd
:
- It is simpler to setup
- We don’t care if the job runs every time, it just should run on a best effort basis
Index:
Crontab
As mentioned above Crontab is simpler to setup, it comes already installed and all we have to do is add our job to the list which we can access using the -l
flag:
This lists all our jobs which currently is probably empty.
In order to add a job we use the -e
flag:
This will let us add a job to the list. The default editor on Mac is VIM but don’t be afraid. Here is a very quick guide to VIM. When the VIM editor opens:
- Use the
i
key to start insert mode and edit the file - Use the arrow keys to move around the cursor
- Use the
esc
key to stop editing - Type
:wq
to write your changes and exit after theesc
key
Now lets get into the actual job running:
Crontab lets you specify the time by putting your desired times in the right slots as followed (based on the above job):
- 1) minute (0 - 59)
- 2) hour (0 - 23)
- 3) day of month (1 - 31)
- 4) month (1 - 12)
- 5) day of the week (0 - 6)
For example a tasks that will run every day at 4pm:
If you don’t specify a day, month or day of the week, it will run every day. If we take a look at our job list again, we can see our newly created job:
A little extra to note, if we leave the cronjob as it is, we will get an email in our terminal every time it executes which can be a little annoying. The fix is fairly simple, open the job list again and add at the top this line:
No more email great ^^
Launchd
While Crontab is a quick solution for scripts that don’t necessarily have to run every day, sometimes we need something more robust. Sometimes we might be commuting at the time our job should run and as mentioned above, Crontab will skip this job and will not run it until tomorrow at the same time. Launchd solves this problem for us because it knows we are not always actively using our computer.
In order to create a new job with Launchd
we have to create our .plist
file first which is just an XML
file with some boilerplate XML from Apple’s docs. We can create the file using touch
:
Using the Crontab example, note my username is Alexander
you have to use yours:
Now we can open it in our favorite editor (mine is Atom):
This is the boilerplate XML we need for any job:
At this point we have two options to schedule our job:
- Run it in intervals (every 10 seconds, 1 minute, etc.)
- Run it a specific times (4pm every day)
If we want to run it in intervals we have to add an interval key to our XML specifying the interval in seconds like this:
This would run every 60 seconds. If we want to run our job based on a specific time we exchange the interval
key for a calendar interval
key:
In our case all we want is to specify the hour since we want to run our job every day at the same time:
Great now all that is left is to load our agent (job). Here you have 2 options, you can do it the manual way or use a small tool for this called lunchy
:
The Manual way
We have to use launchctl
to load and start our job (note, replace Alexander with your username):
Using Lunchy
Lunchy is a Ruby gem so we have to install it first like this:
Once it is downloaded we can load our job a little more simply, we don’t have to specify a path nor the username just the plist’s name:
Similarly to list our jobs:
Finally to stop our Agent: