2016-08-29 5 views
3

Я пытаюсь запустить скрипт pygame python с systemd, и по какой-то причине сценарий просто выходит без ошибки. Это на малиновой пи с распятым «Jessie lite».pygame.init() не работает при запуске с systemd

Если я запускаю сценарий вручную с помощью «sudo python myscript.py», он отлично работает.

Судо systemctl отчеты Статус 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) 

Если я запустить службу вручную с Судо systemctl начинают myscript.service то же самое происходит.

Я удалил свой скрипт только для вызова pygame.init(). Здесь он выходит.

Если я пытаюсь инициализировать модули вручную, тогда «cdrom», «joystick», «threads» и «font» инициализируются нормально, но вызов display.init() заставляет программу выйти. Исключено исключение.

Единственный ресурс, который я мог найти в Интернете, - this guy. Кажется, он столкнулся с тем же, что и я. Я пробовал strace, и если я подожду достаточно долго (2 минуты), это сработает! Очевидно, я не могу работать с strace все время. Я думаю, что это замедляет выполнение инициализации, чтобы каким-то образом позволить ей работать.

EDIT: Таким образом, проблема заключается в отправке системы 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, а другие нет?

+0

Звучит как ошибка или проблема с конфигурацией. Systemd не должен посылать 'SIGHUP', если не указано через' SendSIGHUP = 'или' KillSignal = '... – dhke

ответ

0

Во-первых, проверьте ваши журналы:

journalctl -u myservice.service 

Добавление этого на ваш файл модуля может улучшить ведение журнала:

StandardOutput=journal+console 

В некоторых случаях, если некоторые протоколирование происходит только перед выходом службы, журналы не будут отмечены этим сервисом, поэтому после запуска службы также просмотрите:

journalctl 

Для записи сразу после выхода вашего сервиса.

Также, используя network.target, попробуйте network-online.target.

Я предполагаю, что приложение работает ОК из командной строки. Предполагая, что это работает именно так, а не из systemd, могут быть проблемы с различными переменными среды. Добавьте строку вверху вашего приложения, чтобы сбрасывать все переменные среды и сравнивать этот вывод при запуске от systemd по сравнению с CLI.

Наконец, просмотрите документы для Type=. Если по умолчанию Type = не применяется к вашему делу, установите его соответствующим образом.

Возможные ответы на вопросы, относящиеся к systemd, могут быть лучше удовлетворены на Unix & Linux StackExchange, поскольку они напрямую не связаны с программированием.

Вы также должны опубликовать свой файл systemd, так как это то, с чем вы столкнулись.

+0

Мой скрипт Python записывает собственный файл журнала, поэтому я знаю, что он выполняется и как далеко он добирается. Я не думаю, что это проблема конфигурации systemd. Хорошая идея о переменных среды. Я сопоставил среду в systemd с тегами «Environment =», получая ее точно так же, как когда она запускается в командной строке, но это не помогло. – user5541269

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 

Это сразу же получить SIGCONT после SIGHUP, но не SIGTERM. Systemd утверждает, что только когда-либо посылает SIGHUP после SIGTERM, так что, возможно, это происходит откуда-то еще? Однако я не могу найти ничего полезного в коде pygame.

Я включил ведение журнала отладки 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, onehot и dbus (хотя это не любые из них). Я также пробовал TimeoutStartSec = 20, но никаких изменений. Протестировано на ноутбуке Ubuntu Xenial и на малине pi, работающем на Raspbian. И python2.7, и python3. Код работает отлично, когда запускается вручную, и, похоже, работает при запуске в strace в systemd./o \

Как и в OP, я могу обойти это, поймав SIGHUP, но после этой большой отладки я бы хотел узнать, что происходит.