Ruby + sysstat

Előző blogomban valamelyest fejtegettem mi nem tetszik a Python 3-ban, és a Ruby felé kacsingatok, meg valszeg ezt fogom saját cuccokhoz használni.

Összekapartam ma egy olyan rendszer stat script-et, amelyre igényem volt már régóta, és így legalább kicsit át is tudtam nézni a nyelvet. Főként az kellett, hogy az azonos nevű folyamatokat egyben összesítve lássam. Tehát pl. a tíz db bash process memória fogyasztását és gép bekapcsolás óta eltelt összes CPU idejét egyben lássam szummázva.

Nem nagy cucc, de ha már megírtam, felteszem ide is, hátha valaki örül neki (vagy nem) :)

Még lehet csiholgatok rajta. Forráskód itt, lehet mondjuk egy olyan fantáziadús neve mint "sysstat.rb" - egy kép pedig lejjebb látható.

Hozzávalók:


sudo apt-get install ruby acpi sysstat pydf

Hozzászólások

Sokat segít ha ismerkedsz a standard libraryval, meg az idiomatius rövid megoldásokkal.

Rubyban pl. első körben a különböző adatokon/gyűjteményeken futtatható iteratív blokkok ismerete lehet az egyik fő aha élmény és élvezeti forrás. (each, collect, inject, lines stb...)

Példaként itt a kódod egy részlete átírva - amiben megpróbáltam minél több ilyet használni a példa kedvéért;) : http://pastebin.com/CFiQACcH

Számomra ez a kód sokkal átláthatóbb mint a tiéd (persze ehhez ismerni kell a használt metódusok jelentését), de az talán már avatatlan szemnek is látszik, hogy sokkal rövidebb. :)

szerk: bevallom fogalmam sincs a kódodban textb,textc-s while ciklus mit csinál, szóval ha kihagytam valami funkcionalitást akkor bocsánat és az éles kódméret összehasonlítást tekintsd tárgytalannak ;)

Megjegyzés: collect == map; inject == reduce (aka. fold)
Csak hogy python felől jönve egyértelműbb legyen. :)

Ezeket egy ideje már lehet rubyban aliasként használni.

scan is hasznos tud lenni néha. Pl. itt a meminfós rész kicsit tömörebben (bar nékül):


info = {}

File.read('/proc/meminfo').scan(/(\w+):\s+([0-9]+)/) do |key, val|
  info.update({key => val.to_i / 1024})
end

info['MemUsed'] = info['MemTotal'] - info['MemFree'] - info['Buffers'] - info['Cached']

%w{MemTotal MemUsed Buffers Cached MemFree SwapCached}.each do |key|
  print "#{key} (#{info[key]}) "
end
puts

A map az csak ~ collect, mert mig map! van addig collect! nincs. Illetve a masik, hogy ez szemantikai kerdes is, sokszor en jobban szeretem a mapet hasznalni, mnt a collectet, egyszeruen azert, mert azt erzem az adott kontextusban helyesebbnek.
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal 

En - mivel funkcionalisan megegyezik a ket fuggveny - szemantikai kerdest csinaltam a dologbol. Ahol sok ugyanolyan objektum egy tulajdonsagat kerem le, ott collectet hasznalok, mert ez vegulis az, begyujtom az infot. Illetve meg egyre, a stringekkel kapcsolatos muveletre, mert ott nagy esellyel string lesz a vege. A map marad a tobbinek, foleg ott, ahol tipusvaltas is van.
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal 

Fú, ennek örülök, csak még fel kell fognom :)

Köszi a példákat, pont ezek segítenek hamar elsajátítani. Kambus-nak is kösz.

szerk.: meg telepítettem a rubybook csomagot, nagyon jónak tűnik, ezt akarom átnyálazni hogy hamar ráálljak gondolkodásilag. Ahogy belepapoztam nekem tetszett (sima html az egész).

Ja még annyi, hogy a textb textc-s while true ciklussal csak annyit csinálok, hogy a név oszlopból kikapom az egyformákat, de úgy, hogy a szám oszlopban összegzem az egyforma nevekhez tartozó értékeket. Tehát mintha egy uniq-ot futtatnék a név oszlopra, de azt akarom, hogy az azonos nevű folyamatok értekeit összegezve lássam, mert nem PID érdekel hanem program típus.

Erre egyébként ötlet?

Ugye több dimenziós tömbben tároltam oszlopokat, és így sorokat. Több oszlopra úgy rendezek, hogy a több dimenziós tömbnek loccsantom oda a .sort -ot, ami ekkor elsősorban az első oszlop alapján rendez, másod sorban a második és így tovább. De mi van akkor, ha van 8 oszlopom, és én először a 4., másodsorban a 6. oszlop alapján akarom sorba rendezni az egész hóbelebancot. Erre valami frappáns megoldás? Mert ugye most úgy játszottam vele, hogy az oszlopokat eleve olyan sorrendben vettem fel a több dimenziós tömbbe, hogy jó legyen (mert megérdemlem :). De ha nem optimális, akkor mit lehetne tenni manuális rendezgetés helyett?

Tömbre példa (8 oszlop, 3 sor):
[[1,4,5,6,7,6,7,8] , [4,5,3,2,2,4,5,6] , [4,6,7,7,6,7,6,7]]

Na, letelepítettem a rubybook csomagot (a szerzőnek is dobtam egy köszönő mailt hogy free licenc alá tette). Tudom ajánlani a könyvet Ruby iránt érdeklődőknek (sima HTML text-et telepít). Plusz javaslom a ruby csomag mellé az irb csomagot (interaktív shell hozzá, úgymint python-nál alapból).

Veszem fel a Ruby logikát. Nagyon jó. Másnak érdekességként:

tömb feltöltése pl. 10 elemmel:

a = [] ; a = 10.times.to_a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Tömb értékeket összekeverni:

10.times.to_a.shuffle
=> [0, 3, 4, 6, 7, 9, 5, 1, 2, 8]

Lottóhoz 90-ből 5 véletlen szám (kérek számokat 0-tól 90-ig bezárólag, majd tömbbé konvertálom, majd a sorozatból a 0. elem kivételével lekérem az 1.-től az utolsóig - így kapok egy sorozatot 1-től 90-ig - majd összekeverem, majd pedig az első 5 elemet lekérem):

91.times.to_a[1..-1].shuffle.first(5)
=> [57, 23, 30, 78, 37]

http://ruby-doc.org/core-1.9.3/Array.html

Nem vagyok nagy rajongoja a script nyelveknek, de az elozo postod utan utannaneztem a rubynak es nekem is megtetszett.
Meg nem tudom mire fogom hasznalni, de valamire majdcsak jo lesz. :)

Tök jó kis progi, de akadt egy kis gond vele, Arch-on:

Uptime: 13:33:39 up 2:48, 2 users, load average: 0.15, 0.14, 0.18

Battery: [#######################################]
Battery 0: Unknown, 99%
Battery 0: design capacity 4489 mAh, last full capacity 3981 mAh = 88%
Adapter 0: on-line
Thermal 0: ok, 53.0 degrees C
Thermal 0: trip point 0 switches to mode critical at temperature 100.0 degrees C
Thermal 0: trip point 1 switches to mode passive at temperature 95.5 degrees C
Thermal 1: ok, 54.0 degrees C
Thermal 1: trip point 0 switches to mode critical at temperature 127.0 degrees C

Memory (MB): /home/kisdosi/statistics_system.rb:50:in `': undefined method `to_a' for # (NoMethodError)
[kisdosi@kisdosi-laptop ~]$

Diff:
-print "Total (" + mem_total.to_s + ") "
+print "Total (#{mem_total})"

A #{} automatikusan rahiv az Object#to_s -re.

Bar, ugy remlik, a String#+ is rahiv, ebben azonban biztos nem vagyok. A #{} azonban egeszen biztos.

--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal 


Uptime: 20:22:31 up 18 min, 2 users, load average: 0.08, 0.19, 0.21

Battery: [#######################################]
Battery 0: Unknown, 99%
Battery 0: design capacity 4493 mAh, last full capacity 3985 mAh = 88%
Adapter 0: on-line
Thermal 0: ok, 55.0 degrees C
Thermal 0: trip point 0 switches to mode critical at temperature 100.0 degrees C
Thermal 0: trip point 1 switches to mode passive at temperature 95.5 degrees C
Thermal 1: ok, 56.0 degrees C
Thermal 1: trip point 0 switches to mode critical at temperature 127.0 degrees C

Memory (MB): /home/kisdosi/statistics_system.rb:48:in `': undefined method `to_a' for # (NoMethodError)