232

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?

codeforester
  • 39,467
  • 16
  • 112
  • 140
Hemant
  • 3,893
  • 6
  • 27
  • 22

14 Answers14

355

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.

jpaugh
  • 6,634
  • 4
  • 38
  • 90
markus_b
  • 4,433
  • 2
  • 19
  • 15
  • 59
    on linux, you'll probably need -ww (ie `ps -ww -fp `) to specify wide output since if there are several commands, they could get cut off. – Silfheed May 06 '09 at 18:59
  • 1
    For clarification, the file is not // but rather /proc/ – mklauber Aug 04 '11 at 14:27
  • 3
    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](http://praveen.kumar.in/2010/02/24/getting-untruncated-command-line-options-passed-to-a-solaris-process/) and [ps options](http://linux.about.com/od/commands/l/blcmdl1_ps.htm) – GuruM Aug 09 '12 at 14:33
  • 3
    ``cat /proc//cmdline`` also works on Cygwin, where cmd line arguments are not shown in ``ps`` with any option. – lechup Nov 22 '13 at 10:08
  • 3
    On Linux, if you only need to get the `args`, the command is `ps -o args -p ` and it will only print the `args` or use -o `cmd` if you only need to see the `cmd`. Trying to read `/proc//cmdline` will not always work for unprivilege users. The `ps` utility will work. – alvits Dec 25 '13 at 21:42
  • 3
    Hint: length of `/proc//cmdline` is limited (hard coded to value of PAGE_SIZE kernel parameter), so longer command lines are still shown truncated! See http://stackoverflow.com/questions/199130/how-do-i-increase-the-proc-pid-cmdline-4096-byte-limit for more info. You can query your kernel setting with `getconf PAGE_SIZE`, it's usually 4096. – t0r0X Apr 25 '14 at 14:34
  • wow that is genius, the `ps -fp` command worked for me on Debian and Ubuntu. –  Jul 13 '14 at 01:27
  • Note that the command can be executed with a different name (first arg); in which case you can look at `/proc//comm` – unhammer Oct 19 '16 at 11:29
  • 3c67b1b73daf:~# ps -fp 22823 ps: unrecognized option: p BusyBox v1.28.4 (2018-07-17 15:21:40 UTC) multi-call binary. – Anton Duzenko Oct 13 '22 at 14:49
72

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.

Michael Böckling
  • 7,341
  • 6
  • 55
  • 76
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
jpaugh
  • 6,634
  • 4
  • 38
  • 90
LOGAN
  • 1,025
  • 2
  • 10
  • 14
23

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
hakre
  • 193,403
  • 52
  • 435
  • 836
lothar
  • 19,853
  • 5
  • 45
  • 59
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.

Sopalajo de Arrierez
  • 3,543
  • 4
  • 34
  • 52
  • 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 Oct 19 '16 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 Sep 20 '19 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.

Diego
  • 5,326
  • 1
  • 35
  • 32
  • 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. – TSJNachos117 May 21 '17 at 07: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
Ajean
  • 5,528
  • 14
  • 46
  • 69
Tom Evans
  • 41
  • 2
3

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

Dagang
  • 24,586
  • 26
  • 88
  • 133
2

You can simply use:

ps -o args= -f -p ProcessPid
Mitar
  • 6,756
  • 5
  • 54
  • 86
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

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

Eduardo Cuomo
  • 17,828
  • 6
  • 117
  • 94
repzero
  • 8,254
  • 2
  • 18
  • 40
1

On Solaris

     ps -eo pid,comm

similar can be used on unix like systems.

HuntM
  • 157
  • 1
  • 7
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
Iwan Aucamp
  • 1,469
  • 20
  • 21
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> ... ]
pourhaus
  • 566
  • 6
  • 9