/proc/pid/stat
在 Linux 上按空格分割有哪些缺点?例如,使用bash
一个可以通过访问第三列
$ cat /proc/$$/stat
14198 (bash) S 14195 14198 14198 34816 ...
$ x=($(< /proc/$$/stat)); echo ${x[2]}
S
$
一切似乎都很好?
答案1
主要问题是空格字符 ( 0x20
) 既用作记录之间的分隔符,也可能出现在记录内;本地用户是否应该能够设置进程名称
$ perl -e '$0="like this"; sleep 999' &
[1] 14343
$
那么按空格进行解析分割将会失败
$ x=($(< /proc/14343/stat)); echo ${x[2]}
this)
$
因为命令名称包含空格。
$ cat /proc/14343/stat
14343 (like this) S 14198 14343 ...
$
这有多糟糕?根据proc(5)
“进程的控制终端”很有趣
tty_nr %d (7) The controlling terminal of the process. (The
minor device number is contained in the combination
of bits 31 to 20 and 7 to 0; the major device number
is in bits 15 to 8.)
因此,如果一个进程滥用了由于某人更改了该信息而错误解析的控制终端信息/proc/pid/stat
,那么,您可能会出现安全漏洞。
)
尽管有 15 个字符的限制,但可以将a 放在进程名称中,因此解析变得更加复杂
$ perl -e '$0="lisp) a b c d e f g h i"; sleep 999' &
[4] 14440
$ cat /proc/14493/stat
14493 (lisp) a b c d e) S 14198 14493 14198 34816 ...
$
解析界面缺陷的想法
由于进程名称可以在空字符串和几乎任何内容的 15 字节之间变化
1234 () S ...
4321 (xxxxxxxxxxxxxxx) S ...
一个想法是分割第一个空格以获得 pid,然后从该字符串的末尾向后查找第一个)
;右边第一个之前的内容)
应该是进程名称,左边是常规字段。强烈建议对代码进行单元测试......
答案2
如果您需要思考,为什么不直接阅读/proc/$pid/status
呢?它在标记精美的线条上提供了相同的信息,和转义进程名称中出现的换行符和反斜杠:
$ perl -e '$0="foo\nbar\n"; system "head -3 /proc/$$/status";'
Name: foo\nbar\n
Umask: 0022
State: S (sleeping)