DigitalKitty has asked for the wisdom of the Perl Monks concerning the following question:

Hi all.

Recently, when I lost my connection to a Solaris box, I discovered upon logging back in that my previous login was still there. Of course I could simply use:

$kill -9 pidNumber

This would be somewhat tedious. So, I was wondering if anyone had a suggestion or two for a perl script that would kill the old process(es) but retain my current login. This way, a simple command would suffice.
Thanks,
-DK

Replies are listed 'Best First'.
Re: Killing multiple logins.
by PrimeLord (Pilgrim) on Apr 23, 2002 at 20:58 UTC
    So you don't end up killing something you didn't really want to you could do something interactive like this.

    use strict; open PS, "ps |" or die "$!"; while (<PS>) { chomp; my @process = split; next if $process[0] =~ /[^\d]/; print "Would you like to kill the following process?\n"; print "$_\n"; chomp (my $ans = <STDIN>); kill 9 => $process[0] if $ans eq 'yes'; } close PS;


    Its quick, dirty, and untested but it should provide the funtionality you are looking for. You can have it run out of your .bash_profile or your shells equivalent or just run it manually whenever you want.

    Update: I added the next if $process[0] =~ /[^\d]/; line so it doesn't prompt you to kill the header in the ps listing.

    HTH

    -Prime

      ...the problem I have with this approach (and with the use of who(1)) is that their output is not predictable. Some people still use the BSD version of ps(1), some people use the SysV version, and some use the GNU version. I presume that on Solaris, you're using the SysV version unless you've updated your path.

      Given that assumption, it is possible to use Perl easily enough to parse the output and give you the identities of the processes you hope to kill. And that would look a lot like the classic shell script that does this task.

      I keep thinking (as I write this) that there ought to be a nice one-liner that does the trick. Perhaps I'll work it out.

      ---v

      Well, I took a crack at it, but the only improvements I was able to offer is an invocation of ps(1) that renders the output a little more predicatably.

      Here's the code:

      #!/usr/bin/perl $myself = "student"; chomp ($mytty = `tty`); # gets: /dev/pts/5 $mytty =~ s/.dev.//; # gets: pts/5 =preview We'll run the command: ps -u $myself -o 'pid,tty' It will produce output like this: PID TT 419 pts/3 401 pts/3 398 ? 399 pts/3 437 ? 479 pts/5 513 pts/5 1175 ? =cut @lines = split /\n/, `ps -u $myself -o 'pid,tty'`; shift @lines; # gets rid of header line foreach $entry (@lines) { ($pid, $term) = $entry =~ /^\D*(\d+)\s+(\S+)/; next if ($term =~ /^[?]/ || $term eq $mytty); print "kill 9, $pid\n"; # for testing # kill 9, $pid; # production version }

      With light testing on this system (sol8,perl v5.005), it gave the results I was hoping for. I don't know if there are some anomalous listings that might have to be accounted for.

      But you will note that it finds processes with a TTY other than the current one, and kills them all. It would be better to kill only the process group leader and that would cause the others to be killed by init.

      YMMV

Re: Killing multiple logins.
by perlplexer (Hermit) on Apr 23, 2002 at 20:51 UTC
    who might be useful.
    Run 'who -u' and parse the output; e.g., use 'login time' or 'idle time'. Then kill() unneeded sessions.

    --perlplexer
      I have the same problems on my servers at work (SCO 5.0.5) and quite a while ago I created a small shell script to deal with the problem. You could write this is perl as well but I see no point to it. This works in straight sh so you should be fine with it anywhere. The below code has had the checking part of it removed for brevity.
      #!/bin/sh port=$1 kill -9 `ps -ft$port | sed '1d' | awk '{print $2}'
Re: Killing multiple logins.
by Fletch (Bishop) on Apr 24, 2002 at 03:22 UTC

    TMTOWTDI, some of them not involving perl. :)

    $ TTY=`tty` $ kill -HUP $( ps xuaw | grep $SHELL | grep -v ${TTY#/dev/} | awk '{ p +rint $2 }' )

    Update: This may be somewhat zsh specific. Newer bashen should understand $() for backticks. If you're using zsh (and you should be, because it rules (almost as much as perl :)), ${TTY#/dev/} can be replaced with ${TTY:t} and you shouldn't need to set TTY yourself.

Re: Killing multiple logins.
by Anonymous Monk on Apr 23, 2002 at 21:52 UTC
    Why is this node so badly downvoted? While not a particularily big brainbender it does seem like a reasonable enough question. Of course, this is a simple question but the point of voting in this category isn't to punish people for asking questions that are simple to most of us here, is it?

      ...I'd say don't worry about it. There is a class of technician who believes it to be a personal affront when someone asks a question that they (the technician) already knows the answer to. Usually this sort of person will also take offense at being told a fact that they already possess.

      Just keep posting your earnest questions and your earnest responses, and eventually the right result will occur.

      I certainly thought this question worthy of a little thought. Many programmers are born puzzle-solvers and it's hard for those among us to pass up a good puzzle that needs a solution.

      So keep contributing in good faith.

      ---v

      Thanks Anonymous Monk.

      I wasn't under the impression that it was a difficult question. After asking two of my co-workers, they stated they had also experienced the problem but had never given the issue any more thought. The idea of creating a useful command was the enticing part. If a user didn't find it personally useful, it shouldn't matter. One can never be quite sure when a particular tool will be of benefit.
      -Caitlin.
Re: Killing multiple logins.
by Anonymous Monk on Apr 24, 2002 at 12:22 UTC
    Does solaris use bash?

    If so, how does
    echo 'export TMOUT=600' >> /etc/profile
    fare?
Re: Killing multiple logins.
by graff (Chancellor) on Apr 24, 2002 at 03:00 UTC
    An approach that would work equally well on solaris and linux would be one that scans /proc, figures out which processes belong to you, and which of your processes are older than the shell from which the current perl process is running. This can be done simply in at least a couple different ways, using opendir or just parsing the output of `ls -l /proc | grep myname`.

    Of course, if you happen to run any jobs that are supposed to keep going for days in the background, you might want something like a dot file in your home directory that the killer script can look for, to know which jobs to leave alone (and have a substitute or wrapper for "nohup" that puts pids into such a file). Have fun with that.

    Update:Duh -- just realized I was wrong to think that ls -ld /proc/[1-9]* could tell you how old the jobs are on linux; this does to work on solaris, at least.