ps - -o comm 和 -o 命令有什么区别?

ps - -o comm 和 -o 命令有什么区别?

在 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/0rcu_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 fnamefor 相当于 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
    

相关内容