Как извлечь пару ключ-значение из команды ps

10

Я пытаюсь извлечь имя приложения из psкоманды, как это:

ps -af -u sas |grep "java"| grep -v "grep"

и это производит следующее:

sas 24431     1  0 Oct10 ?        00:51:08 /usr/lib/jvm/java-1.7.0-oracle-1.7.0.25.x86_64/jre/bin/java -Denv=DEV -Dapp.name=myApp -Xms512m -Xmx1g -Dlog.dir=/apps/java/logs

Я пытался использовать, egrepно, похоже, не работает:

ps -af -u sas|grep "java"| grep -v "grep"| egrep -o "-Dapp.name"

Как я могу получить только -Dapp.nameзначение «myApp»?

ПАВ
источник
если grepшаблон начинается с -, вам нужно поставить его после -eопции. В противном случае это будет рассматриваться как вариант. Но это будет соответствовать слову -Dapp.name, а не части после него.
Бармар
поочередно:grep -o -- -Dapp.name
стружка
Вы можете использовать, grep [j]avaчтобы избежать команды grep -v "grep"(проверено на bash)
HVNSweeting

Ответы:

7

С awk:

ps -af -u sas | awk 'BEGIN {RS=" "}; /-Dapp.name/'
jasonwryan
источник
8

Вы не видите сообщение об ошибке, которое вы получаете, но это, вероятно,

grep: метод неизвестных устройств

Это связано с тем, что, как и во всех или, по крайней мере, в большинстве других программ командной строки, grepпредполагается, что все, что начинается с a, -является опцией и пытается проанализировать его как таковое. В этом случае -Dиспользуется для указания grepтого, как обращаться с файлом устройства (см. man grepПодробности). Одним из способов обойти это является использование, --которое говорит, grepчто все, что следует, не является флагом опции.

Комбинируя это с возможностью GNU PCRE grep, вы можете сделать:

ps -af -u sas | grep -v grep | grep -Po -- '*-\KDapp.name=[^\s]+'

Регулярное выражение ищет a -и отбрасывает его ( \K), затем за строкой Dapp.name=следует как можно больше непробельных символов. Выход:

Dapp.name=myApp

Если вы хотите, чтобы myAppчасть была сохранена в переменной, я бы искал это один:

ps -af -u sas | grep -v grep | grep -Po -- '-Dapp.name=\K[^\s]+'

Чтобы назначить его переменной:

$ app="$(ps -af -u sas | grep -v grep | grep -Po -- '-Dapp.name=\K[^\s]+')"
$ echo $app
myApp

Тем не менее, вы никогда не должны grepвыводить psдля такого рода вещи, вот для чего pgrep:

app="$(pgrep -a java | grep -Po -- '^Dapp.name=\K[^\s]+')"
Тердон
источник
4
ps -af -u sas | sed -n '/[j]ava/s/.*-Dapp\.name=\([^ ]*\).*/\1/p'
Barmar
источник
3

Каждый раз, когда вы используете ps … | grep …и хотите исключить grep из результатов, вы делаете это неправильно.

Основное правило анализа выходных данных ps- использовать более надежные инструменты, такие как pgrepдоступные. Если у вас есть pgrep, pgrep -f javaперечисляются все процессы, выполняющие команду java. Опция -lдобавляет командную строку для каждого процесса.

Чтобы извлечь аргумент -Dapp.name, вы можете использовать sed. Подберите всю строку, составьте интересную часть в группе и распечатайте эту группу.

pgrep -lf java | sed -n 's/^.*-Dapp\.name=\([^ ]*\).*$/\1/p'

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

ps -e -o args= | sed -n 's/^.*-Dapp\.name=\([^ ]*\).*$/\1/p'
Жиль "ТАК - перестань быть злым"
источник
3

Сложнее, чем другие ответы, но это использует getoptдля обработки для вас. Еще одна альтернатива.

getopt -aql 'Dapp.name:' $(\
    ps -af -u sas | grep java | grep -v grep | tr -s ' ' | cut -d' ' -f8-\
) | cut -d"'" -f2
  1. ваша команда: ps -af -u sas | grep java | grep -v grep
  2. tr -s ' ' "сжимает" несколько пробелов в одно место при подготовке к cut
  3. cut -d' ' -f8- разбивает строку по пробелам и захватывает все поля после 8 включительно, результат /usr/lib/jvm/java-1.7.0-oracle-1.7.0.25.x86_64/jre/bin/java -Denv=DEV -Dapp.name=myApp -Xms512m -Xmx1g -Dlog.dir=/apps/java/logs
  4. getopts -aql 'Dapp.name:' $(...)анализирует параметры команды и выводит только то длинное имя, которое соответствует Dapp.nameзначению (обозначается символом :), результат--Dapp.name 'myApp' --
  5. cut -d"'" -f2 хватает вещи в одинарных кавычках
  6. Результат: myApp
zamnuts
источник
0

Я бы использовал pgrepвместо этого psтак:

$ pgrep -fa java | grep -op "(<=-Dapp.name=)\w+"

Это вернет все процессы, которые соответствуют, javaа затем отфильтрует те, которые показывают только те, которые содержат -Dapp.name=. Последний бит,\w+ покажет имя программы, предполагая, что оно не содержит пробелов.

ПРИМЕЧАНИЕ . -PПереключатель на grepвключает возможность задавать вещи с помощью регулярных выражений, совместимых с PCRE - Perl . Не все версии grepподдерживают его, но большинство из них включены в более современные версии Linux.

Если вы хотите получить весь ключ / значение, измените его следующим образом:

$ pgrep -fa java | grep -oP -- "-Dapp.name=\w+"
SLM
источник