Php 如何调试exec()问题?

Php 如何调试exec()问题?,php,Php,exec命令在我的服务器上不起作用,它不起任何作用,我关闭了safe_模式,并验证了所有控制台命令都在工作,我尝试了绝对路径。我已经检查了应用程序的权限,我需要的所有应用程序都有执行权限。我不知道还能做什么,这是我试过的代码的摘要 echo exec('/usr/bin/whoami'); echo exec('whoami'); exec('whoami 2>&1',$output,$return_val); if($return_val !== 0) { echo

exec命令在我的服务器上不起作用,它不起任何作用,我关闭了safe_模式,并验证了所有控制台命令都在工作,我尝试了绝对路径。我已经检查了应用程序的权限,我需要的所有应用程序都有执行权限。我不知道还能做什么,这是我试过的代码的摘要

echo exec('/usr/bin/whoami');

echo exec('whoami');

exec('whoami 2>&1',$output,$return_val);
if($return_val !== 0) {
    echo 'Error<br>';
    print_r($output);   
}

exec('/usr/bin/whoami 2>&1',$output,$return_val);
if($return_val !== 0) {
    echo 'Error<br>';
    print_r($output);   
}

我已经联系了服务器服务,他们无法帮助我,他们不知道exec命令为什么不起作用。

您可以检索命令的输出和返回代码,这些可能包含解释问题的信息

exec('my command', $output, $return);

请看一下
/etc/php.ini
,下面有:

; This directive allows you to disable certain functions for security reasons.
; It receives a comma-delimited list of function names. This directive is
; *NOT* affected by whether Safe Mode is turned On or Off.
; http://www.php.net/manual/en/ini.sect.safe-mode.php#ini.disable-functions
disable_functions =
确保exec未按如下方式列出:

disable_functions=exec
如果是这样,请删除它并重新启动apache

为了便于调试,我通常喜欢手动执行php文件(可以请求更多错误,而无需在主ini中设置)。为此,请添加标题:

#!/usr/bin/php
ini_set("display_errors", 1);
ini_set("track_errors", 1);
ini_set("html_errors", 1);
error_reporting(E_ALL);
对于文件的开头,使用
chmod+x myscript.php
为其授予权限,然后执行它
/myscript.php
。特别是在繁忙的服务器上,它非常小心,因为服务器会大量写入日志文件

编辑


听起来像是权限问题。创建一个bash脚本,执行一些简单的操作,如
echo“helo world”
,然后尝试运行它。确保您对文件和包含该文件的文件夹具有权限。您可以选择只做
chmod755
测试

由于您将退出PHP上下文进入本机shell,因此在调试过程中会遇到很多问题

我过去使用过的最好、最简单的方法是将脚本的输出写入日志文件,并在PHP执行期间跟踪它

<?php
shell_exec("filename > ~/debug.log 2>&1");
执行PHP脚本时,shell调用的错误和输出将显示在
debug.log
文件中。

  • 为了进行调试,请始终将exec/shell\u exec函数包装在中

  • 错误报告(-1)
    应该是打开的,应该是
    显示错误
    ,作为最后手段,甚至是
    设置错误处理程序(“变量转储”)-如果只是看看PHP本身是否没有调用
    execvp
    或其他

  • 使用(将shell STDERR合并到STDOUT流)查看调用失败的原因。
    在某些情况下,您可能需要将命令包装到其他shell调用中:

    否则,@Mike建议的日志文件重定向是最值得推荐的方法

  • 在各种exec函数之间交替使用,以发现错误消息。虽然它们主要做相同的事情,但输出返回路径不同:

  • → 将输出作为函数结果返回,或通过可选的
    $output
    参数返回。
    还提供了一个
    $return\u var
    参数,其中包含运行应用程序或shell的errno/exit代码。您可能会得到:

    • enoint
      (2)-无此类文件
    • EIO
      (127)-IO错误:找不到文件
  • → 是您主要希望为shell样式表达式运行的程序。
    确保分配/打印返回值,例如
    var\u dump(shell\u exec(“…”)

  • 内联反勾号→ 与
    shell\u exec
    相同

  • → 类似于
    exec
    ,但总是将输出作为函数结果返回(打印出来!)。另外还允许捕获结果代码

  • → 是另一个
    exec
    备选方案,但始终将任何标准输出结果发送到PHPs输出缓冲区。这通常使它成为最合适的exec包装器

  • 或者更好→ 允许单独捕获标准输出和标准输出

  • 大多数shell错误在未重定向时会出现在PHPs或Apaches
    error.log
    中。如果没有产生有用的错误消息,请检查您的系统日志或Apache日志

最常见的问题

  • 正如@Kuf所提到的:对于过时的网络托管计划,您仍然可以发现启用了
    安全模式
    禁用功能
    。所有PHP exec函数都无法工作。(最好找一个更好的提供商,否则就调查“CGI”-但不要在未安装PHP解释器的情况下安装自己的PHP解释器。)

  • 同样地,AppArmor/SELinux/Firejail有时也会到位。这些限制了每个应用程序生成新进程的能力

  • 所需的二进制文件不存在。几乎没有一个网络主机预装了
    ffmpeg
    这样的工具。您不能在没有准备的情况下运行任意shell命令。有些东西需要安装

  • 路径
    已关闭。如果安装了自定义工具,则需要确保可以访问这些工具。使用
    var\u dump(shell\u exec(“ffmpeg-opts”)
    将搜索所有公共路径——或者正如Apache被告知/约束的那样(通常只是
    /bin:/usr/bin

    检查
    print\r($\u服务器)路径包含的内容,以及该路径是否包含要运行的工具。否则,您可能需要调整服务器设置(/etc/apache2/envvars),或使用完整路径:

    // run with absolute paths to binary
    var_dump(shell_exec("/bin/sh -c '/usr/local/bin/ffmpeg -opts 2>&1'"));
    
这在某种程度上颠覆了shell的概念。就我个人而言,我认为这是不可取的。但出于安全目的,它确实有意义;此外,当然还需要使用定制安装

  • 权限

  • 为了在BSD/Linux系统上运行二进制文件,需要将其设置为“可执行”。这就是
    chmoda+xffmpeg
    所做的

  • 进一步模式这些自定义二进制文件的路径需要能够被运行PHP脚本的Apache用户读取

  • 更现代的设置使用PHPs内置FPM模式(suexec+
    tail -200f ~/debug.log
    
    // capture STDERR stream via standard shell
    echo shell_exec("/bin/sh -c 'ffmpeg -opts 2>&1' ");
    
    // run command, conjoined stderr, output + error number
    var_dump(exec("ffmpeg -h 2>&1", $output, $errno), $output, $errno));
    
    // Check if `ffmpeg` is actually there:
    var_dump(shell_exec("which ffmpeg"));
    
    // run with absolute paths to binary
    var_dump(shell_exec("/bin/sh -c '/usr/local/bin/ffmpeg -opts 2>&1'"));
    
    $q = "escapeshellarg";
    var_dump(shell_exec("echo {$q($_GET['text'])} | wc"));
    
    $null = shell_exec(`wc file.txt`);
                       ↑           ↑
    
    sudo -u www-data gpg -k
    
     system("powershell -Command 'pandoc 2>&1'");
    
    passthru("PYTHONDEBUG=2 python -vvv script.py 2>&1");
    passthru("perl -w script.pl 2>&1");
    passthru("ruby -wT1 script.rb 2>&1");