从Python中查找Linux中特定PID的命令

从Python中查找Linux中特定PID的命令,python,linux,process,Python,Linux,Process,我想知道是否有可能找到PID设置为的“命令”。当我说command时,我指的是在linux shell中运行命令“top”时在最后一列中看到的内容。当我有一个特定的PID时,我希望以某种方式从Python获得这些信息 任何帮助都会很好。谢谢。仔细阅读该命令并分析其输出 ps -p [PID] -o cmd 应该这样做proc文件系统导出此(和其他)信息。 查看/proc/PID/cmd符号链接。查看/proc/$PID/cmdline请不要在生产代码中使用/proc文件系统。相反,使用定义良

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

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

仔细阅读该命令并分析其输出

ps -p [PID] -o cmd 

应该这样做

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

查看
/proc/$PID/cmdline
请不要在生产代码中使用
/proc
文件系统。相反,使用定义良好的POSIX接口,例如glibc调用和标准shell命令!让Linux世界更加标准化,这真的需要

您需要的是通过调用shell命令很好地实现的

ps -p <YOUR PID> -o cmd h
ps-p-o cmd h
不需要解析


更不用说从python读取shell命令输出只需从
/proc
中的文件读取就可以了。这也让你的程序更具可移植性

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

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

  • avahi守护程序:chroot-helper
  • qmgr-l-t先进先出-u
  • /usr/sbin/postgree--pidfile=/var/run/postgree.pid--daemonize--inet=127.0.0.1:60000--delay=55
第一个很明显——它不是有效的路径或程序名。第二个是没有路径名的可执行文件。第三个看起来不错,但整个命令行实际上位于
argv[0]
中,参数之间用空格分隔。通常,应该有NUL分隔参数

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

但是,
/proc/$PID/exe也不是。通常,它是指向可执行文件的符号链接,可执行文件是进程的主要文本段。但如果文件系统中不再有可执行文件,则有时会在其后面加上“
(已删除)

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

我决定解析
/proc/$PID/cmdline
——获取向量的第一个元素,然后在其中查找空格,并在第一个空格之前获取所有内容。如果那是一个可执行文件,我就到此为止。否则,我在
/proc/$PID/exe
上执行了一个readlink(2),并删除了末尾的所有“
(已删除)
”字符串。如果可执行文件名中实际有空格,则第一部分将失败。对此你无能为力


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

一个有趣的python包

例如,要获取特定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
这对我很有用:

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
def过滤器不可打印(str):
ret=“”
对于str中的c:
如果ord(c)>31或ord(c)==9:
ret+=c
其他:
ret+=“”
回程网
#
#获取/proc//cmdline信息
#
def pid_名称(pid):
尝试:
将open(os.path.join('/proc/',pid,'cmdline'),'r')作为pid文件:
返回不可打印的筛选器(pidfile.readline())
除例外情况外:
通过
返回

几乎是真的,但问题是针对linux的,所以我们确实回答了实际问题,我想我们大多数人都假设他知道
ps(1)
@DigitalRoss:那么这个问题听起来像是“ps
从哪里获取命令行信息?”ps通过读取/proc中的虚拟文件来工作。关于定义良好的POSIX接口(到底是哪一个?)就到此为止。听着,我本来会把你们两个都标记为正确答案的,但我做不到。Pavel的答案似乎更符合我的要求,但DigitalRoss的答案也很棒。尼克·斯泰尼特斯和迈克尔·福卡拉基斯都投了赞成票。嘿,我知道ps是如何工作的(是的,它确实可以读取
/proc
中的文件)。但是当他们发明了
/foobar
系统而不是
/proc
时,你必须重写你的程序。不管怎么说,也许我在LSB工作组工作时受到了脑损伤,但你真的应该坚持那些对你来说足够的标准——这就是我们正在考虑的情况。写得好。谢谢你,卡姆。我已经知道如何从Linux获取这些信息了。祝贺您真正获得了“来自Python的此信息”!你赢得了我的选票。