How can I get the command arguments or the whole command line from a running process using its process name?
For example this process:
# ps PID USER TIME COMMAND 1452 root 0:00 /sbin/udhcpc -b -T 1 -A 12 -i eth0 -p /var/run/udhcpc.eth0.pid
And what I want is /sbin/udhcpc -b -T 1 -A 12 -i eth0 -p /var/run/udhcpc.eth0.pid or the arguments. I know the process name and want its arguments. I’m using Busybox on SliTaz.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
You could use the -o switch to specify your output format:
$ ps -eo args
From the man page:
Command with all its arguments as a string. Modifications to the arguments may be shown. […]
You may also use the -p switch to select a specific PID:
$ ps -p [PID] -o args
pidof may also be used to switch from process name to PID, hence allowing the use of -p with a name:
$ ps -p $(pidof dhcpcd) -o args
Of course, you may also use grep for this (in which case, you must add the -e switch):
$ ps -eo args | grep dhcpcd | head -n -1
GNU ps will also allow you to remove the headers (of course, this is unnecessary when using grep):
$ ps -p $(pidof dhcpcd) -o args --no-headers
On other systems, you may pipe to AWK or sed:
$ ps -p $(pidof dhcpcd) -o args | awk 'NR > 1' $ ps -p $(pidof dhcpcd) -o args | sed 1d
Edit: if you want to catch this line into a variable, just use $(...) as usual:
$ CMDLINE=$(ps -p $(pidof dhcpcd) -o args --no-headers)
or, with grep :
$ CMDLINE=$(ps -eo args | grep dhcpcd | head -n -1)
Method 2
Method #1 – Using ps
You could use ps -eaf | grep 1234.
Example
$ ps -eaf | grep 28865 saml 28865 9661 0 03:06 pts/2 00:00:00 bash -c sleep 10000; while [ 1 ];do echo hi;sleep 10;done saml 28866 28865 0 03:06 pts/2 00:00:00 sleep 10000
NOTE: Busybox’s ps doesn’t include the -eaf switches as shown above from a typical ps that’s included with most Linuxes, however Busybox’s ps shows what looks to be very similar output to the example I provided. You can install Busybox on most Linuxes and run it like so:
$ busybox ps
852 root 0:00 /sbin/auditd -n
855 root 0:01 /sbin/audispd
857 root 0:00 /usr/sbin/sedispatch
866 root 0:00 /usr/sbin/alsactl -s -n 19 -c -E ALSA_CONFIG_PATH=/etc/alsa/alsactl.conf --initfile=/lib/alsa/init/00main rdaemon
867 root 0:00 /usr/libexec/bluetooth/bluetoothd
869 root 0:01 {firewalld} /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid
871 root 0:32 /usr/libexec/accounts-daemon
873 rtkit 0:05 /usr/libexec/rtkit-daemon
875 root 0:00 /usr/sbin/ModemManager
876 avahi 0:03 avahi-daemon: running [dufresne.local]
878 root 0:54 /usr/sbin/irqbalance --foreground
884 root 0:00 /usr/sbin/smartd -n -q never
886 avahi 0:00 avahi-daemon: chroot helper
891 chrony 0:01 /usr/sbin/chronyd
892 root 0:01 /usr/lib/systemd/systemd-logind
893 dbus 1:28 /bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
Method #2 – Using /proc
You can also look at the cmdline file that each PID has under /proc/<pid>.
$ cat /proc/28865/cmdline bash-csleep 10000; while [ 1 ];do echo hi;sleep 10;done
But notice that it’s missing the spacing. This is due to a NUL character being used within this file to separate your command line arguments. Not to worry though, these can be stripped out.
$ tr '' ' ' </proc/28865/cmdline bash -c sleep 10000; while [ 1 ];do echo hi;sleep 10;done
References
Method 3
Try something like this:
(example output from busybox on OpenWrt on one of my routers)
<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="12607d7d665273622a">[email protected]</a>:~# xargs -0 printf '%sn' </proc/991/cmdline /usr/sbin/uhttpd -f -h /www -r ap8 -x /cgi-bin -u /ubus -t 60 -T 30 -k 20 -A 1 -n 3 -N 100 -R -p 0.0.0.0:80 -p [::]:80
/proc/$PID/cmdline contains the arguments of process $PID like a C-ish strings one after another. Each string is zero terminated.
Quotes arround some arguments or options are shell stuff. You have to look closer at the lines being shown and where spaces or other characters with special meaning for the shell are used. You will need to quote that character(s) somehow or the complete argument when joining these lines to a command line again.
Method 4
Knowing the PID, just exec
cat /proc/pid/cmdline
For instance, for PID = 127
# cat /proc/127/cmdline ; echo "" /usr/lib/jvm/jdk-8-oracle-x64//bin/java-Djava.util.logging.config.file=/opt/tomcat/conf/logging.properties-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager-Djava.library.path=/usr/lib/jni-javaagent:/jmxtrans-agent-1.2.2.jar=/opt/tomcat/conf/jmxtrans-agent.xml-Dcom.sun.management.jmxremote.port=5000-Dcom.sun.management.jmxremote-Dcom.sun.management.jmxremote.ssl=false-Dcom.sun.management.jmxremote.authenticate=false-Djava.endorsed.dirs=/opt/tomcat/endorsed-classpath/opt/tomcat/bin/bootstrap.jar:/opt/tomcat/bin/tomcat-juli.jar-Dcatalina.base=/opt/tomcat-Dcatalina.home=/opt/tomcat-Djava.io.tmpdir=/opt/tomcat/temporg.apache.catalina.startup.Bootstrapstart #
Method 5
If you like short commands and pgrep is available, I would suggest pgrep -fl <process_name>.
ps -o args is truncated
Method 6
Coming late to the party: extracting the strings from /proc/$pid/cmdline, and displaying them with proper shell quoting.
This requires bash version 4.4+ (but possibly v5.1 for some bug fixes noted in the CHANGES file)
mapfile -d '' -t cmd < /proc/$pid/cmdline
echo "${cmd[@]@Q}"
mapfilereads the lines of a file into an array- the
-d ''option uses null instead of newline as the line terminator @Qtransformation emits each element of the array with shell quoting
Demo:
$ sh -c "echo 'hello world'; sleep 5m" &
[1] 14844
hello world
$ pid=$!
$ mapfile -d '' -t cmd < /proc/$pid/cmdline
$ declare -p cmd
declare -a cmd=([0]="sh" [1]="-c" [2]="echo 'hello world'; sleep 5m")
$ echo "${cmd[@]@Q}"
'sh' '-c' 'echo '''hello world'''; sleep 5m'
Method 7
pgrep -a <name>
In your example :
pgrep -a udhcpc
pgrep does not truncate line, but ps does.
For those that insist on using ps, then do that to avoid truncation :
ps <processID> | tee
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0