为什么有些二进制文件不能与 shell_exec 一起使用?

Why some binaries don't work with shell_exec?

我不明白为什么,但我无法从 PHP 页面执行某些二进制文件。

如果我从 PHP 页面调用它,我没有得到任何输出:

<?php
echo shell_exec('/usr/bin/which ffmpeg');

如果我从 CLI 执行它,它会起作用:

$ sudo -u apache php -r 'echo shell_exec("/usr/bin/which ffmpeg");'
/usr/bin/ffmpeg

但是,如果我尝试从 PHP 页面调用 whereis 而不是 which,我会得到一个输出,尽管它们在同一目录中:

<?php
echo shell_exec('/usr/bin/whereis ffmpeg');

我不明白背后的逻辑...


我已经验证了文件权限,一切似乎都很好:-rwxr-xr-x. root:root,没有 ACL。

我正在使用 Fedora 28(SELinux 设置为宽松)。这些命令适用于 Debian 和 Ubuntu.

which命令会在找到程序时在STDOUT上生成输出,但如果没有这样的命令,它将使用STDERR

$ strace which php
[...]
access("/usr/bin/php", R_OK)            = 0
fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 0), ...}) = 0
write(1, "/usr/bin/php\n", 13) = 13
[...]

注意 write() 处的 1,它是 STDOUT 的处理程序,但是当找不到该命令时,将使用不同的处理程序:

$ strace which something_not_existing
[...]
stat("/usr/games/bin/something_not_existing", 0x7ffc20f046a0) = -1 ENOENT (No such file or directory)
write(2, "which: no something_not_existing"..., 150) = 150
[...]

注意 write() 处的 2,这是 STDERR 的处理程序。

在控制台中,您将看到 STDOUTSTDERR 的输出,但 shell_exec() 只会 output/return STDOUT流。

检查 http://www.php.net/shell_exec 如何捕获 STDERR 流。根据您的要求,您甚至可能想使用 proc_open() 等其他执行函数来控制 STDIN/STDOUT/STDERR 流。

whereis 命令将始终写入 STDOUT,那是因为您通过 shell_exec().

在 php 中看到了输出