symfony コンポーネント Process ( http://symfony.com/doc/current/components/process.html )を使用して、一連のバックグラウンド プロセスを管理する小さなスクリプトを作成しようとしています。
これが正しく機能するために、メインプロセス、主に SIGINT ( ctrl + c) に送信されるシグナルを処理したいと考えています。
メイン プロセスがこのシグナルを受け取ると、新しいプロセスの開始を停止し、現在のすべてのプロセスが終了するのを待ってから終了する必要があります。
メインプロセスでシグナルを正常にキャッチしましたが、問題は、子プロセスもシグナルを取得してすぐに終了することです。
この動作を変更したり、この信号を中断したりする方法はありますか?
これは、動作を示すためのサンプル スクリプトです。
#!/usr/bin/env php
<?php
require_once __DIR__ . "/vendor/autoload.php";
use Symfony\Component\Process\Process;
$process = new Process("sleep 10");
$process->start();
$exitHandler = function ($signo) use ($process) {
print "Got signal {$signo}\n";
while ($process->isRunning()) {
usleep(10000);
}
exit;
};
pcntl_signal(SIGINT, $exitHandler);
while (true) {
pcntl_signal_dispatch();
sleep(1);
}
このスクリプトを実行し、シグナルを送信すると (ctrl + c を押す)、親プロセスと子プロセスがすぐに停止します)。
while ループを isRunning 呼び出しに置き換え、スリープをプロセスの wait-method の呼び出しに置き換えると、RuntimeException が発生します。
より手動のアプローチを取り、exec でビルドされた phps を使用して子プロセスを実行すると、必要な動作が得られます。
#!/usr/bin/env php
<?php
require_once __DIR__ . "/vendor/autoload.php";
exec(sprintf("%s > %s 2>&1 & echo $! >> %s", "sleep 10", "/dev/null", "/tmp/testscript.pid"));
$exitHandler = function ($signo) {
print "Got signal {$signo}\n";
$pid = file_get_contents("/tmp/testscript.pid");
while (isRunning($pid)) {
usleep(10000);
}
exit;
};
pcntl_signal(SIGINT, $exitHandler);
while (true) {
pcntl_signal_dispatch();
sleep(1);
}
function isRunning($pid){
try{
$result = shell_exec(sprintf("ps %d", $pid));
if( count(preg_split("/\n/", $result)) > 2){
return true;
}
}catch(Exception $e){}
return false;
}
この場合、シグナルを送信すると、メイン プロセスはその子プロセスが終了するまで待機します。
symfony プロセス コンポーネントで動作を取得する方法はありますか?