Math-Linux.com

Knowledge base dedicated to Linux and applied mathematics.

Accueil > Linux > Tutoriels Linux > Strace outil de dépannage Linux / debugging

Strace outil de dépannage Linux / debugging

Toutes les versions de cet article : [English] [français]

strace est un utilitaire permettant de tracer/suivre les appels systèmes.
Les appels systèmes sont les interfaces fondamentales entre les applications et le noyau.
Généralement, ils ne sont pas appelés directement, mais via des wrappers de la glibc.
Par exemples : fstat, mmap, open, close

open("/usr/lib/locale/fr_FR.utf8/LC_MONETARY", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=290, ...}) = 0
mmap(NULL, 290, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f841bde9000
close(3)

En utilisant strace, on peut intercepter ces appels systèmes pour un processus ou une commande donnée.
strace est donc un outil puissant de dépannage pour tous les administrateurs et utilisateurs unix/linux.

Strace utilisation basique

strace commande

root@kali:~# strace ifconfig eth0
execve("/sbin/ifconfig", ["ifconfig", "eth0"], [/* 34 vars */]) = 0
brk(0) = 0x1b0f000
...
write(1, " inet adr:192.168.1.14 "..., 75
inet adr:192.168.1.14 Bcast:192.168.1.255 Masque:255.255.255.0
) = 75
open("/proc/net/if_inet6", O_RDONLY) = 6
...
close(5) = 0
exit_group(0)

Appels systèmes dans un fichier

Si vous voulez enregistrer la sortie strace dans un fichier, utilisez :
strace -o filename commande

Par exemple :

root@kali:~# strace -o strace.txt ifconfig eth0
eth0
Link encap:Ethernet  HWaddr 00:0c:29:b9:0e:c0  
inet adr:192.168.1.14  Bcast:192.168.1.255  Masque:255.255.255.0
adr inet6: 2a01:e35:2f20:ed90:20c:29ff:feb9:ec0/64 Scope:Global
adr inet6: fe80::20c:29ff:feb9:ec0/64 Scope:Lien
UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
RX packets:17876 errors:0 dropped:0 overruns:0 frame:0
TX packets:10953 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 lg file transmission:1000
RX bytes:18635399 (17.7 MiB)  TX bytes:980986 (957.9 KiB)

root@kali:~# head -n 2 strace.txt
execve("/sbin/ifconfig", ["ifconfig", "eth0"], [/* 34 vars */]) = 0
brk(0)                                  = 0x1437000

Rapport/sommaire d’appels systèmes

strace -c command permet de faire un rapport des appels systèmes. Par exemple :

root@kali:~# strace -c ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:0c:29:b9:0e:c0  
         inet adr:192.168.1.14  Bcast:192.168.1.255  Masque:255.255.255.0
         adr inet6: 2a01:e35:2f20:ed90:20c:29ff:feb9:ec0/64 Scope:Global
         adr inet6: fe80::20c:29ff:feb9:ec0/64 Scope:Lien
         UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
         RX packets:17294 errors:0 dropped:0 overruns:0 frame:0
         TX packets:10524 errors:0 dropped:0 overruns:0 carrier:0
         collisions:0 lg file transmission:1000
         RX bytes:18290334 (17.4 MiB)  TX bytes:924666 (902.9 KiB)

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
100.00    0.040000        2857        14        11 access
 0.00    0.000000           0         8           read
 0.00    0.000000           0        10           write
 0.00    0.000000           0        35        14 open
 0.00    0.000000           0        22           close
 0.00    0.000000           0        22           fstat
 0.00    0.000000           0        28           mmap
 0.00    0.000000           0         6           mprotect
 0.00    0.000000           0         4           munmap
 0.00    0.000000           0         3           brk
 0.00    0.000000           0        11           ioctl
 0.00    0.000000           0         3           socket
 0.00    0.000000           0         1           execve
 0.00    0.000000           0         1           uname
 0.00    0.000000           0         1           arch_prctl
------ ----------- ----------- --------- --------- ----------------
100.00    0.040000                   169        25 total

Ici, l’appel système open génère 14 erreurs. Comment tracer spécifiquement ces appels systèmes ?

Tracer un appel système spécifique

On utilise l’option -e de strace :

root@kali:~# strace -e open ifconfig eth0
open("/etc/ld.so.cache", O_RDONLY)      = 3
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY) = -1 ENOENT (No such file or directory)

...

open("/usr/lib/x86_64-linux-gnu/gconv/ISO8859-1.so", O_RDONLY) = 6
eth0      Link encap:Ethernet  HWaddr 00:0c:29:b9:0e:c0  
         inet adr:192.168.1.14  Bcast:192.168.1.255  Masque:255.255.255.0
open("/proc/net/if_inet6", O_RDONLY)    = 6
         adr inet6: 2a01:e35:2f20:ed90:20c:29ff:feb9:ec0/64 Scope:Global
         adr inet6: fe80::20c:29ff:feb9:ec0/64 Scope:Lien
         UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
         RX packets:17783 errors:0 dropped:0 overruns:0 frame:0
         TX packets:10915 errors:0 dropped:0 overruns:0 carrier:0
         collisions:0 lg file transmission:1000
         RX bytes:18626514 (17.7 MiB)  TX bytes:978630 (955.6 KiB)

On voit clairement que ifconfig essaye d’ouvrir des fichiers absents. Combien ?

root@kali:~# strace -e open ifconfig eth0 2>&1 | grep "No such file or directory" | wc -l
14

Exactement 14 !!! comme l’indiquait le rapport d’appels systèmes.

Tracer plusieurs appels systèmes spécifiques

On peut utiliser l’option -e trace=function1,function2, ...
Par exemple pour tracer les appels systèmes mprotect ou brk :

root@kali:~# strace -e trace=mprotect,brk ifconfig eth0
brk(0)                                  = 0x1c1f000
mprotect(0x7f400429c000, 2097152, PROT_NONE) = 0
mprotect(0x7f400449c000, 16384, PROT_READ) = 0
mprotect(0x60f000, 4096, PROT_READ)     = 0
mprotect(0x7f40046c5000, 4096, PROT_READ) = 0
brk(0)                                  = 0x1c1f000
brk(0x1c40000)                          = 0x1c40000
mprotect(0x7f4003f1b000, 2093056, PROT_NONE) = 0
mprotect(0x7f400411a000, 4096, PROT_READ) = 0
eth0      Link encap:Ethernet  HWaddr 00:0c:29:b9:0e:c0  
         inet adr:192.168.1.14  Bcast:192.168.1.255  Masque:255.255.255.0
         adr inet6: 2a01:e35:2f20:ed90:20c:29ff:feb9:ec0/64 Scope:Global
         adr inet6: fe80::20c:29ff:feb9:ec0/64 Scope:Lien
         UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
         RX packets:17822 errors:0 dropped:0 overruns:0 frame:0
         TX packets:10932 errors:0 dropped:0 overruns:0 carrier:0
         collisions:0 lg file transmission:1000
         RX bytes:18630337 (17.7 MiB)  TX bytes:979684 (956.7 KiB)

Tracer une catégorie spécifique d’appels systèmes

-e trace=file
On peut penser qu’il s’agit là d’une abréviation de -e trace=open,stat,chmod,unlink,...En outre, utiliser cette
abréviation permet de s’assurer que l’on n’omet pas d’inclure les appels lstat

-e trace=process
Trace tous les appels systèmes liés à la gestion des processus. C’est particulièrement utile pour suivre les étapes fork, wait et exec d’un process.

-e trace=network
Trace tous les appels systèmes de type réseau.

-e trace=signal
Trace tous les appels systèmes de type signal.

-e trace=ipc
Trace tous les appels systèmes IPC.

-e trace=desc
Trace tous les appels systèmes liés aux descripteurs.

Par exemple pour tracer les appels spécifiques au réseau (network) :

root@kali:~# strace -e trace=network ifconfig eth0
socket(PF_FILE, SOCK_DGRAM, 0)          = 3
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 5
eth0      Link encap:Ethernet  HWaddr 00:0c:29:b9:0e:c0  
         inet adr:192.168.1.14  Bcast:192.168.1.255  Masque:255.255.255.0
         adr inet6: 2a01:e35:2f20:ed90:20c:29ff:feb9:ec0/64 Scope:Global
         adr inet6: fe80::20c:29ff:feb9:ec0/64 Scope:Lien
         UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
         RX packets:17836 errors:0 dropped:0 overruns:0 frame:0
         TX packets:10940 errors:0 dropped:0 overruns:0 carrier:0
         collisions:0 lg file transmission:1000
         RX bytes:18631824 (17.7 MiB)  TX bytes:980182 (957.2 KiB)

Récupérer les horodatages/timestamps et les temps d’appels sytèmes

Il peut àªtre utile de récupérer les temps d’appels systèmes et leur timestamp :

strace -r Timestamp relatif - temps passé pour un appel système
strace -t Préfixer chaque ligne par la date du jour
strace -tt Préfixer chaque ligne par la date du jour à la microseconde près
strace -ttt Préfixer chaque ligne par la date du jour à la microseconde près depuis le 1er janvier 1970 (The Epoch)

root@kali:~# strace -r -o strace_r.txt ifconfig eth0 > /dev/null
root@kali:~# strace -t -o strace_t.txt ifconfig eth0 > /dev/null
root@kali:~# strace -tt -o strace_tt.txt ifconfig eth0 > /dev/null
root@kali:~# strace -ttt -o strace_ttt.txt ifconfig eth0 > /dev/null
root@kali:~# ls -rt strace_*
strace_r.txt  strace_t.txt  strace_tt.txt  strace_ttt.txt
root@kali:~# head -n 2 strace_*
==> strace_r.txt <==
    0.000000 execve("/sbin/ifconfig", ["ifconfig", "eth0"], [/* 34 vars */]) = 0
    0.000192 brk(0)                    = 0x75a000

==> strace_ttt.txt <==
1399201553.405215 execve("/sbin/ifconfig", ["ifconfig", "eth0"], [/* 34 vars */]) = 0
1399201553.405410 brk(0)                = 0x159d000

==> strace_tt.txt <==
07:05:50.173343 execve("/sbin/ifconfig", ["ifconfig", "eth0"], [/* 34 vars */]) = 0
07:05:50.173648 brk(0)                  = 0x1398000

==> strace_t.txt <==
07:05:41 execve("/sbin/ifconfig", ["ifconfig", "eth0"], [/* 34 vars */]) = 0
07:05:41 brk(0)

Que faire lorsqu’un processus fork

Vous pouvez suivre les appels systèmes, si un processus fork en utilisant l’option -f

root@kali:~# strace -f -o strace_acroread.txt acroread > /dev/null

Attacher à un processus existant

Pour attacher strace à un processus existant :
strace -p PID

Par exemple :

root@kali:~# pidof sshd
6177
root@kali:~# strace -p 6177
Process 6177 attached - interrupt to quit
select(7, [3 4], NULL, NULL, NULL

Essayons maintenant de nous connecter sur le serveur kali (IP:192.168.1.14) :

root@station:~# ssh kali

Maintenant on a quelque chose du type :

root@kali:~# strace -p 6177
Process 6177 attached - interrupt to quit
select(7, [3 4], NULL, NULL, NULL)      = 1 (in [3])
accept(3, {sa_family=AF_INET, sin_port=htons(45468), sin_addr=inet_addr("192.168.1.23")}, [16]) = 5
fcntl(5, F_GETFL)                       = 0x2 (flags O_RDWR)
pipe([6, 7])                            = 0
socketpair(PF_FILE, SOCK_STREAM, 0, [8, 9]) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f22b8b91a90) = 12420
close(7)                                = 0
write(8, "\0\0\2\263\0", 5)             = 5
write(8, "\0\0\2\252\n\n\n\nPort 22\n\n\n\nProtocol 2\n\nH"..., 690) = 690
close(8)                                = 0
close(9)                                = 0
close(5)                                = 0
select(7, [3 4 6], NULL, NULL, NULL)    = 1 (in [6])
close(6)                                = 0
select(7, [3 4], NULL, NULL, NULL

Une pair de sockets connectés est créé socketpair(...) avec pour addresse distante 192.168.1.23:45468

En outre, on voit clairement que la connection est établie :

root@kali:~# netstat -at | grep -F '192.168.1.23'
tcp        0      0 192.168.1.14:ssh        192.168.1.23:45468      ESTABLISHED

J’espère avoir pu vous aider !!! Strace est un outil très puissant, ne pas oublier man strace !!!

Un message, un commentaire ?

comments powered by Disqus