Systemtap, alternativa a dtrace per a Linux

enviat per Ramon Salvadó el diumenge 11 de Novembre del 2007 a les 01:23 hores

Solaris disposa d’algunes característiques molt interessants, per a mi destaquen sobretot dtrace i el sistema de fitxers ZFS.

Pel que fa a ZFS la seva llicència fa impossible un port per a Linux, si bé sembla que es pot utilitzar mitjançant FUSE tal i com s’explica a ZFS on FUSE/Linux.

Per a Linux en comptes de dtrace tenim systemtap que proporciona funcionalitats similars. Podem veure una taula comparativa que detalla les diferències entre ambdós sistemes.

De moment no es possible d’utilitzar-lo en llenguatges script com ruby o python (cosa que si és possible amb dtrace).

Per a instal·lar systemtap en Centos 5 solament hem de fer:


yum install systemtap

A més també haurem d’instal·lar els paquets:

  • kernel-devel
  • kernel-headers
  • kernel-debuginfo
  • kernel-debuginfo-common

Les versions dels 2 darrers paquets s’han de correspondre amb la versió de kernel instal·lada i es poden trobar aquí

Amb systemtap podem fer coses força interessants, per exemple amb l’script següent podem veure una llista de processos ordenada en funció de l’ample de banda de xarxa que consumeixen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
global ifxmit, ifrecv, ifdevs, ifpid, execname, user

probe netdev.transmit
{
        p = pid()
        execname[p] = execname()
        user[p] = uid()
        ifdevs[p, dev_name] = dev_name
        ifxmit[p, dev_name] <<< length
        ifpid[p, dev_name] ++
}

probe netdev.receive
{
        p = pid()
        execname[p] = execname()
        user[p] = uid()
        ifdevs[p, dev_name] = dev_name
        ifrecv[p, dev_name] <<< length
        ifpid[p, dev_name] ++
}


function print_activity()
{
        printf("%5s %5s %-7s %7s %7s %7s %7s %-15s\n",
                "PID", "UID", "DEV", "XMIT_PK", "RECV_PK",
                "XMIT_KB", "RECV_KB", "COMMAND")

        foreach ([pid, dev] in ifpid-) {
                n_xmit = @count(ifxmit[pid, dev])
                n_recv = @count(ifrecv[pid, dev])
                printf("%5d %5d %-7s %7d %7d %7d %7d %-15s\n",
                        pid, user[pid], dev, n_xmit, n_recv,
                        n_xmit ? @sum(ifxmit[pid, dev])/1024 : 0,
                        n_recv ? @sum(ifrecv[pid, dev])/1024 : 0,
                        execname[pid])
        }

        print("\n")

        delete execname
        delete user
        delete ifdevs
        delete ifxmit
        delete ifrecv
        delete ifpid
}

probe timer.ms(5000)
{
        print_activity()
}

Un exemple de la sortida si l’executem:

1
2
3
4
PID   UID DEV     XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND        
    0     0 eth0          0      13       0       2 swapper        
 1947   501 eth0          4       0       0       0 ping           
 1873     0 eth0          1       0       0       0 sshd

Podem veure més exemples d’scripts en el wiki.