Как вы отправляете выходные данные сценария upstart на терминал, чтобы найти трассировки в коде python? Мне постоянно нужно делать вещи без следов, которые раньше занимали всего секунду. Я должен сделать несколько вызовов записи файла, чтобы отследить ошибки. То, что потребовалось секунда, чтобы найти раньше с помощью traceback, заняло несколько минут. Это жалко Это продолжается уже несколько недель, и мне это надоело. Могут ли некоторые высказаться по этому вопросу, пожалуйста. Я чувствую, что снова использую сборку без отладчика.
Существует целый раздел о методах отладки в Upstart Cookbook . Самое простое, что вы можете сделать, это добавить --debug
к аргументам вашего ядра, что увеличит многословность upstart и сбросит все в syslog. Да, отладка сложна, она отражает сложность сети, необходимую для создания параллельной системы инициализации. Я уверен, что есть место для улучшения.
Если вы используете Upstart 1.4 или новее, вставьте console log
в задание Upstart, и весь вывод в stdout / stderr будет равен /var/log/upstart/<job>.log
. Затем вы можете сделать tail -f /var/log/upstart/<job>.log &
, чтобы вывод появился на терминале.
Когда я пишу Python-демон, я ловлю все исключения и добавляю их в файл журнала. Я использую не только для отладки, но и в производстве. У меня есть небольшой скрипт, который я запускаю каждое утро и который ищет что-то огорчающее в журналах.
Это также помогает поддерживать работу демона.
Пример кода (я убираю неинтересные части):
import logging
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(levelname)s %(message)s',
filename=LOG_FILE,
filemode='w')
logging.info("Sincrod inicializado")
if not DEBUG:
daemonize()
while True:
try:
actua()
except:
logging.error(sys.exc_info())
if (datetime.datetime.now().hour > NOITE_EMPEZA\
and datetime.datetime.now().hour < NOITE_REMATA):
time.sleep(INTERVALO_NOITE)
else:
time.sleep(INTERVALO_DIA)
Где actua () - настоящий демон (он также пишет в журнал). Обратите внимание, что у меня также есть переменная DEBUG в файле настроек, когда она True, я не разветвляю демона, поэтому он запускается на консоли.
Демоны
Демоны - это Unix-эквивалент служб Windows. Это процессы, которые работают в фоновом режиме независимо от других процессов. Это означает, что их отец обычно init, и они отделены от любого tty. Поскольку они независимы, не существует заранее определенного места для размещения их результатов.
Существует множество библиотек python и фрагментов кода для создания демона, в приведенном выше примере я использую свою собственную функцию, которая объединяет некоторые идеи из версий Steinar Knutsens и Jeff Kunces. Это настолько просто, насколько это возможно, обратите внимание, что я разветвляюсь дважды .
def daemonize():
"""Forks this process creating a daemon and killing the original one"""
if (not os.fork()):
# get our own session and fixup std[in,out,err]
os.setsid()
sys.stdin.close()
sys.stdout = NullDevice()
sys.stderr = NullDevice()
if (not os.fork()):
# hang around till adopted by init
ppid = os.getppid()
while (ppid != 1):
time.sleep(0.5)
ppid = os.getppid()
else:
# time for child to die
os._exit(0)
else:
# wait for child to die and then bail
os.wait()
sys.exit()