#!/bin/ksh # @(#) Tidy up logins after PC dies #..# systems: #..# sites: #..# level: #..# publish: y #..# keys: #..# date: Wed Feb 27 08:49:56 GMT 2002 #..# vers: 1.10 04/Aug/2006-08:37 [ $0 = ${0#/} ] && this=$(pwd -H)/$0 || this=$0 tag=${0##*/} tm=/tmp/${tag} tmp=${tm}$$ rm -f ${tm}* set -A AWK $(whence nawk) [ ${#AWK[*]} -gt 0 -a "${AWK[0]}" != no ] && alias awk=${AWK[0]} usage="Usage: $tag [-n] [-z] hostname" set -A id $(id | tr "()=," " ") [ ${id[1]} -eq 0 ] && { print -u2 "Too dangerous for root to use"; exit; } args="$@" unset n typeset -l hostname=$(hostname) up() { [ "${FDBG-}" ] && set -A fDbG ${FDBG-} && [ $fDbG = set ] && eval ${fDbG-} ${fDbG[1]-} uPr=0 for uPh in $*; do /etc/ping $uPh 64 2 | awk 'BEGIN { h = "'"$uPh"'" } /100% packet loss/ { printf("%s down\n", h) exit 1 } /unknown host/ { printf("%s unknown\n", h) exit 2 }' 1>&2 uPs=$? uPr=$((${uPr-0} * 10 + $uPs)) done return $uPr } while [ $# -gt 0 ]; do case "$1" in -v|-x) set "$1" ;; -vi) lockvi $this; exit ;; -view) view $this; exit ;; -about) echo "$tag was written by David Ledger" echo "dledger@ivdcs.co.uk" echo "Free to use at your own risk" echo "Copyright 2002" exit ;; -ver) ver=$(egrep '#..#[ ]*vers:' $this) ver=${ver#"${ver%%[1-9]*}"} print ${ver%%[!0-9.]*} exit ;; -h) echo "" echo "$usage" echo "" echo "$tag copies itself onto the specified host and runs" echo "that copy via a remsh. That kills process trees where" echo "the top process is a known terminal emulator, has a ppid" echo "of 1 and is owned by the user." echo "It also kills 'remshd' processes that are the parent of a" echo "zombie process." echo "" echo "The '-z' flag causes the zombie parents only to be killed" echo "" echo "The '-n' flag shows process information and bypasses the" echo "kill. The script generated commands which are piped to" echo "a 'ksh -v' which has a '-n' added." echo "" echo "root is prevented from using this script as it would be" echo "too dangerous." echo "" exit ;; -n) n=n; dbg=1 ;; -y) y=y ;; -doit) n=""; dbg=0 ;; -z) z=1 ;; -r*([a-z])+([0-9])?([hms])) units=${1##*[0-9]} remotetimeout=${1%$units} remotetimeout=${remotetimeout##*[a-zA-Z]} case "$units" in h) remotetimeout=$(($remotetimeout * 60)) ;; m) ;; s) remotetimeout=$(($remotetimeout / 60)) ;; "") ;; esac ;; -t*([a-z])+([0-9])?([hms])) units=${1##*[0-9]} timeout=${1%$units} timeout=${timeout##*[a-zA-Z]} case "$units" in h) timeout=$(($timeout * 60)) ;; m) ;; s) timeout=$(($timeout / 60)) ;; "") ;; esac ;; -up*) cd rcp cis65:bin/$tag bin && shift && exec bin/$tag $* ;; --) ;; -*) opt="$1" shift set -- -- $(getopt hvxnz $opt) $@ || exit ;; *:) h=${1%:} [ $h = $hostname ] && shift && continue up $h || { print -u2 "$usage"; exit; } [ "${n-}" ] || { stty -echo remsh $h sudo -v stty echo } rcp $this ${h}:bin/$tag remsh $h bin/$tag $args exit ;; *) ;; esac shift done if false; then ps -el | awk ' function decendents(pid, c, l,t,x) { #print "#D", c+0, pid, chid[pid] split(chid[pid], t, " ") for (x in t) { l = sprintf("%s %s %s", l, t[x], decendents(t[x], c+1)) } #print "#L", l return l } BEGIN { me = "'"${id[1]}"'" id = "'"${uid-${id[1]}}"'" split("xterm hpterm dtterm", t, " ") for (x in t) { terms[t[x]] = 1 } v = ("'"${n-}"'" == "n") ? 1 : 0 z = "'"${z-0}"'" } NR == 1 { next } $5 == 0 { next } { print "#" $0 } { uid[$4] = $3 ppid[$4] = $5 chid[$5] = sprintf("%s%c%s", $4, #($5 in chid) ? " " : "", #($5 in chid) ? chid[$5] : "") " ", chid[$5]) cmd[$4] = $NF line[$4] = $0 } #$NF == "" { printf("echo \"%s\" ;\n", $0) } $NF == "" { zombie[$4] = 1 } $5 != 1 { next } $3 != id { next } ! ($NF in terms) { next } { top[$4] = 1 #print "#" $0 } END { #for (x in terms) { print "#" x } for (x in top) { if (v) { printf("echo \"T %s\";\n", line[x]) } split(decendents(x), t) for (y in t) { tokill[t[y]] = 1 } tokill[x] = 1 } for (y in tokill) { if (uid[y] != me) { rootkill[y] = 1 delete tokill[y] } } for (y in tokill) { if (! z) { printf("kill %d;\n", y) } } for (y in rootkill) { if (! z) { printf("sudo kill %d;\n", y) } } for (x in zombie) { if (v) { printf("echo \"Z %s\";\n", line[x]) } if (v) { printf("echo \"Z %s\";\n", line[ppid[x]]) } if (cmd[ppid[x]] == "remshd") { printf("sudo kill %d;\n", ppid[x]) } } } ' | ksh -v${n} fi eval $(w $LOGNAME | awk 'BEGIN { dbg = '"${dbg-0}"' uname = "'"$LOGNAME"'" rto = '"${remotetimeout-48}"'; rto += 0 rto = (rto > 1) ? rto : 1 lto = '"${timeout-24}"'; lto += 0 lto = (lto > 1) ? lto : 1 idlecol = 4 keep[1] = 1 } function tidy() { print | "cat 1>&2" tty = $2 pscmd = sprintf("ps -ft %s", tty) while ( pscmd | getline > 0 ) { psl[$2] = $0 if ($1 != uname) { continue } #print | "cat 1>&2" if ($3 in keep) { #print "Keep", $2 | "cat 1>&2" keep[$2] = $3 } else { #print "Kill", $2 | "cat 1>&2" kill[$2] = $3 } } close( pscmd ) } { print | "cat 1>&2" } $3 ~ /[0-9]+:[0-9amp]+:[0-9]+/ { #print | "cat 1>&2" if (split($3, t, "m") != 2) { next } $3 = sprintf("%sm %s", t[1], t[2]) tidy() } $3 ~ /[0-9]+:[0-9]+[ap]m/ { idlecol = 4 } $3 ~ /[0-9]+[ADFJMNOS][aceopu][bcglnprtvy][0-9]+/ { idlecol = 4 } $3 ~ /[FMSTW][aehoru][deintu]/ { idlecol = 5 } $idlecol ~ /[0-9]+days/ { #print | "cat 1>&2" #print match($4, /[^0-9]/) | "cat 1>&2" #print substr($4, 1, match($4, /[^0-9]/) - 1) + 0 | "cat 1>&2" if ((substr($4, 1, match($4, /[^0-9]/) - 1) * 24) > lto) { tidy() } } (split($idlecol, t, ":") < 2) { next } #{ print | "cat 1>&2" } { idle = t[1] * 60 + t[2] } $5 == "telnet" { if (idle > rto) { tidy() }; next } $5 == "rlogin" { if (idle > rto) { tidy() }; next } #{ print | "cat 1>&2" } (idle > lto) { tidy() ; next } END { for (p in kill) { if (p in keep) { continue } pids = (pids) ? p " " pids : p printf("psl[${#pids[*]}]=\"%s\";\n", psl[p]) printf("pids[${#pids[*]}]=%s;\n", p) } #if (! pids) { exit } #killcmd = sprintf("kill -HUP %s;\n", pids) #print killcmd | "cat 1>&2" #if (! dbg) { system( killcmd ) } }') typeset -i i=0 while [ $i -lt ${#pids[*]} ]; do yorn "${psl[$i]}\nKill ${pids[$i]}" ${y-n} || { i=$(($i + 1)) continue; } kill -HUP ${pids[$i]} i=$(($i + 1)) done cd || exit dirs=$(ls -d .hists .jpi_cache .java 2>/dev/null) [ "$dirs" ] && find $dirs -type f -mtime +300 | xargs rm -f [ -d .nohups ] && find .nohups -type f -mtime +90 \( -size 0 -o -mtime +300 \) | xargs rm -f