From owner-wu-ftpd@wugate.wustl.edu Sat Mar 8 00:05 CST 1997 Message-Id: Date: Fri, 7 Mar 1997 23:58:04 -0600 From: Albert Lunde To: wu-ftpd@wugate.wustl.edu Subject: Re: Hanging ftpd processes X-Sender: lunde@lulu.acns.nwu.edu (Unverified) Below is a perl 5 script I've been using to kill old ftpd processes. I was written for HP/UX 10.20 and is likely full of OS- and site-specific code. It makes a detailed attempt to compute elapsed time from the ps output, to distingush anonymous from real users, to distingush idle vs. active sessions, and applies different time limits to accordingly. It reports by mail when it kills a process. Huristics are used that can sometimes fail. - - cut here - - #!/opt/local/bin/perl -w #1234567890123456789012345678901234567890123456789012345678901234567890123456 # UID PID PPID C STIME TTY TIME COMMAND # root 0 0 0 Dec 13 ? 7:03 swapper # root 1 0 0 Dec 13 ? 0:00 init # root 2 0 0 Dec 13 ? 15:25 vhand # root 28753 660 0 15:40:52 ? 0:00 ftpd: pppb519.pppp.ap.so-net.or.jp: anonymous/mozilla@: IDLE # root 28730 660 0 15:39:39 ? 0:00 ftpd: highwood.library.nwu.edu: jhobbs: IDLE # webserv 28774 13362 0 15:42:04 ? 0:00 /opt/local/etc/httpd/httpd # webserv 28743 13362 0 15:40:14 ? 0:00 /opt/local/etc/httpd/httpd # root 13362 1 0 02:01:24 ? 0:17 /opt/local/etc/httpd/httpd # root 28792 18503 4 15:43:14 ttyp1 0:00 ps -ef sub parse_ps { # parse one line in ps output my($line)=@_; my(@result)=(); my($etotal); my($stotal); my($thensec)=""; my($user,$pid,$ppid,$c,$stimecol,$tty,$etime,$cmd); if ($line =~ /\s*([a-z0-9\-]+)\s+(\d+)\s+(\d+)\s+(\d+)/){ $user=$1; $pid=$2; $ppid=$3; $c=$4; $stimecol=substr($line,24,8); # $stimecol="23:59:58"; $stimecol =~ s/^\s+//; $stimecol =~ s/\s+$//; my($tail)=substr($line,33); $tail=~ /\s*(\S+)\s*(\S+)\s*(.+)/; $tty=$1; $etime=$2; $cmd=$3; $cmd =~ s/\s+$//; # if($etime=~ /(\d+)\:(\d+)/){ my($emin)=$1; my($esec)=$2; $etotal=$esec+(60*$emin); }else{ $etotal=""; }; # if($stimecol =~ /(\d+)\:(\d+)\:(\d+)/){ my($shr)=$1; my($smin)=$2; my($ssec)=$3; # need to parse this to get elapsed time to present $thensec=$ssec+60*($smin+(60*$shr)); # printf "thensec=$thensec\n"; if($thensec>$nowsec){ $thensec=$thensec-86400; }; # printf "thensec=$thensec\n"; $stotal=$nowsec-$thensec; }else{ $thensec=""; $stotal=43200; }; # # my($etmin)=int($etotal/60); # my($stmin)=int($stotal/60); # print "user=$user pid=$pid ppid=$ppid c=$c stime=\"$stimecol\"\ntty=$tty time=$etime cmd=$cmd\nnowsec=$nowsec thensec=$thensec stotal=$stotal $stmin min etotal=$etotal $etmin min \n"; @result=($user,$pid,$ppid,$stotal,$tty,$etotal,$cmd); } return @result; } # main program # run ftpwho and look for old procs # kill after 1 hr if IDLE, 3 hr always for anonymous # kill after 2 hr if IDLE, 4 hr always for others @now=localtime(time); $nowsec=$now[0]+60*($now[1]+(60*$now[2])); my(@report)=(); my($dorep)=0; my($mailto)="FILL-IN-YOUR-NAME-HERE\@some.domain"; open(WHO,"/local-adm/bin/ftpwho|")||die("ftpwho failed"); #while(<>){ while(){ chomp; next if /^Service class/; next if /^\s+\-/; next if /^\s*$/; print "$_\n"; my($mess)=""; my($user,$pid,$ppid,$stotal,$tty,$etotal,$cmd)=&parse_ps($_); my($stmin)=int(($stotal/60)+0.5); next if $cmd =~ /^\s*ftp:/; my($idle)=0; my($anon)=0; $idle=1 if ($cmd =~ /IDLE$/); $idle=1 if ($cmd =~ /IDL$/); $idle=1 if ($cmd =~ /ID$/); $anon=1 if $cmd =~ /^\s*ftpd:\s+\S+\s+anonym/; print "idle=$idle anon=$anon connect time=$stmin min\n"; my($killme)=0; if($anon){ if($idle){ # kill IDLE after 1 hr $killme=($stmin>60); }else{ # kill anything after 3 hr $killme=($stmin>180); } }else{ if($idle){ # kill IDLE after 2 hr $killme=($stmin>120); }else{ # kill anything after 4 hr $killme=($stmin>240); } } if($killme){ $dorep=1; my($mess)=$_; $mess=~ s/^\s+//; $mess=~ s/\s+$//; $mess="KILL: ".$mess; print "$mess\n"; push @report,"idle=$idle anon=$anon connect time=$stmin min"; push @report,$mess; my($doit)="/usr/bin/kill $pid"; print "Do: $doit\n"; system($doit); } } if($dorep){ # report results by mail open (MAIL, "|/usr/sbin/sendmail -oi -t -f root"); # print MAIL "Return_path: \n"; print MAIL "From: root\@pubweb.nwu.edu\n"; print MAIL "To: $mailto\n"; print MAIL "Subject: pubweb ftp process killed cronjob\n"; print MAIL "\n\n"; print join("\n",@report),"\n"; print MAIL join("\n",@report),"\n"; close (MAIL); }; close(WHO); # - - cut here - - --- Albert Lunde Albert-Lunde@nwu.edu