popen pclose 概念
popen(command,mode) 打开一个指向进程的管道,该进程由派生指定的 command 命令执行而产生
command 必需。规定要执行的命令。
mode 必需。规定连接模式 , 可能的值:
r: 只读。
w: 只写 (打开并清空已有文件或创建一个新文件)
pclose(pipe) 关闭由 popen() 打开的管道
pipe 必需。规定由 popen() 打开的管道。
创建类
<?php
/**
* MultiProgress 多进程运行类
* @author Terrence
*/
class MProgress
{
/** error_msg */
const ERROR_MSG = array('status' => 'error', 'message' => 'popen is error');
public function __construct() {
/** 初始化进程池 */
$this->pids = array();
}
/**
* set 在进程池中进行任务设置
* @author Terrence
* @param any 进程名字
* @param string task任务路径
*/
public function set($taskName = '', $taskPath){
if(empty($taskName)){
$this->pids[] = popen($taskPath,'r');
}else{
$this->pids[$taskName] = popen($taskPath,'r');
}
}
/**
* get 获取进程执行结果
* @author Terrence
* @param any $taskName 进程名字
* @param boolean $isJson 返回的结果是否进行解json操作
* @return array 执行结果
*/
public function get($taskName , $isJson = false){
try {
// 读取进程的执行结果 (读取进程中 echo 出来的信息)
$result = fgets($this->pids[$taskName]);
if( $isJson ){
try {
$result = json_decode($result,true);
} catch (Exception $th) {
$result = [];
}
}
} catch (Exception $th) {
$result = $isJson ? [] : '' ;
}
// 杀死进程
pclose($this->pids[$taskName]);
unset($this->pids[$taskName]);
return $result;
}
/**
* getPids 获取当前的进程池里的进程名称
* @author Terrence
*/
public function getPids(){
return array_keys($this->pids);
}
/**
* clear 清空进程池
* @author Terrence
*/
public function clear(){
foreach ($this->pids as &$pid) {
try {
$single = fgets($pid);
pclose($pid);
} catch (Exception $th) { }
}
$this->pids = [];
}
}
使用
/** 创建进程池 */
$pids = new MProgress();
/** 在进程池中创建进程任务 (进程名字为空,以数组下标的方式直接push到进程池) */
/** $taskName 是要执行的任务,一般为命令行操作 */
$pids->set('', $taskName );
/** 遍历进程结果 $result 是进程池的运行结果集,是一个 Array */
$result = array();
foreach (array_reverse( $pids->getPids() ) as $pid) {
$single = $pids->get($pid, true);
/**将结果进行合并 */
if(!empty($single )) $result = array_merge($result, $single);
}
/** 关闭进程 */
$pids->clear();