dec
1
2
Ruby Process Controller – psgrep
Every once in a while a process will freeze and will be too stubborn to die when I try to “Quit” it. For those stubborn processes I tend to use the terminal to `kill` it. For a while I had been using a simple Perl script for searching through processes. The script would find me the processids and I could then kill it, using whatever power I need.
I found that it was taking far too long for me to do the search, and then carefully type out the process id, and hope I got the right one. I discovered killall, but the problem is that sometimes I don’t want to kill “all” of the processes with that name. So, I gave in and wrote up a Ruby script that did what I wanted. Here is psgrep: (Download)
#!/usr/bin/env ruby
# Start Date: Saturday December 6, 2008
# Current Version: 0.9
# Author: Joseph Pecoraro
# Contact: joepeck02@gmail.com
# Decription: Quicker handling of process searching
# and killing. Never type in a PID again, just regexes!
# -----------
# Globals
# -----------
kill_mode = false
icase_mode = false
pattern = nil
targets = []
pids = []
# ---------
# Usage
# ---------
puts "usage: [options] pattern"
puts " -k or --kill kills all processes"
puts " -k# or --kill# kills the [#] process"
exit 0
end
# -----------
# Options
# -----------
if ARGV.size > 1
ARGV.each do |arg|
if arg.match(/^-(k|-kill)(\d*)$/)
kill_mode = true
targets << $2.to_i unless $2.empty?
elsif arg.match(/^-(i|-ignore)$/)
icase_mode = true
end
end
ARGV.delete_if {|e| e.match(/^-/) }
end
# -------------------
# Remaining Args
# -------------------
if ARGV.size != 1
usage
end
if icase_mode
pattern = Regexp.new( ARGV[0], Regexp::IGNORECASE )
else
pattern = Regexp.new( ARGV[0] )
end
# ----------------------
# Actual `ps` Output
# ----------------------
lines = %x{ ps -Au }.split(/\n/)
header = lines.shift
# ----------
# psgrep
# ----------
puts
puts " "
count = 0
lines.each do |line|
unless line =~ /psgrep/
if line.match(pattern)
count += 1
puts "[ ]: "
if targets.empty? || targets.member?(count)
pids << line.strip.split[1]
end
end
end
end
# -------------
# Kill Mode
# -------------
if kill_mode
puts
puts "Killing Processes"
puts "-----------------"
pids.each_with_index do |pid, i|
print targets.empty? ? "[ ]:" : "[ ]:"
print " Killing ... "
STDOUT.flush
res = %x{ kill }
puts "Dead" if $?.exitstatus.zero?
end
end
# Always
puts
So there it is. Less then 100 lines of ruby to get a pretty straightforward psgrep/kill program. Here is an example where I have three perl processes running on my machine. One of the is running as root (the userid is 0). I just type “!! –kill” or “[up-arrow] –kill” and it tries to kill them all. Note that the root perl process doesn’t terminate and there is an error message but psgrep continues as best as it can, and kills the two normal perl processes: [Note: I could have done `sudo psgrep perl -k` to kill the root process]
Here is another good example. I have two python instances that I want to kill but there is another python instance running ExpanDrive in the background. I just ran psgrep and found the two I want to kill are [2] and [3]. Therefore, I can send -k2 and -k3 (or –kill2 and –kill3) to kill only those processes. Here is the result:
Note also that by default psgrep is case-sensitive. To ignore case just add the -i or –ignore switch. So there you have it. Usage is straightforward. Switches can go anywhere on the command line makes it easier to just use your history and tack a switch on the end of your previous command.
Feel free to improve it, it is on GitHub!