PhpTaskDaemon: Current state of running PHP scripts using the command line

The goal of PhpTaskDaemon is to provide an easy and usable API to define task loading and execution run. A command line utility will be provided to execute and monitor one or more tasks. This blog posts I will provide an overview of currect technologies for starting PHP scripts. Minimalist examples will be provided to show the usage of the different technologies. All examples will use the following two functions. The implementation of the two functions below aren’t any useful, but are needed for the examples.

The first method defines the execution of a single task.

{code type=php}
function executeTask($input) {
echo “Task started!\n”;
sleep (1);
echo “Task done\n”;
}
{/code}

The second function loads the tasks in the queue. For simple programs, normally run as cronjobs, this function will return a single array with task input.

{code type=php}
function loadQueue() {
$tasks = array(array());
echo “Queue loaded (” . count($tasks) . ” tasks)!\n”;
return $tasks;
}
{/code}

Running PHP From the command line
In order to run PHP scripts from a terminal the command line has to be enabled. PHP scripts can be executed through the command line by putting the PHP script filename as an argument of the PHP executable.

{code type=php}
$queue = loadQueue();
foreach($queue as $task) {
executeTask($task);
}
{/code}

{code}
php tasks.php
{/code}

To run the php script directly, the script has to be made executable and a SheBang needs to be added.

{code}
chmod +x tasks.php
./tasks.php
{/code}

Command line arguments for the script are stored in the $argv variable. The Zend Framework library contains a nice component, called Zend_Console_Getopt, for setting and handling command line arguments. For more information about running PHP scripts from the command line see the post PHP on the Command Line.

Linux Cron
The Linux Cron allows tasks to be automatically run in the background at regular intervals. Each cron job definition exists of six fields separated with a space. The five arguments define the time (minute, hour, month, year and day of the week) when to run the script. The sixth argument is the script itself. The following crontab line runs a script every workday (mon-fri) at 06:40.

{code}
6 40 * * 1-5 php /path/to/file/tasks.php
{/code}

For more information about the crontab see an article of Kevin van Zonneveld about scheduling tasks on Linux using crontab. For more examples see the article from the geek stuff: 15 practical crontab examples.

Daemon
WikiPedia defines a daemon as a programs that runs in the background, rather than under the direct control of a user; they are usually initiated as background processes. A big difference with using PHP for generating web pages is the time a script runs. Mostly a daemon is supposed to be running all the time. The script needs to be adjusted so it keeps running. A simple while(true) will do the trick. The script sleeps a single second each time after loading and executing tasks.

{code type=php}
while (true) {
$queue = loadQueue();
foreach($queue as $task) {
executeTask($task);
}
sleep(1);
}
{/code}

There are several alternatives to run a program in the background, such as adding an ampersand (&) to the end of the command. The program stops when the terminal is closed. This can be solved by starting the program within a screen. Another way is to solve the problem within the code by forking the process and exit the parent, while the child process will continue running.

{code type=php}
$pid = pcntl_fork();
if ($pid == -1) {
die(‘could not fork’);
} else if ($pid) {
exit;
} else {
while (true) {
$queue = loadQueue();
foreach($queue as $task) {
executeTask($task);
}
sleep(1);
}
}
{/code}

Another way for running php script as daemons can be done with the linux daemon commando. It provides several functionalities commonly used by daemon programs, such as logging and configuration.

Gearman
The gearman website describes gearman provides a generic application framework to farm out work to other machines or processes that are better suited to do the work. It allows you to do work in parallel, to load balance processing, and to call functions between languages. Below is an example of a gearman worker registering the executeTask method.

{code}
$gmworker= new GearmanWorker();
$gmworker->addServer();
$gmworker->addFunction(“executeTask”);
echo “Waiting for job…\n”;
while($gmworker->work()) {
if ($gmworker->returnCode() != GEARMAN_SUCCESS) {
echo “return_code: ” . $gmworker->returnCode() . “\n”;
break;
}
}
{/code}

The gearman worker object only needs to register the executeTask method, because gearman provides its own queuing mechanism. Adding a task to the queue can be done through a gearman client object.

{code}
$gmclient= new GearmanClient();
$gmclient->addServer();
echo “Sending job\n”;
do{
$gmclient->do(“executeTask”, “3”);
}
{/code}

For a more usefull example see Matthew Weier O’Phinney blog post about writing gearman workers in PHP.

Parallel execution
Some scripts can benefit from running in parallel. This is especially the case when the script has to wait for other resources (server). In a multi-core systems performance benefits can be achieved by running scripts in parallel. By splitting up the tasks and running multiple instances of a PHP script for each core such script can benefit from a multi-core environment. The process control function library provides the ability to fork a running process into a child and parent. Most common is to use the parent as a queue manager, which loads the queue and dispatches single tasks to forked processes. Processes are forked only when there are tasks in the queue. Another method is to control the queue from each child process. The child processes will run autonomously and will check for new tasks itself. The drawback of such approach is keeping the queues synchronised. Below is simple example of a script that forks itself for each loaded tasks.

{code}
$pids = array();
for($i = 0; $i < 3; $i++) {
$pids[$i] = pcntl_fork();
if(!$pids[$i]) {
// child process
executeTask();
exit();
}
}
for($i = 0; $i < 3; $i++) {
pcntl_waitpid($pids[$i], $status, WUNTRACED);
}
{/code}

For more information about forking PHP scripts, see an article about Process Forking with PHP on Electric Toolbox or view a presentation called PHP CLI: A cinderella story on SlideShare.

Conclusion
In this blog post I provided an overview of ways to run PHP scripts from the command line and/or as a background script. Each proposed method has its own advantages and disadvantages. A cronjob runs only once per minute and does not check if a process is already running. A daemon can be created to ensure a program is running continuously, the developer has to implement a queuing system himself. Gearman contains a queuing system and uses gearman workers to process the tasks. The gearman client needs to be used to add tasks to the queue. Forking processes can increase performance by running scripts in parallel. Managing and monitoring tasks is a difficult task when using process forks.

The PhpTaskDaemon projects tries to combine a set of the approaches above into a easy to use library. It provides a single start-up script for all background tasks and contains a lot of commonly used functionalities for creating daemons, such as logging. Next article I will blog about creating the managers and task definitions for the PhpTaskDaemon project.

Blog posts in this series
This blog post is an item in a series of blog posts about the development of the PhpTaskDaemon project. Follow the real progress of the project on the GitHub project page. The following blog posts of this series have been published in the past:
* An introduction of the PhpTaskDaemon project
* The current state of running PHP scripts using the command line (this post)

Next time I will blog about the following aspects of the PhpTaskDaemon system.
* Defining Tasks (updated 16 jan 2011)
* Running and monitoring the daemon
* Building managers: shared memory, semaphores and sockets
* Creating a small web front end for monitoring the daemon

Website Pin Facebook Twitter Myspace Friendfeed Technorati del.icio.us Digg Google StumbleUpon Premium Responsive

Share/Bookmark
This entry was posted in Algemeen, Open Source, PHP, PhpTaskDaemon, Projects and tagged , , , , , , . Bookmark the permalink.

One Response to PhpTaskDaemon: Current state of running PHP scripts using the command line

  1. Michael says:

    Danke Dirk. Hat mir sehr geholfen. 😉

Leave a Reply

Your email address will not be published. Required fields are marked *