ps -e
将大写进程名称转换为小写。我无法在手册页或在线中找到对该行为的解释,并且我不擅长阅读源代码来从中找出答案。
我通常使用ps -ef
(完整格式列表),因此从未注意到这种行为,但 DBA 注意到了。
-e
小写是流程线的预期行为吗?有人能解释为什么它被编码为小写吗?
这是相同过程的示例,但使用-e
和 then with -ef
:
server ~> ps -e | grep -Ei pmon
2187719 ? 00:00:02 ora_pmon_foobar
2188497 ? 00:00:02 ora_pmon_phuuba
2188928 ? 00:00:02 ora_pmon_kilgor
[printed as lowercase when instance name (end of line) should be uppercase ]
server ~> ps -ef | grep -Ei pmon
oracle 2187719 1 0 04:00 ? 00:00:02 ora_pmon_FOOBAR
oracle 2188497 1 0 04:00 ? 00:00:02 ora_pmon_PHUUBAR
oracle 2188928 1 0 04:01 ? 00:00:02 ora_pmon_KILGORE
[prints upper case, which is good]
-e
alone 也会截断,但这就是我们得到-f
.主要对-e
小写进程感到好奇。
答案1
ps
有和没有-f
在列中给出不同的信息CMD
。
在 Linux 上,
- 没有-f,这就是进程名称。进程的属性,长度限制为 15 个字节。该属性由系统调用(用于执行命令)设置
execve()
为正在执行的文件的基本名称,截断为 15 个字节,也可以由进程使用prctl(PR_SET_NAME)
.与返回的结果相同ps -o comm
。它可以在/proc/pid/stat
内部(...)
或现场Name:
看到/proc/pid/status
。 - 与-f,这就是参数列表用空格字符连接。这些是
argv[0]
在第二个参数中传递给execve()
已执行命令的进程(或其任何祖先)的系统调用的参数(包括)。 arg 列表可以在 中看到 NUL 分隔/proc/pid/cmdline
。与返回的结果相同ps -o args
。它曾经被截断为 4096 字节,但在最近版本的 Linux 中不再如此(尽管ps
除非给定选项,否则会截断它本身以进行输出-w
)。进程可以(有限制地)通过在找到该信息的堆栈部分写入新文本来更改这一点。
/proc/pid/exe
也将是进程当前正在运行的可执行文件的符号链接(如 所报告的ps -o exe
),这也可能不同。
无论如何,除了转义不可打印的字符之外,ps
不会对这些字符进行任何转换。
你可以运行:
ps -wwo comm,args,exe -p 2187719
要查看 id 2187719 进程的进程名称、参数列表和可执行文件。您可以使用ps
以下命令检查获取该信息的原始源:
cat /proc/2187719/stat
sed -n l /proc/2187719/cmdline
readlink /proc/2187719/exe
例子:
$ cp /usr/bin/sleep 'A longer sleep command for demonstration'
$ (exec -a 'SLEEP though could be anything' './A longer sleep command for demonstration' Infinity) &
[1] 6723
$ ps -fp "$!"
UID PID PPID C STIME TTY TIME CMD
chazelas 6723 6668 0 06:17 pts/2 00:00:00 SLEEP though could be anything Infinity
$ ps -p "$!"
PID TTY TIME CMD
6723 pts/2 00:00:00 A longer sleep
$ cat "/proc/$!/stat"
6723 (A longer sleep ) S 6668 6723 6668 34818 6726 4194304 154 0 0 0 0 0 0 0 25 5 1 0 17863 19312640 448 18446744073709551615 94858855174144 94858855192393 140731919224688 0 0 0 0 0 0 1 0 0 17 0 0 0 0 0 0 94858855206160 94858855207424 94858855886848 140731919232547 140731919232587 140731919232587 140731919237069 0
$ sed -n /Name/l "/proc/$!/status"
Name:\tA longer sleep $
$ sed -n l "/proc/$!/cmdline"
SLEEP though could be anything\000Infinity\000$
$ perl -e '$0 = "whatever you want"; sleep 20' &
[1] 13861
$ ps -wo comm,args,exe -p "$!"
COMMAND COMMAND EXE
whatever you wa whatever you want /usr/bin/perl
就您而言,如果情况有所不同,可能是因为
- 这些过程做了
execve("/path/to/ora_pmon_foobar", ["ora_pmon_FOOBAR", NULL], envlist);
- 他们做到了
execve("/path/to/anything", ["ora_pmon_FOOBAR", NULL], envlist)
(anything
也可能是ora_pmon_FOOBAR
),但后来做了一个prctl(PR_SET_NAME, "ora_pmon_foobar")
。 - 他们这样做了
execve("/path/to/ora_pmon_foobar", ["ora_pmon_foobar", NULL], envlist);
,但后来用 覆盖了argv[0]
它们ora_pmon_FOOBAR
。
或者以上的组合。例如,在 中perl
,分配 to 会$0
同时更改进程名称和参数列表,如上例所示。
1 除非该参数列表为空,例如execve()
由进程以空列表作为第二个参数调用时(导致argc
== 0),或者它们或其任何祖先都没有execve()
像内核任务那样调用过的进程。在这种情况下,ps -f
会在方括号内显示进程/任务名称。