从 PHP 脚本执行 shell 脚本
Posted
技术标签:
【中文标题】从 PHP 脚本执行 shell 脚本【英文标题】:Executing a shell script from a PHP script 【发布时间】:2013-06-13 16:02:12 【问题描述】:我想从 php 脚本执行系统上存在的 Bash 脚本。我在系统上有两个脚本。其中一个是位于/var/www/html
的名为client.php
的PHP 脚本,另一个是位于/home/testuser
的名为testscript
的Bash 脚本。
我的 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 之后,我也会收到此错误。 如何让它从浏览器工作?请帮忙。
【问题讨论】:
read
权限怎么样?没有read
权限,Execute
权限是没有用的。
Apache 将无权访问您的主目录。你也不应该真的想要它。请记住,仅授予脚本权限是不够的。您还必须授予对其所在目录的访问权限。例如如果我在银行保险库里放一个“免费的,拿一张”的报纸夹,即使是免费的,也没有人可以拿走这些报纸。
@MarcB 我忘记了路径的权限。一个很好的类比。
您需要在该脚本上授予您网络服务器的 sudo
权限。或者将脚本包装在 suid 二进制文件中。但无论哪种方式,都要非常非常非常非常小心。错误地调用了脚本,错误地传递了一些数据,并且您已经在您的服务器上为远程用户提供了一个 root shell,然后您的服务器就繁荣了。
这被称为坏主意。 :) 根本不这样做。真正的安全风险。
【参考方案1】:
我会在 WWW 文件夹下的某个地方有一个名为 scripts 的目录,这样它就无法从 Web 访问,但可以通过 PHP 访问。
例如/var/www/scripts/testscript
确保您的testscript
的用户/组与您的网络文件相同。例如,如果您的 client.php
归 apache:apache
所有,请使用 chown
将 bash 脚本更改为相同的用户/组。您可以通过ls -al
了解您的client.php
和网络文件的所有权。
然后运行
<?php
$message=shell_exec("/var/www/scripts/testscript 2>&1");
print_r($message);
?>
编辑:
如果你真的想以 root 身份从网络服务器运行文件,你可以试试下面的这个二进制包装器。查看此解决方案,了解您想要做的同样事情。
Execute root commands via PHP
【讨论】:
由于网络服务器不(或不应该)以 root 身份运行,所以它不能这样做。 我将我的答案更新为适合您的解决方案。节省我写出来的时间。 :) 我希望我的测试脚本仅位于 /home/testuser。我想使用 php 执行它。我怎样才能做到这一点而不必改变我的测试脚本或不必危及安全性。我只想要这个脚本 对我不起作用,如果我以www-data
执行它,我的脚本没有输出,但如果以root
执行它,它就可以工作【参考方案2】:
我为这个确切的问题苦苦挣扎了三天。我已将脚本的权限设置为 755。我一直在调用我的脚本,如下所示。
<?php
$outcome = shell_exec('/tmp/clearUp.sh');
echo $outcome;
?>
我的脚本如下。
#!bin/bash
find . -maxdepth 1 -name "search*.csv" -mmin +0 -exec rm \;
我没有得到任何输出或反馈。我为使脚本运行所做的更改是在脚本内添加一个 cd 到 tmp:
#!bin/bash
cd /tmp;
find . -maxdepth 1 -name "search*.csv" -mmin +0 -exec rm \;
这更多是靠运气而不是判断,但它现在运行良好。我希望这会有所帮助。
【讨论】:
【参考方案3】:在不知道设置的复杂性的情况下,我喜欢 sudo 路线。 首先,您必须配置 sudo 以允许您的网络服务器 sudo 以 root 身份运行给定的命令。然后,您需要让 webserver shell_exec(testscript) 使用 sudo 运行命令的脚本。
对于带有 Apache 和 sudo 的 Debian 机器:
配置 sudo:
以 root 身份运行以下命令来编辑 sudo 的新/专用配置文件:
visudo -f /etc/sudoers.d/Webserver
(或任何你想在/etc/sudoers.d/
中调用你的文件)
将以下内容添加到文件中:
www-data ALL = (root) NOPASSWD: <executable_file_path>
其中<executable_file_path>
是您需要能够以root 身份运行并在其名称中包含完整路径的命令(例如chown 可执行文件的/bin/chown
)。如果可执行文件每次都使用相同的参数运行,您可以在可执行文件的名称之后添加其参数以进一步限制其使用。
例如,假设我们总是想复制 /root/ 目录下的同一个文件,我们会这样写:
www-data ALL = (root) NOPASSWD: /bin/cp /root/test1 /root/test2
修改脚本(testscript):
编辑您的脚本,使sudo
出现在需要root 权限的命令之前(例如sudo /bin/chown ...
或sudo /bin/cp /root/test1 /root/test2
)。确保 sudo 配置文件中指定的参数与此文件中的可执行文件使用的参数完全匹配。
因此,对于我们上面的示例,我们将在脚本中包含以下内容:
sudo /bin/cp /root/test1 /root/test2
如果您仍然获得权限被拒绝,则脚本文件及其父目录的权限可能不允许网络服务器执行脚本本身。 因此,您需要将脚本移动到更合适的目录和/或更改脚本和父目录的权限以允许 www-data(用户或组)执行,这超出了本教程的范围。
记住:
配置 sudo 时,目标是允许该命令以最受限制的形式运行。例如,如果参数是 /root/test1 /root,则只允许 cp 命令,而不是允许一般使用 cp 命令/test2。这意味着 cp 的参数(以及 cp 的功能无法更改)。
【讨论】:
只需按上述方式进行设置,然后在 Centos 6 上 apache 的 error.log 中得到“sudo: no tty present and no askpass program specified”。 我遇到过其他类似的解决方案,指出需要用逗号分隔允许运行命令或脚本路径的 sudoer,即 NOPASSWD: /bin/cp, /root/test1, /root/test2 ? 【参考方案4】:这是一个简单的问题。当您从终端运行时,您是以特权用户身份从终端运行 php 文件。当您从 Web 浏览器访问 php 时,php 脚本正在以 Web 服务器用户身份运行,该用户无权执行主目录中的文件。在 Ubuntu 中,www-data 用户是 apache Web 服务器用户。如果您使用的是 ubuntu,则必须执行以下操作: chown yourusername:www-data /home/testuser/testscript chmod g+x /home/testuser/testscript
上面所做的是将文件的用户所有权转移给您,并将其所有权交给网络服务器组。下一条命令赋予组对该文件的可执行权限。现在,下次您继续从浏览器中执行此操作时,它应该可以工作了。
【讨论】:
我在 RHEL 上。 Web 服务器用户对我来说是 apache。脚本仍然可以由 root 执行吗?你说用户所有权将转移给我。 根包罗万象。它仍然可以通过 root 访问。以上是关于从 PHP 脚本执行 shell 脚本的主要内容,如果未能解决你的问题,请参考以下文章