How to get the command line args passed to a running process on unix/linux systems?
Asked Answered
T

14

242

On SunOS there is pargs command that prints the command line arguments passed to the running process.

Is there is any similar command on other Unix environments?

Tremann answered 4/5, 2009 at 20:18 Comment(1)
tr \\0 ' ' < /proc/<pid>/cmdlineSensorimotor
G
367

There are several options:

ps -fp <pid>
cat /proc/<pid>/cmdline | sed -e "s/\x00/ /g"; echo

There is more info in /proc/<pid> on Linux, just have a look.

On other Unixes things might be different. The ps command will work everywhere, the /proc stuff is OS specific. For example on AIX there is no cmdline in /proc.

Geny answered 4/5, 2009 at 20:26 Comment(9)
on linux, you'll probably need -ww (ie ps -ww -fp <pid>) to specify wide output since if there are several commands, they could get cut off.Ovaritis
For clarification, the file is not /<pid>/ but rather /proc/<pid>Umbilical
the -ww option allows access to full command-line arguments (as much as is stored by the kernel). See Also: how solaris and bsd get the untruncated commandline parameters for a process and ps optionsElurd
cat /proc/<pid>/cmdline also works on Cygwin, where cmd line arguments are not shown in ps with any option.Alderson
On Linux, if you only need to get the args, the command is ps -o args -p <pid> and it will only print the args or use -o cmd if you only need to see the cmd. Trying to read /proc/<pid>/cmdline will not always work for unprivilege users. The ps utility will work.Perilous
Hint: length of /proc/<pid>/cmdline is limited (hard coded to value of PAGE_SIZE kernel parameter), so longer command lines are still shown truncated! See #199630 for more info. You can query your kernel setting with getconf PAGE_SIZE, it's usually 4096.Condensate
wow that is genius, the ps -fp command worked for me on Debian and Ubuntu.Zannini
Note that the command can be executed with a different name (first arg); in which case you can look at /proc/<pid>/commWhalen
3c67b1b73daf:~# ps -fp 22823 ps: unrecognized option: p BusyBox v1.28.4 (2018-07-17 15:21:40 UTC) multi-call binary.Retrieve
D
73

This will do the trick:

xargs -0 < /proc/<pid>/cmdline

Without the xargs, there will be no spaces between the arguments, because they have been converted to NULs.

Doing answered 15/11, 2012 at 14:12 Comment(3)
It is stil truncating my output. Any advise?Gannes
Never noticed any truncation - can you give an example?Radman
This way, you cannot say if it's an inline space or an argument boundary.Darbies
B
28

Full commandline

For Linux & Unix System you can use ps -ef | grep process_name to get the full command line.

On SunOS systems, if you want to get full command line, you can use

/usr/ucb/ps -auxww | grep -i process_name

To get the full command line you need to become super user.

List of arguments

pargs -a PROCESS_ID

will give a detailed list of arguments passed to a process. It will output the array of arguments in like this:

argv[o]: first argument
argv[1]: second..
argv[*]: and so on..

I didn't find any similar command for Linux, but I would use the following command to get similar output:

tr '\0' '\n' < /proc/<pid>/environ
Balbo answered 6/11, 2012 at 5:40 Comment(1)
ps -ef is the command I was looking forThesda
A
25

On Linux

cat /proc/<pid>/cmdline

outputs the commandline of the process <pid> (command including args) each record terminated by a NUL character.

A Bash Shell Example:

$ mapfile -d '' args < /proc/$$/cmdline
$ echo "#${#args[@]}:" "${args[@]}"
#1: /bin/bash
$ echo $BASH_VERSION
5.0.17(1)-release
Arch answered 4/5, 2009 at 20:24 Comment(7)
Whitespace isn't removed, it's replaced with NULs.Jarboe
@Jarboe Ah, I did not check that. Good catch!Arch
xargs -0 echo < /proc/<pid>/cmdline . You can also do this with /proc/<pid>/environ too, although you may want to add -n 1 for that.Unfasten
On my system there is no /proc filesystem :( any other solution ?Tremann
Mine is a java process with long long long parameters. It is stil truncating my output. Any advise?Gannes
I've just realized that I voted down this answer by accident. I intended to vote it up. Sorry.Theatrician
@DavidRissatoCruz That must be where all those mystery down-votes come from! :-)Piegari
C
19

You can use pgrep with -f (full command line) and -l (long description):

pgrep -l -f PatternOfProcess

This method has a crucial difference with any of the other responses: it works on CygWin, so you can use it to obtain the full command line of any process running under Windows (execute as elevated if you want data about any elevated/admin process). Any other method for doing this on Windows is more awkward ( for example ).
Furthermore: in my tests, the pgrep way has been the only system that worked to obtain the full path for scripts running inside CygWin's python.

Cletus answered 2/4, 2014 at 2:16 Comment(2)
This one actually prints the original executable name too: $ exec -a fakename bash & [1] 14102 [1]+ Stopped exec -a fakename bash $ xargs -0 < /proc/14102/cmdline; fakename $ pgrep -l -f fakename; 14102 bashWhalen
Doesn't work for me using pgrep from procps-ng 3.3.15 and 3.3.12. Just prints the pid and prorgam name without arguments.Noticeable
C
4

Another variant of printing /proc/PID/cmdline with spaces in Linux is:

cat -v /proc/PID/cmdline | sed 's/\^@/\ /g' && echo

In this way cat prints NULL characters as ^@ and then you replace them with a space using sed; echo prints a newline.

Chura answered 12/11, 2013 at 10:29 Comment(1)
FYI, you can also use cat -v /proc/PID/cmdline | sed 's/\^@/\n/g'. This will replace the null character with a newline character. In doing so, each argument will be printed to it's own line. That way, it's easier to tell one argument from another.Susannsusanna
J
4

Rather than using multiple commands to edit the stream, just use one - tr translates one character to another:

tr '\0' ' ' </proc/<pid>/cmdline
Jack answered 14/8, 2014 at 11:30 Comment(0)
G
3

ps -eo pid,args prints the PID and the full command line.

Graphy answered 24/8, 2022 at 16:16 Comment(0)
B
2

You can simply use:

ps -o args= -f -p ProcessPid
Bowleg answered 2/2, 2017 at 17:28 Comment(0)
B
1

In addition to all the above ways to convert the text, if you simply use 'strings', it will make the output on separate lines by default. With the added benefit that it may also prevent any chars that may scramble your terminal from appearing.

Both output in one command:

strings /proc//cmdline /proc//environ

The real question is... is there a way to see the real command line of a process in Linux that has been altered so that the cmdline contains the altered text instead of the actual command that was run.

Burnsed answered 30/9, 2014 at 17:7 Comment(0)
M
1

try ps -n in a linux terminal. This will show:

1.All processes RUNNING, their command line and their PIDs

  1. The program intiate the processes.

Afterwards you will know which process to kill

Menhir answered 24/11, 2014 at 2:43 Comment(0)
G
1

On Solaris

     ps -eo pid,comm

similar can be used on unix like systems.

Gracioso answered 19/5, 2016 at 6:28 Comment(0)
Y
1

On Linux, with bash, to output as quoted args so you can edit the command and rerun it

</proc/"${pid}"/cmdline xargs --no-run-if-empty -0 -n1 \
    bash -c 'printf "%q " "${1}"' /dev/null; echo

On Solaris, with bash (tested with 3.2.51(1)-release) and without gnu userland:

IFS=$'\002' tmpargs=( $( pargs "${pid}" \
    | /usr/bin/sed -n 's/^argv\[[0-9]\{1,\}\]: //gp' \
    | tr '\n' '\002' ) )
for tmparg in "${tmpargs[@]}"; do
    printf "%q " "$( echo -e "${tmparg}" )"
done; echo

Linux bash Example (paste in terminal):

{
## setup intial args
argv=( /bin/bash -c '{ /usr/bin/sleep 10; echo; }' /dev/null 'BEGIN {system("sleep 2")}' "this is" \
    "some" "args "$'\n'" that" $'\000' $'\002' "need" "quot"$'\t'"ing" )

## run in background
"${argv[@]}" &

## recover into eval string that assigns it to argv_recovered
eval_me=$(
    printf "argv_recovered=( "
    </proc/"${!}"/cmdline xargs --no-run-if-empty -0 -n1 \
        bash -c 'printf "%q " "${1}"' /dev/null
    printf " )\n"
)

## do eval
eval "${eval_me}"

## verify match
if [ "$( declare -p argv )" == "$( declare -p argv_recovered | sed 's/argv_recovered/argv/' )" ];
then
    echo MATCH
else
    echo NO MATCH
fi
}

Output:

MATCH

Solaris Bash Example:

{
## setup intial args
argv=( /bin/bash -c '{ /usr/bin/sleep 10; echo; }' /dev/null 'BEGIN {system("sleep 2")}' "this is" \
    "some" "args "$'\n'" that" $'\000' $'\002' "need" "quot"$'\t'"ing" )

## run in background
"${argv[@]}" &
pargs "${!}"
ps -fp "${!}"

declare -p tmpargs
eval_me=$(
    printf "argv_recovered=( "
    IFS=$'\002' tmpargs=( $( pargs "${!}" \
        | /usr/bin/sed -n 's/^argv\[[0-9]\{1,\}\]: //gp' \
        | tr '\n' '\002' ) )
    for tmparg in "${tmpargs[@]}"; do
        printf "%q " "$( echo -e "${tmparg}" )"
    done; echo
    printf " )\n"
)

## do eval
eval "${eval_me}"


## verify match
if [ "$( declare -p argv )" == "$( declare -p argv_recovered | sed 's/argv_recovered/argv/' )" ];
then
    echo MATCH
else
    echo NO MATCH
fi
}

Output:

MATCH
Yellowgreen answered 9/6, 2016 at 22:11 Comment(0)
F
1

If you want to get a long-as-possible (not sure what limits there are), similar to Solaris' pargs, you can use this on Linux & OSX:

ps -ww -o pid,command [-p <pid> ... ]
Floccose answered 2/11, 2018 at 19:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.