How to parse /proc/pid/cmdline
I'm trying to split the cmdline of a process on Linux but it seems I cannot rely on it to be separated by '\0' characters. Do you know why sometimes the '\0' character is used as separator and sometimes it is a regular开发者_如何学运维 space?
Do you know any other ways of retrieving the executable name and the path to it? I have been trying to get this information with 'ps' but it always returns the full command line and the executable name is truncated.
Thanks.
use strings
$ cat /proc/self/cmdline | strings -1
cat
/proc/self/cmdline
The /proc/PID/cmdline
is always separated by NUL characters.
To understand spaces, execute this command:
cat -v /proc/self/cmdline "a b" "c d e"
EDIT: If you really see spaces where there shouldn't be any, perhaps your executable (intentionally or inadvertently) writes to argv[]
, or is using setproctitle()
?
When the process is started by the kernel, cmdline is NUL-separated, and the kernel code simply copies the range of memory where argv[]
was at process startup into the output buffer when you read /proc/PID/cmdline
.
Use
cat /proc/2634/cmdline | tr "\0" " "
to get the args separated by blanks, as you would see it on a command line.
The command line arguments in /proc/PID/cmdline
are separated by null bytes. You can use tr
to replace them by new lines:
tr '\0' '\n' < /proc/"$PID"/cmdline
A shot in the dark, but is it possible that \0
is separating terms and spaces are separating words within a term? For example,
myprog "foo bar" baz
might appear in /proc/pid/cmdline
as...
/usr/bin/myprog\0foo bar\0baz
Complete guess here, I can't seem to find any spaces on one of my Linux boxes.
Have a look at my answer here. It covers what I found when trying to do this myself.
Edit: Have a look at this thread on debian-user for a bash script that tries its best to do what you want (look for version 3 of the script in that thread).
Super-simple (but for only one process, not bulk parsing, etc):
$ cat /proc/self/cmdline "a b" "cd e" | xargs -0
How it works: by default, xargs
just echo
'es its input, and switch -0
allows it to read null-separated lines rather than newline-separated ones.
Executable name:
cat /proc/${pid}/comm
Executable path:
readlink -f /proc/${pid}/exe
If you have a recent bash, you can use mapfile to split the command line into its arguments and put them in an array "command_line" like this:
mapfile -d '' -t command_line < "/proc/${pid}/cmdline"
Much more about /proc/ here: proc(5) — Linux manual page
精彩评论