【问题标题】:Executing bash file via php on apache server在apache服务器上通过php执行bash文件
【发布时间】:2016-06-10 19:00:35
【问题描述】:

所以我在我的 apache 服务器上托管了一个网页,当用户通过 PHP 和 AJAX 按下按钮时,我正在尝试运行一些 python 和 bash 脚本。

现在我的 php 文件在 python 脚本(位于 /var/www/html)处执行,该脚本又执行一个 bash 文件(位于 root/files)。

在终端中手动执行此操作,一切正常。

但是当我通过网页尝试这个时,bash 脚本没有被执行。

(我无法将 bash 脚本放在 /var/www/html 中,因为它具有将 git 存储库克隆到服务器的命令,并且在放置时它给出的私钥不应该是公共错误)

我已经在this answer 中尝试了建议,将www-data 添加到sudoers,但它仍然没有按预期工作。

对此的任何帮助将不胜感激。 谢谢

PHP 文件:

if(isset($_POST['timestamp']))
{
$uid = $_POST['timestamp'];
echo "Please wait while the app is being generated".$uid;
exec("python /var/www/html/appgenserver.py $uid");

appgenserver.py

#! /usr/bin/env python
import os
import json,sys
from firebase import firebase
import requests
import subprocess


arg = sys.argv[1]
# Path to be created
path = "/root/files/"+str(arg)
print path
if not os.path.exists(path):
os.makedirs(path)     #Gets executed
subprocess.call(['/root/Final/clone.sh', path)   #Not getting executed

【问题讨论】:

  • 你能粘贴你用来运行 bash 脚本的 php 代码吗?
  • 请检查编辑@VinodKumar
  • OK,在exec函数中尝试使用python的全路径
  • 为什么要涉及 Python?特别是如果您打算只调用 bash 脚本?
  • 你试过放python可执行文件的完整路径吗?

标签: php python git bash apache


【解决方案1】:

很可能是因为 bash 脚本本身无法执行,它只是一个纯文本文件。
您的 bash(甚至可能是 appgenserver.py?)可能位于 /root 下,而 apache 可能以非特权用户身份运行,例如 www-data,该用户将无法访问您的 python 脚本,反过来不是 python 运行的 bash。

考虑改为使用脚本作为参数调用 bash。

#! /usr/bin/env python
import os
import json,sys
from firebase import firebase
import requests
import subprocess


arg = sys.argv[1]
path = "/root/files/"+str(arg)
print path
if not os.path.exists(path):
    os.makedirs(path)
subprocess.call(['/bin/bash', '/root/Final/clone.sh', path)

现在,这不是最漂亮的解决方案。
但是您之前得到的可能是后台出现的一般“权限被拒绝”错误(检查您的/var/log/apache/error.log)。

它的作用是将/bin/bash 作为一个子进程启动,第一个参数是您要执行的脚本。

但是您在这里的错误处理为零,并且您无法与该过程进行太多交互。

考虑做这样的事情:

import subprocess

handle = subprocess.Popen(['/bin/bash', '/root/Final/clone.sh', 'parameter'], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT)
while handle.poll() is None:
    print(handle.stdout.read()) # There's some optimizations here to be done as well so it's not a blocking call etc.

handle.stdout.close()
handle.stdin.close()

最后一个提示是,如果您要将 /root/ 中的内容集成到 Web 前端/后端类型的东西中,则不要完全
你是在自找麻烦:)

另一种方法是使用 sudo

如果您在 PHP 中修改 exec() 以运行 exec("sudo ...") 并允许您的网络用户在没有密码提示的情况下运行脚本,它可以工作。

记住,不建议给www-data sudo 访问权限,而是这样做:

# useradd -m -G www-data -s /bin/bash wwwexec
# echo "myuser ALL=NOPASSWD: /usr/bin/python" >> /etc/sudoers

并将您的 PHP 脚本更改为具有以下内容:

exec("sudo -u wwwexec python /var/www/html/appgenserver.py $uid");

这样至少您的整个网络服务不会通过默认用户名获得 root 访问权限。

方法

将您的appgenserver.py 放在/var/www/cgi-bin/ 下,并在您的apache 配置中为.py 创建一个CGI 挂钩,并将用户交给您访问CGI 脚本的URL。

这样,一切都应该按照最佳实践进行,即使理论上,您也可以让您的原始解决方案发挥作用。

例如,this guide 应该可以帮助您入门。

【讨论】:

  • @HarshitDwivedi Humm,好的,你的 /var/log/apache/error.log 说什么?
  • @HarshitDwivedi 另外,如果你先做sudo -i -u www-data,然后再做python yourscript.py,它还能用吗?因为我猜 www-data 用户(或任何你的 apache 运行的)不能访问 /root 的东西?
  • @HarshitDwivedi 您尝试时appgenserver.py 位于哪个文件夹中?因为如果您以 root 身份站在/root 中,则尝试执行该用户在该上下文中将不可用,因为它没有在那里的权限:) 如果我没记错的话。
  • @HarshitDwivedi 讨厌基于 debian 的发行版.. 试试这个su - www-data -c 'python yourscript.py。帐户 www-data 可能在您的系统上没有主文件夹,因此系统不会让用户生活在已登录的会话中。
  • @HarshitDwivedi 您可以在 PHP 脚本中做一件令人讨厌的事情,exec('sudo -u myuser python appgenserver.py ...');,如果您将 myuser 添加到 sudoers 文件中作为 myuser ALL=NOPASSWD: /usr/bin/python。这里有各种各样的危险信号,但可能会起作用。也别忘了sudo useradd -m -G www-data -s /usr/bin/nologin myuser