問題:我想實現幾個正在MQ服務器隊列上偵聽異步作業的php工作進程。現在的問題是,簡單地在服務器上運行這個進程作爲守護進程並不能真正控制實例(負載,狀態,鎖定)......除了可能用於轉儲ps -aux。 因此,我正在尋找某種允許我監視和控制實例的運行時環境,無論是在系統(進程)級還是在更高層(某種Java風格的應用服務器)上,都可以監視和控制這些實例。PHP守護進程/工作環境
任何指針?
問題:我想實現幾個正在MQ服務器隊列上偵聽異步作業的php工作進程。現在的問題是,簡單地在服務器上運行這個進程作爲守護進程並不能真正控制實例(負載,狀態,鎖定)......除了可能用於轉儲ps -aux。 因此,我正在尋找某種允許我監視和控制實例的運行時環境,無論是在系統(進程)級還是在更高層(某種Java風格的應用服務器)上,都可以監視和控制這些實例。PHP守護進程/工作環境
任何指針?
下面是一些可能有用的代碼。
<?
define('WANT_PROCESSORS', 5);
define('PROCESSOR_EXECUTABLE', '/path/to/your/processor');
set_time_limit(0);
$cycles = 0;
$run = true;
$reload = false;
declare(ticks = 30);
function signal_handler($signal) {
switch($signal) {
case SIGTERM :
global $run;
$run = false;
break;
case SIGHUP :
global $reload;
$reload = true;
break;
}
}
pcntl_signal(SIGTERM, 'signal_handler');
pcntl_signal(SIGHUP, 'signal_handler');
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(PROCESSOR_EXECUTABLE);
die('Failed to fork ' . PROCESSOR_EXECUTABLE . "\n");
}
}
function spawn_processors() {
global $processors;
if($processors)
kill_processors();
$processors = array();
for($ix = 0; $ix < WANT_PROCESSORS; $ix++)
spawn_processor();
}
function kill_processors() {
global $processors;
foreach($processors as $processor)
posix_kill($processor, SIGTERM);
foreach($processors as $processor)
pcntl_waitpid($processor);
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]);
} elseif(count($processors) < WANT_PROCESSORS) {
for($ix = count($processors); $ix < WANT_PROCESSORS; $ix++)
spawn_processor();
}
}
spawn_processors();
while($run) {
$cycles++;
if($reload) {
$reload = false;
kill_processors();
spawn_processors();
} else {
check_processors();
}
usleep(150000);
}
kill_processors();
pcntl_wait();
?>
您是否確實需要它持續運行?
如果您只想根據請求產生新進程,則可以在xinetd中將其註冊爲服務。
這聽起來像你已經有一個MQ並運行在* nix系統上,只是想要一種管理工人的方法。
一個非常簡單的方法是使用GNU屏幕。要啓動10個工人,您可以使用:
#!/bin/sh
for x in `seq 1 10` ; do
screen -dmS worker_$x php /path/to/script.php worker$x
end
這將使用名爲worker_1,2,3等屏幕在後臺啓動10名工人。
您可以通過運行screen -r worker_並通過使用screen -list列出正在運行的工作人員來重新附加到屏幕。
欲瞭解更多信息本指南可能會有所幫助: http://www.kuro5hin.org/story/2004/3/9/16838/14935
相關搜索:
對於生產服務器,我通常會推薦使用正常的系統啓動腳本,但我一直在運行啓動腳本的屏幕命令多年,沒有任何問題。
貝婁是我們@chaos答案的工作實施了pcntl插件類型的服務器守護程序。處理信號的代碼被刪除,因爲這個腳本通常只有幾毫秒。此外,在代碼中,我們添加了2個函數來保存調用之間的pid:restore_processors_state()和save_processors_state()。我們在那裏使用了redis
,但是您可以決定在文件上使用實現。
我們使用cron每分鐘運行一次該腳本。 Cron檢查是否所有進程都活着。如果不是,它會重新運行它們然後死亡。如果我們想要殺死現有進程,那麼我們只需運行參數kill
:php script.php kill
即可運行此腳本。
非常方便的方式運行工作人員沒有注入腳本到init.d.
<?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();
另請參閱:http://symfony.com/doc/master/components/process.html – 2012-07-06 22:02:15