php高性能网络编程之管道(1) | php 技术论坛-大发黄金版app下载
管道是什么?
管道(pipe)是一种用于连接两个或多个命令的标准工具,使得前一个命令的输出成为后一个命令的输入。虽然管道这个词对一些人来说可能有些陌生,但在日常编程工作中,尤其是使用linux或unix
shell时,管道是非常常见的。
例如,考虑下面这条命令:
echo "hello" | grep "he"
为了更好地理解,我们可以将其重写为:
(echo "hello") | (grep "he")
# 这里,“echo” 和 “grep” 都是可执行的二进制程序。
# | 符号表示管道,它的作用是将前一个命令的输出作为后一个命令的输入。
指令的执行流程
- 创建子进程:shell创建一个新的子进程来执行 echo “hello” 命令;
- 标准输出:二进制文件
echo
会根据接收到的参数”hello”将字符串 “hello” 写入其标准输出, 这就是echo
要做的事; - 管道传递:shell通过管道将 “hello” 从
echo
的标准输出传递到grep
的标准输入; - grep处理:grep 从管道读取 “hello” 并检查是否包含模式 “he”;
- 输出结果:如果匹配成功,grep 将匹配的结果渲染并输出到标准输出;
大多数 shell(如 bash 或 zsh)都支持管道功能。通过管道,用户可以构建复杂的命令序列来完成特定任务;
它与php有何关系?
现在我们来看一个具体的示例:
(echo ") | (php)
根据上面的执行流程,我们可以将这个命令分解为以下步骤:
创建子进程:shell 创建一个新的子进程来执行 echo “
脚本输出:echo 命令将 php 脚本输出到标准输出。
管道传递:shell 使用管道将这个 php 脚本作为输入传递给 php 命令。
php解析:php 解释器读取管道中的 php 脚本,并执行其中的代码。
输出结果:由于 php 脚本中包含了 echo ‘hello,world’;,所以 php 解释器会输出 “hello,world”。
接下来,我们尝试一个不同的示例:
(echo ") | (php -v)
结果分析:
在这种情况下
php -v
输出 php 版本信息而不是执行脚本。
这是因为php -v
是一个整体命令,用于显示 php 的版本信息。
为什么不执行管道中的指令呢?
事实上这不是必然性的,这只是二进制文件php
的决定
当php命令带有参数时,它不会从标准输入读取任何内容,而是直接按照另一种自行决定的方式执行
php中的管道
php允许使用proc_open
函数来创建一个进程控制块,这个进程控制块拥有独立的输入输出流,可以用来实现管道的功能
//$descriptorspec的为固定结构,这是它的设计者指明的
$descriptorspec = [
0 => ['pipe', 'r'], // 标准输入
1 => ['pipe', 'w'], // 标准输出
2 => ['pipe', 'w'], // 标准错误
];
$process = proc_open('/bin/sh', $descriptorspec, $pipes);
if (is_resource($process)) {
fwrite($pipes[0], 'echo "hello,world"');
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
proc_close($process);
}
通过上述简单例子我们可以直接使用php来实现管道的功能,直接模拟一个终端会话,甚至能自己实现渲染并实现一个类似于zsh一样的shell管理工具
大胆点想我们是不是可能直接访问php二进制文件打开一个php进程,然后通过管道的方式来执行php脚本呢?
php中打开php进程
//$descriptorspec的为固定结构,这是它的设计者指明的
$descriptorspec = [
0 => ['pipe', 'r'], // 标准输入
1 => ['pipe', 'w'], // 标准输出
2 => ['pipe', 'w'], // 标准错误
];
$process = proc_open(php_binary, $descriptorspec, $pipes);
if (is_resource($process)) {
fwrite($pipes[0], file_get_contents('test.php'));
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
}
是的,上面的代码会如我们所想的那样,打开一个php进程,并通过管道的方式执行test.php内的脚本代码
是不是有种发现新大陆的感觉:掌握了这个方法是不是可以离开shell_exec
这个函数了呢?
没错,它完全可以做到, 但如果需要自己来管理输入输出流,这在复杂的管道操作中会变得非常麻烦
相关项目
相关文章
原创声明: 原创(转载请保留文章主体)
本作品采用《cc 协议》,转载必须注明作者和本文链接
推荐文章: