Как получить всю командную строку из процесса?

44

Как я могу получить аргументы команды или всю командную строку из запущенного процесса, используя его имя процесса?

Например этот процесс:

# 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аргументы. Я знаю имя процесса и хочу его аргументы. Я использую Busybox на SliTaz.

Майкл
источник
Вы хотите обработать вывод из ps(не рекомендуется) или вы ищете какую-то альтернативную команду ps, которая даст вам вывод? Что нужно сделать, когда psвыдает несколько строк вывода? распечатать все / первое / последнее?
Anthon
1
Какую операционную систему вы используете?
Сайрус
Я отредактировал свой вопрос. Я знаю имя процесса и хочу его аргументы. Я использую SliTaz (минималистичный Linux) с Busybox.
Майкл
@Michael Вы пробовали argкак commandв ответе @John ?
Pandya
Да, но как записать это в переменную? Я думаю о двух командах: PID = pidof <process name>ps -o pid, args | grep $ PID | tr -s "" | cut -d "" -f 2 Но таким образом я не получаю аргументы в одной переменной
Майкл

Ответы:

55

Вы можете использовать -oпереключатель, чтобы указать формат вывода:

$ ps -eo args

Со страницы руководства :

Команда со всеми ее аргументами в виде строки. Модификации аргументов могут быть показаны. [...]

Вы также можете использовать -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)
Джон У. Смит
источник
@ Майкл замените argsна command(или cmd).
Pandya
@Pandya И то, cmdи другое command- псевдонимы args, это, вероятно, не нужно.
Джон В. У. Смит,
У меня нет опции -p при использовании Busybox: Использование: ps [-o COL1, COL2 = HEADER] [-T]
Майкл
Вы можете использовать , grepчтобы поймать линию вы на самом деле интересно: ps -eo args | grep dhcpcd | head -n -1. Я отредактировал свой ответ.
Джон У. С. Смит,
О, это выглядит хорошо: ps -o args | grep <имя процесса> | head -n 1
Майкл
12

Попробуйте что-то вроде этого:

(пример вывода из busybox на OpenWrt на одном из моих маршрутизаторов)

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содержит аргументы процесса, $PIDтакие как строки C-ish один за другим. Каждая строка заканчивается нулем.

Кавычки вокруг некоторых аргументов или опций являются оболочкой. Вы должны посмотреть ближе на показанные строки и где используются пробелы или другие символы с особым значением для оболочки. Вам нужно будет как-то заключить в кавычки эти символы или полный аргумент при повторном присоединении этих строк к командной строке.


источник
1
tr "\0" " " </proc/991/cmdline
Сайрус
@Cyrus: Вы не можете отличить арги, соединяющие пробелы, от соседних отдельных аргов. Заменяя нулевой байт пробелом, вы уничтожаете информацию.
1
Я согласен с заменой \0на ``, чтобы быть плохим, но я думаю, tr '\0' '\n' < /proc/$foo/cmdlineчто это немного проще, чем xargs.
Патрик
printfупрощает добавление кавычек в вывод, вставку пробела вместо новой строки и так далее. Если подумать о добавлении дополнительной обработки, то printfэто хороший старт.
12

Метод № 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не включает в себя -eafпереключатели, как показано выше, от типового, psкоторый включен в большинство Linux, однако Busybox psпоказывает то, что похоже на вывод, очень похожий на приведенный мной пример. Вы можете установить Busybox на большинство Linux и запустить его так:

$ 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

Вы также можете посмотреть cmdlineфайл, под которым находится каждый PID /proc/<pid>.

$ 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

Ссылки

SLM
источник
2

Зная PID, просто exec

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
#
jmlotero
источник