Intereting Posts
Какие исправления Debian исправляют shellshock lcamtuf CVE-2014-6277 и CVE-2014-6278? wget неправильно конвертирует URL-адреса, если указано –convert-links Bash: синтаксическая ошибка около неожиданного токена 'done' iptables -I FORWARD -j DROP не сокращает существующие соединения Контрольный + L не очищающий экран Как добавить зависимость к systemd.mount, которая активирована / bin / mount? Определение значений LVM для заданного файла Как установить / использовать sshuttle на Fedora? Оптимальный Linux Distro для установки на SD-карту для использования в качестве USB-загрузчика для ПК? сравнение строк с awk vs во время чтения строки Sphinx Search shutdown down после `FATAL: accept () не удалось: Слишком много открытых файлов` файл sudoers и passwd только для выбранной группы NFS для клиентов с разными uid: s, чем на сервере, где клиент uid: s не будет отображаться на сервере Почему оболочка рыбы должна начать процесс демона? Можно ли перенаправить все URL-адреса wikipedia в wikipedia zero через файл hosts?

Анализ аргументов командной строки из pargs в сценарии оболочки

Я получаю список PID в моих сценариях bash (процессы Java) и должен анализировать их аргументы командной строки, чтобы определить, к какому экземпляру сервера соответствует каждый PID.

В данный момент я делаю так, используя sed / cut:

PARGS=$(pargs -l $PID) PARGS_ARR=($PARGS) NODE='UNKNOWN' for ARG in ${PARGS_ARR[@]} do # trim single quotes ARG=$(echo $ARG | sed "s/'//g") # split by equals sign ARGL=$(echo $ARG | cut -f1 -d=) ARGR=$(echo $ARG | cut -f2 -d=) if [ "$ARGL" == "-DnodeId" ]; then NODE=$ARGR fi done 

Но он работает EXTREMELLY SLOW из-за большого количества параметров командной строки (около 20-30 на каждый PID).

Есть ли способ каким-либо образом проанализировать параметры командной строки и получить ключ => значение синтаксического анализа с помощью одной команды?

Как выглядит выход pargs -l $PID ? Из вашего кода кажется, что это одна строка, содержащая все аргументы командной строки в формате, например:

 arg1=val1 arg2=val2 

Если это так, вы можете собрать значение для аргумента -DnodeId с помощью команды sed :

 $ ARGS="-DfirstArg=foo -DanotherArg=bar -DnodeId=1234 -DlastArg=baz" $ echo "$ARGS" | sed -r 's/.*-DnodeId=([^ ]+).*/\1/g' 1234 

Таким образом, ваш скрипт может стать:

 PARGS=$(pargs -l $PID) NODE='UNKNOWN' if [ -n "$(grep "DnodeId" <(echo "$PARGS"))" ]; then NODE=$(echo "$PARGS" | sed -r 's/.*-DnodeId=([^ ]+).*/\1/g') fi 

Если все, о чем вы заботитесь, – это то, что подходит к -DnodeId = если слева находится -DnodeId , вы можете сделать это:

 NODE=$(pargs -l $PID| awk -F '-DnodeId=' '{sub(" .*","",$2);print $2}') 

Это напечатает все, что попадает справа от шаблона -DnodeId= , но исключая первое пространство. Если в командной строке имеется более одного -DnodeId , оно будет работать только с первым.

Также возможно обработать более одного -DnodeId каждой строки:

 NODES=($(pargs -l $PID| awk -F '-DnodeId=' '{ for(i=2;i<=NF;i++){ sub(" .*","",$i); print $i } }' )) 

Кажется, что то, что вы делаете, определенно будет очень медленным, так как каждый раз, когда вы var=$(command substitute) вы должны остановиться и дождаться выхода, прежде чем переходить к следующему шагу. Я готов поспорить, что вы подождете намного меньше, если бы вы просто обработали его в потоке с помощью sed, stream editor:

 NODE="$(pargs -l $PID | sed -rn '/(-DnodeId)=(\S*)/{s//\2/pq}')" 

Я не совсем уверен в одиночных кавычках – я просто набрал это на своем телефоне, но функция sed's y может, конечно, справиться с этим, если вам все еще нужно.

Над Джошем демонстрируется случай неудачи. Вероятно, было бы гораздо проще просто добавить:

 ${NODE:?PID not found...quitting} 

После запуска указанной команды sed .

Мне кажется, что они не обязательно уже разделены линией, мы можем справиться с этим достаточно легко с еще 1 |pipe – все еще в одном потоке данных, а также учитываем возможность нескольких совпадений:

 . <<PIDSED /dev/stdin $(pargs -l $PID |\ sed -rn 's/(-DnodeId)=(\S*)/\ echo "NODE$((i=i+1))=\2" ;/gp' |\ . /dev/stdin) PIDSED 

Обработать аргументы с помощью bash , а не внешних процессов

 for ARG in "${PARGS_ARR[@]}" do # trim single quotes ARG=${ARG//\'} # split by equals sign IFS="=" read ARGL ARGR <<< "$ARG" if [[ "$ARGL" == "-DnodeId" ]]; then NODE=$ARGR fi done