/**
* 创建所需的 proc_open 的描述符
* @return array
*/
private function getDescriptors()
{// 获取描述符
if ('\\' === DS) {// 如果是windows
$this->processPipes = WindowsPipes::create($this, $this->input);// 创建 windows 管道系统
} else {
$this->processPipes = UnixPipes::create($this, $this->input);// 创建 unix 管道系统
}
$descriptors = $this->processPipes->getDescriptors($this->outputDisabled);// 获取描述信息
if (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
$descriptors = array_merge($descriptors, [['pipe', 'w']]);// 如果满足上述 的全部条件
$this->commandline = '(' . $this->commandline . ') 3>/dev/null; code=$?; echo $code >&3; exit $code';
}// 进行 命令行设置
return $descriptors;// 返回描述,并且 执行 命令行工具
}
/**
* 建立 wait () 使用的回调。
* @param callable|null $callback
* @return callable
*/
protected function buildCallback($callback)
{// wait 使用回调 建立 回调函数
$out = self::OUT;// 输出
$callback = function ($type, $data) use ($callback, $out) {// 回调函数
// 闭包 用法
// 很经典的一个用法
if ($out == $type) {// 如果 可以输出
$this->addOutput($data);
} else {// 否则添加错误数据
$this->addErrorOutput($data);
}
if (null !== $callback) {// 回调
call_user_func($callback, $type, $data);
}
};
return $callback;// 返回一个回调函数
}
/**
* 更新状态
* @param bool $blocking
*/
protected function updateStatus($blocking)
{// 更新状态
if (self::STATUS_STARTED !== $this->status) {// 当前状态不是启动状态 工作状态
return;
}// 如果状态不对,直接返回
$this->processInformation = proc_get_status($this->process);// 获取进程状态信息
$this->captureExitCode();// 获取执行代码
$this->readPipes($blocking, '\\' === DS ? !$this->processInformation['running'] : true);// 读取管道信息
if (!$this->processInformation['running']) {//如果当前信息 没有运行中
$this->close();// 关闭
}
}// 在经历了3次外包之后,基本上就 没有 那个东西了是可以被看见的了
/**
* 是否开启 '--enable-sigchild'
* @return bool
*/
protected function isSigchildEnabled()
{
if (null !== self::$sigchild) {// 返回默认状态
return self::$sigchild;
}
if (!function_exists('phpinfo')) {// 如果没有 phpinfo 这个函数
return self::$sigchild = false;
}
ob_start();// 开启缓存
phpinfo(INFO_GENERAL);// 信息 启动
return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');// 很神奇的判断方式
}
/**
* 验证是否超时
* @param int|float|null $timeout
* @return float|null
*/
private function validateTimeout($timeout)
{// 验证是否超时
$timeout = (float)$timeout;// 设置时间
if (0.0 === $timeout) {// 如果 为0
$timeout = null;// 时间为空
} elseif ($timeout < 0) {// 如果时间 小于0 异常
throw new \InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
}
return $timeout;
}
/**
* 读取pipes
* @param bool $blocking
* @param bool $close
*/
private function readPipes($blocking, $close)
{
$result = $this->processPipes->readAndWrite($blocking, $close);// 读写数据
$callback = $this->callback;// 回调
foreach ($result as $type => $data) {// 对返回数据进行 处理
if (3 == $type) {// 数据类型,返回错误代码
$this->fallbackExitcode = (int)$data;
} else {
$callback($type === self::STDOUT ? self::OUT : self::ERR, $data);
}
}
}
/**
* 捕获退出码
*/
private function captureExitCode()
{// 捕获退出码
if (isset($this->processInformation['exitcode']) && -1 != $this->processInformation['exitcode']) {
$this->exitcode = $this->processInformation['exitcode'];
}
}// 将系统运行命令的退出码,放到系统配置项里面
/**
* 关闭资源
* @return int 退出码
*/
private function close()
{// 执行 资源 关闭
$this->processPipes->close();// 关闭资源
if (is_resource($this->process)) {// 是否有资源
$exitcode = proc_close($this->process);// 执行进程关闭函数
} else {
$exitcode = -1;// 否则 退出码为1
}
$this->exitcode = -1 !== $exitcode ? $exitcode : (null !== $this->exitcode ? $this->exitcode : -1);
$this->status = self::STATUS_TERMINATED;
// 退出码
// 当前状态
if (-1 === $this->exitcode && null !== $this->fallbackExitcode) {
$this->exitcode = $this->fallbackExitcode;
} elseif (-1 === $this->exitcode && $this->processInformation['signaled']
&& 0 < $this->processInformation['termsig']
) {
$this->exitcode = 128 + $this->processInformation['termsig'];
}// 是否正常终止,还是异常中断
return $this->exitcode;// 返回退出码
}
/**
* 重置数据
*/
private function resetProcessData()
{// 重置全部数据
$this->starttime = null;
$this->callback = null;
$this->exitcode = null;
$this->fallbackExitcode = null;
$this->processInformation = null;
$this->stdout = null;
$this->stderr = null;
$this->process = null;
$this->latestSignal = null;
$this->status = self::STATUS_READY;
$this->incrementalOutputOffset = 0;
$this->incrementalErrorOutputOffset = 0;
}
/**
* 将一个 POSIX 信号发送到进程中。
* @param int $signal
* @param bool $throwException
* @return bool
*/
private function doSignal($signal, $throwException)
{// 信号发送到进程中
if (!$this->isRunning()) {
if ($throwException) {// 抛出异常
throw new \LogicException('Can not send signal on a non running process.');
}
return false;
}
if ($this->isSigchildEnabled()) {
if ($throwException) {
throw new \RuntimeException('This PHP has been compiled with --enable-sigchild. The process can not be signaled.');
}// 是否 子进程
return false;
}
if (true !== @proc_terminate($this->process, $signal)) {
if ($throwException) {
throw new \RuntimeException(sprintf('Error while sending signal `%s`.', $signal));
}// 进程 中断
return false;
}
$this->latestSignal = $signal;
// 最终 信号
return true;// 返回值
}
/**
* 确保进程已经开启
* @param string $functionName
*/
private function requireProcessIsStarted($functionName)
{// 确认进程开启
if (!$this->isStarted()) {
throw new \LogicException(sprintf('Process must be started before calling %s.', $functionName));
}
}
/**
* 确保进程已经终止
* @param string $functionName
*/
private function requireProcessIsTerminated($functionName)
{// 确认进程关闭
if (!$this->isTerminated()) {
throw new \LogicException(sprintf('Process must be terminated before calling %s.', $functionName));
}
}
}
[李景山php]每天TP5-20170126|thinkphp5-Process.php-8
最新推荐文章于 2024-09-20 06:12:45 发布