array('pipe', 'r') // stdin ); if ($capture) { $desc[1] = array('pipe', 'w'); // stdout $desc[2] = array('pipe', 'w'); // stderr } $this->process = proc_open($command, $desc, $pipes, null, $env); // start process if (is_resource($this->process)) { // process start success $this->pid = proc_get_status($this->process)['pid']; $this->stdin = $pipes[0]; if ($capture) { // add capture pipes $this->stdout = $pipes[1]; $this->stderr = $pipes[2]; } } } private function getCapture(mixed $stream): string { // read data from target stream return ($stream == null) ? '' : stream_get_contents($stream); } public function getStdout(): string { // fetch data from stdout pipe return $this->getCapture($this->stdout); } public function getStderr(): string { // fetch data from stderr pipe return $this->getCapture($this->stderr); } public function signal(int $signal): void { // send signal to sub process proc_terminate($this->process, $signal); } public function isAlive(): bool { // whether sub process still running return proc_get_status($this->process)['running']; } public function quit(): int { fclose($this->stdout); // close pipe before proc_close (prevent deadlock) fclose($this->stderr); return proc_close($this->process); // return status code } } $p = new Process(['sleep', '10'], $capture = true); echo "PID -> $p->pid\n"; echo "Alive -> " . ($p->isAlive() ? 'yes' : 'no') . "\n"; echo "Sleep 5s...\n"; sleep(5); echo "Alive -> " . ($p->isAlive() ? 'yes' : 'no') . "\n"; echo "Send kill signal\n"; $p->signal(15); sleep(1); echo "Alive -> " . ($p->isAlive() ? 'yes' : 'no') . "\n"; echo '--------------------------------------------' . PHP_EOL; echo $p->getStdout(); echo '--------------------------------------------' . PHP_EOL; echo $p->getStdout(); echo '--------------------------------------------' . PHP_EOL; echo $p->getStderr(); echo '--------------------------------------------' . PHP_EOL; echo "Return code -> " . $p->quit() . "\n";