我正在尝试使用systemd运行python pygame脚本,由于某种原因,脚本只是退出而没有错误。 这是Raspberry Pi与Raspian“Jessie lite”。
如果我使用“sudo python myscript.py”手动运行脚本,它可以正常工作。
sudo systemctl status myscript.service reports:
* myscript.service - Python Script
Loaded: loaded /etc/systemd/system/myscript.service; enabled) Active: inactive (dead) since Mon 2016-08-29 04:33:19 UTC; 1s ago
Process: 3275> ExecStart=/usr/bin/python /home/pi/myscript.py (code=killed, signal=HUP)
Main PID: 3275 (code=killed, signal=HUP)
如果我使用sudo systemctl启动myscript.service手动启动服务,则会发生同样的事情。
我已将我的脚本删除到pygame.init()调用。这就是它退出的地方。
如果我尝试手动初始化模块,则“cdrom”,“joystick”,“threads”和“font”正常初始化,但调用display.init()会导致程序退出。没有例外。
我在网上找到的唯一资源是this guy。看来他遇到了我所看到的完全相同的事情。 我试过strace,如果我等了足够长的时间(2分钟),它会起作用! 显然我不能一直用strace跑。我认为它会减慢初始化的执行速度,以某种方式使其工作。
编辑: 所以这个问题似乎是systemd发送一个SIGHUP。如果在Python中未处理此操作,则默认操作是退出。快速解决方法是抓住SIGHUP:
import signal
def handler(signum, frame):
pass
try:
signal.signal(signal.SIGHUP, handler)
except AttributeError:
# Windows compatibility
pass
这么多灼热的问题。为什么systemd会这样做?为什么strace解决这个问题?为什么有些Python脚本会获得SIGHUP而其他Python脚本却没有?
答案 0 :(得分:1)
对我来说,解决方案只是初始化我需要的特定模块。
在我的情况下pygame.init()
我只初始化pygame.mixer.init()
,现在systemd可以启动服务。
答案 1 :(得分:0)
首先,检查您的日志:
journalctl -u myservice.service
将其添加到您的单元文件可能会改善日志记录:
StandardOutput=journal+console
在某些情况下,如果在服务退出之前发生了某些日志记录,则日志不会被服务标记,因此在运行服务之后,还要查看:
journalctl
对于退出服务后的条目。
另外,使用network.target
代替network-online.target
。
我认为应用程序本身可以从命令行运行。假设它以这种方式工作而不是来自systemd,不同的环境变量可能是一个问题。在应用程序顶部添加一行以转储所有环境变量,并在从systemd
与CLI运行时比较该输出。
最后,查看Type=的文档。如果默认Type =不适用于您的案例,请相应地进行设置。
systemd
可能会更好地回答systemd
特有的未来问题,因为它们与编程没有直接关系。
您还应发布<div class="col-md-3">
<div class="btn-group">
<a type="button" class="btn btn-danger btn-justified-90">Proveedor</a>
<a type="button" class="btn btn-danger dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
</ul>
</div>
</div>
单元文件,因为这是您遇到的问题。
答案 2 :(得分:0)
我没有答案,但我遇到了同样的事情,所以我会添加更多细节。
这是减少的代码:
#!/usr/bin/python2.7
import logging
from pygame import display
import signal
import time
def handler(signum, frame):
"""Why is systemd sending sighups? I DON'T KNOW."""
logging.warning("Got a {} signal. Doing nothing".format(signum))
signal.signal(signal.SIGHUP, handler)
signal.signal(signal.SIGTERM, handler)
signal.signal(signal.SIGCONT, handler)
logging.warning("About to start display.")
try:
display.init() # hups
except Exception as ex:
logging.warning("Got any exception: %s " % ex)
logging.warning("Quitting in 60")
time.sleep(60)
这是产生的日志:
Jul 8 22:30:27 beardog systemd[1]: Started PyGame Test.
Jul 8 22:30:27 beardog pygame[17406]: WARNING:root:About to start display.
Jul 8 22:30:27 beardog pygame[17406]: WARNING:root:Got a 1 signal. Doing nothing
Jul 8 22:30:27 beardog pygame[17406]: WARNING:root:Got a 18 signal. Doing nothing
Jul 8 22:30:27 beardog pygame[17406]: WARNING:root:Quitting in 60
在SIGHUP之后立即获得SIGCONT,但没有SIGTERM。 Systemd声称只在SIGTERM之后发送一个SIGHUP,所以也许它来自其他地方?我在pygame代码中找不到任何相关内容。
我已启用systemd调试日志记录,但它不会打印任何有趣的内容。
这是我的systemd配置。
[Unit]
Description=PyGame Test
After=syslog.target network.target network-online.target graphical.target
[Service]
Type=simple
WorkingDirectory=/path/to/code/pygame/
ExecStart=/path/to/code/pygame/why.py
Restart=always
RestartSec=5
LimitNOFILE=10000
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=pygame
SendSIGHUP=no
[Install]
WantedBy=multi-user.target
我已经尝试过这样的Type = forking,oneshot和dbus(虽然它不是任何一个)。我也试过TimeoutStartSec = 20,但没有变化。在Ubuntu Xenial笔记本电脑和运行Raspbian的Raspberry pi上测试。 python2.7和python3都有。手动运行时代码工作正常,并且在systemd中的strace下运行时似乎有效。 / O \
和OP一样,我可以通过捕获SIGHUP来解决它,但经过这么多的调试后我很想知道发生了什么。