243

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?

1
  • 7
    tr \\0 ' ' < /proc/<pid>/cmdline Commented Feb 8, 2017 at 14:57

14 Answers 14

368

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.

9
  • 63
    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.
    – Silfheed
    Commented May 6, 2009 at 18:59
  • 4
    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 options
    – GuruM
    Commented Aug 9, 2012 at 14:33
  • 3
    cat /proc/<pid>/cmdline also works on Cygwin, where cmd line arguments are not shown in ps with any option.
    – lechup
    Commented Nov 22, 2013 at 10:08
  • 3
    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.
    – alvits
    Commented Dec 25, 2013 at 21:42
  • 3
    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 stackoverflow.com/questions/199130/… for more info. You can query your kernel setting with getconf PAGE_SIZE, it's usually 4096.
    – t0r0X
    Commented Apr 25, 2014 at 14:34
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.

3
  • It is stil truncating my output. Any advise?
    – johnsam
    Commented Aug 29, 2015 at 13:22
  • Never noticed any truncation - can you give an example? Commented Aug 31, 2015 at 8:10
  • This way, you cannot say if it's an inline space or an argument boundary. Commented Apr 28, 2020 at 11:19
29

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
1
  • ps -ef is the command I was looking for
    – Timofey
    Commented Jun 8, 2021 at 21:35
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
7
  • 3
    Whitespace isn't removed, it's replaced with NULs.
    – bdonlan
    Commented May 5, 2009 at 0:34
  • @bdonlan Ah, I did not check that. Good catch!
    – lothar
    Commented May 5, 2009 at 0:58
  • 5
    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.
    – camh
    Commented May 5, 2009 at 12:02
  • On my system there is no /proc filesystem :( any other solution ?
    – Hemant
    Commented May 6, 2009 at 6:20
  • Mine is a java process with long long long parameters. It is stil truncating my output. Any advise?
    – johnsam
    Commented Aug 29, 2015 at 13:23
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.

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 bash
    – unhammer
    Commented Oct 19, 2016 at 11:24
  • 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.
    – Socowi
    Commented Sep 20, 2019 at 15:08
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.

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. Commented May 21, 2017 at 7:49
4

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

tr '\0' ' ' </proc/<pid>/cmdline
3

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

2

You can simply use:

ps -o args= -f -p ProcessPid
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.

1

On Solaris

     ps -eo pid,comm

similar can be used on unix like systems.

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
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> ... ]
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

Not the answer you're looking for? Browse other questions tagged or ask your own question.