Knowledge base dedicated to Linux and applied mathematics.
Accueil > Linux > Tutoriels Linux > 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. Comment utiliser strace pour debugguer des applications ou des exécutables ?
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 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)
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
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 ?
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.
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)
-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)
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)
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
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 !!!