home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / unix / question / 9324 < prev    next >
Encoding:
Internet Message Format  |  1992-07-22  |  9.1 KB

  1. Path: sparky!uunet!dtix!darwin.sura.net!mips!apple!news.oc.com!convex!tchrist
  2. From: tchrist@convex.COM (Tom Christiansen)
  3. Newsgroups: comp.unix.questions
  4. Subject: Re: Script for killing mutiple processes?
  5. Message-ID: <1992Jul23.042937.25827@news.eng.convex.com>
  6. Date: 23 Jul 92 04:29:37 GMT
  7. References: <1992Jul21.135406.10224@ncsu.edu> <smr.711814165@hitkw14>
  8. Sender: usenet@news.eng.convex.com (news access account)
  9. Reply-To: tchrist@convex.COM (Tom Christiansen)
  10. Organization: CONVEX Realtime Development, Colorado Springs, CO
  11. Lines: 362
  12. Originator: tchrist@pixel.convex.com
  13. Nntp-Posting-Host: pixel.convex.com
  14. X-Disclaimer: This message was written by a user at CONVEX Computer
  15.               Corp. The opinions expressed are those of the user and
  16.               not necessarily those of CONVEX.
  17.  
  18. From the keyboard of smr@iti.org (Stephen Riehm):
  19. :odkahn@eos.ncsu.edu (Opher D. Kahn) writes:
  20. :
  21. :>with 10-15 child processes that need to be killed.  Is it possible
  22. :>to somehow pipe the process numbers from 'ps -aux | grep dood' into
  23. :>a kill command, so that I don't have to kill each one of them
  24. :>manually???  (dood is the name of the process).
  25. :
  26. :for a whlie I have had the following script lying around.. it might be
  27. :of some help to you... ( OK its csh, but I wrote it before I got to
  28. :like /bin/sh and I can't be bothered converting it blah blah blah )
  29.  
  30. sloth is no excuse for evil.
  31.  
  32. i'd swear i just reposted this.
  33.  
  34. --tom
  35.  
  36.  
  37. #!/usr/local/bin/perl
  38. #
  39. # zap  -- blow away (or renice) processes
  40. # tom christiansen -- tchrist@convex.com
  41. #
  42. # currently configured for BSD
  43. #
  44. # Patterned after an idea from K&P, an old script
  45. # of mine, and Jeff Forys's humungous C program, skill. :-)
  46. #
  47. #
  48. # some defaults... look out for the first one!
  49.  
  50. ($PRIO_MIN, $PRIO_MAX) = (-64, 64);     # from sys/resource.h
  51. $signal   = 'TERM';
  52. $priority = +4;
  53.  
  54. ###############################################################
  55.  
  56. setpriority(0, $$, $PRIO_MIN);      # faster faster faster
  57. $SIG{HUP} = IGNORE;
  58.  
  59. $| = 1;
  60.  
  61. &init;
  62. &parse_args;
  63. &usage unless @cmd || @tty || @pid || @regexp || @user;
  64. &dump_values if $flag{'d'};
  65. &start_ps;
  66. &kill_procs;
  67. exit $status;
  68.  
  69. #####################################################################
  70.  
  71. sub parse_args {
  72.     local($numarg, $type, $signals);  # include *targets and die
  73.  
  74.     while ($_ = shift @ARGV) {
  75.     if (/^[-+](\d+)$/) { 
  76.         $numarg = $_;   # signal or numeric
  77.     } 
  78.     elsif (s/^-//) {
  79.         if (defined $signame{$_}) { 
  80.         if ($mode eq 'nice') {
  81.             warn "$0: can't mix signals with niceties, ignoring -$_\n";
  82.         } else {
  83.             $signal = $_; 
  84.         }
  85.         } 
  86.         elsif (s/^([cputr])(.*)//) {
  87.         *targets = $targptr{$type = $abbrev{$1}};
  88.         $_ = $2 || shift @ARGV;
  89.         unless (&targets($_)) {
  90.             die "$0: $_: invalid $type" unless $type eq 'regexp';
  91.             die "$0: $@\n";
  92.         }
  93.         push(@targets, $_);
  94.         } 
  95.         else {     # these can be anywhere
  96.         $flag{$1}++ while s/^([ildvNna])//; 
  97.         if (/[cputr]/) { s/^/-/; redo; }   # bad hack
  98.         if ($_ ne '') {
  99.             warn "$0: unknown option -$_\n";
  100.             &usage;
  101.         }
  102.         if ($flag{'l'}) {
  103.             $signals = "@signum";
  104.             write; # see format at end of file
  105.             exit;
  106.         } 
  107.         } 
  108.     } 
  109.     else {                     # time to guess
  110.         if ( s!^/dev/!! || &tty($_)) {
  111.         *targets = $targptr{'tty'};
  112.         } elsif (&user($_)) {
  113.         *targets = $targptr{'user'};
  114.         } elsif (&pid($_)) {
  115.         *targets = $targptr{'pid'};
  116.         } elsif (s!^/(.*)/?$!$1!) {
  117.         die "$0: $@\n" unless ®exp($_);
  118.         *targets = $targptr{'regexp'};
  119.         } else {
  120.         *targets = $targptr{'cmd'};
  121.         } 
  122.         push(@targets,$_);
  123.     } 
  124.     } 
  125.  
  126.     $mode = 'nice' if $flag{'N'};
  127.  
  128.     if (defined $numarg) {
  129.     if ($mode eq 'kill') {
  130.         $numarg =~ s/^[-+]//;
  131.         $signal = $numarg ? $signum[$numarg] : 0; #  perl hates 'ZERO'
  132.     } else {
  133.         undef $signal;
  134.         $priority = $numarg;
  135.         $priority = $PRIO_MIN     if $priority < $PRIO_MIN;
  136.         $priority = $PRIO_MAX     if $priority > $PRIO_MAX;
  137.     } 
  138.     }
  139.  
  140.  
  141.  
  142. #####################################################################
  143.  
  144. sub uid2name {
  145.     local($uid) = @_;
  146.     unless (defined $name{$uid}) {
  147.     local($name) = (getpwuid($uid))[0];
  148.     $uid{$name} = $uid;
  149.     $name{$uid} = $name;
  150.     }
  151.     $name{$uid};
  152.  
  153. sub name2uid {
  154.     local($name) = @_;
  155.     unless (defined $uid{$name}) {
  156.     local($uid) = (getpwnam($name))[2];
  157.     $uid{$name} = $uid;
  158.     $name{$uid} = $name;
  159.     }
  160.     $uid{$name};
  161.  
  162. ######################################################################
  163. # magic names here -- touch these and you are apt to be surprised
  164.  
  165. sub pid {
  166.     local($pid) = @_;
  167.     $pid =~ /^\d+$/;
  168. }
  169.  
  170. sub tty {
  171.     local($tty) = @_;
  172.     $tty =~ /^tty/ && -c "/dev/$tty";
  173.  
  174. sub user { 
  175.     local($who) = @_;
  176.     local($ok) = &name2uid($who); 
  177.     defined $ok;
  178.  
  179. sub cmd {
  180.     1;   
  181.  
  182. sub regexp {
  183.     local($pat) = @_;
  184.     eval '/$pat/';
  185.     $@ =~ s/at \(eval\).*\n//;
  186.     $@ eq '';
  187.  
  188. ######################################################################
  189.  
  190. sub init {
  191.  
  192. #    run either as skill or as snice; this tells whether -5 is a 
  193. #    signal or a priority
  194.  
  195.     $mode = 'kill';
  196.     $mode = 'nice' if $0 =~ /nice/;
  197.  
  198. #   generate signal names ; comment out signames assignment
  199. #   to run kill -l instead to figure it out
  200.  
  201.     $signames = <<__EOLIST__;  # comment out for dynamic determination
  202.     HUP INT QUIT ILL TRAP IOT EMT FPE KILL BUS SEGV SYS PIPE ALRM
  203.     TERM URG STOP TSTP CONT CHLD TTIN TTOU IO XCPU XFSZ VTALRM PROF
  204.     WINCH LOST USR1 USR2
  205. __EOLIST__
  206.  
  207.     local($signal);
  208.     $signum[0] = 'ZERO';
  209.     for (split(' ', $signames ? $signames : `kill -l`)) { 
  210.     $signame{$_} = ++$signal; 
  211.     $signum[$signal] = $_;
  212.     }
  213.  
  214. #   set up pointers and single-char abbrev for our 4 target arrays
  215. #   if you change one of strings, all idents of this name, including
  216. #   the subroutines, must change also.  be VERY CAREFUL.
  217.  
  218.     for ('cmd', 'pid', 'user', 'tty', 'regexp') {
  219.     $abbrev{(/^(.)/)[0]} = $_;
  220.     $targptr{$_} = eval "*$_";
  221.     } 
  222.  
  223. #   some defaults
  224.  
  225. }
  226.  
  227. #####################################################################
  228.  
  229. sub dump_values {
  230.     print "signal is $signal -$signame{$signal}\n" if $mode eq 'kill';
  231.     print "will renice targets to $priority\n" if $mode eq 'nice';
  232.  
  233.     for (keys %targptr) {
  234.     *targ = $targptr{$_};
  235.     next unless defined @targ;
  236.     print "$_ targets are ", join(', ', @targ), "\n";
  237.     } 
  238.  
  239.     @flags = keys %flag;
  240.     grep(s/^/-/, @flags);
  241.     print "option flags are @flags\n";
  242. }
  243.  
  244. #####################################################################
  245.  
  246. sub usage {
  247.      die <<EOF;
  248. Usage:
  249.      skill [-signal] [-Nildvna] {tty user command pid regexp}
  250.      snice [(-|+)priority] [-Nildvna] {tty user command pid regexp}
  251.  
  252.      -i    interactive
  253.      -v    show candidates
  254.      -n    like -v but don't really do it
  255.      -a    all procs are candidates
  256.      -N    nice mode 
  257.      -d    enable debugging
  258.  
  259.      -l    list signals and exit
  260.  
  261.      Uniquely identify {...} args with leading -t, -u, -c, -p, -r
  262.      Or use a leading slash for a regexp.
  263. EOF
  264.     exit 1;
  265.  
  266. ######################################################################
  267.  
  268. sub start_ps {
  269.     $ps = 'ps xl';
  270.     $ps .= 'w';
  271.  
  272.     grep($pid{$_}++, @pid);
  273.     grep($user{&name2uid($_)}++, @user);
  274.     grep($tty{$_}++, @tty);
  275.     grep($cmd{$_}++, @cmd);
  276.     $regexp = join('|', @regexp);
  277.  
  278.     $ps .= 'w' if $regexp;
  279.     $ps .= 'a' if  $> == 0      ||
  280.            $flag{'a'}   ||
  281.            @user > 1     || 
  282.            (@user == 1 && &name2uid($user[0]) != $>);
  283.     
  284.     if (! $pattern && @cmd && !grep(m!^/!, @cmd)) { $ps .= 'c'; } 
  285.  
  286.     if (@tty == 1) {  # faster
  287.     $tty[0] =~ /^tty(..)/;
  288.     $ps .= "t$1";
  289.     } 
  290.  
  291.     print "ps command is $ps\n" if $flag{'d'};
  292.  
  293.     defined($kid_pid = open(PS, "$ps |")) ||   die  "can't run ps: $!";
  294.     if (<PS> !~ /UID/) {
  295.     warn "Something's wrong with ps";
  296.     kill 'TERM', $kid_pid;
  297.     exit 2;
  298.     } 
  299.  
  300.     $dad_pid = getppid();
  301.  
  302. ######################################################################
  303.  
  304. sub kill_procs {
  305.     while (<PS>) {
  306.     ($user, $pid) = /^\s*[a-f\d]+\s+(\d+)\s*(\d+)/i;
  307.  
  308.     next if $pid == $$;
  309.     next if $pid == $kid_pid;
  310.     next if $pid == $dad_pid && $mode eq 'kill';
  311.     
  312.     next if @user && !$user{$user};
  313.     next if @pid  && !$pid{$pid};
  314.  
  315.     ($tty, $cmd) = /\s*(\S*)\s*\d+:\d+\s+(.*)$/;
  316.     $tty = "tty$tty" unless $tty =~ /\?/;
  317.  
  318.     next if @tty  && !$tty{$tty};
  319.     next if @regexp && $cmd !~ /$regexp/o;
  320.  
  321.     if (@cmd) {
  322.         ($cmdname) = ($cmd =~ /^(\S+)/);
  323.         $cmdname =~ s!.*/!!;
  324.         next if !$cmd{$cmd} && !$cmd{$cmdname};
  325.     }
  326.  
  327.     printf "%5d  %-8s %-5s  %s ", $pid, &uid2name($user), $tty, $cmd
  328.         if $flag{'v'} || $flag{'i'} || $flag{'n'};
  329.  
  330.     if ($flag{'i'}) {
  331.         $_ = <STDIN>;
  332.         defined     || exit;
  333.         /^\s*y/i     || next;
  334.     }
  335.  
  336.     $hits++;
  337.  
  338.     unless ($flag{'n'}) {
  339.         $! = 0;
  340.         if ($mode eq 'kill') {
  341.         kill $signal, $pid;
  342.         } else {
  343.         setpriority(0, $pid, $priority);
  344.         } 
  345.         if ($!) { 
  346.         warn (($mode eq 'kill' ? 'kill' : 'setpriority')
  347.             .   " $pid: $!\n");
  348.         $status = 1;
  349.         next;
  350.         }
  351.     }
  352.  
  353.     print "\n" if $flag{'v'} || $flag{'n'};
  354.     } 
  355.     close PS || die "something happened to your $ps";
  356.     warn "$0: no target processes found\n" unless $hits;
  357.  
  358. ######################################################################
  359.  
  360. format STDOUT = 
  361. Any of the following signals are valid, or their numeric equivalents:
  362. ~~   ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  363.       $signals
  364. .
  365. -- 
  366.     Tom Christiansen      tchrist@convex.com      convex!tchrist
  367.  
  368. SCCS, the source motel!  Programs check in and never check out!
  369.                 -- Ken Thompson
  370.