PHP exec()与system()与passthru()


312

有什么区别?

每个功能是否有特定情况或原因?如果是,您可以举一些这种情况的例子吗?

PHP.net表示它们用于执行外部程序。请参阅参考资料 从我看到的示例中,我看不出任何明显的区别。

如果我只是运行脚本(bash或python),那么建议我使用哪个功能?


16
还有proc_open()popen(),两者都允许对生成的过程进行更高程度的控制。
基督教徒

Answers:


195

它们的用途略有不同。

  • exec() 用于调用系统命令,并可能自己处理输出。
  • system() 用于执行系统命令并立即显示输出-大概是文本。
  • passthru() 用于执行您希望从中返回原始值的系统命令-大概是二进制文件。

无论如何,我建议您不要使用其中任何一个。它们都产生高度不可移植的代码。


147
有时必须牺牲功能性的可移植性。PHP有些事情做得不好。
弗兰克·克鲁克

30
@Kalium:您能否详细说明一下?仅陈述一些模糊的百分比统计数据并不能说服我。我相信使用系统调用来执行脚本是完全可以的,只要整个应用程序不依赖后端的一堆脚本即可。
09年

46
@Christian izkata@izein:~$ dir -bash: dir: command not found-FreeBSD
Izkata 2012年

5
@OZ_我遇到了不得不做非常昂贵的计算的情况。没有可用的PHP模块。我编写了自己的C程序,并使用passthru()调用了它。有时可移植性可能不如其他事物重要。取决于项目。
Paolo

9
此外,这是一个谬论认为PHP是便携式的,只要你避免execsystempassthru。PHP代码依赖于其运行的环境,并且许多安全性错误是由于未考虑到这一点。这里有一个简单的例子:stackoverflow.com/questions/3003145/...
Pacerier

131

如从http://php.net/ && Chipmunkninja绘制 :

系统()函数

PHP中的系统函数需要一个字符串参数和要执行的命令,以及希望传递给该命令的所有参数。此函数执行指定的命令,并将所有结果文本转储到输出流(Web服务器情况下为HTTP输出,或者如果您将PHP作为命令行工具运行则为控制台)。如果该函数发出文本输出,则该函数的返回是程序输出的最后一行。

EXEC()函数

系统功能非常有用且功能强大,但是最大的问题之一是程序中产生的所有文本都直接进入输出流。在某些情况下,您可能希望格式化结果文本并以某种不同的方式显示它,或者根本不显示它。

为此,PHP中的exec函数已完美适应。与其自动将正在执行的程序所生成的所有文本自动转储到输出流,不如让您有机会将这些文本放入函数的第二个参数返回的数组中:

了shell_exec()函数

到目前为止,我们执行的大多数程序或多或少都是真实程序1。但是,Windows和Unix用户的操作环境实际上比这要丰富得多。Windows用户可以选择使用Windows命令提示符程序cmd.exe,此程序称为命令外壳程序。

中继()函数

PHP提供的一种引人入胜的功能类似于到目前为止所见的功能,即passthru函数。与其他函数一样,该函数执行您告诉它的程序。但是,它随后继续将来自该程序的原始输出立即发送到PHP当前正在使用的输出流(即,Web服务器方案中的HTTP或PHP命令行版本中的Shell)。

proc_open()函数和POPEN() 函数

proc_open()与popen()类似,但提供了对程序执行的更大程度的控制。cmd是要由外壳执行的命令。descriptorspec是一个索引数组,其中的键表示描述符编号,而值表示PHP如何将该描述符传递给子进程。管道将被设置为文件指针的索引数组,该数组与PHP创建的所有管道的末尾相对应。返回值是表示流程的资源;完成后,应使用proc_close()释放它。


6
shell_exec的执行速度比其他方法快。
Dinesh Saini 2014年

29
您应该提到您直接从ChipmunkNinja复制了答案。
TachyonVortex 2014年

7
@TachyonVortex幸运的是他确实逐字复制了答案,因为ChipmunkNinja不再存在。
Phileo99,2014年

2
Wayback

2
那么popen和proc_open呢?
CMCDragonkai 2015年

103

先前的答案似乎都有些混乱或不完整,因此下面是差异表...

+----------------+-----------------+----------------+----------------+
|    Command     | Displays Output | Can Get Output | Gets Exit Code |
+----------------+-----------------+----------------+----------------+
| system()       | Yes (as text)   | Last line only | Yes            |
| passthru()     | Yes (raw)       | No             | Yes            |
| exec()         | No              | Yes (array)    | Yes            |
| shell_exec()   | No              | Yes (string)   | No             |
| backticks (``) | No              | Yes (string)   | No             |
+----------------+-----------------+----------------+----------------+
  • “显示输出”表示它将输出流式传输到浏览器(如果从命令行运行,则将其输出到命令行)。
  • “可以获取输出”意味着您可以获取命令的输出并将其分配给PHP变量。
  • “退出代码”是命令返回的特殊值(也称为“返回状态”)。零通常表示成功,其他值通常是错误代码。

其他需要注意的杂项:

  • shell_exec()和反引号运算符执行相同的操作。
  • 还有proc_open()和popen(),它们允许您使用执行命令以交互方式读取/写入流。
  • 如果您还想捕获/显示错误消息,请在命令字符串中添加“ 2>&1”。
  • 使用escapeshellcmd()可以转义可能包含问题字符的命令参数。
  • 如果将$ output变量传递给exec()来存储输出,如果$ output不为空,它将在其后追加新的输出。因此,您可能需要先取消设置($ output)。

哪些可以执行php文件?
约翰尼,为什么

1
@johnywhy本身没有作用-除非您明确调用php cli等。我想你想include和朋友
哈根·冯·埃森

21

实际上,这全都取决于您如何处理命令可能返回的输出以及是否要让PHP脚本等待被调用程序完成。

  • exec 执行命令并将输出传递给调用方(或将其返回到可选变量中)。

  • passthruexec()函数相似的是它执行命令。这个功能应该代替使用exec()system()从Unix的命令的输出时是需要被直接返回到浏览器传递的二进制数据。

  • system 执行外部程序并显示输出,但仅显示最后一行。

如果您需要执行命令并直接将命令中的所有数据传回而不会受到任何干扰,请使用该passthru()功能。


8

如果您从命令行运行PHP脚本,则passthru()有一个很大的好处。它可以让你执行脚本/程序,如vimdialog等,让这些程序处理控制并返回到你的脚本,只有当他们这样做。

如果您使用system()exec()执行那些脚本/程序,它将根本无法工作。

疑难杂症:出于某种原因,你不能执行lesspassthru()在PHP。


1
我不明白你在说什么。您可以从CLI和(F)CGI(以及mod_php)执行程序。可能存在系统施加的限制,例如selinux。但是一个设置良好的系统将有选择地关闭这些设置。当然,共享主机是另一回事,但您也不会为尊敬的客户提供共享环境,不是吗?
基督教徒
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.