在 CentOS 7.0.1406 上运行时我得到不同的输出
ps -A -o pid,command | grep [r]esque
比我跑步时
ps -A -o pid,comm | grep [r]esque
后者什么也不返回;前者是我所期望的。我的印象是这comm
是 的别名command
。有人可以解释一下区别吗?
答案1
它们不是别名,command
输出完整命令并且comm
只有命令名称,因此输出可能不同。这完全取决于您想要提取 grep 命令的内容。
一个例子:
$ ps -A -o pid,command | grep 9600
376 /sbin/agetty --keep-baud 115200 38400 9600 ttyS0 vt220
并且以下内容的输出为空:
ps -A -o pid,comm | grep 9600
该字符串9600
是完整命令的一部分,但不是命令名称。
command
、 和cmd
是 , 的别名args
, with 打印命令及其所有参数作为字符串。comm
是一个不同的排序代码,仅打印可执行文件名称。手册页片段:
args COMMAND command with all its arguments as a string.
cmd CMD see args. (alias args, command).
comm COMMAND command name (only the executable name).
command COMMAND see args. (alias args, cmd).
答案2
在 Linux 上,使用 procps(-ng)(至少)实现ps
(CentOS 上就是这种情况):
comm
是进程名称。它是从 16 个字节检索的/proc/<pid>/stat
,并且限制(截断)为 16 个字节。这通常是execve()
进程(或其任何祖先)进行的最后一个系统调用的第一个参数的基本名称,除非它是内核线程,在这种情况下,它是内核线程的名称,例如watchdog/0
或rcu_sched
或进程已使用 更改了它prctl(PR_SET_NAME)
。这是输出CMD
中的字段ps
。command
又名是传递给进程(或其任何祖先)进行的args
最新系统调用的参数的串联。execve()
如果没有参数(如内核线程),则ps
使用[process-name]
(如上所述的用方括号括起来的进程名称)。这是从 检索到的/proc/<pid>/cmdline
。这是输出CMD
中的字段ps -f
。请注意,对于脚本,execve()
在 she-bang 解析后再次在内部调用。进程还可以通过覆盖它收到的 argv[] 字符串来更改该值。
POSIX 指定 comm
(意味着是argv[0]
) 和args
(作为字符串的 arg 列表,尽管没有说明该列表如何表示(用空格连接?)),而不是command
。因此,该procps
实现不符合要求,因为comm
那里没有 argv[0]。 Solaris,经过认证的实现确实具有 argv[0] forcomm
和 has fname
for 相当于 procps' comm
(作为输出CMD
中的列ps
)。
例子:
与 的关系
execve()
:$ ln -s /bin/sleep very-long-alias-for-sleep $ strace -e execve bash -c 'exec -a different-argv0 ./././very-long-alias-for-sleep 12' & execve("/bin/bash", ["bash", "-c", "exec -a different-argv0 ./././ve"...], [/* 52 vars */]) = 0 10:56 execve("/home/stephane/././very-long-alias-for-sleep", ["different-argv0", "12"], [/* 51 vars */]) = 0 $ ps -o comm,command COMMAND COMMAND [...] very-long-alias different-argv0 12 [...]
perl
覆盖其进程名称和参数列表:$ perl -e '$0 = "new name"; system("ps -p $$ -o comm,command")' COMMAND COMMAND new name new name
脚本的行为:
$ cat test-script #! /bin/sh -e ps -o comm,command -p "$$" exit $ strace -e execve ./test-script arg execve("./test-script", ["./test-script", "arg"], [/* 52 vars */]) = 0 COMMAND COMMAND test-script /bin/sh -e ./test-script arg
/bin/sh
最终使用不同的参数列表执行,但进程名称仍然保留test-script
。这里收到argv[0]
的sh
是/bin/sh
。在某些系统上,它test-script
是。关于祖先的注释:
$ ((((ps -o pid,comm,command;:);:);:);:) PID COMMAND COMMAND 4109 zsh /bin/zsh 23146 zsh /bin/zsh 23147 zsh /bin/zsh 23148 zsh /bin/zsh 23149 zsh /bin/zsh 23150 ps ps -o pid,comm,command
2314{6,7,8,9} 进程从未执行过任何命令,它们从执行 /bin/zsh 的父进程 (4109) 继承进程名称和参数列表。
23150
它本身最初有一个与其他进程一样的进程名称,但在执行时zsh
更改为。ps
/bin/ps
用于
-o 'comm'
通过名称来区分线程:$ ps -T -o pid,tid,pcpu,bsdtime,comm,command -C firefox.real | sort -k3nr # result is sorted by third column '%CPU' 10743 10743 4.9 14:44 firefox.real /usr/bin/firefox.real --private-window 10743 10775 0.3 1:01 Compositor /usr/bin/firefox.real --private-window 10743 10750 0.0 0:00 Gecko_IOThread /usr/bin/firefox.real --private-window 10743 10751 0.0 0:16 Timer /usr/bin/firefox.real --private-window 10743 10752 0.0 0:00 Link Monitor /usr/bin/firefox.real --private-window 10743 10753 0.0 0:06 Socket Thread /usr/bin/firefox.real --private-window 10743 10755 0.0 0:00 JS Watchdog /usr/bin/firefox.real --private-window 10743 10756 0.0 0:04 JS Helper /usr/bin/firefox.real --private-window ... PID TID %CPU TIME COMMAND COMMAND