proc_open のコードがカオスになってる
proc_open でプロセスを起動して実行できる。
でも、あれこれ手順が煩雑でわかりにくい。
コールバックを使って整理する
こういうときは、関数の引数に関数を取れば整理されるはず。
<?phpfunction process_exec($cmd, $callback_on_finished=null, $callback_on_every_waiting=null, $callback_on_error=null){$callback_on_finished=$callback_on_finished??function(){}; $callback_on_every_waiting=$callback_on_every_waiting??function(){}; $callback_on_error=$callback_on_error??function(){}; $descriptor=[0=>['pipe', 'r'], 1=>['pipe', 'w'], 2=>['pipe', 'w'], ]; // 実行$process=proc_open($cmd, $descriptor, $pipes, sys_get_temp_dir()); do{usleep(1000*1); $stat=proc_get_status($process); $callback_on_every_waiting($stat, $pipes, $process); }while(preg_match('/process/i', get_resource_type($process))&&$stat['running']); if($stat['exitcode']>0){$callback_on_error($stat, $pipes); proc_close($process); return ; }$callback_on_finished($stat, $pipes); proc_close($process); }
実行する側
<?php$start_time=time(); $waiting=function($status , $pipes)use($start_time){if(preg_match('/stream/i', get_resource_type($pipes[0]))){fwrite($pipes[0],"---\nabcd\nefgh\n----\n"); fclose($pipes[0]); usleep(1000*1); }if($start_time+3<time()){posix_kill($status['pid'], SIGKILL); die('force kill'); }}; $on_error=function(){}; $str=''; $finished=function($staus, $pipes)use(&$str){$str=stream_get_contents($pipes[1]); }; $cmd=["cat", ]; process_exec($cmd, $finished, $waiting, $on_error); print($str);
パイプと最大実行時間
パイプと最大時間をうまく使えば、プロセス起動をうまく使ってゾンビを作らずに済むし、実行時間を気にず、細切れにジョブを実行できる。