#!/bin/ksh # # $Id: skill-solaris.sh,v 1.3 2001/04/29 22:15:13 vogelke Exp $ # # NAME: # skill # # SYNOPSIS: # skill [-signal] [-dhinv] {tty user command pid regexp} # # DESCRIPTION: # "skill" is a program to blow away processes. You can specify # processes by tty, userid, command name, process id, or an # egrep-style regular expression. # # OPTIONS: # -d, --debug show debug output # -h, --help print this message # -i, --interact edit the process list before killing # -n, --nokill show processes but don't kill them # -v, --version print the version and exit # # AUTHOR: # Karl Vogel # Sumaria Systems, Inc. # Based on a script by Tom Christiansen -- tchrist@convex.com # # A similar script by Ric Anderson : # ftp://jaguar.cs.utah.edu/pub/skill/skill-3.7.tar.Z PATH=/bin:/usr/sbin:/usr/bin:/usr/local/bin : ${EDITOR=/bin/vi} # Set default editor if blank. export PATH EDITOR umask 022 tag=`basename $0` tmp=`mktemp /tmp/skilltmp.XXXXXX` plist=`mktemp /tmp/skillps.XXXXXX` trap "rm -f $tmp $plist" 0 trap "rm -f $tmp $plist; exit 1" ERR # ksh variants only # ======================== FUNCTIONS ============================= # # die: prints an optional argument to stderr and exits. # A common use for "die" is with a test: # test -f /etc/passwd || die "no passwd file" # This works in subshells and loops, but may not exit with # a code other than 0. die () { echo "$tag: error: $*" 1>&2 exit 1 } # usage: prints an optional string plus part of the comment # header (if any) to stderr, and exits with code 1. usage () { lines=`egrep -n '^# (NAME|AUTHOR)' $0 | sed -e 's/:.*//'` ( case "$#" in 0) ;; *) echo "usage error: $*"; echo ;; esac case "$lines" in "") ;; *) set `echo $lines | sed -e 's/ /,/'` sed -n ${1}p $0 | sed -e 's/^#//g' | egrep -v AUTHOR: ;; esac ) 1>&2 exit 1 } # version: prints the current version to stdout. version () { lsedscr='s/RCSfile: // s/.Date: // s/,v . .Revision: / v/ s/\$//g' lrevno='$RCSfile: skill-solaris.sh,v $ $Revision: 1.3 $' lrevdate='$Date: 2001/04/29 22:15:13 $' echo "$lrevno $lrevdate" | sed -e "$lsedscr" exit 0 } # ======================== MAIN PROGRAM ========================== # Defaults: ac_help= ac_prev= ac_invalid="invalid option; use -h or --help to show usage" argv= # Initialize some variables set by options. debug=n int=n dokill=y sig= for ac_option do # If the previous option needs an argument, assign it. case "$ac_prev" in "") ;; *) eval "$ac_prev=\$ac_option"; ac_prev=; continue ;; esac case "$ac_option" in -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) ac_optarg= ;; esac # main switch case "$ac_option" in -d | -debug | --debug | --debu | --deb | --de) debug=y ;; -h | -help | --help | --hel | --he) usage ;; -i | -interact | --interac | --intera | --inter |\ --inte | --int ) int=y ;; -n | -nokill | --nokill | --nokil | --noki | --nok | --no) dokill=n ;; -v | -version | --version | --versio | --versi | --vers) version ;; -[0-9]*) sig="$sig $ac_option" ;; -di|-id) int=y; debug=y ;; -dn|-nd) dokill=n; debug=y ;; -in|-ni) dokill=n; int=y ;; -din|-dni|-nid|-ndi|-idn|-ind) dokill=n; int=y; debug=y ;; -*) die "$ac_option: $ac_invalid" ;; *) case "$argv" in "") argv="$ac_option" ;; *) argv="$argv $ac_option" ;; esac ;; esac done case "$ac_prev" in "") ;; *) die "missing arg to --`echo $ac_prev | sed 's/_/-/g'`" ;; esac # # Make sure we have something to look for. # case "$argv" in "") echo "I need something to look for."; usage ;; *) target="$argv" ;; esac # # The default signal strategy is to use TERM, INT, # and KILL on any processes. # case "$sig" in "") sig="-15 -1 -9" ;; *) ;; esac # # Get the processes to kill. Edit the list before showing # it so the -i, -d, and -n options can be used together. # Use a separate file for the process list, so we don't # include our own grep commands. # ps -ef | egrep -v " $$ " > $plist egrep "$target" $plist > $tmp test -s $tmp || die "No processes found." case "$int" in y) $EDITOR $tmp ;; *) ;; esac case "$debug" in y) echo "Signal(s): $sig Kill? $dokill" echo "Interactive? $int Target: $target" ;; *) ;; esac if test "$dokill" = "n" -o "$debug" = "y" then echo Not killing any of these: echo echo ' UID PID PPID C STIME TTY TIME CMD' cat $tmp case "$dokill" in n) exit 0 ;; *) ;; esac fi # # If we get this far, zap the process IDs. # pids=`awk '{print $2}' $tmp` echo "killing:" $pids | fmt -77 for each in $sig do echo kill $each $pids kill $each $pids sleep 1 done exit 0