Tuesday, February 15, 2011

Perl: Killing Multiple Processes

This is done by getting a list of the user owned process' IDs and piping it into a perl one-line program as follows:  

ps -u username perl -ane 'kill 9, $F[0]'

What the above command string does is quite simple. We obtain the list of processes owned by username with: 

ps -u username

A sample output from my Linux host is as below:

  PID TTY          TIME CMD
 1414 ?        00:00:00 gnome-keyring-d
 1432 ?        00:00:00 gnome-session
 1466 ?        00:00:00 ssh-agent
 1469 ?        00:00:00 dbus-launch
 1470 ?        00:00:04 dbus-daemon
 1473 ?        00:00:03 gconfd-2
 1480 ?        00:00:05 gnome-settings-
 1482 ?        00:00:00 gvfsd

The entire list of lines is then piped into the perl program:

perl -ane 'kill 9, $F[0]'

What the 'short-form' Perl command above does is functionally equivalent to the 'expanded' Perl program below: 

while (<>) {
  @F = split; 
  kill 9,$F[0]; 
}

The options and their contribution to the code construct above, is explained in matching colour text here:

-e The Perl executable statement
-n Envelopes the entire Perl executable in a while-loop 
-a Ensures each line read from standard input is split on the spaces, into individual fields, on each iteration of the while-loop. The fields are stored in the array @F. If we consider the line #2 from the sample out of 'ps -u', we will have: 
                                                                    $F[0] = 1414
                                                                    $F[1] = ?
                                                                    $F[2] = 00:00:00
                                                                    $F[3] =  gnome-keyring-d
Since the process ID always gets stored in $F[0], we use that within the 'kill' command.


N.B.  
  • You would have noticed the first line of the output from the ps command is the header. As such, $F[0] would be 'PID' in this case. Perl's kill command will throw a warning for this, which can be safely ignored. Should you wish to avoid the warning altogether with a 'cleaner' run of the command, you ensure only numbers are extracted with the if construct:
ps -u username | perl -ane 'kill 9,$F[0] if $F[0]=~/^\d+/'

Perl: Command Options

Perl is a very-high-level programming language. Although famous for its expressiveness in big programming tasks, it is equally powerful within the limited confines of the Unix command line. With just a few command invocation options of Perl, we could perform tasks in similar succinct ways as provided by the traditional Unix shell utilities much like SED, AWK and so on. We explore the various ways of calling Perl on the command line.

Presented here is a side-by-side mapping of each of several Perl command line constructs to its expanded form. The colours match-up a command line option to its construct within the expanded Perl code form.


Command line Perl                                                                                         Expanded Perl Form

perl -n -e 'perl statements'                                      while (<>) {
                                                 perl statement(s)
                                               }
 
perl -p -e 'perl statements'                   while (<>) {
                                                 perl statement(s)
                                                 print;

                                               }
perl -a -n -e 'perl statements'                while (<>) { 
                                                 @F = split;
                                                 perl statement(s)
                                               } 


perl -a -p -e 'perl statements'                while (<>) {
                                                 @F = split;                                                  perl statement(s)
                                                 print;

                                               }

perl -a -F: -p -e 'perl statements'            while (<>) {
                                                 @F = split ':', $_;                                                  perl statement(s)
                                                 print;

                                               }

Legend:

-e The Perl executable statement
-n Envelopes the entire Perl executable in a while-loop 
-a Ensures each line read from standard input is split on spaces into individual fields, within each iteration of the while-loop. The fields are stored in the array @F. We access each field using Perl's array element access notation $F[0], $F[1] etc.
 -F   Specify a character at which split is made, when used with the -a option.
-p The effect here is identical to that of the  '-n' option but a 'print' statement, which prints out $_ at the end of each pass of the while-loop, is included.