Разбор выходной команды - PullRequest
0 голосов
/ 15 мая 2018

Я пытаюсь извлечь параметр вывода команды. На данный момент у меня есть это:

ps -eaf | grep javaagent

Вывод примерно такой:

-Dweblogic.system.BootIdentityFile=/u06/app/oracle/admin/domains/omservices/servers/profiling03/data/nodemanager/boot.properties -Dweblogic.nodemanager.ServiceEnabled=true -Dweblogic.security.SSL.ignoreHostnameVerification=false -Dweblogic.ReverseDNSAllowed=false -javaagent:/u01/home/app/appdyn/AppDynamics/AppServerAgent/ver4.3.1.5/javaagent.jar -Dappdynamics.agent.applicationName=BFL_PE_Omnichannel -Dappdynamics.agent.tierName=CDLV_Profiling -Dappdynamics.agent.nodeName=profiling03 -Xms3g -Xmx3g -XX:MaxPermSize=756m -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:/u06/app/oracle/admin/logs/omservices/profiling03/gc.log -XX:-DisableExplicitGC -Djava.net.preferIPv4Stack=true -Dweblogic.MuxerClass=weblogic.socket.NIOSocketMuxer -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/u06/app/oracle/admin/logs/omservices/profiling03/dump -Dweblogic.Stdout=/u06/app/oracle/admin/logs/omservices/profiling03/profiling03.out -Dprofiling-services.configPath=/cyberbank/profiling/v2/config/ -Dorg.apache.cxf.Logger=org.apache.cxf.common.logging.Log4jLogger -Dprofiling-services.logPath=/u06/app/oracle/admin/logs/omservices/profiling03 -Duser.timezone=GMT-5 -Dweblogic.management.server=t3://ba410018-priv:4065 weblogic.Server

Я хочу извлечь параметр (меня интересует этот путь):

-javaagent:/u01/home/app/appdyn/AppDynamics/AppServerAgent/ver4.3.1.5/javaagent.jar

Я сделал это с помощью следующей команды:

ps -eaf | grep javaagent | cut -d " " -f XX

В которой "XX" - это столбец, в котором XX Проблема этой команды в том, что процесс не всегда будет одинаковым. Однако javaagent всегда будет в процессе.

Вкратце, некоторая команда, которая позволяет мне извлечь параметр javaagent в процессе X.

Ответы [ 2 ]

0 голосов
/ 15 мая 2018

Обычно первый шаг в ответе на вопросы оболочки в форме "Как мне разобрать вывод ...?"это задать альтернативный вопрос «Как получить [эту информацию] без необходимости разбора вывода команды?».

Конечно, некоторый вид синтаксического анализа почти всегда необходим, но если вы можете уменьшить его до надежного разбиения по какой-либо строке разделителя, вы довольно хорошо подошли к проблеме, потому что есть много способов разделить строку по разделителю.(См. Ниже один из них.)

ПРИМЕЧАНИЕ: Остальная часть этого ответа предполагает достаточно стандартную установку Linux с bash, Gnu awk и ps из пакетаProcps-нг.Это может быть легко приспособлено к другим средам, но детали сделают повествование слишком сложным.

Команда ps поставляется с хорошим набором параметров вывода, которые позволяют очень легко настроить вывод команды.Например, если вы хотите увидеть все командные строки запущенных процессов без каких-либо других запутанных данных, вы можете попробовать это:

ps -e -ops=,cmd=

Это выведет pid и командную строку всех процессов в вашемсистема.(Вы можете использовать -ea, если хотите, и многие это делают. С версией ps procps-ng это не имеет значения.)

Выходная спецификация -o состоит изсписок полей через запятую (имена которых задокументированы в man ps в разделе с пометкой «СТАНДАРТНЫЕ ФОРМАТЫ»).Каждое имя поля может опционально сопровождаться = и некоторым текстом (который не может содержать запятую);текст используется в строке заголовка, которая является выводом первой строки.Использование только = без текста означает, что столбец не имеет заголовка, а если ни один столбец не имеет заголовка, то строка заголовка не печатается.Это облегчает "синтаксический анализ".

Многие из полей ps, которые можно напечатать, легко разбираются, поскольку они не могут содержать пробелы.Фактически, на странице man перечислены несколько полей, которые могут содержать пробелы:

Следующие пользовательские спецификаторы формата могут содержать пробелы: args, cmd, comm, команда, fname, ucmd, ucomm, lstart,bsdstart, start

, и этот список на самом деле намного больше, чем действительное число различных спецификаторов, потому что args и command являются псевдонимами cmd - что показывает всю командную строку -ucmd и ucomm - это псевдонимы comm, в которых указано имя исполняемого файла.

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

Хотя мы не можем получить это из ps, мы можем перейти к источнику информации, который использует ps: /proc файловая система.В частности, для любого pid «file» /proc/PID/cmdline содержит компоненты командной строки, каждый из которых заканчивается байтами NUL.Например, мой init процесс выглядит следующим образом:

$ hd /proc/1/cmdline
00000000  2f 6c 69 62 2f 73 79 73  74 65 6d 64 2f 73 79 73  |/lib/systemd/sys|
00000010  74 65 6d 64 00 2d 2d 73  79 73 74 65 6d 00 2d 2d  |temd.--system.--|
00000020  64 65 73 65 72 69 61 6c  69 7a 65 00 31 38 00     |deserialize.18.|
0000002f

Поскольку параметр командной строки не может содержать байт NUL, это совершенно однозначно.

Мы можем извлечь всекомандные строки для всех запущенных процессов, просто перетаскивая каталог /proc:

cat /proc/[1-9]*/cmdline

(я использовал [1-9]* вместо *, потому что в файловой системе /proc есть другие подкаталоги.)

Но это приводит к появлению строк, разделенных новой строкой, записей, разделенных NUL, что является не самым удобным форматом для большинства утилит. (Кроме того, он вновь вводит неоднозначность, поскольку символ новой строки может быть частью аргумента.) К счастью, Gnu awk рада иметь дело с NUL как разделителями записей и имеет возможность сопоставления регулярных выражений. Таким образом, чтобы найти все аргументы всех запущенных процессов, которые начинаются с -javaagent:, мы можем использовать следующую однострочную строку:

awk -v RS='\0' '/^-javaagent:/' /proc/[1-9]*/cmdline

Примечание:

В приведенном выше описании я пропустил несколько деталей. Одним из них является то, что /proc/PID/cmdline содержит только первые 4 КБ командной строки. Поскольку вызовы Java часто бывают очень длинными, возможно, что часть командной строки будет отсутствовать. Однако, поскольку ps использует файловую систему /proc для получения информации, которую она показывает, она будет страдать от той же проблемы. Я не знаю простого способа обойти это.

Другая проблема заключается в том, что данные, представленные в -ocmd=, могут быть изменены запущенным процессом, если он хочет каким-либо образом скрыть или повторно обработать свою собственную командную строку. Например, если вы посмотрите на записи для chrome процессов, вы увидите, что аргументы разделены пробелами, а не NUL.

0 голосов
/ 15 мая 2018

Следующее должно работать, пока в вашем пути javaagent.jar нет места:

ps -eaf | grep -Eo '-javaagent:[^ ]*'

Соответствует с начала опции -javaagent до следующего исключенного пробела. Использование флага grep -o позволяет вернуть только соответствующий раздел, а не целые строки.

...