|
|
@@ -230,7 +230,7 @@ class Worker
|
|
|
* @var bool
|
|
|
*/
|
|
|
protected $_pauseAccept = true;
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
* Is worker stopping ?
|
|
|
* @var bool
|
|
|
@@ -447,18 +447,18 @@ class Worker
|
|
|
* @var string
|
|
|
*/
|
|
|
protected static $_gracefulStop = false;
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
- * output stream
|
|
|
+ * standard output stream
|
|
|
* @var resource
|
|
|
*/
|
|
|
protected static $outputStream = null;
|
|
|
|
|
|
/**
|
|
|
- * if output stream support decorated
|
|
|
+ * if $outputStream support decorated
|
|
|
* @var bool
|
|
|
*/
|
|
|
- protected static $outputDecorated = false;
|
|
|
+ protected static $outputDecorated = null;
|
|
|
|
|
|
/**
|
|
|
* Run all worker instances.
|
|
|
@@ -664,7 +664,6 @@ class Worker
|
|
|
static::$_maxUserNameLength + 2 - strlen('user')). "<w>worker</w>". str_pad('',
|
|
|
static::$_maxWorkerNameLength + 2 - strlen('worker')). "<w>listen</w>". str_pad('',
|
|
|
static::$_maxSocketNameLength + 2 - strlen('listen')). "<w>processes</w> <w>status</w>\n");
|
|
|
-
|
|
|
foreach (static::$_workers as $worker) {
|
|
|
static::safeEcho(str_pad($worker->user, static::$_maxUserNameLength + 2). str_pad($worker->name,
|
|
|
static::$_maxWorkerNameLength + 2). str_pad($worker->getSocketName(),
|
|
|
@@ -701,7 +700,9 @@ class Worker
|
|
|
);
|
|
|
$usage = "Usage: php yourfile <command> [mode]\nCommands: \nstart\t\tStart worker in DEBUG mode.\n\t\tUse mode -d to start in DAEMON mode.\nstop\t\tStop worker.\n\t\tUse mode -g to stop gracefully.\nrestart\t\tRestart workers.\n\t\tUse mode -d to start in DAEMON mode.\n\t\tUse mode -g to stop gracefully.\nreload\t\tReload codes.\n\t\tUse mode -g to reload gracefully.\nstatus\t\tGet worker status.\n\t\tUse mode -d to show live status.\nconnections\tGet worker connections.\n";
|
|
|
if (!isset($argv[1]) || !in_array($argv[1], $available_commands)) {
|
|
|
- if (isset($argv[1])) static::safeEcho('Unknown command: ' . $argv[1] . "\n");
|
|
|
+ if (isset($argv[1])) {
|
|
|
+ static::safeEcho('Unknown command: ' . $argv[1] . "\n");
|
|
|
+ }
|
|
|
exit($usage);
|
|
|
}
|
|
|
|
|
|
@@ -752,14 +753,14 @@ class Worker
|
|
|
sleep(1);
|
|
|
// Clear terminal.
|
|
|
if ($command2 === '-d') {
|
|
|
- static::safeEcho("\33[H\33[2J\33(B\33[m", true);
|
|
|
+ static::safeEcho("\33[H\33[2J\33(B\33[m", true);
|
|
|
}
|
|
|
// Echo status data.
|
|
|
- static::safeEcho(static::formatStatusData());
|
|
|
+ self::safeEcho(static::formatStatusData());
|
|
|
if ($command2 !== '-d') {
|
|
|
exit(0);
|
|
|
}
|
|
|
- static::safeEcho("\nPress Ctrl+C to quit.\n\n");
|
|
|
+ self::safeEcho("\nPress Ctrl+C to quit.\n\n");
|
|
|
}
|
|
|
exit(0);
|
|
|
case 'connections':
|
|
|
@@ -822,7 +823,9 @@ class Worker
|
|
|
posix_kill($master_pid, $sig);
|
|
|
exit;
|
|
|
default :
|
|
|
- if (isset($command)) static::safeEcho('Unknown command: ' . $command . "\n");
|
|
|
+ if (isset($command)) {
|
|
|
+ static::safeEcho('Unknown command: ' . $command . "\n");
|
|
|
+ }
|
|
|
exit($usage);
|
|
|
}
|
|
|
}
|
|
|
@@ -846,14 +849,14 @@ class Worker
|
|
|
unset($info[0]);
|
|
|
$data_waiting_sort = array();
|
|
|
$read_process_status = false;
|
|
|
- $total_requests = 0;
|
|
|
- $total_qps = 0;
|
|
|
- $total_connections = 0;
|
|
|
- $total_fails = 0;
|
|
|
- $total_memory = 0;
|
|
|
- $total_timers = 0;
|
|
|
- $maxLen1 = static::$_maxSocketNameLength;
|
|
|
- $maxLen2 = static::$_maxWorkerNameLength;
|
|
|
+ $total_requests = 0;
|
|
|
+ $total_qps = 0;
|
|
|
+ $total_connections = 0;
|
|
|
+ $total_fails = 0;
|
|
|
+ $total_memory = 0;
|
|
|
+ $total_timers = 0;
|
|
|
+ $maxLen1 = static::$_maxSocketNameLength;
|
|
|
+ $maxLen2 = static::$_maxWorkerNameLength;
|
|
|
foreach($info as $key => $value) {
|
|
|
if (!$read_process_status) {
|
|
|
$status_str .= $value . "\n";
|
|
|
@@ -866,14 +869,14 @@ class Worker
|
|
|
$pid = $pid_math[0];
|
|
|
$data_waiting_sort[$pid] = $value;
|
|
|
if(preg_match('/^\S+?\s+?(\S+?)\s+?(\S+?)\s+?(\S+?)\s+?(\S+?)\s+?(\S+?)\s+?(\S+?)\s+?(\S+?)\s+?/', $value, $match)) {
|
|
|
- $total_memory += intval(str_ireplace('M','',$match[1]));
|
|
|
- $maxLen1 = max($maxLen1,strlen($match[2]));
|
|
|
- $maxLen2 = max($maxLen2,strlen($match[3]));
|
|
|
- $total_connections += intval($match[4]);
|
|
|
- $total_fails += intval($match[5]);
|
|
|
- $total_timers += intval($match[6]);
|
|
|
+ $total_memory += intval(str_ireplace('M','',$match[1]));
|
|
|
+ $maxLen1 = max($maxLen1,strlen($match[2]));
|
|
|
+ $maxLen2 = max($maxLen2,strlen($match[3]));
|
|
|
+ $total_connections += intval($match[4]);
|
|
|
+ $total_fails += intval($match[5]);
|
|
|
+ $total_timers += intval($match[6]);
|
|
|
$current_total_request[$pid] = $match[7];
|
|
|
- $total_requests += intval($match[7]);
|
|
|
+ $total_requests += intval($match[7]);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -891,18 +894,18 @@ class Worker
|
|
|
$qps = 0;
|
|
|
} else {
|
|
|
$qps = $current_total_request[$pid] - $total_request_cache[$pid];
|
|
|
- $total_qps += $qps;
|
|
|
+ $total_qps += $qps;
|
|
|
}
|
|
|
$status_str .= $data_waiting_sort[$pid]. " " . str_pad($qps, 6) ." [idle]\n";
|
|
|
}
|
|
|
$total_request_cache = $current_total_request;
|
|
|
- $status_str .= "----------------------------------------------PROCESS STATUS---------------------------------------------------\n";
|
|
|
- $status_str .= "Summary\t" . str_pad($total_memory.'M', 7) . " "
|
|
|
- . str_pad('-', $maxLen1) . " "
|
|
|
- . str_pad('-', $maxLen2) . " "
|
|
|
- . str_pad($total_connections, 11) . " " . str_pad($total_fails, 9) . " "
|
|
|
- . str_pad($total_timers, 7) . " " . str_pad($total_requests, 13) . " "
|
|
|
- . str_pad($total_qps,6)." [Summary] \n";
|
|
|
+ $status_str .= "----------------------------------------------PROCESS STATUS---------------------------------------------------\n";
|
|
|
+ $status_str .= "Summary\t" . str_pad($total_memory.'M', 7) . " "
|
|
|
+ . str_pad('-', $maxLen1) . " "
|
|
|
+ . str_pad('-', $maxLen2) . " "
|
|
|
+ . str_pad($total_connections, 11) . " " . str_pad($total_fails, 9) . " "
|
|
|
+ . str_pad($total_timers, 7) . " " . str_pad($total_requests, 13) . " "
|
|
|
+ . str_pad($total_qps,6)." [Summary] \n";
|
|
|
return $status_str;
|
|
|
}
|
|
|
|
|
|
@@ -1054,6 +1057,7 @@ class Worker
|
|
|
@fclose(STDERR);
|
|
|
$STDOUT = fopen(static::$stdoutFile, "a");
|
|
|
$STDERR = fopen(static::$stdoutFile, "a");
|
|
|
+ static::$outputStream = static::$outputDecorated = null;
|
|
|
} else {
|
|
|
throw new Exception('can not open stdoutFile ' . static::$stdoutFile);
|
|
|
}
|
|
|
@@ -1197,7 +1201,7 @@ class Worker
|
|
|
$worker = current(static::$_workers);
|
|
|
|
|
|
// Display UI.
|
|
|
- static::safeEcho(str_pad($worker->name, 21) . str_pad($worker->getSocketName(), 36) . str_pad($worker->count, 10) . "[ok]\n");
|
|
|
+ static::safeEcho(str_pad($worker->name, 21) . str_pad($worker->getSocketName(), 36) . str_pad($worker->count, 10) . "[ok]\n");
|
|
|
$worker->listen();
|
|
|
$worker->run();
|
|
|
exit("@@@child exit@@@\r\n");
|
|
|
@@ -1259,7 +1263,7 @@ class Worker
|
|
|
}
|
|
|
$timer_id = Timer::add(1, function()use($std_handler)
|
|
|
{
|
|
|
- static::safeEcho(fread($std_handler, 65535));
|
|
|
+ self::safeEcho(fread($std_handler, 65535));
|
|
|
});
|
|
|
|
|
|
// 保存子进程句柄
|
|
|
@@ -1282,7 +1286,7 @@ class Worker
|
|
|
{
|
|
|
if(!$status['running'])
|
|
|
{
|
|
|
- static::safeEcho("process $start_file terminated and try to restart\n");
|
|
|
+ static::safeEcho("process $start_file terminated and try to restart\n");
|
|
|
Timer::del($timer_id);
|
|
|
@proc_close($process);
|
|
|
static::forkOneWorkerForWindows($start_file);
|
|
|
@@ -1428,7 +1432,6 @@ class Worker
|
|
|
*/
|
|
|
protected static function monitorWorkersForLinux()
|
|
|
{
|
|
|
- $checkTimes = 0;
|
|
|
static::$_status = static::STATUS_RUNNING;
|
|
|
while (1) {
|
|
|
// Calls signal handlers for pending signals.
|
|
|
@@ -1440,8 +1443,6 @@ class Worker
|
|
|
pcntl_signal_dispatch();
|
|
|
// If a child has already exited.
|
|
|
if ($pid > 0) {
|
|
|
- // reset $checkTimes
|
|
|
- $checkTimes = 0;
|
|
|
// Find out witch worker process exited.
|
|
|
foreach (static::$_pidMap as $worker_id => $worker_pid_array) {
|
|
|
if (isset($worker_pid_array[$pid])) {
|
|
|
@@ -1482,28 +1483,9 @@ class Worker
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
-
|
|
|
// If shutdown state and all child processes exited then master process exit.
|
|
|
- if (static::$_status === static::STATUS_SHUTDOWN) {
|
|
|
- $pids = static::getAllWorkerPids();
|
|
|
- if (!$pids) {
|
|
|
- static::exitAndClearAll();
|
|
|
- } elseif ($checkTimes > 500) {
|
|
|
- // forced stop if all pid exited
|
|
|
- $allExited = true;
|
|
|
- foreach ($pids as $pid) {
|
|
|
- if (posix_kill($pid, 0)) {
|
|
|
- $allExited = false;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if ($allExited) {
|
|
|
- static::exitAndClearAll();
|
|
|
- } else {
|
|
|
- $checkTimes = 0;
|
|
|
- }
|
|
|
- }
|
|
|
- $checkTimes++;
|
|
|
+ if (static::$_status === static::STATUS_SHUTDOWN && !static::getAllWorkerPids()) {
|
|
|
+ static::exitAndClearAll();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -1658,6 +1640,16 @@ class Worker
|
|
|
Timer::add(static::KILL_WORKER_TIMER_TIME, 'posix_kill', array($worker_pid, SIGKILL), false);
|
|
|
}
|
|
|
}
|
|
|
+ // check if child processes is really running
|
|
|
+ Timer::add(1, function() {
|
|
|
+ foreach (static::$_pidMap as $worker_id => $worker_pid_array) {
|
|
|
+ foreach ($worker_pid_array as $pid => $worker_pid) {
|
|
|
+ if (!posix_kill($pid, 0)) {
|
|
|
+ unset(static::$_pidMap[$worker_id][$pid]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
// Remove statistics file.
|
|
|
if (is_file(static::$_statisticsFile)) {
|
|
|
@unlink(static::$_statisticsFile);
|
|
|
@@ -1946,6 +1938,9 @@ class Worker
|
|
|
public static function safeEcho($msg, $decorated = false)
|
|
|
{
|
|
|
$stream = static::getOutputStream();
|
|
|
+ if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
if (!$decorated) {
|
|
|
$line = $white = $green = $end = '';
|
|
|
if (static::$outputDecorated) {
|
|
|
@@ -1954,9 +1949,7 @@ class Worker
|
|
|
$green = "\033[32;40m";
|
|
|
$end = "\033[0m";
|
|
|
}
|
|
|
- $msg = str_replace('<n>', $line, $msg);
|
|
|
- $msg = str_replace('<w>', $white, $msg);
|
|
|
- $msg = str_replace('<g>', $green, $msg);
|
|
|
+ $msg = str_replace(['<n>', '<w>', '<g>'], [$line, $white, $green], $msg);
|
|
|
$msg = str_replace(['</n>', '</w>', '</g>'], $end, $msg);
|
|
|
} elseif (!static::$outputDecorated) {
|
|
|
return;
|
|
|
@@ -1980,10 +1973,10 @@ class Worker
|
|
|
}
|
|
|
$stat = fstat($stream);
|
|
|
if (($stat['mode'] & 0170000) === 0100000) {
|
|
|
- // output to file
|
|
|
+ // file
|
|
|
static::$outputDecorated = false;
|
|
|
} elseif (false !== getenv('BABUN_HOME')) {
|
|
|
- // win Babun
|
|
|
+ // Babun
|
|
|
static::$outputDecorated = true;
|
|
|
} elseif (static::$_OS === OS_TYPE_LINUX) {
|
|
|
// linux
|
|
|
@@ -1991,9 +1984,9 @@ class Worker
|
|
|
} else {
|
|
|
// window
|
|
|
static::$outputDecorated = '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD
|
|
|
- || false !== getenv('ANSICON')
|
|
|
- || 'ON' === getenv('ConEmuANSI')
|
|
|
- || stripos(getenv('TERM'), 'xterm') === 0;
|
|
|
+ || false !== getenv('ANSICON')
|
|
|
+ || 'ON' === getenv('ConEmuANSI')
|
|
|
+ || stripos(getenv('TERM'), 'xterm') === 0;
|
|
|
}
|
|
|
return static::$outputStream = $stream;
|
|
|
}
|
|
|
@@ -2003,7 +1996,7 @@ class Worker
|
|
|
* doesn't properly convert character-encodings between ASCII to EBCDIC.
|
|
|
* Licensed under the MIT/X11 License (http://opensource.org/licenses/MIT)
|
|
|
* (c) Fabien Potencier <fabien@symfony.com>
|
|
|
- * @see https://github.com/symfony/console/blob/master/Output/ConsoleOutput.php#L121
|
|
|
+ * @see https://github.com/symfony/console/blob/master/Output/ConsoleOutput.php#L131
|
|
|
* @return bool
|
|
|
*/
|
|
|
private static function isRunningOS400()
|