プロセス名を使用して、実行中のプロセスからコマンド引数またはコマンドライン全体を取得するにはどうすればよいですか?
たとえば、このプロセス:
# ps
PID USER TIME COMMAND
1452 root 0:00 /sbin/udhcpc -b -T 1 -A 12 -i eth0 -p /var/run/udhcpc.eth0.pid
そして、私が欲しいのは/sbin/udhcpc -b -T 1 -A 12 -i eth0 -p /var/run/udhcpc.eth0.pid
または引数。プロセス名を知っているので、その引数が必要です。 SliTazでBusyboxを使用しています。
_-o
_スイッチを使用して、出力形式を指定できます。
_$ ps -eo args
_
manページ から:
すべての引数を文字列として持つコマンド。引数の変更が表示される場合があります。 [...]
_-p
_スイッチを使用して、特定のPIDを選択することもできます。
_$ ps -p [PID] -o args
_
pidof
を使用してプロセス名からPIDに切り替えることもできるため、次の名前で_-p
_を使用できます。
_$ ps -p $(pidof dhcpcd) -o args
_
もちろん、grep
を使用することもできます(この場合、_-e
_スイッチを追加する必要があります):
_$ ps -eo args | grep dhcpcd | head -n -1
_
GNU psではヘッダーを削除することもできます(もちろん、これはgrep
を使用する場合は不要です):
_$ ps -p $(pidof dhcpcd) -o args --no-headers
_
他のシステムでは、AWKまたはsedにパイプできます。
_$ ps -p $(pidof dhcpcd) -o args | awk 'NR > 1'
$ ps -p $(pidof dhcpcd) -o args | sed 1d
_
編集:この行を変数にキャッチする場合は、通常どおり$(...)
を使用します。
_$ CMDLINE=$(ps -p $(pidof dhcpcd) -o args --no-headers)
_
または、grep
を使用:
_$ CMDLINE=$(ps -eo args | grep dhcpcd | head -n -1)
_
ps -eaf | grep 1234
を使用できます。
$ 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
注:Busyboxのps
には、上記の一般的なps
の-eaf
スイッチが含まれていませんこれはほとんどのLinuxに含まれていますが、Busyboxのps
は、提供した例と非常によく似た出力を示しています。ほとんどのLinuxにBusyboxをインストールして、次のように実行できます。
$ 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
各PIDが/proc/<pid>
の下にあるcmdline
ファイルも確認できます。
$ cat /proc/28865/cmdline
bash-csleep 10000; while [ 1 ];do echo hi;sleep 10;done
ただし、間隔が不足していることに注意してください。これは、コマンドライン引数を区切るためにこのファイル内でNUL文字が使用されているためです。ただし、心配する必要はありません。これらは取り除くことができます。
$ tr '\0' ' ' </proc/28865/cmdline
bash -c sleep 10000; while [ 1 ];do echo hi;sleep 10;done
次のようなものを試してください:
(私のルーターの1つでOpenWrtのbusyboxからの出力例)
root@ap8:~# xargs -0 printf '%s\n' </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
には、Cっぽい文字列のように、プロセス$PID
の引数が次々と含まれています。各文字列はゼロで終了します。
一部の引数またはオプションを囲む引用符はシェルのものです。表示されている行と、スペースやシェルにとって特別な意味を持つその他の文字が使用されている場所をよく見る必要があります。これらの行をコマンドラインに再度結合するときは、その文字または何らかの引数を引用符で囲む必要があります。
PIDを知って、ただ実行する
cat/proc/pid/cmdline
たとえば、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
#
短いコマンドが好きで、pgrepが利用可能な場合は、pgrep -fl <process_name>
。
ps -o args
は切り捨てられます
ps
コマンドのライトバージョン(BusyBox):
PROCNAME="udhcpc"
CMD=$(ps | grep $PROCNAME | grep -v grep | head -n 1 | grep -o '/.*$')
ps
コマンドのフル機能バージョン:
PROCNAME="udhcpc"
CMD=$(ps -f --no-headers -C $PROCNAME | head -n 1 | grep -o '/.*$')
または両方の組み合わせ。 BusyBoxのps
にはバージョンを判別するための引数がないため(終了エラーが渡されます)、これを利用できます。
PROCNAME="udhcpc"
if ps --version; then
CMD=$(ps -f --no-headers -C $PROCNAME | head -n 1 | grep -o '/.*$') # full-featured "ps" command
else
CMD=$(ps | grep $PROCNAME | grep -v grep | head -n 1 | grep -o '/.*$') # "ps" command from BusyBox
fi
プロセス名の後にのみ引数が必要な場合は、次のように、最初のスペースの後に文字列を分割します。
echo $CMD | cut -d ' ' -f 2-99