python脚本script.py
位于/usr/bin/monitor/scripts
,它的主要功能是使用subprocess.check_call()
和subprocess.check_output()
来调用各种管理工具(/usr/bin/monitor/
中的c程序1}}专为机器创建,以及/sbin
中的fdisk -l
和df -h
中的Linux可执行文件。它被编写为以root
运行,并以有用的方式将这些程序的输出打印到命令行。
我的项目是通过网页查看此脚本的输出。我正在使用Apache2进行Beaglebone Black,它使用来自其DocumentRoot www-data
的用户/var/www/html/
执行文件。网页设置如下:
index.html
使用iframe显示python CGI脚本的输出,该脚本也位于/var/www/html/
script.cgi
尝试使用子流程模块调用/显示script.py
输出的输出
问题是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特权,但我不想引入安全问题或制作什么是旨在成为一个简单的脚本,允许输出到网页变得比现在更复杂。任何建议或指示都将不胜感激。
答案 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