我怎样才能debuggingexec()问题?

exec命令在我的服务器上不起作用,它什么都不做,我已经closures了safe_mode,并validation了所有的控制台命令正在工作,我尝试了绝对path。 我已经检查了应用程序的权限以及我需要的所有应用程序的执行权限。 我不知道还有什么要做,这里是我试过的代码的破败。

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); } 

最后两个代码显示:

 Error Array ( ) 

我已经联系了服务器服务,他们不能帮助我,他们不知道为什么exec命令不工作。 原谅我的坏英语。

看看/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。

为了便于debugging,我通常喜欢手动执行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 。 特别是在一个繁忙的服务器上写了很多的日志文件是非常值得的。

编辑

听起来像一个权限问题。 创build一个bash脚本,做一些简单的echo "helo world"并尝试运行它。 确保您拥有该文件和包含该文件的文件夹的权限。 你只需要做chmod 755就可以testing了。

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

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

由于您正在将PHP上下文从本地shell中删除,因此您将会遇到很多debugging问题。

我过去使用的最好,最安全的方法是将脚本输出写入日志文件,并在PHP执行过程中将其拖尾。

 <?php shell_exec("filename > ~/debug.log 2>&1"); 

然后在一个单独的shell中:

 tail -200f ~/debug.log 

当你执行你的PHP脚本时,你的错误和shell调用的输出将显示在你的debug.log文件中。

还有一些笔记。

  • 对于debugging,总是将你的exec / shell_exec函数包装在var_dump()

  • error_reporting(-1); 应该是,应该是display_errors ,作为最后的手段甚至set_error_handler("var_dump"); – 如果只是为了看看PHP本身是否不调用execvp或其他。

  • 使用2>&1 (合并STDERR到STDOUTstream的shell)来查看调用失败的原因。
    对于某些情况,您可能需要将命令封装在一个额外的shell调用中:

     // capture STDERR stream via standard shell shell_exec("/bin/sh -c 'ffmpeg -opts 2>&1' "); 

    否则@Mikebuild议的日志文件redirect是最值得推荐的方法。

  • 在各种执行function之间进行交替以便发现错误消息。 虽然他们大多数做同样的事情,输出返回path有所不同:

    1. exec() →返回输出作为函数结果,或通过可选的$output参数。
      还提供$return_var参数,其中包含运行应用程序或shell的errno / exit代码。 你可能会得到:

      • ENOENT (2) – 没有这样的文件
      • EIO (127) – IO错误:找不到文件
    2. shell_exec() →是你最想运行的shell风格的expression式。
      确保使用例如var_dump(shell_exec("..."));分配/打印返回值var_dump(shell_exec("..."));

    3. `` inline backticks→与shell_exec完全相同。

    4. system() →与exec类似,但总是以函数结果的forms返回输出(打印出来!)。 另外允许捕获结果代码。

    5. passthru() →是另一个exec选项,但总是将任何STDOUT结果发送到PHP输出缓冲区。 这通常使它成为最适合的高层包装。

    6. popen()或更好的proc_open() →允许单独捕获STDOUT和STDERR。

  • 大多数shell错误在PHP或者Apaches error.log没有redirect。 检查您的系统日志或Apache日志如果没有产生有用的错误消息。

困扰PHP / LAMP新手的最常见问题是:

  • 正如@Kuf所提到的:对于过时的虚拟主机计划,您仍然可以find启用safe_modedisable_functions 。 没有一个PHP的exec函数将工作。 (最好find一个更好的提供者,否则调查“CGI” – 但是不要在不受约束的情况下安装你自己的PHP解释器。)

  • 同样, AppArmor / SELinux / Firejail也可以安装。 那些限制每个应用程序的能力来产生新的进程。

  • 预期的二进制文件不存在 。 几乎没有networking主机有预装ffmpeg工具。 你不能没有准备就运行任意的shell命令。 有些东西需要安装!

     // Check if `ffmpeg` is actually there: var_dump(shell_exec("which ffmpeg")); 
  • PATHclosures。 如果您安装了自定义工具,则需要确保它们可以访问。 使用var_dump(shell_exec("ffmpeg -opts"))将search所有常见的path – 或者Apache被告知/限制(通常只是/bin:/usr/bin )。

    print_r($_SERVER); 你的path包含了什么,如果这覆盖了你想运行的工具。 否则,您可能需要修改服务器设置(/ etc / apache2 / envvars),或使用完整path:

     // run with absolute paths to binary var_dump(shell_exec("/bin/sh -c '/usr/local/bin/ffmpeg -opts 2>&1'")); 

    这有点颠覆了shell的概念。 我个人不认为这是可取的。 尽pipe这对于安全目的来说确实有意义。 而且是为了利用自定义的安装过程。

  • 权限

    1. 为了在BSD / Linux系统上运行一个二进制文件,它需要被设置为“可执行文件”。 这是chmod a+x ffmpeg所做的。

    2. 进一步模拟这种自定义二进制文件的path需要被Apache脚本运行的Apache用户读取。

    3. 更现代的设置使用PHP内置FPM模式(suexec + FastCGI),其中您的虚拟主机帐户等于什么PHP运行。

  • SSH进行testing。 应该不用说,但是在通过PHP运行命令之前,在真正的shell中testing它是非常合理的。 如果所有的lib依赖关系都存在,并且如果它工作正常,则使用eg ldd ffmpeg探测。

  • 在execstring中作为命令参数传递的input值(GET,POST,FILE名称,用户数据)需要使用escapeshellarg()进行转义。

     $q = "escapeshellarg"; var_dump(shell_exec("echo {$q($_GET['text'])} | wc")); 

    否则,你会很容易地得到shell语法错误。 并可能利用稍后安装的代码…