2011. augusztus 19., péntek

CPU usage monitoring by processes

Kaptam egy érdekes feladatot mostanság: Kéne valahogy monitorozni a gépen futó alkalmazások által használt CPU időt, de mindezt úgy, hogy az adatokat később diagram-ban ábrázolni lehessen processekre lebontva.
Első gondolatom az nmon volt, de sajna az nem képes a processenkénti lebontásra ahogy néztem.. topasrec detto nem.
Aztán próbáltam a ps listából kiszedni az adatokat ('ps -o ruser,pid,ppid,pcpu,args') de ott is bajba ütköztem, mivel sokszor a ps által reportolt eredmény durván eltért a topas/nmon által visszaadottól.
Aztán jó kis kutatás után kikötöttem a tprof-nál.. Ennek azonban alapvetően 1 nagy baja van: eredetileg csak arra készítették fel, hogy egy alatta futó alkalmazást monitorozzon és annak minden kis forkolását és mozgását kövesse, majd a végén reportot generáljon belőle. Viszont mint kiderült a tprof tud offline módban is dolgozni, bár elég hülye megkötésekkel.
A módszer kb így néz ki:
- Generáljunk a trace parancsal egy tracefile-t
- Hagyjuk kicsit futni a trace-t, majd állítsuk le (nálam ez 30 sec volt)
- Ez után a gensyms-el generáljuk le az address mappingot
- Majd futtassuk a kinyert adatokra a tprof-ot offline módban

Ez nálam a script-ben így nézett ki:

#!/usr/bin/ksh
mkdir /tmp/cpucheck 2>/dev/null
cd /tmp/cpucheck
DATE=$(date +"%Y.%m.%d. %H:%M:%S")
echo $DATE >> cpu_check_output_total
echo $DATE >> cpu_check_output
trace -af -T 1000000 -L 10000000 -o trace1.trc -j 000,001,002,003,005,006,234,106,10C,134,139,00A,465
sleep 30
trcoff
gensyms > trace1.syms
trcstop
tprof -skjue -R -P all -r trace1
grep -p Freq trace1.prof >> cpu_check_output_total
grep -p TID trace1.prof >> cpu_check_output
rm trace1*

Nem mondom, hogy szép megoldás, viszont a célnak bőven megtette. Annyi extrát adtam hozzá, hogy mivel a trace1.[trc|sysms] file-ok sok helyet igényeltek, így azokat a ciklus végén töröltem, miután kinyertem belőlük a számomra szükséges adatokat.
A scriptet crontabba belerakva és 10 percenként futtatva már egy egész szép kis kimutatást lehetett kapni arról, hogy mikor mi is folyik a rendszeren.
Valami ilyesfélét:

2011.08.14. 02:20:00
Process                          Freq  Total Kernel   User Shared  Other   Java
=======                          ====  ===== ======   ==== ======  =====   ====
dsapi_slave                         4  50.69  10.17  27.66  12.86   0.00   0.00
kuxagent                            2  22.34   0.06   0.00  22.28   0.00   0.00
/usr/bin/sh                       150   7.72   6.28   0.70   0.75   0.00   0.00
/usr/bin/echo                     129   5.24   5.16   0.00   0.08   0.00   0.00
/usr/bin/awk                      116   5.04   4.45   0.46   0.13   0.00   0.00
/usr/bin/sed                      106   4.37   4.25   0.00   0.13   0.00   0.00
wait                                4   2.39   2.39   0.00   0.00   0.00   0.00
dscs                                2   1.01   0.84   0.00   0.17   0.00   0.00
/usr/sbin/syncd                     1   0.35   0.35   0.00   0.00   0.00   0.00
l/DataStage/DSEngine/bin/dsjob      2   0.35   0.19   0.00   0.16   0.00   0.00
/db2gpsp1/sqllib/bin/db2usrinf      3   0.13   0.13   0.00   0.00   0.00   0.00
/bin/sh                             3   0.12   0.12   0.00   0.00   0.00   0.00
xmgc                                1   0.09   0.09   0.00   0.00   0.00   0.00
kulagent                            2   0.07   0.00   0.00   0.07   0.00   0.00
/usr/bin/vmstat                     1   0.03   0.03   0.00   0.00   0.00   0.00
/usr/bin/ksh                        1   0.03   0.03   0.00   0.00   0.00   0.00
/usr/bin/lparstat                   1   0.02   0.02   0.00   0.00   0.00   0.00
=======                          ====  ===== ======   ==== ======  =====   ====
Total                             528 100.00  34.57  28.83  36.61   0.00   0.00

Amit erről az ábráról le lehetett olvasni:
- A gépet a különböző scriptek elég durván meghajtják (jelen esetben a gépnek van 0.3 EC-je :))
- A legtöbb CPU időt a dsapi_slave nevű bináris viszi (mellesleg ez hívogatja a scripteket is)
- Szépen processekre lehet nézni, hogy a 30 sec-es mérésen belül mi és mennyiszer hívódott meg, az CPU kihasználtság viszont összesítve (Kernel, User,Shared-re lebontva) látható, ami nekem most nagyon is kapóra jött

Egy dologra viszont mindenképp felhívnám a figyelmet: Ez a report nem azt mutatja, hogy a gép 100%-ban ki volt hajtva, ahogy a Total mutatja! Csupán annyit mutat, hogy a felhasznált CPU mennyiség (!) mekkora része mely processek által lett kihasználva! Ergo ha valaki szeretne ez alapján egy átfogó képet készíteni, annak szüksége lesz egy külön log-ra, amely a global CPU usage-et nézi! Erre viszont már könnyű szerrel használhatóak a normal toolok (nmon/topasrec/sar). Ezt a kis "apróságot" leszámítva viszont szerintem nagyon is jól használható ez a kis módszer az esetleges bottleneck-ek kiderítésére (jelen esetben, hogy a gépen futó applikáció iszonyat sokat forkol (szerintem feleslegesen)

2011. augusztus 9., kedd

VirtualBox - hogy én mennyire szeretlek

Új ötlettől vezérelve úgy gondoltam, hogy felrakom a Linux (Ubuntu 10.04 LTS) alá a legújabb virtualbox-ot (4.1 build 73209),aztán abban meg majd futtattatok jó kis VM-eket, amiken meg kényem-kedvem szerint kísérletezgethetek. Mivel a kernel egy 2.6.38-10es PAE kernel volt (32 bit), így az OSE verzió már nem tudott felmenni (az még mindig csak 3.1-es, az meg ezzel a kernellel nem kompatibilis), ergo mentem a szokásos úton: A virtualbox.org-ról letöltöttem a 10.04-hez való 32 bites .deb-et, feltettem, majd elkezdtem játszadozni a virutális gépekkel.

Nem is volt ez gond egészen addig, amíg úgy nem gondoltam, hogy mára elég is lesz, sleep-eljük le a notit, aztán menjünk haza -> Itt ugyan is úgy gondolta a gépem, hogy ő nem megy el aludni, helyette dob egy kernel panic-ot.. Na gondoltam szupi, a legtöbb adat hála az égnek mentve van, szóval majd otthon megnézem, addig is full kikapcs.
Itthon aztán elkezdtem nézegetni, hogy ki és hogy, majd kb fél órás bug vadászat és tesztelgetés után kijött, hogy a probléma bizony a vboxdrv modul körül forog: Amennyiben a modul aktív a sleep pillanatában, úgy a kernel dob egy hátast.

Így első gondolatom az volt, hogy semmi gond, fogom magam és szimplán kilapátolom a modulok közül a Virtualboxos modulokat, amikor meg visszajön akkor visszatöltetem.. Ezt kb a következő módon követtem el:
A /etc/pm/sleep.d alatt létrehoztam egy 12virtualbox file-t a következő tartalommal:
#!/bin/bash
case "$1" in
	hibernate|suspend)
		for i in vboxpci vboxnetadp vboxnetflt vboxdrv; do rmmod $i;done
		;;
	thaw|resume)
		for i in vboxdrv vboxpci vboxnetadp vboxnetflt;do modprobe $i;done
		sleep 1
		;;
	*)
		;;
esac
Tesztelés, és lám - így tényleg megy is a játék.. A probléma ezzel a megoldással viszont az, hogy amennyiben fut egy virtuális gép, úgy a gép -persze hogy- nem bírja kilőni a modulokat, úgy hogy ebben az esetben még mindig gáz van.. Szóval goto #dolgozoasztal...
Kis keresés után bele is botlottam az alábbi szálba: http://www.virtualbox.org/ticket/9305
Itt egész szépen ecsetelik is, hogy ez bizony tényleg a 4.1-nek a hülyesége, sőt a végén még oda is biggyesztik, hogy Jul. 28-al commitálták is a változást, és hogy a következő release-ekben ez bent is lesz.. Szupi.. Csak hogy az a release még sehol nem jött ki, szóval innentől vagy "csináld magad", vagy várj.. Én az előbbi mellett döntöttem, így az alábbi játékot játszottam el:
sudo su -
cd /usr/share/virtualbox/src/vboxhost/vboxdrv
wget http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/app-emulation/virtualbox-modules/files/virtualbox-modules-4.1.0-vboxbug9305.patch
patch -p1 < virtualbox-modules-4.1.0-vboxbug9305.patch 
/etc/init.d/vboxdrv setup
ls -l /lib/modules/$(uname -r)updates/dkms/vboxdrv.ko

Ez után jött egy újabb sleep teszt, és láss csodát - így már futó VM esetén is szépen le tud sleepelni a gép... Öröm és bóduttá... Az viszont biztos, hogy most egy jó ideig nem akarok vbox-ot frissíteni, hacsak valami tényleg nem indokolja azt meg..

2011. július 23., szombat

SFTP - Couldn't canonicalise: Permission denied

Noh akkor mai érdekes esetem a következő:
Tisztelt user a gépre gond nélkül be tud SSH-val jelentkezni:
p1ngw1n@Twitchy-Thinkpad:~$ ssh client_user@sftp_server
client_user@sftp_server's password:
[client_user@sftp_server:/home/client_user]
Csak hogy kerek legyen a kép: nézzük az SSH számára használt file-okat/mappákat is:
[client_user@sftp_server:/home/client_user] ls -ld ~
drwxr-xr-x 9 client_user staff 512 Jun 28 15:43 /home/client_user
[client_user@sftp_server:/home/client_user] ls -ld ~/.ssh
drwx------ 2 client_user staff 512 Jun 28 15:46 /home/client_user/.ssh
[client_user@sftp_server:/home/client_user] ls -l ~/.ssh
total 8
-rw------- 1 client_user staff 2428 Jun 27 11:26 authorized_keys
[client_user@sftp_server:/home/client_user] ls -la ~/.ssh
total 24
drwx------ 2 client_user staff 512 Jun 28 15:46 .
drwxr-xr-x 9 client_user staff 512 Jun 28 15:43 ..
-rw------- 1 client_user staff 2428 Jun 27 11:26 authorized_keys
A home mappa 755ön (ez jó: csak az ownernek van írási joga), a .ssh mappa 700 (perfect) és az alatta lévő authorized_keys file pedig 600as jogokkal ott is van, ami szintén teljesen megfelel a számunkra. A felhasználó igénye viszont az, hogy az SSH kapcsolat mellett még secure filetransfert is tudjon csinálni (SFTP), ami viszont (hiába megy a bejelentkezés) a jelek szerint nem akar menni:
p1ngw1n@Twitchy-Thinkpad:~$ sftp client_user@sftp_server
Connecting to sftp_server...
client_user@sftp_server's password:
Couldn't canonicalise: Permission denied
Need cwd
User persze minket piszkál, hogy Wattafák, mert ilyet még ő se látott.. Megnézve az SSH konfigot szépen látszik, hogy az sftp-server a /etc/ssh/sshd_config alatt engedélyezve van:
[root@sftp_server:/home/root] grep sftp /etc/ssh/sshd_config
Subsystem sftp /usr/sbin/sftp-server
Illetve az még rátesz egy lapáttal, hogy mi pedig szépen és hiba nélkül tudunk SFTP-zni a szerverre (ergo tűzfal, és hasonló mókák kilőve). Tekintve, hogy az SFTP is a 22 portot használná csak a kommunikációra (mint az SSH), így a felhasználó esetében is elvileg adott minden lehetőség arra, hogy belépjen.. Ehhez képest mégse ez a helyzet a jelek szerint....

Az már csak fokozza a "fun" faktort, hogy a verbose login szerint az authentikáció sikeres, ergo a user be tud lépni, de aztán az SFTP eldobja a kapcsolatot:
p1ngw1n@Twitchy-Thinkpad:~$ sftp -v client_user@sftp_server
Connecting to sftp_server...
OpenSSH_5.3p1 Debian-3ubuntu6, OpenSSL 0.9.8k 25 Mar 2009
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Applying options for *
debug1: Connecting to sftp_server [10.1.0.230] port 22.
debug1: Connection established.
debug1: identity file /home/p1ngw1n/.ssh/id_rsa type -1
debug1: identity file /home/p1ngw1n/.ssh/id_dsa type -1
debug1: Remote protocol version 1.99, remote software version OpenSSH_5.2
debug1: match: OpenSSH_5.2 pat OpenSSH*
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_5.3p1 Debian-3ubuntu6
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-md5 none
debug1: kex: client->server aes128-ctr hmac-md5 none
debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP
debug1: SSH2_MSG_KEX_DH_GEX_INIT sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY
debug1: Host 'sftp_server' is known and matches the RSA host key.
debug1: Found key in /home/p1ngw1n/.ssh/known_hosts:370
debug1: ssh_rsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,password,keyboard-interactive
debug1: Next authentication method: publickey
debug1: Trying private key: /home/p1ngw1n/.ssh/id_rsa
debug1: read PEM private key done: type RSA
debug1: Authentications that can continue: publickey,password,keyboard-interactive
debug1: Trying private key: /home/p1ngw1n/.ssh/id_dsa
debug1: Next authentication method: keyboard-interactive
debug1: Authentications that can continue: publickey,password,keyboard-interactive
debug1: Next authentication method: password
client_user@sftp_server's password:
debug1: Authentication succeeded (password).

debug1: channel 0: new [client-session]
debug1: Requesting no-more-sessions@openssh.com
debug1: Entering interactive session.
debug1: Sending environment.
debug1: Sending env LANG = en_US.utf8
debug1: Sending subsystem: sftp
Couldn't canonicalise: Permission denied
Need cwd

client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: channel 0: free: client-session, nchannels 1
debug1: fd 0 clearing O_NONBLOCK
Transferred: sent 2224, received 2248 bytes, in 0.3 seconds
Bytes per second: sent 6468.5, received 6538.3
debug1: Exit status 0
A hibaüzenet egyértelműen permission denied-ot mond, viszont a fenti listából is látszik, hogy az összes SSH/SFTP által használt file ownere maga a user, és az összes file-nak jók a jogosultságai, ergo itt valami megint nem kóser.

Megnézve az SFTP kliens forrását (sftp-client.c) láthatjuk, hogy az alábbi kódrészlet felelős a hibaüzenetért, illetve az ellenőrzésért
do_realpath(struct sftp_conn *conn, char *path)
{
Buffer msg;
u_int type, expected_id, count, id;
char *filename, *longname;
Attrib *a;

expected_id = id = conn->msg_id++;
send_string_request(conn->fd_out, id, SSH2_FXP_REALPATH, path,
strlen(path));

buffer_init(&msg);

get_msg(conn->fd_in, &msg);
type = buffer_get_char(&msg);
id = buffer_get_int(&msg);

if (id != expected_id)
fatal("ID mismatch (%u != %u)", id, expected_id);

if (type == SSH2_FXP_STATUS) {
u_int status = buffer_get_int(&msg);

error("Couldn't canonicalise: %s", fx2txt(status));
return(NULL);
} else if (type != SSH2_FXP_NAME)
fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
SSH2_FXP_NAME, type);

count = buffer_get_int(&msg);
if (count != 1)
fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count);

filename = buffer_get_string(&msg, NULL);
longname = buffer_get_string(&msg, NULL);
a = decode_attrib(&msg);

debug3("SSH_FXP_REALPATH %s -> %s", path, filename);

xfree(longname);

buffer_free(&msg);

return(filename);
}
A kód tényleges analizálása nélkül felhívnám a figyelmet egy fontos tényezőre, amit az SFTP csinál: A valós útvonalat (SSH2_FXP_REALPATH) ellenőrzi, nem pedig azt, hogy a file-ok amivel dolgozik valóban elérhetőek e.. Ez esetben ez azért is okozhatott gondot, mivel a user home-ja egy külön FS volt ->
Mint kiderült az SSH ezt a realpath ellenőrzést annyira komolyan veszi, hogy (szokásához híven) megy a saját feje után, és a mount point eredeti attributumait lekérve vizsgálja meg, hogy az vajon jó lesz e majd neki..
Csak hogy érthető is legyen a probléma:
[root@sftp_server:/var/adm] ls -ld ~client_user
drwxr-xr-x 9 client_user staff 512 Jun 28 15:43 /home/client_user
[root@sftp_server:/var/adm] mount |grep client_user
/dev/lv00 /home/client_user jfs Aug 02 03:51 rw,log=/dev/loglv00
[root@sftp_server:/var/adm] umount /home/client_user
[root@sftp_server:/var/adm] ls -ld /home/client_user
drw------- 2 root system 256 Dec 3 2009 /home/client_user
[root@sftp_server:/var/adm] chmod 755 /home/client_user
[root@sftp_server:/var/adm] mount /home/client_user
Pontosan - Az eredeti mount point-ra az adott usernak tényleg nincs semmiféle joga.. Miután átraktuk 755-re (root owner maradt!) nézzük az újjab tesztet:
p1ngw1n@Twitchy-Thinkpad:~$ sftp client_user@sftp_server
Connecting to sftp_server...
client_user@sftp_server's password:
sftp> quit
Aham.. Szóval így már megy -> szimpla reader jog kellett csak neki.. OpenSSH, én így szeretlek..