A simple, one-job PHP/cron dispatcher

Goal: To provide a way for a website administrator to dispatch a long-running command-line program, one that might take hours to complete (so exec is out). The admin interface should show that the process is running. There is only one job that will ever be dispatched.

Solution: I wanted something really secure, so I didn’t want PHP actually specifying the commands to be executed. To this end, I made something very, very simple that uses PHP, cron, a shell script, and a token file (a semaphore of sorts). The actual command being executed, in this case, is hard-coded into the shell script. The flow is this:

  1. User clicks a link that creates an empty file (the ‘token’).
  2. A cron task on a 5-minute cycle calls the shell script.
  3. The shell script checks for the existence of the token file. If the file exists, it calls the long-running process, then removes the token file.

The individual parts are below.

The PHP/HTML with user interaction:

<?php if (file_exists("/path/to/token")) : ?>
    Job running...
<?php else : ?>
    <a href="link/to/start_job.php">Start the job!</a>
<?php endif; ?>

The PHP to start the job:

touch('/path/to/token');

The shell script:

#!/bin/sh
TOKEN=/path/to/token
if [ -f $TOKEN ] ; then
    /path/to/long_running_process
    rm $TOKEN
fi

The crontab entry:

*/5 * * * * /path/to/shell_script

Notes

The long-running executable in my case is a Ruby script. This fact poses a special problem for cron, since cron executes its tasks in a very limited environment—in this case, an environment that doesn’t have its Ruby paths set up. As a result, I was getting in `require’: no such file to load — rubygems (LoadError) errors. The fix is quite simple; just add the following to the shell script:

export PATH=/usr/local/bin:/bin:/sbin:/usr/bin:/usr/sbin
export RUBYLIB=/usr/local/lib/ruby/1.9.1:/usr/local/lib/ruby/site_ruby/1.9.1/
export GEM_HOME=/usr/local/lib/ruby/gems/1.9.1
export GEM_PATH=/usr/local/lib/ruby/gems/1.9.1:/home/username/.gem/ruby/1.9.1

Obviously, you would need to update the paths as appropriate

1 Comment

  1. I believe anacron might also do this automatically, it doesn't come with all distro's by default, but debian has a package and I believe ubuntu does ship with it.

Leave your thoughts
  • You can use some HTML in your comment.
  • Your comment may not display immediately due to spam filtering. Please wait for moderation.