Aug 10
Automation, automation, automation! [0..2]{automation}!
There are always tasks that look too small to worry about, copying a file pasting that line, the comforting sound of repetition.
Uh? as devs we are better than that, we can program complex logic in commercial settings there is no reason not to apply our knowledge to every day tasks, let the machines do what they do best, repeat!
For example the enjoyable task of copying the contents of cd's (remember those?) onto your hard drive, the drill is quite simple you pop in a cd, head on to the file manager gui select all files, enter copy and move into the destination folder, oh and don't forget to create a unique folder for each copied cd, now repeat that 50x times, can we do better?
PREFIX = '/home/ronen/temp/'
last_cd_in = lambda{ %x(dmesg | grep ISOFS).split("\n").last }
def mounted_at
res = nil
res_ok = lambda{res && res.split(' ')[1]}
10.times {
puts 'another attempt'
res = `cat /proc/mounts | grep sr0`; break if res_ok.call
sleep 1
}
notify 'failed to find mount point' and exit 1 if !res_ok.call
res.split(' ')[1].gsub('040',' ')
end
def notify (msg)
`notify-send '#{msg}' -t 10`
end
def sh(cmd)
res = `#{cmd}`
notify("#{cmd} failed") and exit(1) if $?.to_i != 0
res
end
last = nil
eject_action = lambda {
sh 'eject'
last = last_cd_in.call
puts 'place the cd in, press enter when your done'
gets
}
eject_action.call
while(true)
sh 'eject -t'
begin
curr = last_cd_in.call
end while last==curr
dest ="#{PREFIX}#{%x(uuid)}"
sh "mkdir #{dest}"
if !system("cp -rv #{mounted_at()}/* #{dest}")
notify 'Failed to copy cd, please check media!'
end
eject_action.call
end
This script enables the following functionality:
- Cdrom tray is popped out and the user is prompted to enter a new one in.
- A unique destination folder is created (using uuid).
- The contents is copied to the destination.
- The cd is popped out ready for another round.
As for the implementation its Ruby mixed with good old unix tools like cp, mkdir eject and some /proc trickery to keep track of new mounted cd path, I find this combination a win win,
we use Ruby instead of bash and use standard unix tools set instead of writing them ourself, Ruby has excellent unix process management API's (as any one who used Java for that can approve).
Notify-send is a nice decor (Ubuntu notification system) that growls at us when things go wrong (keeping us free to roam into more interesting domains).
require 'rubygems'
require 'open4'
def numeric?(object)
true if Float(object) rescue false
end
while (true)
pid=`jps -v | grep AppMain | awk '{print $1}'`
if numeric?(pid)
puts "JUnit found at PID #{pid}"
opid, stdin, stdout, stderr = Open4::popen4("strace -p #{pid}")
Process::waitpid2 opid
lines = stderr.readlines
if lines.last.include? '255'
`notify-send 'tests failed!' -u critical`
else
`notify-send 'all tests passed!' -u critical`
end
end
sleep 2.5
end
Same idea again, using Linux tool box with Ruby to automate our task, this script polls all Java processes for AppMain (Intellij main class runner), once found strace is attached to it in order to grab the exit code and notify-send the matching return status, the theme is repeating levrage the operating system and Ruby in order to turn a mundane task into an enjoyable one!

Follow me online