Listing 1: KP script
#!/usr/bin/wish -f
#
# -----------------------------------------
# KillProc -- signal a hung/runaway process
# -----------------------------------------
#
lappend auto_path "/usr/local/lib/tkextra"
# ------------------------------
# Application-specific globals
# ------------------------------
# arguments for the 'ps' command (change to suite your 'ps')
# SysV:
set ps_user "-fu"
set ps_all "-ef"
# pre-SysV:
# set ps_user "-au | grep "
# set ps_all "-ax"
# initial values for menu options
set user $env(LOGNAME)
set signal -INT
# ------------------------------
# Application-specific routines
# ------------------------------
#
# Get the selected line(s) from the list-box,
# extract the pid, signal the process
#
proc kill_proc {} {
global user signal
#
# Get the list of selected line numbers
# If the list is empty, nothing is selected, so return
#
set sellist [.ps.list curselection]
if {[llength $sellist] == 0} {
return
}
#
# For each entry in the selected-lines-list,
# Get the line, extract the pid, append to a list of PID's
# (optional: filter out critical processes that shouldn't be touched)
#
foreach index $sellist {
set line [.ps.list get $index]
scan $line "%s %d" uid pid
if {$pid <= 0} {
continue
}
# Use this to skip over "must-not-kill" processes:
# if {[string match "*xyz*" $line]} {
# err "$line\n\nLooks like a 'xyz' process;\n Should not kill it!"
# continue
# }
lappend pid_list $pid
}
#
# Construct a "kill" command line,
# Execute it and get the error return
#
set cmd [list exec kill $signal $pid_list]
set ret [catch $cmd err]
#
# If there was a problem signalling a process,
# Let the user know
#
if {$ret == 1} {
msg "Could not kill a process;\nit's already gone?"
return
}
#
# Refresh the process list
#
scan_proc
}
#
# Do a "ps", collect the output, put into a list-box
#
proc scan_proc {} {
global user ps_user ps_all
#
# Generate the "ps" command line
#
if {$user == "Any"} {
set cmd "|ps $ps_all | sort"
} {
set cmd "|ps $ps_user $user | sort"
}
#
# Evaluate the command line
# Get the resulting list of lines
# Fill the list-box with the lines
#
fill_list .ps.list [read_list $cmd] 0
}
# ------------------------------
# GUI Specific Routines
# ------------------------------
#
# Make the main control panel -- fill it with some controls
#
proc make_control_panel { } {
global user signal
#
# Setup some window-manager options
#
wm title . "Process Killer"
wm iconname . "KP"
wm command . "KillProc"
#
# Make the menu
#
menu_bar .mbar 0 \
{menu File} \
{cmd Quit exit} \
{end left} \
{menu Signals} \
{radio " 1 Hangup" signal "-HUP"} \
{radio " 2 Interrupt" signal "-INT"} \
{radio " 3 Quit" signal "-QUIT"} \
{radio " 9 Kill" signal "-KILL"} \
{radio "14 Alarm" signal "-ALRM"} \
{radio "15 Terminate" signal "-TERM"} \
{radio "23 Stop" signal "-STOP"} \
{radio "24 Term. Stop" signal "-TSTP"} \
{radio "25 Continue" signal "-CONT"} \
{end left} \
{menu User} \
{radio Any user Any} \
{radio Me user $user} \
{sep} \
{radio moe user moe} \
{radio curly user curly} \
{radio larry user larry} \
{end left}
#
# Make the scrolling list-box
#
mk_list .ps kill_proc
#
# Make the control buttons
#
buttons .cmd "" left 0 \
{width 4} \
{cmd "Scan" scan_proc} \
{cmd "Kill" kill_proc} \
{cmd "Quit" exit }
# pack menu -> top
# pack btns -> on the bottom
# pack scroll-box -> in the middle
pack .mbar -side top -fill x
pack .ps -side top -fill both -expand yes
pack .cmd -side bottom -fill x
}
# ------------------------------
# M A I N L I N E
# ------------------------------
make_control_panel
scan_proc
# wait for the User menu item to change, then refresh the list-box
while {1} {
tkwait variable user
scan_proc
}
# ------------------------------
# The End.
# ------------------------------
|