Bellow 是我们对@chaos answer 的工作实现。处理信号的代码已被删除,因为该脚本通常只存在几毫秒。
此外,我们在代码中添加了 2 个函数来在调用之间保存 pid:restore_processors_state() 和 save_processors_state()。我们在那里使用了redis,但您可以决定对文件使用实现。
我们使用 cron 每分钟运行一次这个脚本。 Cron 检查所有进程是否还活着。如果不是 - 它重新运行它们然后死亡。如果我们想杀死现有的进程,那么我们只需使用参数kill:php script.php kill 运行这个脚本。
无需将脚本注入 init.d 即可运行 worker 的非常方便的方法。
<?php
include_once dirname( __FILE__ ) . '/path/to/bootstrap.php';
define('WANT_PROCESSORS', 5);
define('PROCESSOR_EXECUTABLE', '' . dirname(__FILE__) . '/path/to/worker.php');
set_time_limit(0);
$run = true;
$reload = false;
declare(ticks = 30);
function restore_processors_state()
{
global $processors;
$redis = Zend_Registry::get('redis');
$pids = $redis->hget('worker_procs', 'pids');
if( !$pids )
{
$processors = array();
}
else
{
$processors = json_decode($pids, true);
}
}
function save_processors_state()
{
global $processors;
$redis = Zend_Registry::get('redis');
$redis->hset('worker_procs', 'pids', json_encode($processors));
}
function spawn_processor() {
$pid = pcntl_fork();
if($pid) {
global $processors;
$processors[] = $pid;
} else {
if(posix_setsid() == -1)
die("Forked process could not detach from terminal\n");
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
pcntl_exec('/usr/bin/php', array(PROCESSOR_EXECUTABLE));
die('Failed to fork ' . PROCESSOR_EXECUTABLE . "\n");
}
}
function spawn_processors() {
restore_processors_state();
check_processors();
save_processors_state();
}
function kill_processors() {
global $processors;
foreach($processors as $processor)
posix_kill($processor, SIGTERM);
foreach($processors as $processor)
pcntl_waitpid($processor, $trash);
unset($processors);
}
function check_processors() {
global $processors;
$valid = array();
foreach($processors as $processor) {
pcntl_waitpid($processor, $status, WNOHANG);
if(posix_getsid($processor))
$valid[] = $processor;
}
$processors = $valid;
if(count($processors) > WANT_PROCESSORS) {
for($ix = count($processors) - 1; $ix >= WANT_PROCESSORS; $ix--)
posix_kill($processors[$ix], SIGTERM);
for($ix = count($processors) - 1; $ix >= WANT_PROCESSORS; $ix--)
pcntl_waitpid($processors[$ix], $trash);
}
elseif(count($processors) < WANT_PROCESSORS) {
for($ix = count($processors); $ix < WANT_PROCESSORS; $ix++)
spawn_processor();
}
}
if( isset($argv) && count($argv) > 1 ) {
if( $argv[1] == 'kill' ) {
restore_processors_state();
kill_processors();
save_processors_state();
exit(0);
}
}
spawn_processors();