Sometimes you may run into situation where you would need to set a cron job but your hosting provider doesn’t support them or only allows you to run scheduled jobs for example only once in hour when you would need to do a task more often. In my case I ran into latter case and didn’t want to change my hosting plan just for more frequent cron jobs. So I developed the following workaround.
Note! Please use the following code at your own risk. There’s many different scenarios why this may not work in your environment or why it could stop working, so I wouldn’t recommend using this for anything very important.
Running a script once in a minute
Let’s first create a script called cron_job.php. The basic idea here is to first run do_something.php (which is your scheduled task), then wait for one minute and start another instance of itself.
<?php // remove remove execution time limits for this script set_time_limit(0); $my_pid = getmypid(); file_put_contents("./cron_script_pid", $my_pid); // Save script pid shell_exec('php do_something.php > /dev/null 2>&1 &'); sleep(60); // Wait for a minute // Start another instance of the same script shell_exec('php cron_job.php > /dev/null 2>&1 &'); // kill this script die(); ?>
Now when you run cron_job.php once, it keeps on running every minute as long as the web server is running or something unexpected (which will terminate the loop) happens. To handle situations like this, we need another script which will check that the cron_job.php is still running. For that we can create a new script called cron_check.php:
<?php $output = shell_exec('ps -C php -f'); if (strpos($output, "php cron_job.php")===false) { // cron script is not running, start it shell_exec('php cron_job.php > /dev/null 2>&1 &'); } ?>
If you don’t have ability to run cron jobs at all, you can run this script for example on your websisite footer, so the check will run every time someone visits your website.
In my case, I was able to set this script to run in a cron job that runs once an hour. So basically, if my script gets terminated, it will restart in an hour.
Terminating the loop manually
You may have also noticed that cron_job.php saves its PID to the file called cron_script_pid. That’s for the cases where we would like to terminate the cron job without having a shell access to the server. Here’s the code that will terminate the cron_job.php -loop.
<?php $pid = file_get_contents("./cron_script_pid"); system("kill ".$pid); ?>
Creating multiple tasks with different intervals
In my case, I also had to run multiple tasks with different intervals. Instead of duplicating the code above, I modified it so the same script handles them all. Here’s a modified cron_job.php script with few different interval examples:
<?php // remove remove execution time limits for this script set_time_limit(0); $my_pid = getmypid(); file_put_contents("./cron_script_pid", $my_pid); // Save script pid if(intval(date("H")) == 13 && intval(date("i")) == 30 && intval(date("s")) < 30) { // Run this every day at 13:30 shell_exec('php cron_job_13_30.php > /dev/null 2>&1 &'); } if(intval(date("i")) == 35 && intval(date("s")) < 30) { // Run this every hour at xx:35 shell_exec('php cron_job_xx_35.php > /dev/null 2>&1 &'); } if(intval(date("i")) == 45 && intval(date("s")) < 30) { // Run this every hour at xx:45 shell_exec('php cron_job_xx_45.php > /dev/null 2>&1 &'); } if(intval(date("i")) % 5 == 0 && intval(date("s")) < 30) { // Run this every 5 minutes shell_exec('php cron_job_5min.php > /dev/null 2>&1 &'); } // Run this every 30 seconds shell_exec('php cron_job_30s.php > /dev/null 2>&1 &'); sleep(30); // Wait for 30 seconds // Start another instance of the same script shell_exec('php cron_job.php > /dev/null 2>&1 &'); // kill this script die(); ?>