I have written a shell script that removes semaphores and shared
memory as follows. The script works fine.
Can this be written with any less number of lines?
Thanks in advance
=====================================================================
user=`whoami`
sems=`ipcs -s|grep $user| awk '{print $2}'`
shmem=`ipcs -m|grep $user| awk '{print $2}'`
count=0
for semaphore in $sems
do
ipcrm -s $semaphore
((count=count+1))
done
echo "$count semaphores for $user removed"
count=0
for sharedmem in $shmem
do
ipcrm -m $sharedmem
((count=count+1))
done
echo "$count shmem for $user removed"
=====================================
Obviously it can, just replace all but the last newline character with a
semicolon.
You can reduce the number of processes by some transformations
grep $user | awk '{print $2}' --> awk "/$user/ { print \$2 }"
(assuming that $user has no / characters in it)
As ipcrm can remove more than one thing at a time, and you are not going
to be hitting size limits
user=$(whoami)
set -- $(ipcs -s | awk "/$user/ { print \$2}")
if [ $# -gt 0 ] ; then
ipcrm -s "$@"
fi
echo $# semaphores for $user removed
set -- $(ipcs -m | awk "/$user/ { print \$2}")
if [ $# -gt 0 ] ; then
ipcrm -m "$@"
fi
echo $# shmem for $user removed
If say you have 10 semaphores and no shared memory segments the original
script will use 17 processes, and the new one will use 6 (this assume a
good modern shell implementation).
Congratulations!
> Can this be written with any less number of lines?
Almost certainly, but I don't think that should be viewed as a
primary goal.
> user=`whoami`
> sems=`ipcs -s|grep $user| awk '{print $2}'`
> shmem=`ipcs -m|grep $user| awk '{print $2}'`
Consider:
sems=$(ipcs -s | awk '$5 == "'"$user"'" { print $2 }'`
I may have the quoting wrong, but the intent is to have awk do the
check directly. Consider what happens, otherwise, if you have a user
named 'heel' and a semaphore owned by group 'wheel'.
Note that you might still have issues for some possible boundaries.
So consider:
'/^Shared Memory/ { x = 1 } x && $5 == "'"$user"'" { print $2 }'
as the awk script for the shmem case.
> count=0
> for semaphore in $sems
> do
> ipcrm -s $semaphore
> ((count=count+1))
> done
> echo "$count semaphores for $user removed"
This can be simplified.
set -- $sems
printf "Removing %d semaphores for %s:\n" "$#" "$user"
for semaphore; do
ipcrm -s $semaphore
done
Note that you are not checking for failures from ipcrm, which you
should be. I would probably do:
set -- $sems
failed=0
printf "Removing %d semaphores for %s:\n" "$#" "$user"
for semaphore; do
ipcrm -s $semaphore || failed=`expr $failed + 1`
done
if [ $failed -ne 0 ]; then
printf >&2 "%d error(s).\n" "$failed"
fi
Remember, fewer lines isn't as important as handling errors and
unexpected inputs.
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.
If you have doubts about correct quoting consider to pass the argument
through an awk variable, which is IMO also a much clearer and cleaner
construct.
sems=$( ipcs -s | awk -v user="$user" '$5 == user { print $2 }' )
Janis
> but the intent is to have awk do the
> check directly. Consider what happens, otherwise, if you have a user
> named 'heel' and a semaphore owned by group 'wheel'.
>
[snip]
D'oh! Right you are.
> sems=$( ipcs -s | awk -v user="$user" '$5 == user { print $2 }' )
That is much prettier.
eschew variables: use bash functions. (debugging left to the
interested parties)
# new -- 5 lines
uipcs() { ipcs -$1 | grep $2 | awk '{ print $2 }'; }
foreachi() { cmd=$1; g=$2; shift 2; for a; do $cmd $g $a; done;
echo $# for user $g removed; }
myipcrm() { ipcrm -$1 $2; }
wholelot() { foreachi myipcrm s $(uipcs s $1); foreachi myipcrm m
$(uipcs m $1); }
wholelot $(whoami)
# old -- 18 lines
user=`whoami`
sems=`ipcs -s|grep $user| awk '{print $2}'`
shmem=`ipcs -m|grep $user| awk '{print $2}'`
count=0
for semaphore in $sems
do
ipcrm -s $semaphore
((count=count+1))
done
echo "$count semaphores for $user removed"