百科狗-知识改变命运!
--

proc_open() - 执行一个命令,并且打开用来输入/输出的文件指针 - php 执行命令函数

百变鹏仔1年前 (2023-11-21)阅读数 19#技术干货
文章标签进程

proc_open()

(PHP 4 >= 4.3.0, PHP 5, PHP 7)

执行一个命令,并且打开用来输入/输出的文件指针。

说明

proc_open(string $cmd,array $descriptorspec,array &$pipes[,string $cwd=NULL[,array $env=NULL[,array $other_options=NULL]]]): resource

类似popen()函数,但是proc_open()提供了更加强大的控制程序执行的能力。

参数

$cmd

proc_open() - 执行一个命令,并且打开用来输入/输出的文件指针 - php 执行命令函数

要执行的命令

$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.exeshell。

返回值

返回表示进程的资源类型,当使用完毕之后,请调用proc_close()函数来关闭此资源。如果失败,返回FALSE

更新日志

版本说明
5.2.1为$other_options参数增加bypass_shell选项。

范例

Example #1proc_open()例程

以上例程的输出类似于:

Array
(
    [some_option] => aeiou
    [PWD] => /tmp
    [SHLVL] => 1
    [_] => /usr/local/bin/php
)
command returned 0

注释

Note:

Windows 兼容性:超过 2 的描述符也可以作为可继承的句柄传送到子进程。但是,由于 Windows 的架构并不将文件描述符和底层句柄进行关联,所以,子进程无法访问这样的句柄。标准输入,标准输出和标注错误会按照预期工作。Note:

如果你只需要单向的进程管道,使用popen()函数会更加简单。

参见

  • popen() 打开进程文件指针
  • exec() 执行一个外部程序
  • system() 执行外部程序,并且显示输出
  • passthru() 执行外部程序并且显示原始输出
  • stream_select()Runs the equivalent of the select() system call on the given arrays of streams with a timeout specified by tv_sec and tv_usec
  • The执行操作符
The call works as should. No bugs.
But. In most cases you won't able to work with pipes in blocking mode.
When your output pipe (process' input one, $pipes[0]) is blocking, there is a case, when you and the process are blocked on output.
When your input pipe (process' output one, $pipes[1]) is blocking, there is a case, when you and the process both are blocked on own input.
So you should switch pipes into NONBLOCKING mode (stream_set_blocking).
Then, there is a case, when you're not able to read anything (fread($pipes[1],...) == "") either write (fwrite($pipes[0],...) == 0). In this case, you better check the process is alive (proc_get_status) and if it still is - wait for some time (stream_select). The situation is truly asynchronous, the process may be busy working, processing your data.
Using shell effectively makes not possible to know whether the command is exists - proc_open always returns valid resource. You may even write some data into it (into shell, actually). But eventually it will terminate, so check the process status regularly.
I would advice not using mkfifo-pipes, because filesystem fifo-pipe (mkfifo) blocks open/fopen call (!!!) until somebody opens other side (unix-related behavior). In case the pipe is opened not by shell and the command is crashed or is not exists you will be blocked forever.
Note that when you call an external script and retrieve large amounts of data from STDOUT and STDERR, you may need to retrieve from both alternately in non-blocking mode (with appropriate pauses if no data is retrieved), so that your PHP script doesn't lock up. This can happen if you waiting on activity on one pipe while the external script is waiting for you to empty the other, e.g: 
If you have a CLI script that prompts you for a password via STDIN, and you need to run it from PHP, proc_open() can get you there. It's better than doing "echo $password | command.sh", because then your password will be visible in the process list to any user who runs "ps". Alternately you could print the password to a file and use cat: "cat passwordfile.txt | command.sh", but then you've got to manage that file in a secure manner.
If your command will always prompt you for responses in a specific order, then proc_open() is quite simple to use and you don't really have to worry about blocking & non-blocking streams. For instance, to run the "passwd" command:

鹏仔微信 15129739599 鹏仔QQ344225443 鹏仔前端 pjxi.com 共享博客 sharedbk.com

免责声明:我们致力于保护作者版权,注重分享,当前被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理!邮箱:344225443@qq.com)

图片声明:本站部分配图来自网络。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

内容声明:本文中引用的各种信息及资料(包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主体(包括但不限于公司、媒体、协会等机构)的官方网站或公开发表的信息。部分内容参考包括:(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供参考使用,不准确地方联系删除处理!本站为非盈利性质站点,本着为中国教育事业出一份力,发布内容不收取任何费用也不接任何广告!)