Pregunta

Un colega me dijo una vez que la última opción cuando todo fallaba en depurar Linux era usar strace .

Intenté aprender la ciencia detrás de esta extraña herramienta, pero no soy un experto en administración de sistemas y realmente no obtuve resultados.

Entonces,

  • ¿Qué es exactamente y qué hace?
  • ¿Cómo y en qué casos se debe utilizar?
  • ¿Cómo se debe entender y procesar la salida?

En resumen, en palabras sencillas , ¿cómo funciona esto?

¿Fue útil?

Solución

Descripción general de Strace
strace puede verse como un depurador de peso ligero. Permite a un programador / usuario descubrir rápidamente cómo interactúa un programa con el sistema operativo. Lo hace monitorizando las llamadas y señales del sistema.

Usos
Es bueno para cuando no tienes el código fuente o no quieres que te molesten en hacerlo.
Además, es útil para su propio código si no tiene ganas de abrir GDB, pero solo está interesado en comprender la interacción externa.

Una buena pequeña introducción
Me encontré con esta introducción para usar el estilo el otro día: strace hello world

Otros consejos

En palabras simples, strace rastrea todas las llamadas al sistema emitidas por un programa junto con sus códigos de retorno. Piense en cosas como las operaciones de archivo / socket y mucho más oscuras.

Es más útil si tiene algún conocimiento práctico de C, ya que aquí las llamadas al sistema serían más precisas para las llamadas de la biblioteca C estándar.

Digamos que su programa es / usr / local / bin / cough. Simplemente use:

strace /usr/local/bin/cough <any required argument for cough here>

o

strace -o <out_file> /usr/local/bin/cough <any required argument for cough here>

para escribir en 'out_file'.

Todas las salidas de strace irán a stderr (cuidado, su gran volumen a menudo solicita una redirección a un archivo). En los casos más simples, su programa abortará con un error y podrá ver cuáles son sus últimas interacciones con el sistema operativo en la salida de strace.

Más información debe estar disponible con:

man strace

strace enumera todas las llamadas al sistema hechas por el proceso al que se aplica. Si no sabe qué significan las llamadas al sistema, no podrá obtener mucho kilometraje de él.

Sin embargo, si su problema involucra archivos o rutas o valores de entorno, ejecutar strace en el programa problemático y redirigir la salida a un archivo y luego grepping ese archivo para su ruta / archivo / cadena env puede ayudarlo a ver cuál es su programa en realidad intentando hacerlo, a diferencia de lo que esperabas.

Strace se destaca como una herramienta para investigar sistemas de producción en los que no puede darse el lujo de ejecutar estos programas bajo un depurador. En particular, hemos utilizado strace en las siguientes dos situaciones:

  • El programa foo parece estar en un punto muerto y no responde. Esto podría ser un objetivo para gdb; sin embargo, no siempre hemos tenido el código fuente o, a veces, estábamos tratando con lenguajes de script que no eran fáciles de ejecutar bajo un depurador. En este caso, ejecuta strace en un programa que ya se está ejecutando y obtendrá la lista de llamadas del sistema que se están realizando. Esto es particularmente útil si está investigando una aplicación cliente / servidor o una aplicación que interactúa con una base de datos.
  • Investigar por qué un programa es lento. En particular, acabábamos de mudarnos a un nuevo sistema de archivos distribuidos y el nuevo rendimiento del sistema era muy lento. Puede especificar strace con la opción '-T' que le indicará cuánto tiempo pasó en cada llamada al sistema. Esto ayudó a determinar por qué el sistema de archivos estaba causando que las cosas se ralentizaran.

Para ver un ejemplo de análisis usando strace, vea mi respuesta a esta pregunta .

Uso strace todo el tiempo para depurar problemas de permisos. La técnica es la siguiente:

$ strace -e trace=open,stat,read,write gnome-calculator

Donde gnome-calculator es el comando que desea ejecutar.

strace -tfp PID monitoreará las llamadas al sistema del proceso PID, por lo que podemos depurar / monitorear nuestro proceso / estado del programa.

Strace se puede utilizar como una herramienta de depuración, o como un generador de perfiles primitivo.

Como un depurador, puede ver cómo se llamaron, ejecutaron las llamadas del sistema y qué devuelven. Esto es muy importante, ya que le permite ver no solo que un programa falló, sino POR QUÉ falló un programa. Por lo general, es solo el resultado de una mala codificación que no logra captar todos los resultados posibles de un programa. Otras veces son solo rutas codificadas a archivos. Sin esfuerzo, puedes adivinar qué salió mal, dónde y cómo. Con strace obtienes un desglose de un syscall, por lo general, solo mirar un valor de retorno te dice mucho.

El perfilado es otro uso. Puede usarlo para cronometrar la ejecución de cada syscalls individualmente, o como un agregado. Si bien esto podría no ser suficiente para solucionar sus problemas, al menos en gran medida reducirá la lista de posibles sospechosos. Si ve una gran cantidad de pares de cierre / cierre en un solo archivo, es probable que abra y cierre archivos innecesariamente cada ejecución de un bucle, en lugar de abrirlo y cerrarlo fuera de un bucle.

Ltrace es el primo cercano de strace, también muy útil. Debes aprender a diferenciar dónde está tu cuello de botella. Si la ejecución total es de 8 segundos y gasta solo 0.05secs en llamadas al sistema, entonces el programa no le hará mucho bien, el problema está en su código, que generalmente es un problema lógico, o el programa realmente necesita tomar tanto tiempo para correr.

El mayor problema con strace / ltrace es leer su salida. Si no sabe cómo se hacen las llamadas, o al menos los nombres de syscalls / funciones, será difícil descifrar el significado. Saber qué devuelven las funciones también puede ser muy beneficioso, especialmente para diferentes códigos de error. Si bien es un dolor descifrar, a veces realmente devuelven una perla de conocimiento; Una vez que vi una situación en la que me quedé sin inodos, pero no sin espacio libre, todas las utilidades habituales no me dieron ninguna advertencia, simplemente no pude crear un archivo nuevo. La lectura del código de error de la salida de strace me indicó la dirección correcta.

Strace es una herramienta que te dice cómo interactúa tu aplicación con tu sistema operativo.

Para ello, le indica qué sistema operativo llama el sistema que usa su aplicación y con qué parámetros la llama.

Entonces, por ejemplo, ves qué archivos intenta abrir tu programa y si la llamada es exitosa.

Puedes depurar todo tipo de problemas con esta herramienta. Por ejemplo, si la aplicación dice que no puede encontrar la biblioteca que sabe que ha instalado, strace le dirá dónde está buscando la aplicación ese archivo.

Y eso es solo una punta del iceberg.

strace es una buena herramienta para aprender cómo su programa realiza varias llamadas al sistema (solicitudes al kernel) y también informa las que han fallado junto con el valor de error asociado con esa falla. No todos los fallos son errores. Por ejemplo, un código que está intentando buscar un archivo puede obtener un error ENOENT (no existe dicho archivo o directorio), pero ese puede ser un escenario aceptable en la lógica del código.

Un buen caso de uso del uso de strace es depurar las condiciones de carrera durante la creación del archivo temporal. Por ejemplo, un programa que puede estar creando archivos al anexar el ID de proceso (PID) a una cadena predeterminada puede tener problemas en escenarios de subprocesos múltiples. [Un PID + TID (id de proceso + id de hilo) o una mejor llamada al sistema como mkstemp solucionará esto].

También es bueno para la depuración de bloqueos. Puede encontrar este (mi) artículo sobre strace y errores de depuración útil.

Me gustaron algunas de las respuestas donde lee strace y verifica cómo interactúas con tu sistema operativo.

Esto es exactamente lo que podemos ver. El sistema llama. Si compara strace y ltrace , la diferencia es más obvia.

<*>gt;ltrace -c cd
Desktop  Documents  Downloads  examples.desktop  Music  Pictures  Public  Templates  Videos
% time     seconds  usecs/call     calls      function
------ ----------- ----------- --------- --------------------
 15.52    0.004946         329        15 memcpy
 13.34    0.004249          94        45 __ctype_get_mb_cur_max
 12.87    0.004099        2049         2 fclose
 12.12    0.003861          83        46 strlen
 10.96    0.003491         109        32 __errno_location
 10.37    0.003303         117        28 readdir
  8.41    0.002679         133        20 strcoll
  5.62    0.001791         111        16 __overflow
  3.24    0.001032         114         9 fwrite_unlocked
  1.26    0.000400         100         4 __freading
  1.17    0.000372          41         9 getenv
  0.70    0.000222         111         2 fflush
  0.67    0.000214         107         2 __fpending
  0.64    0.000203         101         2 fileno
  0.62    0.000196         196         1 closedir
  0.43    0.000138         138         1 setlocale
  0.36    0.000114         114         1 _setjmp
  0.31    0.000098          98         1 realloc
  0.25    0.000080          80         1 bindtextdomain
  0.21    0.000068          68         1 opendir
  0.19    0.000062          62         1 strrchr
  0.18    0.000056          56         1 isatty
  0.16    0.000051          51         1 ioctl
  0.15    0.000047          47         1 getopt_long
  0.14    0.000045          45         1 textdomain
  0.13    0.000042          42         1 __cxa_atexit
------ ----------- ----------- --------- --------------------
100.00    0.031859                   244 total
gt;strace -c cd Desktop Documents Downloads examples.desktop Music Pictures Public Templates Videos % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 0.00 0.000000 0 7 read 0.00 0.000000 0 1 write 0.00 0.000000 0 11 close 0.00 0.000000 0 10 fstat 0.00 0.000000 0 17 mmap 0.00 0.000000 0 12 mprotect 0.00 0.000000 0 1 munmap 0.00 0.000000 0 3 brk 0.00 0.000000 0 2 rt_sigaction 0.00 0.000000 0 1 rt_sigprocmask 0.00 0.000000 0 2 ioctl 0.00 0.000000 0 8 8 access 0.00 0.000000 0 1 execve 0.00 0.000000 0 2 getdents 0.00 0.000000 0 2 2 statfs 0.00 0.000000 0 1 arch_prctl 0.00 0.000000 0 1 set_tid_address 0.00 0.000000 0 9 openat 0.00 0.000000 0 1 set_robust_list 0.00 0.000000 0 1 prlimit64 ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000000 93 10 total

Por otro lado, hay ltrace que rastrea las funciones.

<*>

Aunque revisé los manuales varias veces, no he encontrado el origen del nombre strace , pero es probable que sea un rastreo de llamadas al sistema, ya que esto es obvio.

Hay tres notas más importantes que decir acerca de strace .

Nota 1: estas dos funciones strace y ltrace están usando la llamada al sistema ptrace . Entonces, la llamada al sistema de ptrace es efectivamente cómo funciona strace .

  

La llamada al sistema ptrace () proporciona un medio por el cual un proceso (el          " trazador ") puede observar y controlar la ejecución de otro proceso          (el " tracee "), y examine y cambie la memoria del tracee y          registros Se utiliza principalmente para implementar la depuración de punto de interrupción          y el rastreo de llamadas al sistema.

Nota 2: hay diferentes parámetros que puedes usar con strace , ya que strace puede ser muy detallado. Me gusta experimentar con -c que es como un resumen de las cosas. En función de -c puede seleccionar una llamada del sistema como -e trace = open donde solo verá esa llamada. Esto puede ser interesante si está examinando qué archivos se abrirán durante el comando que está rastreando. Y, por supuesto, puede usar grep para el mismo propósito, pero tenga en cuenta que necesita redireccionar así 2 > & amp; 1 | grep etc para comprender que se hace referencia a los archivos de configuración cuando se emitió el comando.

Nota 3: Encuentro esta nota muy importante. No estás limitado a una arquitectura específica. strace te sorprenderá, ya que puede rastrear binarios de diferentes arquitecturas. ingrese la descripción de la imagen aquí

Ejemplo ejecutable mínimo

Si un concepto no está claro, hay un ejemplo más simple que no has visto que lo explica.

En este caso, ese ejemplo es el ensamblaje de Linux x86_64 independiente (no libc) hello world:

hola.S

.text
.global _start
_start:
    /* write */
    mov $1, %rax    /* syscall number */
    mov $1, %rdi    /* stdout */
    mov $msg, %rsi  /* buffer */
    mov $len, %rdx  /* buffer len */
    syscall

    /* exit */
    mov $60, %rax   /* exit status */
    mov 
as -o hello.o hello.S
ld -o hello.out hello.o
./hello.out
, %rdi /* syscall number */ syscall msg: .ascii "hello\n" len = . - msg

https://unix.stackexchange.com/questions/48994/how-to-run-a-program-in-a-clean-environment-in-bash

  • -s999 -v para mostrar información más completa sobre los registros
  • strace.log ahora contiene:

    #define _XOPEN_SOURCE 700
    #include <unistd.h>
    
    int main(void) {
        char *msg = "hello\n";
        write(1, msg, 6);
        return 0;
    }
    

    Con un ejemplo tan mínimo, cada uno de los caracteres de la salida es evidente:

    • execve línea: muestra cómo strace se ejecutó hello.out , incluidos los argumentos y el entorno de la CLI, tal como se documenta en man execve

    • write : muestra la llamada al sistema de escritura que hicimos. 6 es la longitud de la cadena " hola \ n " .

      = 6 es el valor de retorno de la llamada al sistema, que tal como se documenta en man 2 write es el número de bytes escritos.

    • exit : muestra la llamada al sistema de salida que hemos realizado. ¡No hay valor de retorno, ya que el programa se cerró!

    Ejemplos más complejos

    La aplicación de strace es, por supuesto, para ver qué llamadas del sistema están haciendo los programas complejos para ayudar a depurar / optimizar su programa.

    Notablemente, la mayoría de las llamadas de sistema que probablemente encuentres en Linux tienen envoltorios glibc, muchos de ellos desde POSIX .

    Internamente, los envoltorios glibc utilizan el ensamblaje en línea más o menos así: ¿Cómo invocar una llamada del sistema a través del sysenter en el ensamblaje en línea?

    El siguiente ejemplo que debes estudiar es un POSIX write hello world:

    main.c

    gcc -std=c99 -Wall -Wextra -pedantic -o main.out main.c
    ./main.out
    

    Compila y ejecuta:

    write(1, "hello\n", 6)                  = 6
    exit_group(0)                           = ?
    +++ exited with 0 +++
    

    Esta vez, verás que glibc realiza una serie de llamadas al sistema antes de main para configurar un entorno agradable para main.

    Esto se debe a que ahora no estamos usando un programa independiente, sino un programa glibc más común, que permite la funcionalidad libc.

    Luego, en cada extremo, strace.log contiene:

    <*>

    Entonces, llegamos a la conclusión de que la función POSIX de write utiliza, por sorpresa, la llamada al sistema write de Linux.

    También observamos que return 0 lleva a una llamada a exit_group en lugar de a exit . Ja, yo no sabía acerca de este! Esta es la razón por la que strace es genial. man exit_group luego explica:

      

    Esta llamada al sistema es equivalente a exit (2), excepto que termina no solo el subproceso de llamada, sino todos los subprocesos del grupo de subprocesos del proceso de llamada.

    Y aquí hay otro ejemplo en el que estudié qué llamada del sistema dlopen utiliza: https://unix.stackexchange.com/questions/226524/what-system-call-is-used-to-load-libraries-in- linux / 462710 # 462710

    Probado en Ubuntu 16.04, GCC 6.4.0, kernel de Linux 4.4.0.

    Licenciado bajo: CC-BY-SA con atribución
    No afiliado a StackOverflow
    scroll top