#!/usr/bin/perl -w # process_killer.pl # # Interactive process killer utilizing the Tk GUI toolkit. # Uses the system's "ps" command to get a list of the currently-running processes, # and the system's "kill" command to send them signals. # # My machine's "ps", when run with "ps ux", gives output like the following: # USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND # falkkin 531 0.0 1.4 2316 1380 tty1 S 08:53 0:00 -bash # # My machine's "kill" is of the form "kill -s $signal $pid". # Supported signals include TERM, STOP, CONT, INT, HUP, and KILL. # # You'll need to modify this script if your "ps" command formats output differently # or your "kill" command has different syntax. # Eventually, I hope to make this script more portable. # # Authored by Colin McMillen (e-mail: colin at jenovaproject.org) and released # into the public domain. You may use, copy, redistribute, and modify this program # without any restrictions. # # use strict; use Tk; my $VERSION = v0.1; # Choose the options to send to "ps". Defaults to "ps ux". my $PS_OPTIONS = $ARGV[0] || "ux"; # Index (starting from 0) of the fields for process ID and command name. my $PID_FIELD = 1; my $COMMAND_FIELD = 10; # Create the main window and add an informational label. my $top = MainWindow->new(); $top->title("process_killer.pl"); $top->Label(text => "Double-click on the process you would like to kill.")->pack(); # Create a frame to hold the process list and its scrollbar. my $frame1 = $top->Frame()->pack(fill => "both", expand => "y"); # Get the actual process list and discard the first line of output (which # contains informational headers that we want to ignore). my @processes = `ps $PS_OPTIONS`; shift @processes; # Use the process list to create a listbox. Add the listbox to $frame1. my $process_list = $frame1->Listbox(width => 80, height => 15)->pack(side => "left", fill => "both", expand => "y"); # Split each line of output into fields, based on whitespace. Then, get the # process ID and command name out of the fields, and add them to the listbox. foreach my $process (@processes) { my (@fields) = split(/\s+/, $process); my $pid = $fields[$PID_FIELD]; my @command = @fields[ $COMMAND_FIELD .. @fields-1 ]; my $command = join(" ", @command); $process_list->insert("end","$pid $command"); } # Bind a double-click on the listbox to the kill() subroutine. $process_list->bind("", \&kill); # Create a scrollbar to scroll the listbox vertically and add it to $frame1. my $scrollbar = $frame1->Scrollbar(orient => "vertical", width => 10, command => ["yview", $process_list], )->pack(side => "left", fill => "y"); $process_list->configure(yscrollcommand => ["set", $scrollbar]); # Create a frame to hold radiobuttons for choosing a signal. my $frame2 = $top->Frame()->pack(); # Create the radiobuttons inside $frame2. $frame2->Label(text => "Choose a signal:")->pack(side => "left"); my $signal = "TERM"; $frame2->Radiobutton(variable => \$signal, text => "Terminate", value => "TERM")->pack(side => "left"); $frame2->Radiobutton(variable => \$signal, text => "Stop", value => "STOP")->pack(side => "left"); $frame2->Radiobutton(variable => \$signal, text => "Continue", value => "CONT")->pack(side => "left"); $frame2->Radiobutton(variable => \$signal, text => "Interrupt", value => "INT")->pack(side => "left"); $frame2->Radiobutton(variable => \$signal, text => "Hangup", value => "HUP")->pack(side => "left"); $frame2->Radiobutton(variable => \$signal, text => "Kill", value => "KILL")->pack(side => "left"); # Hand control of the program off to the GUI. MainLoop(); # Subroutine called when a field in the listbox is double-clicked. # The process ID of the process is the first field in the listbox's active item. # The signal to send the process is set by the radiobuttons and stored in # the variable $signal. sub kill { my $process = $process_list->get('active'); my ($pid) = split(/ /, $process); return unless $pid; system("kill -s $signal $pid"); }