【问题标题】:Finding the command for a specific PID in Linux from Python通过 Python 在 Linux 中查找特定 PID 的命令
【发布时间】:2009-09-17 19:44:09
【问题描述】:

我想知道是否有可能找出 PID 设置的“命令”。当我说命令时,我的意思是当您在 linux shell 中运行命令“top”时在最后一列中看到的内容。当我有一个特定的 PID 时,我想以某种方式从 Python 获取这些信息。

任何帮助都会很棒。谢谢。

【问题讨论】:

    标签: python linux process


    【解决方案1】:

    使用 /proc 文件的缺点是可移植性较低,这可能是问题,也可能不是问题。以下是您可以使用标准 shell 命令的方法

    ps -w -w -p <YOUR PID> -o cmd h
    

    注意两个 -w 选项,它们指示 ps 不截断输出(默认情况下会截断)

    从 python 读取其输出就像调用单个函数 subprocess.check_output() 记录的 here 一样简单。

    【讨论】:

    • @DigitalRoss:那么问题听起来就像“ps 从哪里获取命令行信息?”
    • ps 通过读取 /proc 中的虚拟文件来工作。定义良好的 POSIX 接口就这么多(到底是哪一个?)。
    • 听着,我会把你们两个都标记为正确答案,但我不能。 Pavel 的答案似乎更像是我所寻找的,但为 DigitalRoss 提供的答案也很棒。两者都赞成。
    • @Nick Stinemates,@Michael Foukarakis。嘿,我知道 ps 是如何工作的(是的,它确实读取了/proc 中的文件)。但是当他们发明/foobar 系统而不是/proc 时,你将不得不重写你的程序。无论如何,也许我在 LSB 工作组工作时受到了脑损伤,但你真的应该坚持对你来说足够的标准——这是正在考虑的情况。
    • 这个命令会输出命令行参数,但是用空格隔开。如果您尝试将参数拆分回字符串列表,您将无法区分 args 和带空格的 args。 (你可以/proc/$PID/cmdline做)
    【解决方案2】:

    查看/proc/$PID/cmdline

    【讨论】:

      【解决方案3】:

      一个有趣的 Python 包是psutil

      例如,获取特定 PID 的命令:

      import psutil
      pid = 1234 # The pid whose info you're looking for
      p = psutil.Process(pid)
      print(p.cmdline())
      

      最后一行将打印['/usr/bin/python', 'main.py']

      获取此信息的更可靠的方法,如果 pid 代表不再运行的进程,请小心:

      import psutil
      pid = 1234 # The pid whose info you're looking for
      if pid in psutil.get_pid_list():
          p = psutil.Process(pid)
          print(p.cmdline())
      

      【讨论】:

        【解决方案4】:

        阅读ps 命令并解析其输出。

        ps -p [PID] -o cmd 
        

        应该这样做

        【讨论】:

        • 如果命令行太长,此命令将截断命令行,并且不适用于包含空格的参数(有关详细信息,请参阅Thanatos's comment here)。
        【解决方案5】:

        查看/proc/$PID/cmdline,然后查看/proc/$PID/exe 上的os.readlink()。

        /proc/$PID/cmdline 不一定是正确的,因为程序可以更改其参数向量,或者它可能不包含完整路径。我当前的进程列表中的三个示例是:

        • avahi-daemon: chroot helper
        • qmgr -l -t fifo -u
        • /usr/sbin/postgrey --pidfile=/var/run/postgrey.pid --daemonize --inet=127.0.0.1:60000 --delay=55

        第一个很明显 - 它不是有效的路径或程序名称。第二个只是一个没有路径名的可执行文件。第三个看起来不错,但整个命令行实际上是在argv[0] 中,用空格分隔参数。通常你应该有 NUL 分隔的参数。

        所有这些都表明/proc/$PID/cmdline(或 ps(1) 输出)不可靠。

        但是,/proc/$PID/exe 也不是。通常它是作为进程主要文本段的可执行文件的符号链接。但有时如果可执行文件不再在文件系统中,它后面会有“(deleted)”。

        此外,作为文本段的程序并不总是您想要的。例如,上面的/usr/sbin/postgrey 示例中的/proc/$PID/exe/usr/bin/perl。这将适用于所有解释脚本 (#!)。

        我决定解析/proc/$PID/cmdline - 获取向量的第一个元素,然后在其中寻找空格,并在第一个空格之前获取所有元素。如果那是一个可执行文件 - 我停在那里。否则我在/proc/$PID/exe 上做了一个readlink(2) 并在最后删除了任何“(deleted)”字符串。如果可执行文件名中实际上包含空格,则第一部分将失败。您对此无能为力。

        顺便说一句。使用 ps(1) 而不是 /proc/$PID/cmdline 的参数在这种情况下不适用,因为您将退回到 /proc/$PID/exe。您将依赖于/proc 文件系统,因此您最好使用 read(2) 而不是 pipe(2)、fork(2)、execve(2)、readdir(3)...、write( 2),阅读(2)。虽然从 Python 代码行的角度来看 ps 和 /proc/$PID/cmdline 可能是相同的,但 ps 在幕后还有很多事情要做。

        【讨论】:

        • 很棒的文章。谢谢你,camh。
        【解决方案6】:

        proc 文件系统导出此(和其他)信息。 查看 /proc/PID/cmd 符号链接。

        【讨论】:

          【解决方案7】:

          这对我有用:

          def filter_non_printable(str):
              ret=""
              for c in str:
                  if ord(c) > 31 or ord(c) == 9:
                      ret += c
                  else:
                      ret += " "
              return ret
          
          
          #
          # Get /proc/<cpu>/cmdline information
          #
          def pid_name(pid):
              try:
                  with open(os.path.join('/proc/', pid, 'cmdline'), 'r') as pidfile:
                      return filter_non_printable(pidfile.readline())
          
              except Exception:
                  pass
                  return
          

          【讨论】:

            猜你喜欢
            • 2014-11-06
            • 1970-01-01
            • 2011-03-04
            • 2022-01-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-09-13
            • 1970-01-01
            相关资源
            最近更新 更多