![](https://www.both.org/wp-content/uploads/2024/01/checklist_todo_clock_time_team.png)
Automate Raspberry Pi tasks with crontab
I have a Raspberry Pi at home that I use to automate several things. For example, my printer is old enough that it doesn’t support networking, so it’s connected to the Raspberry Pi, which shares the printer to my home network using CUPS. I also use the Raspberry Pi as an at-home web server to work on websites, and as a “file server” of sorts by using SFTP from my file manager.
This became somewhat less useful last year when my Internet provider “upgraded” the home WiFi router. The new router has an added security feature where it disconnects any device from the network after about two or three days. Without a network connection, I can’t print, backup files, or work on web pages.
Restarting the Raspberry Pi would put it back on the network. So I needed to find a way to restart the Raspberry Pi every other day. And I needed it to happen automatically, and gracefully, when I wasn’t likely to use it. That’s the perfect use case for cron and crontab.
Using ‘cron’ and ‘crontab’
On Unix-like systems, cron
is the system that executes tasks at specific times. The jobs that run, and when they run, are controlled using a special file called the crontab. Every user can create their own crontab to run tasks according to their own schedule.
The crontab file is arranged like a plain text “table” with fields that define the time, day, month, and day of the week to run the job. You can find detailed information about the crontab file in the crontab(1) online manual page, with this command:
$ man 5 crontab
The classic fields of the crontab file are:
Field | Range of values |
---|---|
1. Minute | 0 to 59 |
2. Hour | 0 to 23 |
3. Day of month | 1 to 31 |
4. Month | 1 to 12 |
5. Day of week | 0 to 6 |
6. Command to run | (enter the full command here) |
Modern crontab implementations, like the one on Linux, also support extensions to these fields. For example, the Vixie cron
implementation (by Paul Vixie) on most Linux distributions also accepts 0 to 7 as days of the week, where 0 and 7 are the same (Sunday). You can also use names for the months and days of the week, such as sun
for Sunday or jan
for January. But I like using numbers, so I’ll use that here.
For example, let’s say you needed to run a tar
backup of a website, every Sunday at 6:00 AM. You can create this crontab entry:
0 6 * * 0 /bin/tar czf $HOME/website.tar.gz /var/www/html
The first two fields indicate 0
for the minutes and 6
for the hour. The fifth field says 0
for the day of the week, which means “Sunday.” The third and fourth fields are *
to mean “any day of the month” and “any month.” Together, these five fields will execute the tar
backup every Sunday at 6:00 AM.
To enter the crontab file into the cron
system, you need to use the crontab
command. If your crontab file is called jobs
, then you would type this:
$ crontab jobs
You can verify the contents of the crontab file with crontab -l
to list (-l
) the contents of the file. You can also erase your crontab from the system with crontab -r
to remove (-r
) the file.
Scheduled reboot
In my case, I needed to reboot the Raspberry Pi before the router took it off the network. One way to do this is with the telinit
command, to change the “System V” run level. On Linux systems that run systemd, this executes the appropriate systemctl
command. But I learned on original Unix systems, so I prefer telinit
.
To reboot every day at 7:00 AM, I started by creating this crontab file for the root user:
0 7 * * * /sbin/telinit 6
The first two fields are 0
for the minutes and 7
for the hour, with *
for all of the other fields; this will run at 7:00 AM every day. I saved this file as /root/jobs
and I saved it into the system with this command as root:
# crontab /root/jobs
But I didn’t need to reboot every day; I only needed to reboot every other day. And Vixie cron
has a neat syntax where you can specify /
and then a number to create an alternate schedule. For example, 0-30/2
for “minutes” would run a job every other minute: “:00,” “:02,” “:04,” … and so on until “:26,” “:28,” and “:30.” This runs on even minutes because “minute” can have values from 0 to 59, and zero is an even number.
To reboot my Raspberry Pi every other day, I updated the crontab entry to use */2
for “day of the month.” This runs the job every other day: 1, 3, 5, … until 27, 29, and 31. These are odd days because “day of the month” is a value between 1 and 31, and 1 is an odd number.
0 7 */2 * * /sbin/telinit 6
With this entry, my Raspberry Pi rebooted itself at 7:00 AM every other day of the month: June 1, June 3, June 5, … and so on for the rest of the month.
Combining jobs
I figured as long as the Raspberry Pi would reboot every other day, I might as well apply updates at the same time. For that, I wanted to run the dnf
command to install any updates, then use telinit
to reboot the system.
When you need to combine multiple tasks into a single crontab job, I recommend collecting the commands into a script. In my case, I created this Bash script called /root/bin/update_reboot
to run dnf
and telinit
, plus keep a log of what it did:
#!/bin/bash
# apply updates, reboot anyway
logdir=/root/log
[ -d $logdir ] || mkdir -p $logdir
today=$(date '+%d')
dnf -y update > $logdir/dnf_update.$today.log
telinit 6
In this script, I wanted to keep a private log in /root/log
to capture the output from the dnf
command. The two lines that set the logdir
variable and run mkdir
ensure that my /root/log
directory is present, so I have a place to store logs.
I use the $()
shell expansion to run date
to print today’s day of the month as a zero-padded number, so I can use the date as part of the log file’s name when I run the dnf
command to apply all updates. The last line reboots the system for me.
Automating tasks made easy
While job automation might sound like something that only system administrators do, it’s a feature that anyone can use. If you need to do a task on a regular schedule, explore how you can use crontab to do the repetitive work for you.