Running a cron every N seconds

March 25, 2018
Cyclist
Photo by Roman Koester on Unsplash

Quite often, when developing websites or web services, some application logic, like sending letters or re-indexing a search database, must be executed in the background on the server side. In UNIX-like systems, there is a software utility cron that allows you to run scripts periodically at a certain time. Using this job scheduler, it is possible to execute scripts with a frequency not more than once per minute. But it is not always enough to solve specific tasks.

Therefore, I will show an approach that I use in my projects and that allows scripts to be run periodically every few seconds. We'll look at how to run shell scripts with another rarely used but useful nohup utility.

Shell script with an infinite loop

First, create a shell script cron.sh in the project folder /var/www/example.com with the following content.

#!/bin/bash

while true
do
    # Execute another server script.
    /usr/bin/php ./backend_logic.php

    # Wait for 10 seconds.
    sleep 10
done

As you can see, the code is very simple: an infinite loop in which another PHP script is invoked with a delay of 10 seconds after each iteration.

Note that when running PHP script with a cron, there may be a situation when the same script is run in parallel two or more times. It is possible in cases where the execution time of the script is more than one minute and the job scheduler is configured to run the script every minute. This is because cron does not wait until the task is completed. With a shell script, it will never happen, because the code is always executed sequentially.

Save this file and set execute permission on it.

sudo chmod a+x cron.sh

In fact, this script can already be used, but let's see how it can be run from the command line in the background.

Running the shell script in the background

For a fully working method, we need the nohup. A command or script launched by the utility will continue to run on the server even after the user's logout. To run our script from the local directory, execute the next command from the console.

sudo nohup ./cron.sh &

The output, which would normally send to the terminal, sends to a file called nohup.out. If, for some reason, you want to use the nohup command without getting nohup.out, here's how to do it.

sudo nohup ./cron.sh </dev/null >/dev/null 2>&1 &

With such parameters, the standard I/O streams (stdin, stdout, and stderr) will be redirected to a device file /dev/null that discards all data written to it.

Killing nohup process

In order to stop running the cron.sh script, we need to find this process in the list of all running processes of the system. For this, use the command:

sudo ps -ef | grep "cron.sh"
Output
UID PID PPID C STIME TTY TIME CMD root 877 1 0 Jan18 ? 00:12:36 /bin/bash ./cron.sh

As a result, you will see a list of processes matching the keyword in the form of a table. The value in the second column is the process PID, which is needed to stop the execution of the specific process with the kill command.

sudo kill -9 877

Running the command on system reboot

And finally, if you want the cron.sh script to be executed even after rebooting the server add the following simple configuration in the system's crontab file.

@reboot    nohup /var/www/example.com/cron.sh

Use crontab with -e option to open the schedule file in your preferred text editor.

Conclusion

I showed you one approach you can use to perform certain application logic in the background with a frequency greater than the system utility cron allows. This method, as I mentioned, is convenient to use in conjunction with the poorer software stack. Of course, you can replace nohup with something else, for example, screen.