Проблема с AWK внутри Bash

Здравствуйте, длинная история: я пытаюсь создать скрипт для запуска через CI-сервер, чтобы убить определенный процесс.

Поэтому, просматривая в Интернете, я обнаружил эту команду:

myuser@server:/home/myuser# ps -ef | grep someUniqueText | grep -v grep | awk '{print $2}'
5263

Когда я запускаю его в консоли, он возвращает мне именно то, что мне нужно (5263), поэтому я создал этот bash:

#!/bin/bash

PROCESSNAME=$1
PID=$(ps -ef | grep $PROCESSNAME | grep -v grep | awk '{print $2}');

echo $PID;

Когда я выполняю его следующим образом:

myuser@server:/home/myuser# ./killProcess.sh somename
5263 4587 1236

Скрипт bash возвращает 3 числа, являющиеся первым процессом, который мне нужен, и я понятия не имею, чем являются другие два, Почему? oO

PS .: Сначала я использую echo, чтобы проверить его, я изменю его на kill -9

1
задан 11 May 2018 в 18:01

2 ответа

При выполнении ./killProcess.sh somename затем процесс, подобный

/bin/bash ./killProcess.sh somename

существует и ps | grep | grep | awk- строка также находит этого, потому что она имеет текст somename в нем. Я не абсолютно уверен, почему Вы получаете два дополнительных PIDs (и не всего один), но и я считаю, что это - некоторая родительская/дочерняя штука между bash и killProcess.sh. В каждый выстраивает в линию шоу PID как PID и в другом как PPID.

Можно избежать этих PIDs путем захвата их далеко на основе названия сценария. Это хранится в $0, так

PID=$(ps -ef | grep $PROCESSNAME | grep -v grep | grep -v $0 | awk '{print $2}');

или (с меньшим количеством вызовов программы):

PID=$(ps -ef | grep $PROCESSNAME | grep -v -e grep -e $0 | awk '{print $2}');

Другим (более безопасным) путем был бы к grep далеко PID сценария. Это хранится в $$:

PID=$(ps -ef | grep $PROCESSNAME | grep -v -e grep -e $$ | awk '{print $2}');

Или выполните во всем этом awk:

PID=$(ps -ef | awk "/$PROCESSNAME/ && !/awk/ && !/$$/ {print \$2}");

Мы должны выйти \$2 здесь, таким образом, это не интерпретируется оболочкой, но awk. То средство команды:

Если строка содержит $PROCESSNAME и не содержит awk и не содержит наш очень собственный PID, затем печатает второй столбец.

Преимущество (в теории), который это выполняет быстрее потому что только одна дополнительная команда (awk) требуется в противоположность 3 властям и awk.

Но:

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

  • killall somename # к предварительному просмотру, первому показу killall -v -s 0 somename
  • pgrep somename # просто перечислите PIDs
  • pkill somename # подобный killall
2
ответ дан 3 December 2019 в 06:51

Я когда-то реализовал подобную идею как функция оболочки, которую я вызываю psg (для "ps|grep")

psg() {
    local -a patterns=()
    (( $# == 0 )) && set -- $USER
    for arg do 
        patterns+=( "-e" "[${arg:0:1}]${arg:1}" )
    done
    ps -ef | grep "${patterns[@]}"
}

Это использует прием помещения первого символа шаблона в скобках, таким образом, Вы добираетесь

ps -ef | grep "[s]omename"

Это позволяет Вам отбрасывать grep -v grep часть конвейера.

Если Вы не передаете аргументов, это использует Ваше имя пользователя для поиска процессов.

2
ответ дан 3 December 2019 в 06:51

Другие вопросы по тегам:

Похожие вопросы: