允许用户www-data(apache)调用需要来自CGI脚本

时间:2018-03-03 21:32:38

标签: python linux apache subprocess file-permissions

python脚本script.py位于/usr/bin/monitor/scripts,它的主要功能是使用subprocess.check_call()subprocess.check_output()来调用各种管理工具(/usr/bin/monitor/中的c程序1}}专为机器创建,以及/sbin中的fdisk -ldf -h中的Linux可执行文件。它被编写为以root运行,并以有用的方式将这些程序的输出打印到命令行。

我的项目是通过网页查看此脚本的输出。我正在使用Apache2进行Beaglebone Black,它使用来自其DocumentRoot www-data的用户/var/www/html/执行文件。网页设置如下:

  1. index.html使用iframe显示python CGI脚本的输出,该脚本也位于/var/www/html/

  2. script.cgi尝试使用子流程模块调用/显示script.py输出的输出

  3. 问题是script.py被调用得很好,但是script.py中的每个调用都会失败并返回script.py的错误消息,因为我认为当apache以用户身份运行时,它们需要以root身份运行www-data

    为了解决这个问题,我创建了一个名为bbb的新组,向该组添加了www-data,然后运行chown :bbb script.py将其组更改为bbb。不幸的是它仍然会导致相同的问题,所以我尝试将权限从755更改为775,这也不起作用。我尝试在script.py使用的文件/程序上运行chown :bbb *,但也无济于事。此外,script.py使用的一些可执行文件位于/sbin中,我谨慎地给它这样的目录提供全权限访问。

    由于我尝试修复所有权问题感觉有点像1000个猴子代码,我创建了新版本的脚本,我在其中创建了一个html输出列表,并且在原始代码中的每个print语句之后,我追加了同一行将文本作为带有html标记的字符串输出到html输出列表,然后在脚本的末尾(在whatami中)我创建并写入/var/www/html/中的.txt文件,然后调用os.chmod("/var/www/html/data.txt", 0o755)给apache访问权限。然后,CGI在script.py上调用subprocess.check_call(),然后打开,读取并将带有html格式的每一行打印到网页中的iframe。这种尝试至少可以产生准确的输出,但是......只有当它作为root在终端中运行时才会更新,而不是在刷新页面时重新运行script.py,这会破坏网页的这一点。我假设这意味着CGI脚本中的子进程check_call不能正常工作,但由于某种原因,子进程调用本身不会抛出任何错误或失败的迹象,但文本文件返回而不更新。即使“try”块中的子进程调用由“print('call successful')”成功,它也会返回成功消息,然后返回未更新的文本文件。

    我有点不知所措,试图弄清楚如何强制脚本运行并在后台执行此操作,以便文件将更新而不仅仅提供apache root访问权限。我已经阅读了一些关于将python脚本包装在shell中导致它以root身份运行,或者更改sudoers以提供www-data sudo特权,但我不想引入安全问题或制作什么是旨在成为一个简单的脚本,允许输出到网页变得比现在更复杂。任何建议或指示都将不胜感激。

1 个答案:

答案 0 :(得分:0)

最好的方式 IMO 将通过创建一个localhost-only服务来“解耦”执行,你可以通过本地套接字从apache进程“调用”。

E.g。如果使用systemd

  

创建:/etc/systemd/system/my-svc.socket

[Unit]
Description=My svc socket

[Socket]
ListenStream=127.0.0.1:1234
Accept=yes

[Install]
WantedBy=sockets.target
  

创建:/etc/systemd/system/my-svc@.service

[Unit]
Description=My Service
Requires=my-svc.socket

[Service]
Type=simple
ExecStart=/opt/my-service/script.sh %i
StandardInput=socket
StandardError=journal
TimeoutStopSec=5

[Install]
WantedBy=multi-user.target
  

创建/opt/my-service/script.sh:

#!/bin/sh
echo "id=$(id)"
echo "args=$*"
  

完成设置:

$ sudo chmod +x /opt/my-service/script.sh
$ sudo systemctl daemon-reload
  

尝试一下:

$ nc 127.0.0.1 1234
id=uid=0(root) gid=0(root) groups=0(root)
args=55-127.0.0.1:1234-127.0.0.1:32938

然后从您的cgi开始,您需要执行上述nc命令(仅限tcp连接)。

- jjo