proc_open のコードがカオスになってる
proc_open でプロセスを起動して実行できる。
でも、あれこれ手順が煩雑でわかりにくい。
コールバックを使って整理する
こういうときは、関数の引数に関数を取れば整理されるはず。
<?php function 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);
パイプと最大実行時間
パイプと最大時間をうまく使えば、プロセス起動をうまく使ってゾンビを作らずに済むし、実行時間を気にず、細切れにジョブを実行できる。