PHP shell_exec()与exec()


345

我努力理解之间的区别shell_exec()exec()...

我一直习惯于exec()执行服务器端命令,何时使用shell_exec()

是否shell_exec()只是一个速记exec()?较少的参数似乎是同一件事。


2
很好的例子,看看分歧是尝试这些命令:datewhoamiifconfignetstat

还有其他功能:system(),passthru()…参见此相关问题,尤其是此答案
Gras Double

Answers:


353

shell_exec以字符串形式返回所有输出流。exec默认情况下返回输出的最后一行,但是可以将所有输出作为指定为第二个参数的数组提供。

看到


21
如果需要退出值和所有输出,最好还是使用“ exec”而不是“ shell_exec”。一旦将输出参数传递给“ exec”,它将被输出的每一行填充,在我看来,“ exec”可以使“ shell_exec”的所有内容以及更多的东西:)
Preexo

4
@ daniel-a-white我知道这是一个旧的,但是它很流行,因此您应该编辑答案以反映@preexo的注释-exec()也可以返回整个输出(如果使用其可选参数) 。另外,不相关的是,有人应该对这两个命令进行基准测试,以便更好地看待@preexo所说的“ 我看来exec()可以[完成] shell_exec()[可以,]以及更多的工作:)
SimpleAnecdote 2015年

77

这是区别。注意最后的换行符。

> shell_exec('date')
string(29) "Wed Mar  6 14:18:08 PST 2013\n"
> exec('date')
string(28) "Wed Mar  6 14:18:12 PST 2013"

> shell_exec('whoami')
string(9) "mark\n"
> exec('whoami')
string(8) "mark"

> shell_exec('ifconfig')
string(1244) "eth0      Link encap:Ethernet  HWaddr 10:bf:44:44:22:33  \n          inet addr:192.168.0.90  Bcast:192.168.0.255  Mask:255.255.255.0\n          inet6 addr: fe80::12bf:ffff:eeee:2222/64 Scope:Link\n          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1\n          RX packets:16264200 errors:0 dropped:1 overruns:0 frame:0\n          TX packets:7205647 errors:0 dropped:0 overruns:0 carrier:0\n          collisions:0 txqueuelen:1000 \n          RX bytes:13151177627 (13.1 GB)  TX bytes:2779457335 (2.7 GB)\n"...
> exec('ifconfig')
string(0) ""

请注意,反引号运算符的使用与相同shell_exec()

更新:我真的应该解释最后一个。多年以后,看着这个答案,我什至不知道为什么会显得空白!Daniel在上面进行了解释-这是因为exec仅返回最后一行,而ifconfig的最后一行恰好为空白。


如果命令发生一个错误,该怎么办?我收到错误/没有这样的文件或目录,但是如何捕获到变量?
快乐编码员

@AlwinAugustin:嗯?可能正在写入STDERR。2>&1如果您使用的是Linux计算机,请尝试在命令末尾添加以将STDERR重定向到STDOUT。
mpen

我也添加了它。但是我仍然得到0作为值。我使用了一个wc -l命令,如果文件不存在,我需要获取错误消息,提示没有此类文件或目录。
快乐编码员

50

shell_exec-通过shell执行命令并以字符串形式返回完整的输出

exec -执行外部程序。

区别在于shell_exec您将输出作为返回值。


4
简洁的摘要!仍应注意,exec返回输出的最后一行。如果需要,您可以选择传入一个数组作为第二个参数以捕获完整的输出,并传入一个整数作为第三个参数以捕获shell命令的返回值,该值可用于错误检查。最大的缺点shell_exec是,如果命令失败,或者如果它不产生任何输出,则返回null,因此其返回值不能可靠地用于错误检查。
肖恩·比恩

38

这里没有涉及的几个区别:

  • 使用exec(),您可以传递一个可选的param变量,该变量将接收输出行数组。在某些情况下,这可能节省时间,尤其是在命令输出已经以表格形式显示的情况下。

相比:

exec('ls', $out);
var_dump($out);
// Look an array

$out = shell_exec('ls');
var_dump($out);
// Look -- a string with newlines in it

相反,如果命令的输出是xml或json,则不需要将每一行作为数组的一部分,因为您需要将输入后处理为其他形式,因此在这种情况下,请使用shell_exec 。

还值得指出的是,shell_exec是backtic运算符的别名,对于* nix而言是这样的。

$out = `ls`;
var_dump($out);

exec还支持一个附加参数,该参数将提供已执行命令的返回代码:

exec('ls', $out, $status);
if (0 === $status) {
    var_dump($out);
} else {
    echo "Command failed with status: $status";
}

如shell_exec手册页所述,当您实际上需要执行的命令返回代码时,您别无选择,只能使用exec。


3
另外:exec通过该&$return_var参数,您可以获取命令的返回代码(通过参数),而shell_exec无法获取它。
Mark Amery 2014年

尽管接受的答案也是正确的,但我认为该答案更为重要。最好的答案可能是两者结合。
UncaAlby
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.