Есть ли способ изменить эффективное имя процесса в Python? - PullRequest
72 голосов
/ 19 февраля 2009

Могу ли я изменить эффективное имя процесса скрипта Python? Я хочу показать другое имя вместо реального имени процесса, когда получаю список системных процессов. В C я могу установить

strcpy(argv[0],"othername");

Но в Python

argv[0] = "othername"

не похоже на работу. Когда я получаю список процессов (с ps ax в моем окне Linux), настоящее имя не меняется. Я предпочитаю переносимое решение (или одно решение для posix, а другое для среды Windows), если оно существует.

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

Ответы [ 8 ]

81 голосов
/ 08 декабря 2009

Я недавно написал модуль Python для переноса изменения названия процесса: check https://github.com/dvarrazzo/py-setproctitle

Это обертка вокруг кода, используемого PostgreSQL для изменения названия. В настоящее время он протестирован на Linux и Mac OS X: порты Windows (с ограниченной функциональностью) и BSD находятся в процессе.

Редактировать: по состоянию на июль 2010 г. модуль работает с BSD и имеет ограниченную функциональность в Windows и был портирован на Python 3.x.

50 голосов
/ 29 мая 2009

На самом деле вам нужно 2 вещи в Linux: изменить argv[0] из C (для ps auxf и друзей) и вызвать prctl с флагом PR_SET_NAME.

Нет абсолютно никакого способа сделать первый кусок из самого Python. Хотя вы можете просто изменить имя процесса, вызвав prctl.

def set_proc_name(newname):
    from ctypes import cdll, byref, create_string_buffer
    libc = cdll.LoadLibrary('libc.so.6')
    buff = create_string_buffer(len(newname)+1)
    buff.value = newname
    libc.prctl(15, byref(buff), 0, 0, 0)

def get_proc_name():
    from ctypes import cdll, byref, create_string_buffer
    libc = cdll.LoadLibrary('libc.so.6')
    buff = create_string_buffer(128)
    # 16 == PR_GET_NAME from <linux/prctl.h>
    libc.prctl(16, byref(buff), 0, 0, 0)
    return buff.value

import sys
# sys.argv[0] == 'python'

# outputs 'python'
get_proc_name()

set_proc_name('testing yeah')

# outputs 'testing yeah'
get_proc_name()

ps auxf после этого покажет только «python» :(. Но top и ps -A покажут новое имя процесса «testing yeah» :). Также killall и pkill будут работать с новым именем.

кстати, procname из googlecode также меняет argv[0], таким образом, даже меняет ps auxf вывод.

ОБНОВЛЕНИЕ : Решение, опубликованное в этом ответе, иногда плохо работает на FreeBSD. Сейчас я использую py-setproctitle , указанный в этом ответе в течение года или около того на различных Linux и FreeBSD коробках. Пока нет неудач! Все тоже должны! :). Он использует почти тот же код, что и PostgreSQL использует в своей основной базе данных и дочерних процессах.

13 голосов
/ 19 февраля 2009

Проще говоря, нет портативного пути. Вам придется проверить систему и использовать предпочтительный метод для этой системы.

Кроме того, я не совсем понимаю, что вы подразумеваете под именами процессов в Windows.

Вы имеете в виду название сервиса? Я так полагаю, потому что больше ничего не имеет смысла (по крайней мере, для моего не-Windows, использующего мозг).

Если это так, вам нужно использовать WMI-интерфейс Тима Голдена и вызывать метод .Change в службе ... хотя бы в соответствии с его учебником .

Для Linux ни один из найденных мною методов не работал, кроме этого плохо упакованного модуля , который устанавливает argv [0] для вас.

Я даже не знаю, будет ли это работать на вариантах BSD (в которых есть системный вызов setproctitle). Я уверен, что argv [0] не будет работать на Solaris.

7 голосов
/ 05 января 2010

Посмотрите на setproctitle package

Это довольно портативная версия и работает на многих платформах.

4 голосов
/ 19 февраля 2009

Во-первых, я не уверен, что просто настройки argv[0] в программе на C переносят имя, показанное в ps. Может быть, так и есть в некотором Unixen, но я понимаю, что это не ожидается.

Во-вторых, поскольку Windows не совместима с POSIX, только несколько вещей «переносимы» между POSIX и не POSIX. Поскольку вы специально говорите «ps», я предполагаю, что POSIX является вашим приоритетом, и Windows может не работать.

Что более важно, мое понимание изменения argv[0] заключается в том, что для внесения этих изменений требуется вызов exec. В частности, вызов exec имеет как путь к исполняемому файлу, так и отдельный список argv. Выполнение вашего собственного вызова позволяет нарушить соглашение оболочки о введении имени исполняемого файла в argv[0].

У вас есть Управление процессами библиотеки ОС , которое дает вам прямой доступ к библиотеке ОС для этого. Вы должны рассмотреть возможность разбить ваш сценарий на две части - стартер и «настоящая работа». Стартер устанавливает среду выполнения и выполняет реальную работу с требуемыми параметрами.

В C вы заменяете свой собственный процесс другим. В Python вы заменяете старый интерпретатор Python новым, который имеет другой аргумент argv [0]. Надеюсь, это не помешает. Некоторые программы проверяют argv [0], чтобы решить, что они делают.

У вас также есть subprocess.popen , который вы можете использовать для установки желаемых аргументов и исполняемого файла. В этом случае, однако, родительский процесс должен задерживаться, чтобы собрать ребенка, когда ребенок заканчивает. Родитель может не делать ничего, кроме Popen.wait

3 голосов
/ 25 ноября 2015

Мой ответ на аналогичный вопрос, помеченный как duplicate :

Есть более простой (вам не нужно импортировать какие-либо библиотеки), но, возможно, не такой элегантный способ. Вы не должны использовать «env» внутри линии Шебанга.

Другими словами, это будет называться "python" в списке процессов:

#!/usr/bin/env python

Но это будет названо с вашим именем сценария:

#!/usr/bin/python

Так что вы сможете найти что-то вроде pidof -x scriptname или ps -C scriptname

2 голосов
/ 07 февраля 2011

Я нашел python-prctl , который очень хорошо работает под Linux. Вам придется найти что-то еще для Windows.

0 голосов
/ 19 февраля 2009
In [1]: import sys

In [2]: print sys.argv[0]
C:\Python25\scripts\ipython.py

In [3]: sys.argv[0] = 'foo'

In [4]: print sys.argv[0]
foo

Обратите внимание на одиночный знак '='

...