【问题标题】:Is there a way to change effective process name in Python?有没有办法在 Python 中更改有效的进程名称?
【发布时间】:2010-10-08 13:25:52
【问题描述】:

我可以更改 Python 脚本的有效进程名称吗?当我获取系统进程列表时,我想显示一个不同的名称而不是进程的真实名称。在 C 中我可以设置

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

但是在 Python 中

argv[0] = "othername"

似乎不起作用。当我获得进程列表(在我的 linux 框中使用ps ax)时,真实名称不会改变。如果存在,我更喜欢便携式解决方案(或者一个用于 posix 的解决方案和另一个用于 Windows 环境的解决方案)。

提前致谢

【问题讨论】:

  • 现在有适用于 Windows 的解决方案吗? (也许使用 Python 3.x?)更准确地说:“Windows 任务管理器”(CTRL+SHIFT+ESCAPE)选项卡“进程”应在第一列“图像名称”中显示自定义字符串,而不仅仅是 python.exe或 pythonw.exe。注意:另一种解决方案,而不是将 python.exe 复制到 mycustomstring.exe ;)

标签: python process arguments hide ps


【解决方案1】:

我最近编写了一个 Python 模块来以可移植的方式更改进程标题:查看https://github.com/dvarrazzo/py-setproctitle

它是 PostgreSQL 用于执行标题更改的代码的包装器。它目前针对 Linux 和 Mac OS X 进行了测试:Windows(功能有限)和 BSD 移植正在进行中。

编辑:截至 2010 年 7 月,该模块适用于 BSD,但在 Windows 上功能有限,并已移植到 Python 3.x。

【讨论】:

  • 无法在 Windows 上安装。
  • @user 没关系:它在 Windows 上不是很有帮助,但没什么可做的。
  • 有没有办法改变 ps -f 显示的参数?我并不真正关心程序名称(总是 python),但我想更改显示的参数。
  • @KillianDS:你的意思是你想要“ps -f”的输出不同于“ps”的输出吗?你不能把它搞砸。
  • 那不是 Python 模块。它是一个 C 模块。
【解决方案2】:

实际上,你需要在 linux 上做两件事:从 C 修改 argv[0](用于 ps auxf 和朋友)并使用 PR_SET_NAME 标志调用 prctl

绝对没有办法从 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”:(。但topps -A 将显示新的“正在测试”进程名称:)。 killallpkill 也可以使用新名称。

顺便说一句,来自 googlecode 的 procname 也会更改 argv[0],因此,甚至会更改 ps auxf 输出。

更新:此答案中发布的解决方案有时在 FreeBSD 上效果不佳。我现在在各种 linux 和 freebsd 机器上使用 py-setproctitle 声明 in this answer 一年左右。到目前为止没有失败!大家也应该! :)。它在其主数据库和子进程中使用与PostgreSQL uses 几乎相同的代码。

【讨论】:

  • procname 在 PyPy 上不起作用(仅在 CPython 上)必须使用 setproctitle。
  • 函数的等效且更简单的实现是只写/读/proc/self/comm。另见:stackoverflow.com/a/68508813/427158
【解决方案3】:

看看setproctitle

这是一个相当便携的版本,适用于许多平台。

pip install setproctitle

 

import setproctitle

setproctitle.setproctitle('new proc title as seen in top')

【讨论】:

  • 这里是漂亮的简单解决方案。
  • 在 Linux 上完美运行。不能在 Windows 上运行,setproctitle 的文档也承认这一点。真正的 Windows 解决方案很可能很困难。
【解决方案4】:

简单地说,没有便携的方式。您必须测试系统并使用该系统的首选方法。

此外,我对 Windows 上的进程名称的含义感到困惑。

您的意思是服务名称吗?我想是的,因为没有其他东西真正有意义(至少对我的非 Windows 使用大脑而言)。

如果是这样,您需要使用Tim Golden's WMI interface并在服务上调用.Change方法......至少根据他的tutorial

对于 Linux,除了为您设置 argv[0] 的 this poorly packaged module 之外,我发现没有其他方法有效。

我什至不知道这是否适用于 BSD 变体(它确实有一个 setproctitle 系统调用)。我很确定 argv[0] 不会在 Solaris 上工作。

【讨论】:

  • 我知道已经很晚了,但对于新读者,还可以考虑@MattWritesCode answer,在 Linux 上快速简单地使用 CPython。
【解决方案5】:

首先,我不确定在 C 程序中简单地设置 argv[0] 是否会更改 ps 中显示的名称。也许它在某些 unixen 中确实如此,但我的理解是它不是预期的。

其次,由于 Windows 特别不兼容 POSIX,因此在 POSIX 和非 POSIX 之间只有少数东西是“可移植的”。由于您特别说“ps”,我假设 POSIX 是您的优先事项,Windows 可能无法正常工作。

更重要的是,我对更改argv[0] 的理解是,它需要调用exec 来进行这些更改。具体来说,exec 调用既有可执行文件的路径,也有单独的argv 列表。自己调用可以打破将可执行文件名称放在argv[0] 中的shell 约定。

您有OS library process management,它使您可以直接访问操作系统库来执行此操作。您应该考虑将您的脚本分成两部分——启动器和“实际工作”。启动器建立运行时环境,并使用所需参数执行实际工作。

在 C 中,您将自己的进程替换为另一个进程。在 Python 中,您将使用具有不同 argv[0] 的新解释器替换旧的 Python 解释器。希望它不会因此而犹豫。一些程序检查 argv[0] 来决定它们在做什么。

您还可以使用subprocess.popen 来设置所需的参数和可执行文件。但是,在这种情况下,父进程应该在子进程完成时逗留以收集子进程。家长可能除了Popen.wait

【讨论】:

  • 不,在 Linux(可能还有其他 Unix,但不是全部)中更改 argv 确实会立即更改可见进程名称,许多广泛使用的程序使用该名称为其进程提供描述性名称:两者ssh 和 postgres 会这样做,有些人会主动更改其名称以指示其当前状态。可以编写一个 Python 模块来执行此操作,使用 Py_GetArgcArgv API 调用。
【解决方案6】:

我对标记为duplicate的类似问题的回答:

有更简单的方式(您不需要导入任何库)但可能不是那么优雅。您必须不要在 shebang 行中使用“env”。

也就是说,这将在进程列表中被命名为“python”:

#!/usr/bin/env python

但这会以你的脚本名命名:

#!/usr/bin/python

因此,您可以使用 pidof -x scriptnameps -C scriptname 之类的内容找到它

【讨论】:

    【解决方案7】:

    我发现python-prctl 在 Linux 下工作得很好。您将不得不为 Windows 找到其他东西。

    【讨论】:

      【解决方案8】:

      如果你只需要支持 Linux 并且只需要更改进程名称,那么你可以简单地将其写入/proc/self/comm

      例子:

      import os
      import subprocess
      
      print(subprocess.run(['pidof', 'foo'], stdout=subprocess.PIPE,
              universal_newlines=True))
      print(subprocess.check_output(['ps', 'p', str(os.getpid()), '-o', 'pid,comm,cmd'],
              universal_newlines=True))
      
      with open(f'/proc/self/comm', 'w') as f:
          f.write('foo')
      
      print(subprocess.check_output(['pidof', 'foo'], universal_newlines=True))
      print(subprocess.check_output(['ps', 'p', str(os.getpid()), '-o', 'pid,comm,cmd'],
          universal_newlines=True))
      

      输出:

      $ python3 test.py argone argtwo
      CompletedProcess(args=['pidof', 'foo'], returncode=1, stdout='')
          PID COMMAND         CMD
      2881003 python3 test.py python3 test.py argone argtwo
      
      2881003
      
          PID COMMAND         CMD
      2881003 foo             python3 test.py argone argtwo
      

      注意:在 Linux 上,在 C 程序中,写入 argv[0] 只会更改 /proc/self/cmdlinenot 中的参数 /proc/self/comm。因此,它不会影响pidoftop COMMAND 列、ps COMMAND 列、普通pgrep 等。


      setproctitle 包支持多个平台,并且 - 在 Linux 上 - 更改了命令和参数向量。但是,它是一个 C 扩展。

      【讨论】:

        【解决方案9】:

        Windows 上的一个超级技巧是复制 python.exe,将其重命名为 process_name.exe,使用重命名的 python 调用您的脚本。

        这是一个超级 hacky,但由于在 Windows 上没有简单的解决方案,如果一个人只需要快速完成它以便一个脚本能够监控它,它是一个公平的选择。

        理论上它甚至可以编写脚本...超级骗子黑客!?

        【讨论】:

          【解决方案10】:
          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
          

          注意单个“=”符号

          【讨论】:

          • 但如果我运行 ps(linux 框中的进程列表),进程名称保持完全相同。试试
          • 这根本不会改变进程名称。它只会更改 Python 的 argv 副本。我建议删除这个明显错误的答案。
          猜你喜欢
          • 2015-02-02
          • 2021-02-12
          • 1970-01-01
          • 2021-09-12
          • 2018-12-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-28
          相关资源
          最近更新 更多