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

Hello Lovely Monks, I have snippet of code I created to kill user processes. We were to put the processes of a specified user into an array and kill them off one by one. I have the script working with no errors and it is killing off the processes. However I'm getting a system return that is kicking me out of my do-while loop. Not sure why this is happening. Some guidance would be appreciated. This subroutine takes place after I find the user's processes and have already written them to the array and printed the array.

sub kill_process{ do { print"Kill processes for the user (y orn?\n"; my $ans = <>; chomp $ans; print "choose pid: "\n; my $pid =<>; chomp $pid; system `kill $pid`; print "process killed \n"; }while ($ans eq "Y" || $ans eq "y"); },

forgot to show the sytem return message IPC::System::Simple::run called with no arguments at testarray_perl line 52. Line 52 is the system kill line.

Replies are listed 'Best First'.
Re: Killing processes
by Athanasius (Archbishop) on Mar 20, 2015 at 16:04 UTC

    Hello deyaneria,

    The logic of the do ... while loop is wrong. If the user answers “N”, the script still asks for a PID and then attempts to kill it! Also, you shouldn’t mix system with backticks (they are two ways of doing the same thing). Try something like this (untested):

    sub kill_process { print "Kill processes for the user? (y or n)?\n"; my $ans = <>; while ($ans =~ /^Y/i) { print "Enter pid to kill:\n"; my $pid = <>; chomp $pid; if (is_valid($pid)) { `kill $pid`; print "Process $pid killed\n"; } else { print "Process $pid is invalid\n"; } print "Kill more processes for the user? (y or n)?\n"; my $ans = <>; } }

    (You will need to implement sub is_valid too.)

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      I see what your saying but since I have previously listed all the processes running for the user, you are already pulling the pid from a valid list so I don't see the need for the is_valid, I know the code for that wasn't listed but it was a previous part of the code. So do I still need validate it? I guess i might need to in case of typo?
        I guess i might need to in case of typo?

        Yes, exactly. But since you already have an array of valid PIDs, it might be a better idea to change the logic of the subroutine and present each PID to the user instead. Like this:

        my @pids = ...; ... kill_processes(\@pids); ... sub kill_processes { my $pids = shift; for my $pid (@$pids) { print "Kill process $pid? ([y]es, [n]o, [q]uit)?\n"; my $ans = <>; last if $ans =~ /^Q/i; next unless $ans =~ /^Y/i; `kill $pid`; print "Process $pid killed\n"; } }

        Using this approach there is no possibility of a user-input typo. And as a bonus, the loop logic is simpler.

        Hope that helps,

        Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Killing processes
by choroba (Cardinal) on Mar 20, 2015 at 16:11 UTC
    Backticks call a shell command and return its output. system just runs a command, letting its output go to the standard output. But you combined them into
    system `kill $pid`;

    So, backticks call kill. Kill doesn't return anything on the standard output, so system gets called with an empty string as the argument. Remove the backquotes and just call system:

    my $status = system 'kill', $pid;

    Update: Or, even better, use kill:

    kill $pid;
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      so it's basically like i'm telling it to do it twice:) Thanks you guys pick up on stuff my teacher misses, he couldn't find anything wrong with it.

        My 2˘ - a very basic kata, featuring the usage of kill:

        karls-mac-mini:monks karl$ perl -e 'print $$;sleep;' & [1] 434 karls-mac-mini:monks karl$ jobs [1]+ Running perl -e 'print $$;sleep;' & karls-mac-mini:monks karl$ ps aux | grep [p]erl karl 434 0,0 0,0 2440564 2148 s000 S 7:20pm 0: +00.01 perl -e print $$;sleep; karls-mac-mini:monks karl$ perl -e 'print kill q(TERM), 434;' 1[1]+ Terminated: 15 perl -e 'print $$;sleep;' karls-mac-mini:monks karl$ jobs karls-mac-mini:monks karl$ ps aux | grep [p]erl karls-mac-mini:monks karl$

        Regards, Karl

        «The Crux of the Biscuit is the Apostrophe»

Re: Killing processes
by jimw54321 (Acolyte) on Mar 20, 2015 at 18:19 UTC

    Greeting Everyone,

    Two comments

    My understanding is that the kill command only reports whether or not it successfully sent a signal which may or may not have actually killed the process. The only safe thing to do is to check whatever mechanism you have for getting the PIDs in the first.

    Tangentially, IMHO, backticks are best avoided in Perl code. The syntax `some command` looks nicer as qx|some command|.

      I check to see if the process has been terminated. I start something like an infinite loop under another users name and switch accounts and kill it(run the script) from su access. Then flip back and make sure. It was definitely killing the processes. I also have checked the pids of the user under the unix terminal after running the script. I thank you for your insights:)