Herramientas de usuario

Herramientas del sitio


notas:strace

¡Esta es una revisión vieja del documento!


Tabla de Contenidos

Strace

strace es una utilidad que nos puede ayudar en la comprobación de errores y cuellos de botella en procesos en el sistema operativo GNU/Linux. La misma sirve para monitorear las llamadas al sistema usadas por un determinado programa, todas las señales que éste recibe y cuando tiempo toma cada llamada. Esto es posible por una característica del núcleo linux llamada ptrace.

Se puede arrancar junto al programa al que se le efectúa el trace, imprime la lista de llamadas al sistema que dicho programa ejecuta. Es útil para averiguar la causa del fallo de un programa determinado porque informa de situaciones en las que por ejemplo, el programa está intentando acceder a un fichero que no existe o que no tiene permiso de lectura o tiempos de espera muy altos al intentar obtener un servicio remoto por red.

Uso

En simples palabras su ejecución mas simple es strace -p pid

Si ejecutamos un strace al numero de proceso del squid obtendríamos algo como esto

22118289675}}, {EPOLLOUT, {u32=227, u64=227}}, {EPOLLOUT, {u32=287, u64=287}}}, 256, 10) = 5
gettimeofday({1266513451, 218933}, NULL) = 0
write(299, "HTTP/1.0 200 OK\r\nServer: Apache/"..., 558) = 558
msgsnd(65536, {3, "\316\254H\0\245o\257\1\330\300\325\v\0\20\0\0\5\2\0\0\377\377\377\377\0\0\0\0"}, 28, IPC_NOWAIT) = 0
epoll_ctl(4, EPOLL_CTL_MOD, 299, {EPOLLIN|EPOLLERR|EPOLLHUP, {u32=299, u64=299}}) = 0
accept(94, {sa_family=AF_INET, sin_port=htons(40369), sin_addr=inet_addr("192.168.16.2")}, [16]) = 418
getsockname(418, {sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.168.2.100")}, [16]) = 0
fcntl64(418, F_GETFL)                   = 0x2 (flags O_RDWR)
fcntl64(418, F_SETFD, FD_CLOEXEC|0x2)   = 0
fcntl64(418, F_GETFL)                   = 0x2 (flags O_RDWR)
fcntl64(418, F_SETFL, O_RDWR|O_NONBLOCK) = 0
epoll_ctl(4, EPOLL_CTL_ADD, 418, {EPOLLIN|EPOLLERR|EPOLLHUP, {u32=418, u64=578448656441541026}}) = 0
accept(94, 0xbfe9e758, [16])            = -1 EAGAIN (Resource temporarily unavailable)
read(267, "UBX cayu16@hotmail.com 1 "..., 65535) = 442
epoll_ctl(4, EPOLL_CTL_MOD, 229, {EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP, {u32=229, u64=578448763815723237}}) = 0
write(227, "GIF89a\t\0\27\0\263\0\0\0\0\0\377\377\377\377\377\373\376\346\0\376\352+\376\353/\376"..., 111) = 111
write(7, "1266513451.218     19 10.248.2.1"..., 139) = 139

Esto es útil por ejemplo si creemos que los helpers de autenticación no se están ejecutando correctamente

f = hace un traceo del proceso y de sus forks

p = numero de PID (process ID)

strace -fp PID
strace -fp processID -o outputfile

r = agregar timestamp a cada línea

strace -fp processID -o outputfile -r

Ejemplo de ejecución

Podemos tomar este código : https://gist.github.com/nolim1t/126991

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
 
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
 
int socket_connect(char *host, in_port_t port){
	struct hostent *hp;
	struct sockaddr_in addr;
	int on = 1, sock;     
 
	if((hp = gethostbyname(host)) == NULL){
		herror("gethostbyname");
		exit(1);
	}
	bcopy(hp->h_addr, &addr.sin_addr, hp->h_length);
	addr.sin_port = htons(port);
	addr.sin_family = AF_INET;
	sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
	setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&on, sizeof(int));
 
	if(sock == -1){
		perror("setsockopt");
		exit(1);
	}
 
	if(connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) == -1){
		perror("connect");
		exit(1);
 
	}
	return sock;
}
 
#define BUFFER_SIZE 1024
 
int main(int argc, char *argv[]){
	int fd;
	char buffer[BUFFER_SIZE];
 
	if(argc < 3){
		fprintf(stderr, "Usage: %s <hostname> <port>\n", argv[0]);
		exit(1); 
	}
 
	fd = socket_connect(argv[1], atoi(argv[2])); 
	write(fd, "GET /\r\n", strlen("GET /\r\n")); // write(fd, char[]*, len);  
	bzero(buffer, BUFFER_SIZE);
 
	while(read(fd, buffer, BUFFER_SIZE - 1) != 0){
		fprintf(stderr, "%s", buffer);
		bzero(buffer, BUFFER_SIZE);
	}
 
	shutdown(fd, SHUT_RDWR); 
	close(fd); 
 
	return 0;
}

Extras

A veces también puede servirnos ltrace, que es una utilidad de depuración, que se usa para mostrar las llamadas que una aplicación de espacio de usuario hace a las bibliotecas compartidas.

notas/strace.1587086732.txt.gz · Última modificación: 2020/04/17 01:25 por cayu