从PHP脚本运行shell脚本

27

我想要从一个PHP脚本中执行系统上存在的一个Bash脚本。我有两个脚本在系统上存在。其中一个是名为 client.php 的PHP脚本,位于 /var/www/html ,另一个是名为 testscript 的Bash脚本,位于 /home/testuser

我的client.php脚本如下:

<?php
  $message=shell_exec("/home/testuser/testscript 2>&1");
  print_r($message);
?>  

我的测试脚本看起来像

#!/bin/bash
echo "Testscript run succesful"

当我在终端上执行以下操作时:

php client.php

我在终端上得到了以下输出

Testscript run successful

但当我打开页面时

http://serverdomain/client.php
我得到了以下输出。
sh: /home/testuser/testscript: Permission denied 
我在执行chmod +x testscript后仍然遇到了这个错误。如何让它能够在浏览器中正常工作?请帮忙。

1
“读取”权限怎么样?没有“读取”权限,“执行”权限就毫无用处。 - Samveen
9
Apache将无法访问您的主目录,这也是您永远不应该想要的。请记住,授予脚本权限并不足够,您还必须授予其所在目录的访问权限。例如,如果我在银行保险库内放置一个“免费拿取”的报纸架,即使这些报纸是免费的,也没有人能够拿走它们。 - Marc B
@MarcB 我忘记了路径的权限。还有一个好的比喻。 - Samveen
4
你需要在那个脚本上赋予Web服务器sudo权限,或者将该脚本封装成SUID二进制文件。但无论哪种方式,都要非常小心。如果错误调用脚本或传递错误数据,你就会为远程用户提供一个能访问你服务器root shell的入口,而你的服务器也会崩溃。 - Marc B
1
这被称为“坏主意”。 :) 简单地不要这样做。真正的安全风险。 - clt60
显示剩余8条评论
4个回答

20

我会在WWW文件夹下创建一个名为scripts的目录,这样它就无法从Web访问但可以被PHP访问。

例如:/var/www/scripts/testscript

确保testscript的用户/组与您的Web文件相同。例如,如果您的client.php的所有者是apache:apache,请使用chown将bash脚本更改为相同的用户/组。您可以通过执行ls -al来查找您的client.php和Web文件所属的用户/组。

然后运行命令:

<?php
      $message=shell_exec("/var/www/scripts/testscript 2>&1");
      print_r($message);
    ?>  

编辑:

如果您真的想从Web服务器以root身份运行文件,您可以尝试下面的二进制包装器。查看此解决方案,了解与您想要执行的相同的操作。

通过PHP执行root命令


由于Web服务器不应该以root身份运行,因此它将无法执行该操作。 - Barmar
我更新了我的答案,并提供了解决方案的信息,这应该适用于您。为我节省了写出来的时间。 :) - Panama Jack
1
我希望我的测试脚本只能位于/home/testuser位置。我想使用PHP来执行它。我如何在不移动测试脚本或不影响安全性的情况下实现它?我只是想针对这个脚本这样做。 - nmadhok
对我来说不起作用,如果我使用“www-data”执行脚本,则没有输出,但如果我使用“root”执行它,则可以正常工作。 - Black

5

不知道设置的复杂性,但我喜欢使用sudo方式。 首先,您必须配置sudo以允许您的Web服务器sudo以root身份运行给定的命令。然后,您需要让Web服务器shell_exec(testscript)脚本使用sudo来运行该命令。

对于具有Apache和sudo的Debian系统:

  1. Configure sudo:

    • As root, run the following to edit a new/dedicated configuration file for sudo:

      visudo -f /etc/sudoers.d/Webserver
      

      (or whatever you want to call your file in /etc/sudoers.d/)

    • Add the following to the file:

      www-data ALL = (root) NOPASSWD: <executable_file_path>
      

      where <executable_file_path> is the command that you need to be able to run as root with the full path in its name(say /bin/chown for the chown executable). If the executable will be run with the same arguments every time, you can add its arguments right after the executable file's name to further restrict its use.

      For example, say we always want to copy the same file in the /root/ directory, we would write the following:

      www-data ALL = (root) NOPASSWD: /bin/cp /root/test1 /root/test2
      
  2. Modify the script(testscript):

    Edit your script such that sudo appears before the command that requires root privileges(say sudo /bin/chown ... or sudo /bin/cp /root/test1 /root/test2). Make sure that the arguments specified in the sudo configuration file exactly match the arguments used with the executable in this file. So, for our example above, we would have the following in the script:

    sudo /bin/cp /root/test1 /root/test2
    
如果您仍然收到权限被拒绝的错误提示,那么脚本文件及其父目录的权限可能不允许Web服务器执行脚本本身。 因此,您需要将脚本移动到更合适的目录,并/或更改脚本和父目录的权限以允许www-data(用户或组)执行,这超出了本教程的范围。
请注意: 在配置sudo时,目标是允许命令以最受限制的形式运行。例如,不允许广泛使用cp命令,而只有在参数为/root/test1 /root/test2时才允许使用cp命令。这意味着cp的参数(和cp的功能)不能被修改。

刚按照上述步骤设置好了一切,但在Centos 6上Apache的error.log中出现了“sudo:no tty present and no askpass program specified”的错误提示。 - webcoder.co.uk
我曾经看到过其他类似的解决方案,它们说明需要使用逗号分隔 sudoers 所允许运行命令或脚本路径,例如:NOPASSWD: /bin/cp, /root/test1, /root/test2? - webcoder.co.uk

3
我曾为这个确切的问题苦苦挣扎了三天。我已将脚本权限设置为755。我一直在按以下方式调用我的脚本。
<?php
   $outcome = shell_exec('/tmp/clearUp.sh');
   echo $outcome;
?>

我的脚本如下:
#!bin/bash
find . -maxdepth 1 -name "search*.csv" -mmin +0 -exec rm {} \;

我没有得到任何输出或反馈。为了使脚本运行,我所做的改变是在脚本中添加了一个进入tmp目录的命令(cd):

#!bin/bash
cd /tmp;
find . -maxdepth 1 -name "search*.csv" -mmin +0 -exec rm {} \;

这更多是运气而非判断,但现在它已经完美地运作了。我希望这能帮到您。


2
这是一个简单的问题。当你从终端运行时,你作为特权用户运行php文件。当你从web浏览器访问php时,php脚本将作为Web服务器用户运行,该用户没有执行家目录中文件的权限。在Ubuntu中,www-data用户是Apache Web服务器用户。如果你使用的是Ubuntu,你需要执行以下操作: chown yourusername:www-data /home/testuser/testscript chmod g+x /home/testuser/testscript
上述命令的作用是将文件的所有权转移给你,并将其设置为Web服务器组的所有权。下一个命令将授予组对文件的可执行权限。现在,当你从浏览器再次执行该操作时,它应该可以正常工作。

我在使用RHEL系统。对于我来说,Web服务器用户将是apache。此外,脚本仍然可以由root执行吗?您说用户所有权将转移到我名下。 - nmadhok
根是全面的。它仍然可以被root访问。 - priyolahiri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接