Pull to refresh

Переименование процессов в Python

Reading time 4 min
Views 6.3K
Когда пишешь многопроцессное приложение на питоне хочется иметь какой-то максимально простой способ мониторинга за работой отдельных процессов. Я сейчас не говорю про детальные аналитические отчеты на 10 страницах, а про получение минимальной информации о здоровьи и работе каждого процесса: чем он сейчас занят, насколько грузит систему, сколько памяти отожрал и т.п. Примерно как nginx или postgres сообщают о себе: одного взгляда в top либо ps достаточно, чтобы понять что и как делает каждый процесс.
Осталось разобраться как это можно сделать в питоне на ОС Linux (на примере Debian и FC).


В поисках решения:
Увы, решить проблему «одним наскоком» не удалось — какого-то готового решения не существовало. Это было для меня странно: такой развитый язык, огромное коммунити, первые сообщения об успешном запуске в космос переименовании процесса датированы чуть ли не 2003 годом. И вот спустя пять лет еще нет хорошего готового решения. Были ссылки на умершие проекты, рецепты, разнозненные куски кода. Кроме того, выяснилось, что top и ps, которые мне всегда казались братьями-близнецами, имеют разные взгляды на то, откуда надо брать название процесса для показа. А значит, по-хорошему, надо для каждого из них проводить отдельное переименование.

Анализ исходников показал: чтобы успешно переименовать процесс нужно сделать два действия — заменить его название в argv[0], а так же сделать системный вызов с новым именем. Сделать такое на C — как два байта переслать, а вот на питоне это становится задачкой со звездочкой. К счастью, питон хорошо интегрируется с C и нам нужно сделать библиотечный вызов. Увы, со стандартными средствами типа dl дело не заладилось — оказалось, что эта библиотека стандартна только для 32-битного дебиана, а в 64-битном ее нет даже в расширенных пакетах. Нашелся такой пакет для сусяшки (suse), но, пардон, варить жуткую кашу из разнородных пакетов на своей системе совсем не хочется. Альтернативная либа ctypes (само название которой говорит само за себя), увы, тоже не помогла. Из экзотики могу еще отметить решение на PyInline — компиляция куска С-шного кода в питоновский модуль по ходу выполнения программы с загрузкой этого модуля. Но от такого «интерпретируемого С» волосы встают дыбом! И, как оказалось, не зря — программа захворала. Примерно в половине случаев запуск заканчивался выпадением даже не в traceback, а сразу в кору с вываливанием кишок стека на 3 экрана. Может дело было и не в самом инлайне — просто в объемной программе всегда есть коктейль из модулей, с которыми он мог конфликтовать, а в жизни есть более интересные и важные задачи, чем разгребание этих конфликтов.

Решение:
В конце концов меня утомили эти заигрывания С-шным кодом. Если уже и так понятно, что надо писать главную рабочую часть на Сях, то нафик эти костыли и прокладки! Лучше сразу сделать честый С-шный код и дать ему интерфейсы к питону — то бишь сделать такой модуль.

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

Спасибо, Гвидо! Где можно записаться в армию твоих фанатов? :)

В итоге все получилось просто и красиво: исходный код ровно на 1 страницу + коротенький Makefile для сборки. После компиляции получается so-файл размером около 7К.

Использование
Проще простого:
>>> import procname
>>> procname.getprocname() # получить текущее имя процесса
'python'
>>> procname.setprocname('Bla-bla test') # дать новое имя процесса — проверьте в top и ps!
# снова можно посмотреть имя процесса
>>> procname.getprocname()
'Bla-bla test'


Где взять и как собрать?
Я выложил проект на гугль-код: code.google.com/p/procname
Скачайте исходники во временную папку, а дальше как обычно:
$ tar -zxf procname-XX.tar.gz
$ cd procname-XX
$ make

После этого у вас в текущей папке должен оказаться файл procname.so — скопируйте его в папку своей программы либо, если хотите, чтобы либу можно было использовать в любой программе, то в папку /usr/lib/python2.5/site-packages
Если вместо файла выдаются какие-то ошибки, проверьте есть ли у вас все необходимое. Для сборки потребуется пакет python-devel, make (тот который gnu) и, конечно, компилятор gcc :)
Скорее всего проблема будет в неверном указании местонахождения заголовочных файлов Python.h и sys/prctl.h. Найдите их поиском и укажите папку в файле Makefile. Если не поможет — пишите сюда будем разбираться вместе.

Отказ от ответственности:
Как обычно в таких случаях, данная библиотека предоставляется «как есть». Я не гарантирую ничего: в т.ч. что она у вас заработает, будет работать правильно, или хотя бы соберется. А так же то, что ваш сервер не превратится в Большой Андронный Коллайдер и не поглотит все в радиусе 100 миль.
От себя добавлю, что либа протестирована на Debian (32- и 64-bit), FedoraCore (все с ядрами ветки 2.6). Я использую либу почти месяц на «боевом» сервере.

Как насчет других *nix?
В других unix-ах организовано немного по-другому. В частности во FreeBSD есть специальный системный вызов setproctitle, позволяющий задать имя процесса для отображения в ps. Там же, кстати, указывается на его нестандартность. Впрочем аналог есть в AltLinux. В Debian ситуация непонятная, хотя вроде как Дмитрий из Альтов портировал свою либу, но я не смог ее обнаружить в etch и lenny.

Как я это использую на практике?
В моей программе каждый процесс в один момент времени обрабатывает одну задачу. При запуске он первым делом переименовывается, ставя себе в имя нечто вроде номер задачи и статус, примерно так: 'ICd: 7562 — starting'. Далее при каждом важном событии (напрмиер, смена статуса, новая задача, получение сигнала от ОС и т.п.) он снова переименовывается. В итоге я вижу ход обработки каждой задачи, могу своевременно обнаруживать аномалии в потреблении ресурсов, замедлении обработки, повторах и т.п. и вовремя на них реагировать.

Вывод
Мониторинг процессов стал приятным занятием — запускаешь top, откидываешься в кресле и наблюдаешь как твои «питошки» радостно вгрызаются в данные :)

Вообще, на мой взгляд было бы правильно сделать такую универсальную питоновскую библиотеку, чтобы на любом линуксе и фришке можно было свободно работать с именами процессов, не привязываясь к тому, как это реализовано. А может даже и на винде!


Буду рад любым замечаниям, предложениям, идеям.

P.S. Большое спасибо всем, кто помог в подготовке данной статьи к публикации на Хабре. Без вас она была бы невозможна!
Tags:
Hubs:
+12
Comments 16
Comments Comments 16

Articles