strace en Linux es la herramienta de referencia para entender qué hace un proceso a nivel del kernel. Cuando un programa falla silenciosamente, se cuelga o se comporta de forma inesperada, strace revela las llamadas al sistema exactas que se están realizando: aperturas de archivos, conexiones de red, asignaciones de memoria y gestión de señales. Esta guía cubre el uso práctico de strace desde el rastreo básico hasta las técnicas de depuración en producción, con escenarios del mundo real que demuestran cómo diagnosticar los problemas que realmente te encuentras.
Requisitos Previos
- Un sistema Linux (cualquier distribución — strace funciona en todas)
- Acceso root o
sudo(necesario para rastrear procesos de otros usuarios) - Conocimiento básico de procesos Linux y descriptores de archivo
- strace instalado (se cubre en la sección de instalación a continuación)
Instalación de strace en Linux
strace está disponible en el repositorio de paquetes de todas las distribuciones principales. Puede que ya esté instalado en tu sistema.
# Debian / Ubuntu
sudo apt install strace
# RHEL / CentOS / Fedora
sudo dnf install strace
# Arch Linux
sudo pacman -S strace
# Alpine Linux
sudo apk add strace
# Verificar la versión instalada
strace --version
En imágenes de contenedor mínimas (Alpine, distroless), strace suele faltar. Instálalo temporalmente para depurar y luego elimínalo de las imágenes de producción.
Rastrear un Comando desde el Inicio
El uso más sencillo de strace es ejecutarlo delante de cualquier comando:
strace ls /tmp
Esto imprime cada llamada al sistema que ls realiza desde execve() hasta exit_group(). La salida va a stderr, por lo que la salida normal del comando sigue apareciendo en stdout.
Lectura de la Salida de strace
Cada línea sigue este formato:
syscall_name(arguments...) = return_value
Por ejemplo:
openat(AT_FDCWD, "/tmp", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
getdents64(3, [{d_ino=2, d_off=1, d_type=DT_DIR, d_name="."},...], 32768) = 480
close(3) = 0
Esto te indica: ls abrió /tmp como descriptor de archivo 3, leyó las entradas del directorio y luego lo cerró. Un valor de retorno -1 significa que la llamada falló, y strace muestra el errno:
openat(AT_FDCWD, "/etc/shadow", O_RDONLY) = -1 EACCES (Permission denied)
Esa única línea a menudo revela por qué falla un programa — sin necesidad de leer el código fuente ni añadir registros de depuración.
Flags Útiles al Arrancar
# Seguir procesos hijos (fork/clone)
strace -f ./my_app
# Imprimir marcas de tiempo para cada syscall
strace -t ls /tmp
# Imprimir tiempo relativo entre syscalls (detectar bloqueos)
strace -r ls /tmp
# Imprimir argumentos de cadena completos (por defecto trunca a 32 caracteres)
strace -s 256 ./my_app
# Escribir la salida en un archivo en lugar de stderr
strace -o /tmp/trace.log ls /tmp
Adjuntarse a un Proceso en Ejecución
No es necesario reiniciar un proceso para rastrearlo. Adjúntate a cualquier proceso en ejecución mediante su PID:
# Encontrar el PID
pidof nginx
# o
ps aux | grep my_app
# Adjuntarse al proceso
sudo strace -p 12345
# Adjuntarse y seguir todos los hilos/hijos
sudo strace -fp 12345
Pulsa Ctrl+C para desconectarte. El proceso rastreado continúa ejecutándose normalmente — strace no lo mata al desconectarse.
Escenario Real: Depurar una Aplicación Colgada
Tienes una aplicación web en producción que ocasionalmente deja de responder a las peticiones. Los registros no muestran nada. En lugar de reiniciar a ciegas:
# Encontrar el PID del worker bloqueado
sudo strace -fp $(pidof my_app) -e trace=network,file -s 256 -o /tmp/hang_trace.log
Envía una petición de prueba y luego examina el rastreo:
grep -E 'futex|poll|select|epoll_wait' /tmp/hang_trace.log | tail -20
Si ves el proceso bloqueado en futex(FUTEX_WAIT) — está esperando un bloqueo mutex (deadlock). Si está bloqueado en connect() o poll() con un timeout largo — está esperando un servicio externo que no responde.
Filtrado de Llamadas al Sistema con strace
Los rastreos completos son ruidosos. Usa -e trace= para centrarte en lo que importa:
# Solo operaciones de archivo (open, read, write, close, stat, etc.)
strace -e trace=file ls /tmp
# Solo operaciones de red (socket, connect, send, recv, etc.)
strace -e trace=network curl https://example.com
# Gestión de procesos (fork, clone, execve, wait, exit)
strace -e trace=process bash -c "ls | grep foo"
# Operaciones de memoria (mmap, mprotect, brk)
strace -e trace=memory ./my_app
# Syscalls específicas por nombre
strace -e trace=openat,read,write cat /etc/hostname
# Negación — rastrear todo EXCEPTO estas
strace -e trace=!mmap,mprotect,brk ./my_app
Filtrado por Valor de Retorno
Encontrar solo las llamadas al sistema fallidas — extremadamente útil para depurar:
# Mostrar solo las llamadas que devolvieron un error
strace -Z ./my_app
# Mostrar solo las llamadas exitosas
strace -z ./my_app
El flag -Z (strace 5.2+) es una mejora radical para la depuración en producción. En lugar de revisar miles de llamadas exitosas, ves únicamente los fallos.
Análisis de Rendimiento con strace
Resumen de Llamadas al Sistema
El flag -c produce un resumen estadístico en lugar de un rastreo en vivo:
strace -c ls /tmp
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
25.00 0.000045 5 9 mmap
19.44 0.000035 5 7 close
16.67 0.000030 5 6 openat
11.11 0.000020 4 5 fstat
8.33 0.000015 5 3 mprotect
5.56 0.000010 3 3 read
...
------ ----------- ----------- --------- --------- ----------------
100.00 0.000180 4 42 2 total
Esto te indica qué llamadas al sistema consumen más tiempo. Si read o write domina, tienes un proceso limitado por E/S. Si futex domina, hay contención de bloqueos.
Temporización de Llamadas Individuales
# Tiempo de reloj de pared por syscall
strace -T ./my_app
# Combinado: marcas de tiempo + duración
strace -tT ./my_app
El flag -T añade la duración entre corchetes angulares:
openat(AT_FDCWD, "/etc/resolv.conf", O_RDONLY) = 3 <0.000024>
read(3, "nameserver 8.8.8.8\n", 4096) = 19 <0.000011>
connect(4, {sa_family=AF_INET, sin_port=htons(443)}, 16) = -1 EINPROGRESS <0.000089>
Ese connect() tardando 89 microsegundos está bien. Si ves que tarda 5 o más segundos, tu DNS o el servicio externo es el cuello de botella.
Comparación de strace con Herramientas de Rastreo Alternativas
| Característica | strace | ltrace | perf trace | bpftrace |
|---|---|---|---|---|
| Rastrea | Syscalls del kernel | Llamadas a bibliotecas | Syscalls del kernel | Kernel + espacio de usuario |
| Overhead | Alto (10-100x) | Alto | Bajo (~5%) | Muy bajo (~2%) |
| Adjuntarse a PID en ejecución | Sí | Sí | Sí | Sí |
| Filtrar por syscall | Sí (-e trace=) | Sí (-e) | Sí (—filter) | Sí (scripts personalizados) |
| Resumen estadístico | Sí (-c) | Sí (-c) | Sí (—summary) | Scripts personalizados |
| Versión de kernel necesaria | Cualquiera | Cualquiera | 3.7+ | 4.9+ (eBPF) |
| Seguro en producción | Solo uso breve | Solo uso breve | Sí | Sí |
| Ideal para | Depuración rápida | Problemas con bibliotecas | Perfilado de bajo overhead | Lógica de rastreo compleja |
Regla general: Usa strace para diagnósticos rápidos (adjuntarse, encontrar el problema, desconectarse). Cámbialo por perf trace o bpftrace para monitorización sostenida en producción donde el overhead importa.
Patrones Comunes de Depuración con strace
Patrón 1: Averiguar Por Qué un Programa No Encuentra un Archivo
strace -e trace=openat,stat,access ./my_app 2>&1 | grep -i "no such file\|enoent\|eacces"
Esto muestra al instante cada archivo que el programa intenta abrir y falla. Es habitual para problemas de archivos de configuración, bibliotecas compartidas faltantes o rutas incorrectas.
Patrón 2: Saber Qué Archivos de Configuración Lee un Programa
strace -e trace=openat ./my_app 2>&1 | grep -v ENOENT | grep '= [0-9]'
Esto filtra para mostrar solo las aperturas de archivo exitosas — mostrándote exactamente qué archivos de configuración, bibliotecas y archivos de datos usa realmente el programa.
Patrón 3: Depurar Problemas de Resolución DNS
strace -e trace=network -s 256 curl https://example.com 2>&1 | grep -E 'connect|sendto|recvfrom'
Verás la consulta DNS yendo a los servidores de nombres de /etc/resolv.conf, la respuesta y luego la conexión HTTPS real. Si la consulta DNS tarda segundos, has encontrado tu fuente de latencia.
Patrón 4: Averiguar Por Qué un Servicio Falla al Arrancar
sudo strace -f -o /tmp/service_trace.log systemctl start my_service
# Luego buscar errores en el rastreo
grep '= -1' /tmp/service_trace.log | grep -v 'ENOENT.*locale\|ENOENT.*lib' | head -30
El grep filtra los errores inofensivos “archivo no encontrado” provenientes del sondeo de locale y bibliotecas (que son normales), dejándote con los fallos reales.
Patrón 5: Monitorizar Escrituras en Archivo en Tiempo Real
sudo strace -fp $(pidof my_app) -e trace=write -s 1024 2>&1 | grep 'write([0-9]*,'
Observa cada byte que el proceso escribe en cualquier descriptor de archivo — útil para depurar problemas de logging o modificaciones inesperadas de archivos.
Casos Especiales y Trampas
Rastreo de binarios setuid: strace no puede adjuntarse a programas setuid a menos que ejecutes el propio strace como root. El kernel elimina los permisos de ptrace por seguridad.
Aplicaciones multihilo: Usa siempre -f (seguir forks) con aplicaciones multihilo. Sin él, solo ves las syscalls del hilo principal y te pierdes los hilos worker donde vive el problema real.
Entornos de contenedor: Dentro de contenedores Docker, strace requiere la capability SYS_PTRACE. Ejecuta con --cap-add=SYS_PTRACE o usa --privileged para depurar:
docker run --cap-add=SYS_PTRACE my_image strace ./my_app
En Kubernetes, añade la capability al security context de tu pod:
securityContext:
capabilities:
add: ["SYS_PTRACE"]
El impacto en el rendimiento es real: strace intercepta cada llamada al sistema vía ptrace, lo que requiere dos cambios de contexto por llamada. Un proceso que realiza 100.000 syscalls/segundo se ralentizará drásticamente. Nunca dejes strace adjunto a un proceso de producción más tiempo del necesario para capturar el problema.
strace -c enmascara llamadas lentas individuales: El resumen -c muestra promedios. Un proceso puede hacer 10.000 llamadas read() rápidas y una de 30 segundos — el promedio parece correcto. Usa -C (mayúscula) para obtener tanto el resumen como el rastreo en vivo y capturar valores atípicos.
Solución de Problemas
”Operation not permitted” al adjuntarse
# Comprobar el ámbito de ptrace (Ubuntu/Debian)
cat /proc/sys/kernel/yama/ptrace_scope
Si el valor es 1 (predeterminado en Ubuntu), solo puedes rastrear tus propios procesos. Para permitir temporalmente rastrear cualquier proceso:
# Temporal — se restablece al reiniciar
sudo sysctl kernel.yama.ptrace_scope=0
# O simplemente usa sudo con strace
sudo strace -p 12345
La salida del rastreo es abrumadora
# Combinar filtros: solo operaciones de archivo fallidas con temporización
strace -Z -e trace=file -T -s 256 ./my_app 2>&1 | head -50
Necesitas rastrear un proceso de vida corta
Para procesos que arrancan y terminan rápidamente (como trabajos cron):
# Envolver el comando
strace -f -o /tmp/cron_trace.log /path/to/cron_script.sh
# O rastrear el proceso padre que lo lanza
sudo strace -fp $(pidof crond) -o /tmp/cron_trace.log
Resumen
- strace rastrea llamadas al sistema del kernel — úsalo cuando un proceso falla silenciosamente, se cuelga o se comporta mal y los registros no ofrecen pistas
- Adjúntate a procesos en ejecución con
strace -p PIDsin reiniciarlos — añade-fpara aplicaciones multihilo - Filtra con
-e trace=para centrarte en operaciones de archivo, red, proceso o memoria en lugar de ahogarte en ruido - Usa
-Zpara mostrar solo las llamadas fallidas — la forma más rápida de encontrar por qué algo está roto - Usa
-cpara resúmenes de rendimiento — identifica qué llamadas al sistema consumen más tiempo - El overhead de rendimiento es significativo — adjúntate brevemente en producción y luego desconéctate. Para rastreos sostenidos, usa
perf traceobpftrace - Los contenedores necesitan la capability SYS_PTRACE — añádela explícitamente en Docker o Kubernetes