Введите 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) он не должен быть интерактивным, то есть вы можете легко написать скрипт, который подключается к процессу и печатает некоторую информацию из него.