my very first (ehm… useful ?!?!) ruby script.
So concerning my first try of a web based zfs managment interface i will restart the project with some new conditions:
- 1. i will switch from the former language PHP to the – like everywhere told – dev-friendly language ruby.
- 2. i will first concentrate on just the basic functions.
- 3. i have to use the system build in security realms (so either PAM or an equal interface)
- 4. i will use dynamic JS-Functions to enhance the GUI. But the system should also work with simple browser (e.g. lynx/links)
- 5. i will offer a RESTful interface. So it should be very easy for 3rd party apps to connect to them and use alle the functionality.
The Beginning ^^:
So my first task is to bring an overview of all system-disks (other devices are not necessary at the moment) into my ruby context.
So basic system command is:
root@sunny:~# format < /dev/null
Searching for disks…
The device does not support mode page 3 or page 4,
or the reported geometry info is invalid.
WARNING: Disk geometry is based on capacity data.
The current rpm value 0 is invalid, adjusting it to 3600
done
c3t0d0: configured with capacity of 18.61GB
AVAILABLE DISK SELECTIONS:
0. c0d0 <DEFAULT cyl 3734 alt 2 hd 255 sec 63>
/pci@0,0/pci-ide@11,1/ide@0/cmdk@0,0
1. c3t0d0 <ST92011A–3.04 cyl 2430 alt 2 hd 255 sec 63>
/pci@0,0/pci925,1234@11,3/storage@2/disk@0,0
Specify disk (enter its number):
Beside of the interesting warning, this will do the job. The format command will normally lead to a prompt. To avoid this, you just pipe the output to /dev/null.
The really valuable stuff is in the upper part of the output.
After consulting the ruby API about strings and arrays i ended up with the following (dirty) lines of code:
#!ruby
#!/usr/local/bin/ruby -rubygems
s = %x{format < /dev/null}
sa = s.split(“\n”)
counter = 0
dsk = false
puts “Array: “+sa.length().to_s()
sa.map do |i|
if i.strip().length() > 0
print counter.to_s()+” ”
if counter == (sa.length()-1)
dsk = false
end
if dsk == true
puts “DSK: “+i.strip()+”\n”
else
puts i.strip()+”\n”
end
if i.eql?(“AVAILABLE DISK SELECTIONS:”)
dsk = true
end
end
counter += 1
end
I found a really nice post about the ruby command line interface. That post gave me a good start in experimenting with the produced string output. You just always remember the irb to test parts of your code. Of course there is _A_Lot_ of debugging code. But the end-result is correct. Of course there should no hard-coded string in there. A by the way: it was a little bit inconvenient to quarrel again with the integer<->string conversion after some relaxing and luxurious years coding Java ^^. Okay so no implicit casting in ruby (?). Oh wait a minute – no typed language, so no casting?.
Oh yes… i don’t want to hide the output:
root@sunny:~$ ruby cmd.rb
The device does not support mode page 3 or page 4,
or the reported geometry info is invalid.
WARNING: Disk geometry is based on capacity data.
The current rpm value 0 is invalid, adjusting it to 3600
Array: 12
0 Searching for disks…
1 done
3 c3t0d0: configured with capacity of 18.61GB
6 AVAILABLE DISK SELECTIONS:
7 DSK: 0. c0d0 <DEFAULT cyl 3734 alt 2 hd 255 sec 63>
8 DSK: /pci@0,0/pci-ide@11,1/ide@0/cmdk@0,0
9 DSK: 1. c3t0d0 <ST92011A–3.04 cyl 2430 alt 2 hd 255 sec 63>
10 DSK: /pci@0,0/pci925,1234@11,3/storage@2/disk@0,0
11 Specify disk (enter its number):
So i guess i found my disks. At the end, i can just iterate about the even number of entries :-).
Okay ruby-gurus. How can i optimize my code. I am beginner level and “slurred” during years, coding Java and anciently PHP.
I am sure there is a lot of potential to cleanup this mess ^^.
looks like you could significantly shorten that implementation and make it more human-readable at the same time:
#!ruby
#!/usr/local/bin/ruby -rubygems
return_value = `format < /dev/null`
what_i_want = return_value.split(‘AVAILABLE DISK SELECTIONS:’)[1].strip
disks = []
what_i_want.each_line do |line|
line = line.strip
if /^(\d+\.\s[a-z0-9]+\s\)$/.match line
disks.push {:device => line}
puts “DSK: #{line}”
elsif line[0] == ‘/’
disks.last[:location] = line
puts ” line”
end
end
puts “Specify disk (enter its number):”
the disks array now looks something like this:
[{:device => ‘c0d0 ‘, :location => ‘/pci@0,0/pci-ide@11,1/ide@0/cmdk@0,0’},
{:device => ‘c3t0d0 ‘, :location => ‘ /pci@0,0/pci925,1234@11,3/storage@2/disk@0,0’}]
I guess, that is what you intended to get 😉
btw: beware of bugs in the above code, I have not run nor tested it whatsoever…