How to create a linux systemd service and timer that activates a script every few seconds

You have a bash script on your linux installation that you would like to run periodically, it could be anything, for instance you have a script that takes periodic snapshots of the database and performs a backup, or a script that pulls in changes from the remote repository and then rebuilds the source files for your app. You can activate script periodically using a cron job or you could use a systemd service in combination with a timer, in this blog post, I explore how to set up a service and timer that will run a bash script every thirty seconds.

Systemd is a system and service manager for Linux operating systems, designed to start and manage system processes. Two key components of systemd are its handling of services and timers

Systemd manages system services using unit files with the .service extension. These files define how and when a service should be started, stopped, or restarted. Service units specify the executable to run, dependencies, and conditions for execution.

Systemd timers are used to schedule tasks, similar to cron jobs. Timer units have the .timer extension and are associated with a corresponding service unit that defines the action to be executed. Timers can trigger based on time intervals, specific dates, or events.

Creating the service and timer

The goal is to create a .service file that activates a bash script and a timer that will run that service every thirty seconds.

First the bash script

The bash script could be for anything, for demonstration lets have a simple bash script that outputs hello world and the date when it was activated to a log file. Create a file example-script.sh and save it in /usr/local/bin/ so that the full path is /usr/local/bin/example-script.sh

echo "Hello, world! The script ran at $(date)" >> /var/log/example-script.log

After creating the bash script, make it executable using the command

sudo chmod +x /usr/local/bin/example-script.sh

Then the service

Create a file in /etc/systemd/system called hello.service so that the full path is

/etc/systemd/system/hello.service

[Unit]
Description=Run the hello world script
After=network.target  # Ensures the service starts after the network is up

[Service]
User=yourUsername  # Runs the script as a user that you specify who has the right permissions 
Type=simple  # Default type if not specified; appropriate for most scripts
ExecStart=/usr/local/bin/example-script.sh  # Command to start the service
Restart=on-failure  # Optional: Restart the service if it fails

[Install]
WantedBy=multi-user.target  # Links the service to the multi-user runlevel

There are some interesting parameters specified in the service file

  • After=network.target: Include this if your script requires network access.

  • Type: Only necessary if you need to specify a type other than the default simple.

  • Restart=on-failure: Useful if you want the script to automatically restart on failure.

  • WantedBy=multi-user.target: This is necessary if you want to enable the service to start at boot.

Creating the timer

The final file the timer which has a .timer extention, in this file we define a timer which will trigger the service we just created which in turn runs the script, the file should be in the same folder as the .service file . The end effect is that our bash script will be triggered periodically based on the interval specified

Below is an example of a timer that will run the service every thirty seconds

[Unit]
Description=Run the script every thirty seconds

[Timer]
OnBootSec=30sec
OnUnitActiveSec=30sec
Unit=hello.service

[Install]
WantedBy=timers.target

Note the Unit field where you specify the name of the .service file created earlier.

Activating them

After setting up the script, the .service file and the .timer file, its time to activate them.

Begin by first reloading the systemd manager configuration with the command

sudo systemctl daemon-reload

Then enable the service with the command

sudo systemctl enable --now hello.service

Then enable the timer

sudo systemctl enable --now hello.timer

To check whether the timer and service were activated correctly use the commands

sudo systemctl status hello.service

sudo systemctl status hello.timer

If everything goes well, the log file at /var/log/example-script.log where our bash script outputs its message should begin getting populated with the hello world message every time the script runs in the time specified in the timer.

Using a sytemd service and timer to periodically run a bash script offers more flexibility than a cron job and can be used for any number of tasks like automatic backup or even creating a build and deploy pipeline that automatically pulls new changes from a repository and rebuilds the app.