訊號
- 訊號只是用來通知某程式發生了什麼事件,並不給該程式傳遞任何資料
1.忽略此訊號
大多數訊號都可以使用這種方式進行處理
但有兩種訊號不能忽略,SIGKILL 和 SIGSTOP
SIGKILL 和 SIGSTOP 向核心和超級使用者提供使程式終止的可靠方法
2.捕捉訊號
通知核心在某種訊號發生時,呼叫一個使用者函式,執行希望對事件的處理
3.執行系統預設動作
大多數訊號的系統預設動作是終止該程式
<?php
// 守護程式化
function daemon() {
// 1-1
$pid = pcntl_fork();//
switch ($pid) {
case -1:
die('Create failed');
break;
case 0:
// Child
// 2.
if ( ($sid = posix_setsid()) <= 0 ) {
die("Set sid failed.\n");
}
// 3.
if (chdir('/') === false) {
die("Change dir failed.\n");
}
// 4.
umask(0);
// 5.
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
break;
default:
// Parent
// 1-2
exit;
break;
}
}
// Fork一個程式
function fork() {
global $childs;
$pid = pcntl_fork();
switch ($pid) {
case -1:
die('Create failed');
break;
case 0:
// Child
pcntl_signal(SIGTERM, SIG_IGN, false);//安裝一個訊號 忽略kill 殺死程式 導致重新執行下面的任務
while (true) {
sleep(5);
}
break;
default:
// Parent
$childs[$pid] = $pid;
break;
}
}
$cmd = ( $_SERVER['argv'][1] ?? '' );
switch ($cmd) {
case 'start':
// 啟動
if (file_exists('/tmp/master_pid')) {//如果存在了主程式的程式id
die("Already running\n");
}
break;
case 'reload':
// 過載子程式
$master_pid = file_get_contents('/tmp/master_pid');//得到主程式的程式id
exec("ps --ppid {$master_pid} | awk '/[0-9]/{print $1}' | xargs", $output, $status);//shell 指令碼得到這個主程式下的所有的子程式的id
if ($status == 0) {
$childs = explode(' ', current($output));
foreach ($childs as $id) {
posix_kill($id, SIGKILL);//迴圈殺死子程式
}
}
exit;
break;
case 'stop':
// 停止所有
$master_pid = file_get_contents('/tmp/master_pid');//得到主程式的程式id
exec("ps --ppid {$master_pid} | awk '/[0-9]/{print $1}' | xargs", $output, $status);//shell 指令碼得到這個主程式下的所有的子程式的id
posix_kill($master_pid, SIGKILL);//殺死主程式
if ($status == 0) {
$childs = explode(' ', current($output));
foreach ($childs as $id) {
posix_kill($id, SIGKILL);//迴圈殺死子程式
}
}
while (true) {
if (! posix_kill($master_pid, 0)) {
@unlink('/tmp/master_pid');//把主程式的程式id 檔案給殺死
break;
}
}
exit;
break;
default:
die("Please enter command\n");
break;
}
// 守護程式
daemon();
$childs = [];
$count = 3;
// 儲存主程式pid
$master_pid = posix_getpid();
file_put_contents('/tmp/master_pid', $master_pid);
// Fork子程式
for ($i = 0; $i < $count; $i++) {
fork();
}
// 監控子程式
while ( count($childs) ) {
if ( ($exit_id = pcntl_wait($status)) > 0 ) {
unset($childs[$exit_id]);
}
if ( count($childs) < 3 ) {
fork();
}
}