【问题标题】:pygame.init() fails when run with systemd使用 systemd 运行时 pygame.init() 失败
【发布时间】:2017-01-05 01:18:29
【问题描述】:

我正在尝试使用 systemd 运行 python pygame 脚本,由于某种原因,该脚本只是退出而没有错误。 这是在带有 Raspian “Jessie lite” 的 Raspberry Pi 上。

如果我使用“sudo python myscript.py”手动运行脚本,它可以正常工作。

sudo systemctl status myscript.service 报告:

* 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 start 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 而有些却没有?

【问题讨论】:

  • 听起来像是错误或配置问题。除非通过 SendSIGHUP=KillSignal= 指定,否则 Systemd 不应发送 SIGHUP ...
  • 一个可能的解决方案是在 systemd 中禁用 SIGHUP,但我不确定这会产生什么其他影响:stackoverflow.com/questions/55392107/…

标签: python-2.7 raspberry-pi pygame systemd


【解决方案1】:

对我来说,解决方案是只初始化我需要的特定模块。

在我的例子中,pygame.init() 我只初始化了pygame.mixer.init(),现在 systemd 可以启动服务了。

【讨论】:

    【解决方案2】:

    我没有答案,但我遇到了同样的事情,所以我会添加更多细节。

    以下是精简代码:

    #!/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 来解决它,但经过这么多调试后,我很想知道发生了什么。

    【讨论】:

      【解决方案3】:

      首先,检查您的日志:

      journalctl -u myservice.service
      

      将此添加到您的单元文件可能会改进日志记录:

      StandardOutput=journal+console
      

      在某些情况下,如果某些日志记录发生在服务退出之前,日志不会被服务标记,因此在运行服务后,还要查看:

      journalctl
      

      适用于服务退出后的条目。

      另外,改用network.target,试试network-online.target

      我认为应用程序本身可以从命令行运行。假设它以这种方式工作而不是来自 systemd,那么不同的环境变量可能是一个问题。在您的应用程序顶部添加一行以转储所有环境变量,并比较从 systemd 与 CLI 运行时的输出。

      最后,查看Type= 的文档。如果默认 Type= 不适用于您的情况,请适当设置。

      systemd 的未来问题可能会在Unix & Linux StackExchange 得到更好的回答,因为它们与编程没有直接关系。

      您还应该发布您的systemd 单元文件,因为这是您遇到的问题。

      【讨论】:

      • 我的 Python 脚本正在编写自己的日志文件,因此我知道它正在执行以及它正在执行多远。我认为这不是系统配置问题。关于环境变量的好主意。我将 systemd 中的环境与“Environment=”标签相匹配,使其与在命令行中运行时完全相同,但没有帮助。
      猜你喜欢
      • 2021-07-30
      • 2020-05-27
      • 2016-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多