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

非 Y 不嫁゛ 提交于 2019-11-27 05:50:16
markus_b

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.

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.

LOGAN

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

On Linux

cat /proc/<pid>/cmdline

get's you the commandline of the process (including args) but with all whitespaces changed to NUL characters.

Sopalajo de Arrierez

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.

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.

Tom Evans

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

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

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.

On Solaris

     ps -eo pid,comm

similar can be used on unix like systems.

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

You can simply use:

ps -o args= -f -p ProcessPid

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

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> ... ]
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!