Starts the process and returns after sending the STDIN.
This method blocks until all STDIN data is sent to the process then it returns while the process runs in the background.
The termination of the process can be awaited with wait().
The callback receives the type of output (out or err) and some bytes from the output in real-time while writing the standard input to the process. It allows to have feedback from the independent process during execution. If there is no callback passed, the wait() method can be called with true as a second parameter then the callback will get all data occurred in (and since) the start call.
callback|null $callback A PHP callback to run whenever there is some: output available on STDOUT or STDERR
RuntimeException When process can't be launch or is stopped
RuntimeException When process is already running
public function start($callback = null) {
if ($this
->isRunning()) {
throw new RuntimeException('Process is already running');
}
$this->starttime = microtime(true);
$this->stdout = '';
$this->stderr = '';
$this->incrementalOutputOffset = 0;
$this->incrementalErrorOutputOffset = 0;
$callback = $this
->buildCallback($callback);
$descriptors = $this
->getDescriptors();
$commandline = $this->commandline;
if (defined('PHP_WINDOWS_VERSION_BUILD') && $this->enhanceWindowsCompatibility) {
$commandline = 'cmd /V:ON /E:ON /C "' . $commandline . '"';
if (!isset($this->options['bypass_shell'])) {
$this->options['bypass_shell'] = true;
}
}
$this->process = proc_open($commandline, $descriptors, $this->pipes, $this->cwd, $this->env, $this->options);
if (!is_resource($this->process)) {
throw new RuntimeException('Unable to launch a new process.');
}
$this->status = self::STATUS_STARTED;
foreach ($this->pipes as $pipe) {
stream_set_blocking($pipe, false);
}
if ($this->tty) {
$this->status = self::STATUS_TERMINATED;
return;
}
if (null === $this->stdin) {
fclose($this->pipes[0]);
unset($this->pipes[0]);
return;
}
$writePipes = array(
$this->pipes[0],
);
unset($this->pipes[0]);
$stdinLen = strlen($this->stdin);
$stdinOffset = 0;
while ($writePipes) {
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
$this
->processFileHandles($callback);
}
$r = $this->pipes;
$w = $writePipes;
$e = null;
$n = @stream_select($r, $w, $e, 0, ceil(static::TIMEOUT_PRECISION * 1000000.0));
if (false === $n) {
break;
}
if ($n === 0) {
proc_terminate($this->process);
throw new RuntimeException('The process timed out.');
}
if ($w) {
$written = fwrite($writePipes[0], (string) substr($this->stdin, $stdinOffset), 8192);
if (false !== $written) {
$stdinOffset += $written;
}
if ($stdinOffset >= $stdinLen) {
fclose($writePipes[0]);
$writePipes = null;
}
}
foreach ($r as $pipe) {
$type = array_search($pipe, $this->pipes);
$data = fread($pipe, 8192);
if (strlen($data) > 0) {
call_user_func($callback, $type == 1 ? self::OUT : self::ERR, $data);
}
if (false === $data || feof($pipe)) {
fclose($pipe);
unset($this->pipes[$type]);
}
}
$this
->checkTimeout();
}
$this
->updateStatus();
}