web-dev-qa-db-ja.com

プロセスからコマンドライン全体を取得する方法は?

プロセス名を使用して、実行中のプロセスからコマンド引数またはコマンドライン全体を取得するにはどうすればよいですか?

たとえば、このプロセス:

# 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を使用しています。

58
Michael

_-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)
_
70
John WH Smith

方法#1-psを使用する

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

方法#2-/ procの使用

各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

参考文献

15
slm

次のようなものを試してください:

(私のルーターの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の引数が次々と含まれています。各文字列はゼロで終了します。

一部の引数またはオプションを囲む引用符はシェルのものです。表示されている行と、スペースやシェルにとって特別な意味を持つその他の文字が使用されている場所をよく見る必要があります。これらの行をコマンドラインに再度結合するときは、その文字または何らかの引数を引用符で囲む必要があります。

13
user62916

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
#
5
jmlotero

短いコマンドが好きで、pgrepが利用可能な場合は、pgrep -fl <process_name>

ps -o argsは切り捨てられます

0
Mickael Cagnion

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
0
s3n0