【问题标题】:Cannot run shell command through php exec, but can as user on shell?无法通过 php exec 运行 shell 命令,但可以作为 shell 用户吗?
【发布时间】:2014-07-03 00:00:16
【问题描述】:

我正在尝试让 exiftool 在我的专用服务器上工作。问题是 PHP exec 的运行似乎与以用户身份运行命令时不同。奇怪的是,PHP 显示为我登录时使用的同一用户,但它与系统命令的行为不同。

奇怪的是,在我的本地主机上一切正常,但在我的服务器上却不行。

如前所述,运行通过 ssh 登录的 exiftool 命令就可以了。

但是在 php 测试脚本中运行(注意我在每个测试目录上都安装了 exiftool,并且它通过 ssh 运行),没有任何东西可以访问,尽管它以用户 orangeman 运行...

失败了

这是一个更新 - 整天都在关注这个:

在外壳上:

-bash-4.1$ which exiftool -a
~/perl5/bin/exiftool
/usr/bin/exiftool
~/perl5/bin/exiftool

在 PHP 中 shell_exec('exiftool -a');

/usr/bin/exiftool

这是该文件链接到的内容:

lrwxrwxrwx    1 root root          33 May 15 02:10 exiftool -> /home/orangeman/perl5/bin/exiftool

我也尝试过创建各种符号链接,通过 php 中的putenv(); 篡改主要的 $PATH 变量……我在这里真的一头雾水。在本地主机上工作,而不是在专用服务器上。


我已经用赏金更新了这个 - 这是开发中的一个严重问题。

我在专用服务器上,问题如上所述。


更新 根据@gcb 的建议,我能够打印出当 php 的 exec() 函数运行系统命令无效时发生的错误。

PHP

<?php
exec('exiftool 2>&1', $output, $r);
var_dump($output, $r);
?>

输出:

array(2) {
  [0]=>
  string(230) "Can't locate Image/ExifTool.pm in @INC (@INC contains: /bin/lib /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at /bin/exiftool line 33."
  [1]=>
  string(59) "BEGIN failed--compilation aborted at /bin/exiftool line 33."
}

更新

@gcb 的解决方案奏效了。非常感谢。

【问题讨论】:

  • php 在 chroot 中吗?它是否有权实际查看这些目录?
  • 'which php' 返回 '/usr/local/bin/php'。我不熟悉“chroot”,但如果有可能,那么解决方法是什么?
  • 你可以把你需要的文件/程序放在chroot里面。至于它是什么,请参阅维基百科条目。 en.wikipedia.org/wiki/Chroot
  • /usr/bin/exiftool 不是目录。 /usr/bin 是一个目录,而/usr/bin/exiftool(如果存在)是一个文件。

标签: linux perl bash shell exiftool


【解决方案1】:

所以你现在没有 php 问题,而是 perl 问题。你的包含路径不好。

回复here

You either have to install the ExifTool libraries in the
standard location (ie. somewhere in the @INC directories
listed in your post), or add the location to the include path,
something like this:

Code:
#!/usr/bin/perl
BEGIN { unshift @INC, "PATH_TO_DIRECTORY_CONTAINING_LIBRARIES" }
use Image::ExifTool;

You should be able to add "Image/ExifTool.pm" to the path you add
to find the ExifTool module.

- Phil

我仍然认为使用上一个答案中的建议 #3 可以解决它。如果没有,并且您真的想知道原因,请创建一个新的 perl 脚本,它只输出 @INC 的内容并通过 shell 和 php 运行它。你会看到区别,然后你需要找到哪个登录脚本在 php 中没有被尊重,并针对 shell_exec 不尊重它打开一个针对 php 的错误...

虽然您的问题更简单的解决方案(因为您似乎对解释不太感兴趣)是在调用脚本之前设置 PERLLIB var。

所以,做吧:

  1. find / -name ExifTool.pm 这将告诉您 lib 的安装位置。假设这会返回/example/perl/Image/ExifTool.pm
  2. PERL5LIB=/example/perl/ 附加到您的 exec() 调用中。
  3. exec("PERL5LIB=/example/perl/ /var/www/myscript/execscript.sh {$param}"); #和

【讨论】:

  • "...因为看起来您对解释不太感兴趣"...不是这样!我很感兴趣。我一直在这个几乎一个星期。这似乎是最有可能的答案。我现在正在检查它。我在一个临时目录中解压缩并运行“make”......假设它会正确安装。显然它没有以标准方式安装。根据你的观察,我今天早上一直在研究。我根本没有使用 perl 的经验,所以这对我来说比较慢。
  • @Orangeman555 谢谢。关于学习,老实说,我不认为你应该学习 perl 来解决这个问题。如果您想改进,请学习 linux(文件系统结构、文件权限、stdout 与 stdout 即缓冲区和流,以及关于一个或另一个 shell,我建议 bash)并了解您选择的工作环境(php、apache,我是假设)学习在哪里搜索错误日志等。最终你会看到一切都遵循相同的模式并且变得容易:)欢呼。
【解决方案2】:

0) 你应该查看你的错误日志。通常在 /var/log/apache/error 下

它会有诸如“拒绝访问”之类的消息。

1) 您显然没有得到足够的命令输出来查看任何错误。所以尝试使用exiftool 2&gt;&amp;1 运行它。这会将 stderr 重定向到 stdout,因此错误将出现在输出中。不确定这是否相关或php已经这样做了。您可能还想使用passthru 而不是exec

2) 安全模式执行目录

您的文件可能超出了您的安全模式执行目录。仔细阅读:

http://www.php.net/manual/en/ini.sect.safe-mode.php#ini.safe-mode-exec-dir

3) 一切都失败了,将命令作为登录 shell 运行,它应该加载与通过 ssh 登录时相同的脚本。只需将 exec 替换为 shell_exec

...我很确定查看错误日志会解决您的问题。

【讨论】:

  • 我现在正在检查您的建议。会尽快回复您 - 非常感谢。
  • 很棒的建议。我已经用结果更新了原始帖子。我不知道如何从 shell 中获取错误日志,所以这是一个巨大的进步。现在我们看到它抛出了一个我们在通过 shell 登录时显然不会得到的错误,那么这显示了什么?
【解决方案3】:

一种可能性是,在命令行上,您的$PATH 已由您的$HOME/.bashrc 和您的$HOME/.bash_profile 设置/修改,因为您的命令行是一个登录shell。当 Web 服务器调用 PHP 时,它作为“橙子”运行 BUT 只是作为一个 shell,而不是一个登录 shell,所以它的$PATH 可能不是一样,这就是你在这里看到的。 您是否尝试将export PATH="what:you:want:your:PHP:path:to:be" 放入您的$HOME/.bashrc

【讨论】:

  • 我已经修改过 - 我不确定我做对了。这应该在 PHP 脚本运行时完成,还是有一种固定的方式来为系统设置它?
【解决方案4】:

我相信这是因为您为您的用户私人安装了 perl。

基本上@INC 是perl 用来定位其库的数组,它不包含安装库的路径。

有几种方法可以更改@INC,您可以在以下链接中找到它们:

http://perlmaven.com/how-to-change-inc-to-find-perl-modules-in-non-standard-locations

我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2012-06-25
    • 1970-01-01
    • 2015-10-02
    • 2011-03-28
    • 1970-01-01
    • 2011-03-06
    • 2019-02-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多