Введите pdb с сигналом уничтожения

В недавнем проекте я хочу отладить свою программу в состоянии производственного использования. Производственная среда очень сложная, поэтому я хочу отлаживать программу всякий раз, когда обнаруживаю проблему.

Это то, чего я хочу достичь: всякий раз, когда я хочу отладить, я отправлю в программу сигнал уничтожения, и, надеюсь, появится отладчик pdb. Это что-то вроде этого:

import pdb
import signal
import time

def handler(signal, frame):
  pdb.set_trace()

signal.signal(signal.SIGTERM, handler)
a=1
while True:
  a+=1
  time.sleep(1)

Тем не менее, так как я должен запустить программу с nohupвсе выходные данные будут перенаправлены в nohup.out, поэтому я не могу взаимодействовать с pdb.

Есть ли что-нибудь подобное, чтобы сделать это?

2 ответа

Решение

Если вы запускаете программу из терминала, вы можете использовать tty Команда, чтобы отметить устройство tty, на котором вы находитесь, и передать его программе в среде:

TTY=`tty` nohup ./myprog.py

а затем в обработчике снова откройте tty и установите stdin и stdout в файл:

import sys,os

def handler(signal, frame):
  tty = os.getenv('TTY')
  sys.stdin = sys.stdout = open(tty,"r+")
  pdb.set_trace()

Если вы отсоединяете программу от текущего tty, как в вашем комментарии, то вы можете попробовать нечто подобное с тем же кодом на python. На этот раз запустите вашу программу с:

TTY=/tmp/link  nohup ./myprog.py &

и закройте терминал. Откройте новый терминал и создайте недостающую ссылку на этот новый tty:

ln -s `tty` /tmp/link

Затем в одной строке введите команду kill, чтобы сообщить процессу Python, а затем немедленно выполните команду sleep, Это связано с тем, что оболочка больше не конкурирует с pdb за ввод tty. Например, в одной строке:

kill -term $pid; sleep 99999

Затем у вас будет pdb-соединение с / tmp / link, которое является вашим tty. Когда вы выйдете из pdb, нажатие ctrl-c остановит сон.

Если вам нужно использовать ctrl-c в pdb, и вы используете bash, замените sleep 99999 от suspend, Когда вы выходите из pdb, используйте меню вашего терминала для отправки сигнала sigcont процессу, чтобы вернуть приостановленный bash.

Совершенно другой подход, который, на мой взгляд, проще и элегантнее, заключается в использовании rpyc, Я уже давно использую этот подход в своей сложной системе, и это значительно облегчает отладку в режиме реального времени.

По сути, вам нужно определить простую службу API rpyc, которая содержит "открытые" методы для возврата ссылок ("netrefs") на наиболее интересные объекты в вашей системе. Затем вы запускаете rpyc ThreadedServer в своем процессе во время запуска.

Затем, когда вы захотите, вы можете просто создать клиент rpyc и подключиться к процессу, получить ссылки на объекты через API и проверить их (прозрачно, как если бы эти netrefs были локальными объектами). Используя правильные методы API, вы можете в значительной степени получить доступ ко всему, что вы хотите в процессе реального времени.

Другие преимущества этого подхода заключаются в том, что (1) этот интерактивный сеанс даже не должен влиять на запущенный процесс (если, конечно, вы не вызываете методы, которые вызывают побочные эффекты и т. Д.), (2) он не должен быть интерактивным, то есть вы можете легко написать скрипт, который подключается к процессу и печатает некоторую информацию из него.

Другие вопросы по тегам