简体   繁体   English

无法通过 php exec 运行 shell 命令,但可以作为 shell 上的用户?

[英]Cannot run shell command through php exec, but can as user on shell?

I'm trying to get exiftool to work on my dedicated server.我正在尝试让 exiftool 在我的专用服务器上工作。 The issue is that PHP exec seems to run different than when a command is run as a user.问题是 PHP exec 的运行方式似乎与以用户身份运行命令时的运行方式不同。 Oddly enough, PHP shows up as the same user I log in with, but it does not behave the same with system commands.奇怪的是,PHP 显示为我登录时使用的同一用户,但它的行为与系统命令不同。

Oddly enough everything works great on my localhost, but not on my server.奇怪的是,一切都在我的本地主机上运行良好,但在我的服务器上却没有。

So as mentioned, running exiftool commands logged in via ssh is fine.如前所述,运行通过 ssh 登录的 exiftool 命令很好。

But running in a php testing script (note I've installed exiftool on each tested directory, and it runs through ssh), nothing is accessible, though it runs as user orangeman...但是在 php 测试脚本中运行(注意我已经在每个测试目录上安装了 exiftool,并且它通过 ssh 运行),尽管它以用户 orangeman 身份运行,但没有任何东西可以访问......

And it fails它失败了

Here is an update - having been on this all day:这是一个更新- 整天都在做这个:

On the shell:在外壳上:

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

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

/usr/bin/exiftool

And here is what that file links to:这是该文件链接到的内容:

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

I've also tried creating symlinks of various sorts, tampering with the main $PATH variable via putenv();我还尝试创建各种符号链接,通过putenv();篡改主要的 $PATH 变量putenv(); in php ... I'm truly in the dark here.在 php 中......我真的在黑暗中。 Works on localhost, not on dedicated server.在本地主机上工作,而不是在专用服务器上。


I've updated this with a bounty - its a serious issue in development.我已经用赏金对其进行了更新 - 这是开发中的一个严重问题。

I'm on a dedicated server, and the problem is as outlined above.我在专用服务器上,问题如上所述。


UPDATE Per @gcb suggestion, I was able to print out the error that is occurring when php's exec() function runs the system command with no effect.更新根据@gcb 的建议,我能够打印出当 php 的 exec() 函数运行系统命令而没有效果时发生的错误。

PHP PHP

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

Output:输出:

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."
}

UPDATE更新

@gcb's solution worked. @gcb 的解决方案奏效了。 Thank you very much.非常感谢。

So you do not have a php problem now, but a perl one.所以你现在没有 php 问题,而是一个 perl 问题。 your include path is bad.你的包含路径不好。

answer herehttp://u88.n24.queensu.ca/exiftool/forum/index.php?topic=2217.0在这里回答http://u88.n24.queensu.ca/exiftool/forum/index.php?topic=2217.0

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

I still think using my suggestion #3 from the previous answer will fix it.我仍然认为使用上一个答案中的建议 #3 可以解决它。 If not and you really want to know the reason, create a new perl script that just outputs the contents of @INC and run it via the shell and via php.如果没有并且您真的想知道原因,请创建一个新的 perl 脚本,该脚本仅输出@INC的内容并通过 shell 和 php 运行它。 you will see the difference, then you need to find which login script is not being honored in php and open a bug against php for shell_exec not respecting it...你会看到不同之处,然后你需要找到哪个登录脚本在 php 中没有得到尊重,并针对shell_exec不尊重它打开一个针对 php 的错误......

though the easier solution for your problem (as it does not look like you are too interested in explanations) is to just set the PERLLIB var before calling the script.尽管解决您的问题的更简单的方法(因为看起来您对解释不太感兴趣)是在调用脚本之前设置 PERLLIB 变量。

So, just do:所以,只要这样做:

  1. find / -name ExifTool.pm This will tell you where the lib is installed. find / -name ExifTool.pm这将告诉您 lib 的安装位置。 let's say this returns /example/perl/Image/ExifTool.pm假设这返回/example/perl/Image/ExifTool.pm
  2. append PERL5LIB=/example/perl/ to your exec() call.PERL5LIB=/example/perl/附加到您的 exec() 调用中。
  3. exec("PERL5LIB=/example/perl/ /var/www/myscript/execscript.sh {$param}"); exec("PERL5LIB=/example/perl/ /var/www/myscript/execscript.sh {$param}"); #and #和

0) you should look on your error log. 0) 你应该查看你的错误日志。 usually under /var/log/apache/error通常在 /var/log/apache/error 下

it will have messages such as "access denied" or something else.它会有诸如“拒绝访问”之类的消息。

1) you are clearly not getting enough output of that command to see any error. 1)您显然没有获得足够的命令输出来查看任何错误。 so try to run it with exiftool 2>&1 .所以尝试使用exiftool 2>&1运行它。 this will redirect stderr to stdout, so errors will appear on the output.这会将 stderr 重定向到 stdout,因此输出中会出现错误。 not sure if that is relevant or php already does that.不确定这是否相关或 php 已经这样做了。 you may also want to use passthru instead of exec您可能还想使用passthru而不是exec

2) safe-mode exec dir 2)安全模式执行目录

your file may be out of your safe mode exec dir.您的文件可能不在您的安全模式 exec 目录中。 read this up:阅读这个:

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

3) all else fails, run the command as a login shell, which should have the same scripts loaded as when you login in via ssh. 3) 所有其他方法都失败了,将命令作为登录 shell 运行,它应该加载与通过 ssh 登录时相同的脚本。 just replace exec with shell_exec只需用shell_exec替换 exec

...i'm pretty sure looking at the error log will solve your mistery. ...我很确定查看错误日志会解决您的谜团。

One possibility is that on the command line, your $PATH had been set/modified by both your $HOME/.bashrc and your $HOME/.bash_profile because your command line is a log-in shell.一种可能性是,在命令行上,您的$HOME/.bashrc$HOME/.bash_profile都设置/修改了您的$PATH因为您的命令行是一个登录 shell。 When PHP is invoked by the Web server, it runs as "orangeman" BUT only as a shell, not a log-in shell, so its $PATH may not be the same, which is what you're seeing here.当 Web 服务器调用 PHP 时,它作为“orangeman”运行,仅作为 shell,而不是登录 shell,所以它的$PATH可能不一样,这就是您在这里看到的。 Have you tried putting export PATH="what:you:want:your:PHP:path:to:be" in your $HOME/.bashrc ?您是否尝试将export PATH="what:you:want:your:PHP:path:to:be"放在$HOME/.bashrc

I believe this is happening because you have a private installation of perl for you user.我相信这是因为您为您的用户私人安装了 perl。

Basically @INC is an array which perl uses for locate its library, and it does not contain the path for your installation library.基本上@INC 是 perl 用于定位其库的数组,它不包含安装库的路径。

There are a couple of ways to change @INC which you can find on the below link:有几种方法可以更改 @INC,您可以在以下链接中找到这些方法:

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

I hope this helps.我希望这有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM