getPid

Maps process i.d.'s to program names and program names to process i.d.'s, returning a list of matches. Unix only, but works with all flavors of ps

 proc getPid { { prog "" } } {

      set tmp {}

      set data [ exec ps -c ]
      set data [ split $data "\n" ]
      foreach line $data {
         set pid  [ lindex $line 0   ]
         set name [ lindex $line end ]
         if { [ regexp ^$name $prog ] || [ regexp ^$prog $name ] } {
            lappend tmp $pid
         }
         if { [ regexp ^$pid $prog  ] || [ regexp ^$prog $pid  ] } {
            lappend tmp $name
         }   
      }
      set tmp [ lsort -dictionary $tmp ]   
      return $tmp
 } ;## PSE fecit

And a little app that uses it (sort of a generalised zillakilla):

 proc killZem { pids_or_names } {
      foreach item $pids_or_names {
         if { [ regexp {^[0-9]+$} $item pid ] } {
            catch { exec kill -TERM $pid }
            catch { exec kill -KILL $pid }
         } else {
            set pids [ getPid $item ]
            foreach pid $pids {
               if { [ regexp {[0-9]+} $pid ] } {
                  catch { exec kill -TERM $pid }
                  catch { exec kill -KILL $pid }
               }
            }
         }
      }
 }

The cgi.tcl includes a spiffy CGI script that uses this idea, wrapped up in a form to allow easy selection of pids to kill:

http://pitch.nist.gov/cgi-bin/cgi.tcl/kill.cgi

The script that processes the form is the same one that draws it, so click on the "See the Tcl script that create this page" to see the script.


For the getPid proc, a process name with a space in it would not be matched. Changing the "set name" line to:

  set name [ lrange $line end-[expr [llength [split $prog]]-1] end]

would correct for that.

(Also, in cases where you need to parse all processes, the ps line might be better as: ps -cA