Esto funciona, pero la forma en que lo hice es un poco tonta. ¿Hay una mejor manera de hacer esto?
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
Así es como se ve ipcs cuando lo ejecuto.
$ 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
Necesito ejecutar estos dos comandos con regularidad.
ipcrm -s $(ipcs | grep bob | awk '{printf "%s ",$2}')
ipcrm shm $(ipcs | grep bob | awk '{printf "%s ",$2}')
Entonces estaba pensando que podría hacer algo como esto.
if [ `$(ipcs | grep Shared | awk '{print $2}')` == "Shared"]
ipcrm shm $(ipcs | grep bob | awk '{printf "%s ",$2}')
Quiero hacer ese primer comportamiento hasta que $2 sea igual a Semaphore.
if [ `$(ipcs | grep Semaphore | awk '{print $2}')` == "Semaphore"]
ipcrm -s $(ipcs | grep bob | awk '{printf "%s ",$2}'
Entonces, para resumir, quiero que se ejecute el primer bloque if después de ver "Compartido". Luego quiero el segundo bloque if después de ver "Semáforo".
Respuesta1
Si entiendo correctamente, desea ejecutar el comando ipcrm shm <ids>
para todos los segmentos de memoria compartida del usuario bob. Luego, el comando ipcrm -s <ids>
para todos los Semaphore Arrays del usuario bob.
Para lograrlo, utilice los siguientes comandos (no es necesario realizar un bucle en un script):
Para la parte de Segmentos de memoria compartida:
ipcrm shm $(ipcs -m | awk '$3=="bob" {printf "%s ",$2}')
Para la parte de la matriz de semáforos:
ipcrm -s $(ipcs -s | awk '$3=="bob" {printf "%s ",$2}')
Explicación:
Desde la ipcs
página de manual:
-m shared memory segments
-s semaphore arrays
La awk
pieza imprime los identificadores solo cuando el tercer campo es bob.
Respuesta2
Tal vez...
ipcs | sed -n '
s/[^ ]* *//
/^Messages/q
/^Semaphores/cshift
/ *bob .*/!d;s///
/ /!s/./ipcrm $1 &/p
'| sh -s -- shm \-s
Eso elimina líneas que no contienen la cadena.Betocomo el tercer campo delimitado por espaciosoque no tienen en su segundo campoMensajes/Semáforos.
Inserta la cadena ipcrm $1 <field 2>
para aquellas líneas que quedan. Cierra la entrada al hacer coincidirMensajesy reemplaza unSemáforoscoincidir con shift
.
sed
La salida de es interpretada por un proceso de shell con dos posicionales.shm/-s. Entonces, cuando sed
dice shift
que Shell deja de ejecutar el comando ipcrm shm <field2>
y comienza a ejecutarse -s
en lugar de shms.
Supongo que si quisieras una solución de shell pura, esto se aproxima:
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
Respuesta3
Como sugirió slm entu otra pregunta, sugiero hacer esto con un while
bucle en lugar de un for
bucle:
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
Esto lee el resultado del ipcs
comando una línea a la vez, dividiendo los primeros tres campos como key
, id
y owner
. Como dice el comentario, usamos la looking_at
variable para realizar un seguimiento de en qué sección estamos. Luego, en cada línea que contiene bob
el tercer campo, usamos looking_at
para determinar qué ipcrm
opción usar.