Running Cron Jobs On Your Local Mac
January 19, 2021
Today’s post will demonstrate how to have a script automatically run as a cron job on your Mac computer using
We will demonstrate by automating a simple script to add the word “hello” onto a new line every minute and showing how we can log out
stderr to a file after each run for our sake.
We will create a
.scripts folder at the root using to store our scripts to be used by
crontab and create a file
hello.sh to store our script:
# Create the .scripts folder at the root mkdir ~/.scripts # Change into the folder cd ~/.scripts # Create the file ~/.scripts/hello.sh touch hello.sh # Ensure we enable execution permissions for the file chmod u+x ./hello.sh
Inside of the file
hello.sh, add the following:
#!/bin/bash echo "Starting script" # Echoes the word "hello" in a file "hello.txt" in the same folder echo hello >> hello.txt echo "Finished"
The above simply does the following:
- Echo “Starting script” to
- Append the word “hello” to the
- Echo “Finished” to
Will all this out of the way, we can now tell
crontab to run the script each minute.
Setting the script to run in crontab
On the Mac, we can use
crontab -e to open an editor in Vim which will allow us to enter the following.
* * * * * cd ~/.scripts && ./hello.sh >/tmp/stdout.log 2>/tmp/stderr.log
Note: if you want to use another editor you are familiar with, you will need to update your run command file to change the editor ie if you use Bash, add
export EDITOR=/usr/bin/nano to your
.bashrc file (or equivalent for your shell of choice). More on this below in “handling issues”.
The line added can be broken down into two parts: The cron schedule expression and the command to invoke.
cron schedule expression in the line above consists of the
* * * * * part of the line. This line in layperson’s terms means “at every minute”. This means that at every minute, the
[command] part of the expression will be run.
For those unfamiliar with cron expressions, websites such as crontab guru are great for giving a layperson expression in understandable English.
Below are some basic expressions and some human readable translations to give you some insight:
# At minute 5 of every hour 5 * * * * # At 5:00 0 5 * * * # At minute 15, 30, 45, and 0 past hour 5 15,30,45,0 5 * * * # At 05:00 on day-of-month 1 0 5 1 * * # At 05:00 on day-of-month 1 in April 0 5 1 4 * # At 05:00 on Monday, Wednesday, Friday, and Sunday in April 0 5 * 4 1,3,5,7
As for the rest of the line
cd ~/.scripts && ./hello.sh >/tmp/stdout.log 2>/tmp/stderr.log, we are simply say “change to the
~/.scripts directory, run
./hello.sh and log stdout to
/tmp/stdout.log and stderr to
You can update that line to be whatever you want. What is important is that
~/.scripts/hello.sh has the correct permissions to execute.
The script in action
Once you set the value in the crontab file, exit your editor of choice after saving the file.
If successful, you should get an indicator that things are okay if you run
crontab -l and see your job listed. If not, check
Handling issues below to see if one of them ends up as your issue. If not, you may have to do some online searching!
Assuming that you are successful, all we really need to do now is wait a few minutes and we can
~/.scripts/hello.sh file out and see the results!
# After waiting 5 minutes $ cat ~/.scripts/hello.txt hello hello hello hello hello $ cat /tmp/stdout.log Starting script Finished $ cat /tmp/stderr.log # Nothing - there was no error
Success! We have successfully set up our first automated crontab job in OSX!
To remove the cron job, simple run
crontab -e again and remove the job with the editor.
This is not an exhaustive list, but two issues I came across was the need to update my editor to reference
/usr/bin/vim instead of
/usr/bin/vi and to update my
Security & Privacy to allow Full Disk Access for iTerm (enable at your own risk).
To update the editor, ensure that your shell run command files that are loaded (ie
~/.bashrc etc) includes the following export value for
# Attempt to fix crontab using Vim export EDITOR=/usr/bin/vim
As for the Full Disk Access, simply head to
Security and Privacy, enable changes through the lock on the bottom-left and add your terminal of choice.
The post today is a very beginner-friendly one that does the bare minimum to demonstrate how to get
From here, it is up to you to automate what you wish to automate! You can adjust the shell script to run very complex web scrapers in other languages and more!
Resources and further reading
Image credit: Elia Pellegrini
Slowly introducing yourself to the world of generative art with this short introduction
Use the Node debugger to visualise performance
See how you can get started with the VSCode debugger for Node.js applications
Learn how to setup LocalStack to help with local development emulating AWS products
Learn how to play around with DynamoDB locally and use NoSQL Workbench to plan out your work
See how you can dynamically create UIs based on React State using dynamic imports, Next.js 10 and React State
Have you ever wanted to build a UI Component Library with TypeScript and React? This blog post will take you through a straightforward set up that uses the bare minimum to get a working component library that you can re-use across your different React projects.
A look into how you can run a cron job to self-destruct tweets
A personal blog on all things of interest. Written by Dennis O'Keeffe, Follow me on Twitter