демон python убит (ядром?)

У меня есть процесс демона python2.7, использующий модуль из http://www.jejik.com/files/examples/daemon.py

Это тяжелый процесс с использованием около 40 ГБ ОЗУ и 9 дочерними потоками. Сервер использует RHEL 6.3 с 192 ГБ ОЗУ и достаточной мощностью процессора.

После запуска процесс длится где-то 3-7 часов, но потом его кто-то убил, может ядро. Но я не смог найти никаких подсказок ни в dmesg, ни в журнале ядра (который я активировал вручную), там ничего нет. Когда я не запускался как демон, я просто получил сообщение в терминале: «убит».

Были предприняты следующие меры предосторожности:

  • сброс оценки oom в /proc//oom_score_adj, чтобы oom killer не выбирал процесс при сортировке ресурсов
  • увеличение всех rlimits (которые могут быть увеличены) до максимума
  • установите процесс хороший/приоритет выше (приоритет -15)

Эта проблема существует уже до применения этих мер предосторожности, поэтому они не несут ответственности за убийство

У меня также есть механизм для перехвата всех исключений, STDERR, STDOUT и регистрации всего в ротационном файле журнала. Но не было ничего интересного непосредственно перед смертью процесса.

Модули, используемые в процессе, среди прочего: oracle_cx, ibm_db, suds, wsgi_utils. Но все они всегда пишут логи при возникновении ошибок.

Кто-нибудь знает, как отследить убийство? Кто и почему?

заранее спасибо


person Kurnia Hendrawan    schedule 06.05.2013    source источник
comment
Включили ли вы coredump, чтобы увидеть, получаете ли вы дамп при убийстве?   -  person Mansour    schedule 06.05.2013
comment
Нет у меня нет. Проблема в том, что мы используем SSD объемом около 128 ГБ, и места для дампа ядра не хватает, когда у процесса было 40 ГБ ОЗУ.   -  person Kurnia Hendrawan    schedule 06.05.2013
comment
Учитывая вашу большую оперативную память и предполагая, что ваш процесс на мгновение не заполняет все это (что приводит к тому, что ядро ​​​​убивает его), вы можете сохранить дамп памяти в оперативной памяти (через tmpfs).   -  person Mansour    schedule 06.05.2013
comment
возможный дубликат Кто убил мой процесс и почему?   -  person Aaron Digulla    schedule 06.05.2013


Ответы (2)


Чтобы увидеть, кто вошел в систему в момент, когда процесс был убит, используйте команду last.

Если в это время никто не вошел в систему, процесс был убит каким-то сигналом.

Поскольку это Python, самый простой способ выяснить, что убило процесс, — написать обработчик сигналов для всех сигналов и запротоколировать их. См. здесь, как написать обработчик сигнала. См. этот вопрос, как поймать их все.

Если вы получили дамп ядра, подключите внешний жесткий диск с достаточным пространством. Или ограничить размер ядра до 1 ГБ, используя ulimit; этого может быть достаточно, чтобы увидеть, где он разбился.

Либо запустите процесс с помощью отладчика, такого как gdb; это гарантирует, что вы получите подсказку, когда процессу будут отправлены сигналы «дампа ядра».

person Aaron Digulla    schedule 06.05.2013
comment
Ни один человек не убил процесс, я в этом почти уверен. Нельзя изменить обработчик SIGKILL. - person Kurnia Hendrawan; 06.05.2013
comment
Если вы видите kill в терминале, это не значит, что его убил SIGKILL. Сообщение печатается для любого необработанного сигнала. И точно не режет :-) - person Aaron Digulla; 06.05.2013
comment
Демон уже обрабатывает сигналы SIGTERM, SIGABRT, SIGINT и SIGSTOP. Другие сигналы приведут к другому сообщению, чем «убито». Сейчас я пытаюсь получить дамп ядра с помощью виртуального диска, как это было предложено Мансуром. - person Kurnia Hendrawan; 06.05.2013
comment
Я видел Killed для процесса, который не обрабатывал SIGCHLD. Также ищите слишком усердные процессы мониторинга, которые пытаются защитить систему. - person Aaron Digulla; 06.05.2013
comment
Не могли бы вы назвать некоторые из таких процессов мониторинга? Я действительно думал об этом, но я не знаю. Кстати, я также использую monit, чтобы попытаться перезапустить процесс, если он умер, но он перестал отслеживать, когда процесс умер, но это другая проблема. - person Kurnia Hendrawan; 06.05.2013
comment
Опечатка выше: SIGALRM вместо SIGSTOP - person Kurnia Hendrawan; 06.05.2013
comment
системные администраторы иногда устанавливают инструменты; У меня нет под рукой имени. Кто следит за машиной? Они должны знать :-) Также: Вы заглядывали в /var/log/kern.log? - person Aaron Digulla; 06.05.2013
comment
И проверьте также /etc/security/limits.conf - person Aaron Digulla; 06.05.2013

Я думаю, что нашел основную причину, и это может быть ошибка в Python 2.7. После перехвата всех улавливаемых сигналов и их игнорирования я мог отследить еще несколько сообщений об ошибках и получить подсказку о socket.error. Дело в том, что такая ошибка сначала вызовет SIGTERM (попробуйте убить процесс), а затем запишется в STDERR. Мой механизм для перехвата всех STDOUT и STDERR мог регистрировать сообщения, потому что основной процесс был убит. В любом случае это проблема демона. Это были последние строки в журнале непосредственно перед завершением процесса.

2013-05-07 11:05:53,194 - STDERR - ERROR - Traceback (most recent call last):
2013-05-07 11:05:53,304 - STDERR - ERROR -   File "/var/lib/netcam_epd/lib/python2.7/SocketServer.py", line 582, in process_request_thread
2013-05-07 11:05:53,415 - STDERR - ERROR -     self.finish_request(request, client_address)
2013-05-07 11:05:53,489 - STDERR - ERROR -   File "/var/lib/netcam_epd/lib/python2.7/SocketServer.py", line 323, in finish_request
2013-05-07 11:05:53,587 - STDERR - ERROR -     self.RequestHandlerClass(request, client_address, self)
2013-05-07 11:05:53,684 - STDERR - ERROR -   File "/var/lib/netcam_epd/lib/python2.7/SocketServer.py", line 640, in __init__
2013-05-07 11:05:53,835 - STDERR - ERROR -     self.finish()
2013-05-07 11:05:53,887 - STDERR - ERROR -   File "/var/lib/netcam_epd/lib/python2.7/SocketServer.py", line 693, in finish
2013-05-07 11:05:54,084 - STDERR - ERROR -     self.wfile.flush()
2013-05-07 11:05:54,182 - STDERR - ERROR -   File "/var/lib/netcam_epd/lib/python2.7/socket.py", line 303, in flush
2013-05-07 11:05:54,326 - STDERR - ERROR -     self._sock.sendall(view[write_offset:write_offset+buffer_size])
2013-05-07 11:05:54,387 - STDERR - ERROR - error: [Errno 32] Broken pipe

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

Я проверю, действительно ли это основная причина.

person Kurnia Hendrawan    schedule 07.05.2013