优雅的玩PHP多进程
proc_open
(PHP 4 >= 4.3.0, PHP 5, PHP 7)
proc_open — 执行一个命令,并且打开用来输入/输出的文件指针。
说明¶
$cmd , array $descriptorspec , array &$pipes [, string$cwd [, array $env [, array $other_options ]]] )类似 popen() 函数, 但是 proc_open() 提供了更加强大的控制程序执行的能力。
参数¶
cmd-
要执行的命令
descriptorspec-
一个索引数组。 数组的键表示描述符,数组元素值表示 PHP 如何将这些描述符传送至子进程。 0 表示标准输入(stdin),1 表示标准输出(stdout),2 表示标准错误(stderr)。
数组中的元素可以是:
- 包含了要传送至进程的管道的描述信息。 第一个元素为描述符类型, 第二个元素是针对该描述符的选项。 有效的类型有:pipe (第二个元素可以是: r 向进程传送该管道的读取端,w 向进程传送该管道的写入端), 以及 file(第二个元素为文件名)。
- 表达一个真实文件描述符的流资源类型 (例如:已打开的文件,一个 socket 端口,
STDIN)。
文件描述符的值不限于 0,1 和 2,你可以使用任何有效的文件描述符 并将其传送至子进程。 这使得你的脚本可以和其他脚本交互操作。 例如,可以通过指定文件描述符将密码以更加安全的方式 传送至诸如 PGP,GPG 和 openssl 程序, 同时也可以很方便的获取这些程序的状态信息。
pipes-
将被置为索引数组, 其中的元素是被执行程序创建的管道对应到 PHP 这一端的文件指针。
cwd-
要执行命令的初始工作目录。 必须是 绝对 路径, 设置此参数为
NULL表示使用默认值(当前 PHP 进程的工作目录)。 env-
要执行的命令所使用的环境变量。 设置此参数为
NULL表示使用和当前 PHP 进程相同的环境变量。 other_options-
你还可以指定一些附加选项。 目前支持的选项包括:
- suppress_errors (仅用于 Windows 平台): 设置为
TRUE表示抑制本函数产生的错误。 - bypass_shell (仅用于 Windows 平台): 设置为
TRUE表示绕过 cmd.exe shell。
- suppress_errors (仅用于 Windows 平台): 设置为
返回值¶
返回表示进程的资源类型, 当使用完毕之后,请调用 proc_close() 函数来关闭此资源。 如果失败,返回 FALSE。
更新日志¶
| 版本 | 说明 |
|---|---|
| 5.2.1 | 为 other_options 参数增加 bypass_shell 选项。 |
范例¶
Example #1 proc_open() 例程
<?php
$descriptorspec = array(
0 => array("pipe", "r"), // 标准输入,子进程从此管道中读取数据
1 => array("pipe", "w"), // 标准输出,子进程向此管道中写入数据
2 => array("file", "/tmp/error-output.txt", "a") // 标准错误,写入到一个文件
);
$cwd = '/tmp';
$env = array('some_option' => 'aeiou');
$process = proc_open('php', $descriptorspec, $pipes, $cwd, $env);
if (is_resource($process)) {
// $pipes 现在看起来是这样的:
// 0 => 可以向子进程标准输入写入的句柄
// 1 => 可以从子进程标准输出读取的句柄
// 错误输出将被追加到文件 /tmp/error-output.txt
fwrite($pipes[0], '<?php print_r($_ENV); ?>');
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
// 切记:在调用 proc_close 之前关闭所有的管道以避免死锁。
$return_value = proc_close($process);
echo "command returned $return_value\n";
}
?>
以上例程的输出类似于:
Array
(
[some_option] => aeiou
[PWD] => /tmp
[SHLVL] => 1
[_] => /usr/local/bin/php
)
command returned 0
注释¶
Note:
Windows 兼容性:超过 2 的描述符也可以作为可继承的句柄传送到子进程。 但是,由于 Windows 的架构并不将文件描述符和底层句柄进行关联, 所以,子进程无法访问这样的句柄。 标准输入,标准输出和标注错误会按照预期工作。
Note:
如果你只需要单向的进程管道, 使用 popen() 函数会更加简单。
<?php
#popen.php
$process = array();
for($i=0;$i<5;$i++)
{
echo $i.' opening ... '.chr(10);
$process[$i] = popen('php '.dirname(__FILE__).'/popen_child.php', 'w');
sleep(1);
} echo 'OK>>'.chr(10);
sleep(3);
for($i=0;$i<5;$i++)
{
$read = fread($process[$i], 64);
echo $read;
pclose($process[$i]);
echo $i.' closed'.chr(10);
sleep(1);
}
<?php
#popen_child.php
while(1)
{
$echo =getmypid() .'->'. date("YmHis").chr(10);
echo $echo ;
system('echo '.$echo.'> logp');
sleep(5);
}
例子1(popen):
<?php
function foo() {
echo date('Y-m-d H:i:s')."\n";
echo shell_exec('php -r \'sleep(1); echo date("Y-m-d H:i:s")." by shell_exec:blocking\n";\''); //阻塞
$pipe1 = popen('php -r \'sleep(2); echo date("Y-m-d H:i:s")." by popen1:non-blocking\n";\'', 'r'); //非阻塞(管道)
$pipe2 = popen('php -r \'sleep(1); echo date("Y-m-d H:i:s")." by popen2:non-blocking\n";\'', 'r'); //非阻塞(管道)
echo date('Y-m-d H:i:s')."\n";
register_shutdown_function(function() use ($pipe1, $pipe2) { //事件驱动(脚本结束事件),异步回调
echo stream_get_contents($pipe1); //输出子进程返回的数据
echo stream_get_contents($pipe2); //输出子进程返回的数据
pclose($pipe1);
pclose($pipe2);
});
}
foo();
//输出
2016-09-11 20:25:30
2016-09-11 20:25:31 by shell_exec:blocking
2016-09-11 20:25:31
2016-09-11 20:25:33 by popen1:non-blocking
2016-09-11 20:25:32 by popen2:non-blocking 例子2(proc_open):
<?php
function foo() {
$proc = proc_open(
//task.php 内容为 $arr = unserialize(stream_get_contents(STDIN)); $arr['time'] = date('Y-m-d H:i:s', $arr['time']); echo serialize($arr);
'/png/php/5.4.45/bin/php /home/eechen/task.php',
array(
0 => array('pipe','r'), //stdin (用fwrite写入数据给管道)
1 => array('pipe','w'), //stdout(用stream_get_contents获取管道输出)
2 => array('pipe','w'), //stderr(用stream_get_contents获取管道输出)
//2 => array('file','/tmp/err.txt','a') //stderr(写入到文件)
),
$pipes, //管道(stdin/stdout/stderr)
'/tmp', //当前PHP进程的工作目录
array('foo' => 'bar') //php.ini 配置 variables_order = "EGPCS" 其中E表示$_ENV,否则$_ENV输出为空
);
//var_dump($pipes); //resource of type (stream)
if(is_resource($proc)) {
//stdin
$stdin = serialize(array('time' => time()));
fwrite($pipes[0], $stdin); //把参数传给脚本task.php
fclose($pipes[0]); //fclose关闭管道后proc_close才能退出子进程,否则会发生死锁
register_shutdown_function(function() use($pipes, $proc) { //事件驱动(脚本结束事件),异步回调
//stdout
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
//stderr
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
//exit code (返回进程的终止状态码,如果发生错则返回-1)
$status = proc_close($proc);
$data = array(
'stdout' => $stdout,
'stderr' => $stderr,
'status' => $status,
);
var_export($data); //echo json_encode($data);
});
}
}
foo();
//输出:
array (
'stdout' => 'a:1:{s:4:"time";s:19:"2016-09-11 21:26:29";}',
'stderr' => '',
'status' => 0,
)
优雅的玩PHP多进程的更多相关文章
- 我也来----xia bi bi 一下----微信小程序
工作刚到一阶段 就看了看微信小程序 自己做了个小dome 主要是为了让我女朋友能够学习做菜! 然而悲催的发现我根本没有App ID 不说快了 直接上图 个人感觉开发起来还是很简单的. 对着AP ...
- zcelib - One cplusplus C++ crossplatform library use for develop server,similar to ACE.
zcelib - One cplusplus C++ crossplatform library use for develop server,similar to ACE.OS适配层,为了适应WIN ...
- Java public 和 private 访问修饰符
何为封装 从事面向对象编程的 Java 程序员,不可能不知道封装,它是面向对象编程的精髓,非常重要. 那什么是封装?字面意思就是把摆在外面的东西包起来. 一句话,封装就是对外隐藏内部细节. 那为何要封 ...
- 优雅地乱玩Linux-6-Chrome端SSH插件
文章最初发表于szhshp的第三边境研究所转载请注明 优雅地乱玩Linux-6-Chrome端SSH插件 最近注册了个AWS,免费一年,一年内可以各种乱玩~ 从自己的电脑连接云主机一般需要SSH这样的 ...
- 玩转nodeJS系列:使用cluster创建nodejs单机多核集群(多进程)
前言: nodejs提供了cluster集群(支持端口共享的多进程),cluster基于child_process,process二次封装,方便我们使用该功能实现单机nodejs的web集群. 1.c ...
- Nginx深入详解之多进程网络模型
一.进程模型 Nginx之所以为广大码农喜爱,除了其高性能外,还有其优雅的系统架构.与Memcached的经典多线程模型相比,Nginx是经典的多进程模型.Nginx启动后以daemon ...
- 【转】 Nginx深入详解之多进程网络模型
[转自]http://blog.chinaunix.net/uid-22312037-id-3974068.html 一.进程模型 Nginx之所以为广大码农喜爱,除了其高性能外,还有其 ...
- 如何优雅地使用 Windows 10 ?
身为一个伪电脑Geek,就算不懂电脑,也要把那些更不懂电脑的人给唬住. 1.入门级别: 当然就是让别人从视觉上感觉你的电脑不一般啦 第一步:桌面要干净,干净到什么程度呢,要像这样 当别人第一眼看到你的 ...
- [小北De编程手记] : Lesson 06 玩转 xUnit.Net 之 定义自己的FactAttribute
xUnit.Net本身提供了标记测试方法的标签Fact和Theory.在前面的文章<Lesson 02 玩转 xUnit.Net 之 基本UnitTest & 数据驱动>中,也对它 ...
随机推荐
- android 数据重构(仿淘宝浏览记录,足迹)
数据结构 ->数据重构 原因 处理这个数据的主要原因是,后台服务器返回的数据格式在ios那边因为其控件可以对数据进行分区显示,可以直接处理,而在android上我们显示控件就是listview, ...
- 【52】java多线程剖析
线程的状态: 线程共有下面4种状态: 新建状态(New): 新创建了一个线程对象,当你用new创建一个线程时,该线程尚未运行. 就绪状态(Runnable): 线程对象创建后,其他线程调用了该对象的s ...
- C语言高级应用---操作linux下V4L2摄像头应用程序
我们都知道,想要驱动linux下的摄像头,其实很简单,照着V4L2的手册一步步来写,很快就可以写出来,但是在写之前我们要注意改变系统的一些配置,使系统支持framebuffer,在dev下产生fb0这 ...
- Ubuntu 14.04 32位 JDK+ADT Bundle+NDK安装
1. 安装JDK tar或GUI解压jdk-8u25-linux-i586.tar.gz 编辑/etc/environment文件 CLASSPATH="/home/zhouwei/jdk1 ...
- Struts2数据传输的背后机制:ValueStack(值栈)
1. 数据传输背后机制:ValueStack(值栈) 在这一切的背后,是因为有了ValueStack(值栈)! ValueStack基础:OGNL 要了解ValueStack,必须先理解OGN ...
- javaScript(6)---流程控制语句
学习要点: 1.语句的定义 2.if 语句 3.switch语句 4.do...while语句 5.while语句 6.for语句 7.for...in语句 8.break和continue语句 9. ...
- Struts2,Spring,Hibernate优缺点
struts框架具有组件的模块化,灵活性和重用性的优点,同时简化了基于MVC的web应用程序的开发. 优点: Struts跟Tomcat.Turbine等诸多Apache项目一样,是开源软件,这是它的 ...
- Nuget发布教程
nuget setApiKey Your-API-Key -Source https://www.nuget.org/api/v2/package nuget spec nuget pack Monk ...
- 一款C++写的tcp性能测试(压力测试)工具
基线终于开发完了,自己写的服务器性能和压力承受能力到底怎么样,在网上没有找到合适的测试工具可以用.于是自己基于MFC写了一款测试工具. 启动界面如下: 设置参数后,运行如下: 运行完界面如下: 源码路 ...
- Android Studio使用手记
1.官方的Tip and Tricks:http://developer.android.com/intl/zh-cn/sdk/installing/studio-tips.html 2.项目的目录树 ...