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ísticastraceltraceperf tracebpftrace
RastreaSyscalls del kernelLlamadas a bibliotecasSyscalls del kernelKernel + espacio de usuario
OverheadAlto (10-100x)AltoBajo (~5%)Muy bajo (~2%)
Adjuntarse a PID en ejecución
Filtrar por syscallSí (-e trace=)Sí (-e)Sí (—filter)Sí (scripts personalizados)
Resumen estadísticoSí (-c)Sí (-c)Sí (—summary)Scripts personalizados
Versión de kernel necesariaCualquieraCualquiera3.7+4.9+ (eBPF)
Seguro en producciónSolo uso breveSolo uso breve
Ideal paraDepuración rápidaProblemas con bibliotecasPerfilado de bajo overheadLó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 PID sin reiniciarlos — añade -f para aplicaciones multihilo
  • Filtra con -e trace= para centrarte en operaciones de archivo, red, proceso o memoria en lugar de ahogarte en ruido
  • Usa -Z para mostrar solo las llamadas fallidas — la forma más rápida de encontrar por qué algo está roto
  • Usa -c para 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 trace o bpftrace
  • Los contenedores necesitan la capability SYS_PTRACE — añádela explícitamente en Docker o Kubernetes

Artículos Relacionados