Это работает, но то, как я это сделал, немного глупо. Есть ли способ сделать это лучше?
for e in $(ipcs | awk '{print $2}'); do
[[ "$e" = "Semaphore" ]] && break
echo $e
ipcrm shm $e
done
echo $e outside for loop
for e in $(ipcs | awk '{print $2}'); do
[[ "$e" = "Message" ]] && break
echo $e
ipcrm -s $e
done
echo
exit 0
Вот как выглядит ipcs для меня, когда я его запускаю.
$ ipcs
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 262145 bob 600 393216 2 dest
0x00000000 2523138 bob 600 393216 2 dest
0x00000000 2555907 bob 600 393216 2 dest
0x00000000 3375108 bob 600 998400 2 dest
0x00000000 3440645 bob 666 40 1
------ Semaphore Arrays --------
key semid owner perms nsems
0x000005b1 262146 bob 600 6
------ Message Queues --------
key msqid owner perms used-bytes messages
Мне нужно регулярно выполнять эти две команды.
ipcrm -s $(ipcs | grep bob | awk '{printf "%s ",$2}')
ipcrm shm $(ipcs | grep bob | awk '{printf "%s ",$2}')
Поэтому я подумал, что могу сделать что-то подобное.
if [ `$(ipcs | grep Shared | awk '{print $2}')` == "Shared"]
ipcrm shm $(ipcs | grep bob | awk '{printf "%s ",$2}')
Я хочу выполнять это первое поведение до тех пор, пока $2 не станет равным Semaphore.
if [ `$(ipcs | grep Semaphore | awk '{print $2}')` == "Semaphore"]
ipcrm -s $(ipcs | grep bob | awk '{printf "%s ",$2}'
Итак, подведем итог: я хочу, чтобы первый блок if запускался после того, как я увижу «Shared». Затем я хочу, чтобы второй блок if запускался после того, как я увижу «Semaphore».
решение1
Если я правильно понял, вы хотите запустить команду ipcrm shm <ids>
для всех сегментов общей памяти пользователя bob. Затем команду ipcrm -s <ids>
для всех массивов семафоров пользователя bob.
Для этого используйте следующие команды (вам не нужно зацикливать скрипт):
Для раздела «Сегменты общей памяти»:
ipcrm shm $(ipcs -m | awk '$3=="bob" {printf "%s ",$2}')
Для части массива семафоров:
ipcrm -s $(ipcs -s | awk '$3=="bob" {printf "%s ",$2}')
Объяснение:
Из ipcs
страницы руководства:
-m shared memory segments
-s semaphore arrays
Часть awk
печатает идентификаторы только тогда, когда третье поле — bob.
решение2
Может быть...
ipcs | sed -n '
s/[^ ]* *//
/^Messages/q
/^Semaphores/cshift
/ *bob .*/!d;s///
/ /!s/./ipcrm $1 &/p
'| sh -s -- shm \-s
Это удаляет строки, которые не содержат строкубобкак третье поле, разделенное пробеломиликоторые не имеют во втором полеСообщения/Семафоры.
Вставляет строку ipcrm $1 <field 2>
для тех строк, которые остались. Он прекращает ввод при сопоставленииСообщенияи он заменяетСемафорысоответствует shift
.
sed
вывод интерпретируется процессом оболочки с двумя позиционнымишм/-с. Итак, когда sed
говорится shift
, что оболочка прекращает выполнение команды ipcrm shm <field2>
и начинает работать -s
вместо shms.
Думаю, если вам нужно чисто оболочное решение, то это будет близко:
set -f; IFS='
'; for l in $(ipcs);
do IFS=\ ;set -- $l
case "$1:$2:${3#bob}" in
(-*:Sh*) a=shm;;
(-*:Se*) a=-s;;
(-*:Me*) break 2;;
(*:*:) ipcrm "$a" "$2";;
esac; done
решение3
Как slm предложил наВаш другой вопрос, я предлагаю сделать это с помощью while
цикла, а не for
цикла:
looking_at=
ipcs | while read key id owner other
do
# Keep track of which section we’re in.
if [ "$id" = "Shared" ] # $id is the second field; i.e., $2.
then
looking_at=shm
elif [ "$id" = "Semaphore" ]
then
looking_at=sem
elif [ "$id" = "Message" ]
then
break
fi
if [ "$owner" = "bob" ]
then
if [ "$looking_at" = "shm" ]
then
ipcrm shm "$id"
elif [ "$looking_at" = "sem" ]
then
ipcrm -s "$id"
fi
fi
done
Это считывает вывод команды ipcs
по одной строке за раз, разбивая первые три поля на key
, id
, и owner
. Как говорится в комментарии, мы используем looking_at
переменную для отслеживания раздела, в котором мы находимся. Затем, в каждой строке, содержащей bob
третье поле, мы используем , looking_at
чтобы определить, какую ipcrm
опцию использовать.