ps只能在Linux上显示非内核进程吗?


Answers:


37

这应该做(在Linux下):

ps --ppid 2 -p 2 --deselect

kthreadd(PID 2)具有PPID 0(在Linux 2.6+上),但ps不允许过滤PPID 0;因此,此变通办法。


很好,但是如何保证kthreadd始终使用PID 2?
l0b0 2013年

@ l0b0我不知道:-)您可以分两个步骤进行操作:确定的PID kthreadd,然后构建相应的ps调用。如何保证这个东西“总是”被称为“ kthreadd”?一个安全的解决方案将更加复杂,可以ps正常运行并解析输出,还可以进行一些测试。
Hauke Laging 2013年

2
至少在x86 arch上的Linux 2.4中,这些进程具有ppid 1,因此无法通过这种方式进行区分。
斯特凡Chazelas

1
像“ ps -ef”一样做“ ps --ppid 2 -p 2 --deselect -f”,做像“ ps aux”一样做“ ps --ppid 2 -p 2 --deselect u”
彼得

1
我检查了@Totor,看起来像是对此x不起作用的标志。ps au --ppid 2 -p 2 --deselect工作正常。
Sankalp

9

识别内核进程的一种方法是它们不使用任何用户内存,因此vsz字段为0。这也捕获了僵尸(感谢Stephane Chazelas的观察),可以根据其状态将其消除。

ps axl | awk '$7 != 0 && $10 !~ "Z"'

仅列出PID:

ps -e -o pid= -o state= -o vsize= | awk '$2 != "Z" && $3 != 0 {print $1}'

像我的解决方案一样,它还将包括僵尸进程。
斯特凡Chazelas

1
@StephaneChazelas好点,我已经为过滤器添加了一个条件。
吉尔(Gillles)“所以-不要再邪恶了”

9

在实践中,我发现以下习语足够了:

ps auxf | grep -v ]$

它会过滤以方括号结尾的行,这可能会导致省略不需要的条目,但这是不太可能的。作为交换,它很容易记住并且键入起来相对较快。

诸如avahi-daemon之类的某些进程在其进程名称信息中添加方括号(对于avahi-daemon而言,为主机名),并将被此命令过滤掉。


8

这些进程的特殊性之一是它们没有可执行文件的支持,因此可以这样做(在zsh中):

ps /proc/[0-9]*/exe(^-@:h:t)

或与任何POSIX shell:

ps -p "$(find -L /proc/[0-9]*/exe ! -type l | cut -d / -f3 | paste -sd , -)"

那就是检查那些/proc/<pid>/exe是文件链接的进程。

但这意味着您需要成为超级用户才能检查/proc/<pid>/exe符号链接的状态。

编辑:僵尸进程(至少)满足相同条件,因此,如果您不希望将它们排除在外,则必须将其重新添加。喜欢:

ps -p "$(
  { find -L /proc/[0-9]*/exe ! -type l | cut -d / -f3
    ps -Ao pid=,state= | sed -n 's/ Z//p'
  } | paste -sd , -)"

请注意,将ps -f这些进程名称显示在方括号中并不是因为它们是内核进程,而是因为它们有一个空的argv[](因此ps显示的是进程名称,而不是argv[0]那里)。您可以使用户空间的进程也为空argv[],也可以使进程名argv[0]的形式为,[some-string]因此ps基于这些方括号过滤输出不是万无一失的选择。


我认为这是非标准的Shell语法。
Totor 2013年

1
就像我说的,@ Totor,第一个是zsh语法。第二种是标准POSIX sh(以及psfindcut与和paste)语法。当然/proc不是POSIX指定的。
斯特凡Chazelas

接受此答案,因为它是通用的(感谢您的编辑)。但是,只要不使用2.4内核,Hauke Laging的答案也非常好和直接。
Totor

@ Totor,Hauke的答案还具有不需要超级用户特权的优点。我的答案适用于2.4和2.6 / 3内核,但我想不能保证它一定能在4.x中运行。
斯特凡Chazelas

嗯,您是对的,我没有考虑过root特权。这可能会导致错误,因为当您不是root用户时仍会得到答案,但这是不同的(因此,在对它们进行计数时,请务必谨慎wc -l)。好吧,那我会接受Hauke Laging的回答,并给您点赞。;)
Totor 2013年

1

您也可以仅解析ps输出并查找不在方括号中的进程名称:

ps aux | awk '$NF!~/^\[.+\]$/'

获取感兴趣的用户列表的方法不太可靠:awk -F: '$7 ~ home { print $1 }' /etc/passwd-但是您仍将获得提及任何此类用户名的进程,并且将临时文件保留在身边。我将撤回我的赞成票,但这只是因为您的第三个解决方案是合理的。
Keith Thompson

Bah,您一直都是对的,@KeithThompson,删除了其他人,他们不值得。您能帮我清理一下(现在)过时的评论吗?
terdon

2
请注意,这$NFps aux输出中命令行的最后一个字。非内核进程可以在[...]那里。正如我在回答中所说的,[xxx]表示法不是因为它们是内核进程,而是因为它们没有命令行(没有参数),这也允许非内核进程使用。
斯特凡Chazelas

1

对于在busybox中尝试了此功能ps且简化程度大且输出不同的任何人,这种Gilles很好的答案很好用:

ps -o pid,user,comm,vsz,stat | awk '$4 != 0 && $5 !~ "Z"'

根据Gilles的回答,这里的方法是查找不使用任何用户内存的进程(vsz col == 0),并过滤掉僵尸进程(status col不是'Z')。

只要从1开始的awk字段号进行了相应调整,就可以轻松调整输出列。通过输入伪造的值来查看ps可用的选项,它将告诉您。例如:

$ ps -o foo
ps: bad -o argument 'foo', supported arguments: user,group,comm,args,pid,ppid,pgid,tty,vsz,stat,rss

0

如果您只需要计数... 我同样需要过滤内核与用户进程,但我只需要每个计数。这是我的解决方案:

ps -eo vsize | awk '{p[$1==0]++} END {printf "%-16s %6d\n%-16s %6d\n%-16s %6d\n", "Kernel processes", p[1], "User processes", p[0], "Total processes", p[0]+p[1]}'

样本输出

Kernel processes    353
User processes       52
Total processes     405

说明:我正在使用VSZ = 0进程可以假定为内核进程的技巧。因此,通过awk,我评估了VSZ(来自ps -eo vsize)的比较,是否等于零。比较的结果将是布尔值0或1。我创建一个数组p[],然后在进程列表中运行,如果它是内核进程,则我递增p[1]++。否则,作为用户进程,我将递增p[0]++。在所有增量之后,我标记并打印END { }块中p [0]和p [1]的值(即计数)。


0

我的朋友,您要找的不是ps,而是pstree

首先,确定第一个内核进程。它的PID通常在不带systemd的系统上为1,而带systemd的系统上为2。

然后使用以下命令:

$ pstree -p <1 or 2> | grep -o '([0-9]\+)' | grep -o '[0-9]\+'

所选答案(带有✅的答案)正在使用另一个命令:

$ ps --ppid 2 -p 2 --deselect

ps命令的问题在于它仅包括直接子代,而不包括所有后代。该pstree命令包括所有后代。您可以比较和计算这两个命令的输出(一种简单的方法是使用| wc)进行验证。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.