![从 ps 输出中排除 ps 本身](https://linux22.com/image/219526/%E4%BB%8E%20ps%20%E8%BE%93%E5%87%BA%E4%B8%AD%E6%8E%92%E9%99%A4%20ps%20%E6%9C%AC%E8%BA%AB.png)
我想获取系统中所有进程的信息除了ps
过程本身。
也就是说,类似:
ps --no-headers --pid 1111 -N
在哪里1111
是进程ID现在运行ps
命令。
我尝试过类似的东西
ps --no-headers --ppid $$ -N
然而,这确实不行何时ps
在“子进程”中运行,例如:
IFS=' ' read pctd proc <<<$(/bin/ps --no-headers --ppid $$ -No pcpu,pid,comm --sort=+pcpu | tail -n 1)
最后一个命令尝试获取“最近”使用最多 CPU 的进程的 CPU 使用百分比和进程 ID 以及名称。
IFS=' ' read pctd proc <<<$(/bin/ps --no-headers -eo pcpu,pid,comm --sort=+pcpu | tail -1)
直到最近都工作正常。然而,更新到 Ubuntu 23.04(或内核 6.x)后ps
开始有时将自己列为使用 100% CPU。
目前,以下似乎是一种解决方法(但并不安全):
IFS=' ' read pctd proc <<<$(/bin/ps --no-headers -eo pcpu,pid,comm --sort=+pcpu | grep -v \ ps | tail -1)
答案1
排除ps
自身:
sh -c 'exec ps --no-headers --pid "$$" -N'
sh
将其自己的 PID 替换为$$
,但随后将其自身替换为ps
。 PID不改变,这就是exec
工作原理。这种方式ps
接收它自己的 PID 作为 的选项参数--pid
。
注意此方法排除这 ps
本身而不是其他ps
进程(如果有)。
答案2
作为一般化如何去除ps
自己的条目,特别是对于ps
不支持非标准-N
/--deselect
选项的实现,常见的做法是:
print_pid_and_run() {
sh -c 'echo "$$" && exec "$@"' sh
}
print_pid_and_run ps ...ps-options... |
awk 'NR == 1 {pid = $0; next}
$1 != pid'
(根据传递给的选项,更改输出$1
中具有进程 pid 的实际字段)。ps
ps
在 zsh 中,sh
可以通过执行以下操作来避免运行:
zmodload zsh/system
print_pid_and_run() (echo $sysparams[pid] && exec "$@")
在bash中:
print_pid_and_run() (echo "$BASHPID" && exec "$@")
(请记住bash
,与上面相反zsh
, in 不能用于运行内置函数或函数)。
答案3
不是对您问题的回答,而是对您的评论:
IFS=' ' read pctd proc <<<$(/bin/ps --no-headers --ppid $$ -No pcpu,pid,comm --sort=+pcpu | tail -n 1)
最后一个命令尝试获取“最近”使用最多 CPU 的进程的 CPU 使用百分比和进程 ID 以及名称。
我不知道,你的方法在那里被误导了。pcpu
返回自进程存在以来任何 CPU 运行进程的任何线程所花费的时间与总时间的比率。
例如,一个进程可能会启动,花几毫秒初始化自身,就像执行命令时一样(在此期间,它可能会在 1 毫秒内使用接近 100% 的 CPU),然后休眠 10 小时,然后生成 20 个线程,充分利用 20 个线程。 CPU 持续 1 分钟(top
例如,在此期间将显示 2000% CPU 使用率)。如果此时运行ps -o pcpu
,该进程将在总共 601 分钟内使用 20 分钟的 CPU,因此您会看到大约 3%,而不是 2000%。另一方面,如果您碰巧在命令启动ps
时运行该命令,可能会发现该进程使用了 1 毫秒的 CPU 时间超过 1 毫秒,并报告 100% CPU 利用率。sleep 1h
ps
如果您想获取仍在运行且在过去 3 秒内使用最多 CPU 时间的进程,您需要在某一时刻收集所有进程的 CPU 时间,然后在 3 秒后再次收集并执行以下操作:减法,你不能使用ps -o pcpu
它,或者你可以top
在批处理模式下使用一些类似的应用程序来为你进行计算。