Прежде всего, вы должны использовать while read
конструкцию вместо for
.С циклом for
необходимо дождаться выполнения команды в $(...)
, прежде чем цикл for может начаться.Кроме того, вы могли бы переполнить буфер команд.Сегодня это не главная проблема, но когда вы столкнетесь с этим, вы никогда не получите никаких признаков того, что что-то пошло не так:
ps | awk '$4 == "foo" { print $1 }' | while read pid
do
i=1
echo "killing foo at pid $pid"
kill $pid && echo 'ok' || echo 'failed'
done
Ничего общего с вашей проблемой, но мне нужно избавиться от неекомод.
Теперь перейдем к вашему ответу:
awk
автоматически делает цикл, поэтому, так как вы все равно используете awk
, почему бы не позволить ему выполнить работудля тебя?В большинстве реализаций awk
есть команда system
, поэтому вы можете выполнить kill
прямо внутри скрипта awk
.
Кроме того, взгляните на man ps
и проверьте параметры PS.Большинство команд ps принимают опцию -o
, которая позволяет вам указать, какие поля печатать.Моя команда ps
(которая, как правило, используется в OS X) позволяет вам использовать ucomm
, которая является просто именем команды без каталога или параметров командной строки.Звучит полезно для вашей ситуации.Я буду использовать ps -opid, ucomm
, который будет печатать только два столбца для команды ps
: PID и имя команды без параметров каталога и командной строки:
$ ps -o pid,ucomm
PID UCOMM
1 launchd
10 kextd
11 UserEventAgent
12 mDNSResponder
13 opendirectoryd
14 notifyd
15 fseventsd
16 configd
17 diskarbitrationd
18 syslogd
(выглядит только одно предупреждениекак ucomm
обрезает все в 14-м или 16-м столбце. Просто, чтобы вы знали).
Для awk
мы можем использовать параметр -v
, чтобы определить переменную Awk.Это полезно, если вы пишете сценарий оболочки и хотите, чтобы awk взял имя программы из параметров команды.
В Awk, как вы знаете, $ 1 будет представлять PID, а $ 2 будет представлять командубез параметров каталога или командной строки.
Мы можем использовать $2 == command
, чтобы отфильтровать все строки в вашей команде ps
, где команда foo
.Это сокращение от оператора if
.
И большинство реализаций awk
имеют функцию system
, которую можно использовать для запуска таких команд, как kill
, изнутри вашего скрипта awk
.Похоже, что у нас есть почти все, что нам нужно:
ps -o pid,ucomm | awk -v command="foo" '$2 == command {system("kill " $1)}'
Это хорошая чистая строка, но она не проверяет состояние системной команды и не выводит эхо при сбое или какой команде иПИД ты убиваешь.
Хорошо, что Awk - не просто заумная команда.Это также заумный язык программирования.Мы могли бы проверить возвращение команды system
и добавить несколько операторов печати.Я не проверял это, но это должно быть довольно близко:
ps -o pid,ucomm | awk -v command="foo" '$2 == command {
print "Killing " $2 " at PID " $1
if (system("kill " $1)) {
print "Failed to kill PID " $1
}
}'
Возможно, вместо if
будет if (! system("kill " $1)) {
.