El creciente aprecio de Microsoft por Linux y el código abierto no es un secreto. La empresa ha aumentado constantemente sus contribuciones al código abierto en los últimos años, incluida la migración de algunos de sus programas y herramientas a Linux. A finales de 2018, Microsoft anunció que trasladaría algunas de sus herramientas Sysinternals a Linux como código abierto, y ProcDump para Linux fue la primera versión de este tipo.
Si ha trabajado en Windows en la depuración o solución de problemas, probablemente haya oído hablar de Sysinternals. Es un conjunto de herramientas tipo "navaja suiza" que ayuda a los administradores de sistemas, desarrolladores y profesionales de seguridad de TI a monitorear y solucionar problemas en entornos de Windows.
Más recursos de Linux
- Hoja de trucos de los comandos de Linux
- Hoja de trucos de comandos avanzados de Linux
- Curso en línea gratuito:Descripción general técnica de RHEL
- Hoja de trucos de red de Linux
- Hoja de trucos de SELinux
- Hoja de trucos de los comandos comunes de Linux
- ¿Qué son los contenedores de Linux?
- Nuestros últimos artículos sobre Linux
Una de las herramientas más populares de Sysinternals es ProcDump. Como sugiere su nombre, se utiliza para volcar la memoria de un proceso en ejecución en un archivo central en el disco. Luego, este archivo principal se puede analizar con un depurador para comprender el estado del proceso cuando se realizó el volcado. Habiendo usado Sysinternals anteriormente, tenía curiosidad por probar el puerto Linux de ProcDump.
Empezar con ProcDump para Linux
Para probar ProcDump para Linux, debe descargar la herramienta y compilarla. (Uso Red Hat Enterprise Linux, aunque estas instrucciones deberían funcionar igual en otras distribuciones de Linux):
$ cat /etc/redhat-release
Red Hat Enterprise Linux release 8.2 (Ootpa)
$
$ uname -r
4.18.0-193.el8.x86_64
$
Primero, clone el repositorio de ProcDump para Linux:
$ git clone https://github.com/microsoft/ProcDump-for-Linux.git
Cloning into 'ProcDump-for-Linux'...
remote: Enumerating objects: 40, done.
remote: Counting objects: 100% (40/40), done.
remote: Compressing objects: 100% (33/33), done.
remote: Total 414 (delta 14), reused 14 (delta 6), pack-reused 374
Receiving objects: 100% (414/414), 335.28 KiB | 265.00 KiB/s, done.
Resolving deltas: 100% (232/232), done.
$
$ cd ProcDump-for-Linux/
$
$ ls
azure-pipelines.yml CONTRIBUTING.md docs INSTALL.md Makefile procdump.gif src
CODE_OF_CONDUCT.md dist include LICENSE procdump.1 README.md tests
$
Luego, construye el programa usando make
. Imprime la interfaz de línea de comandos GCC exacta necesaria para compilar los archivos fuente:
$ make
rm -rf obj
rm -rf bin
rm -rf /root/ProcDump-for-Linux/pkgbuild
gcc -c -g -o obj/Logging.o src/Logging.c -Wall -I ./include -pthread -std=gnu99
gcc -c -g -o obj/Events.o src/Events.c -Wall -I ./include -pthread -std=gnu99
gcc -c -g -o obj/ProcDumpConfiguration.o src/ProcDumpConfiguration.c -Wall -I ./include -pthread -std=gnu99
gcc -c -g -o obj/Handle.o src/Handle.c -Wall -I ./include -pthread -std=gnu99
gcc -c -g -o obj/Process.o src/Process.c -Wall -I ./include -pthread -std=gnu99
gcc -c -g -o obj/Procdump.o src/Procdump.c -Wall -I ./include -pthread -std=gnu99
gcc -c -g -o obj/TriggerThreadProcs.o src/TriggerThreadProcs.c -Wall -I ./include -pthread -std=gnu99
gcc -c -g -o obj/CoreDumpWriter.o src/CoreDumpWriter.c -Wall -I ./include -pthread -std=gnu99
gcc -o bin/procdump obj/Logging.o obj/Events.o obj/ProcDumpConfiguration.o obj/Handle.o obj/Process.o obj/Procdump.o obj/TriggerThreadProcs.o obj/CoreDumpWriter.o -Wall -I ./include -pthread -std=gnu99
gcc -c -g -o obj/ProcDumpTestApplication.o tests/integration/ProcDumpTestApplication.c -Wall -I ./include -pthread -std=gnu99
gcc -o bin/ProcDumpTestApplication obj/ProcDumpTestApplication.o -Wall -I ./include -pthread -std=gnu99
$
La compilación crea dos nuevos directorios. Primero es un obj/
directorio, que contiene los archivos de objetos creados durante la compilación. El segundo (y más importante) directorio es bin/
, que es donde se compila el procdump
se almacena el programa. También compila otro binario de prueba llamado ProcDumpTestApplication
:
$ ls obj/
CoreDumpWriter.o Handle.o ProcDumpConfiguration.o ProcDumpTestApplication.o TriggerThreadProcs.o
Events.o Logging.o Procdump.o Process.o
$
$
$ ls bin/
procdump ProcDumpTestApplication
$
$ file bin/procdump
bin/procdump: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=6e8827db64835ea0d1f0941ac3ecff9ee8c06e6b, with debug_info, not stripped
$
$ file bin/ProcDumpTestApplication
bin/ProcDumpTestApplication: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=c8fd86f53c07df142e52518815b2573d1c690e4e, with debug_info, not stripped
$
Con esta configuración, cada vez que ejecuta procdump
utilidad, debe pasar al bin/
carpeta. Para que esté disponible desde cualquier lugar dentro del sistema, ejecute make install
. Esto copia el binario en el habitual bin/
directorio, que es parte del $PATH
de su shell :
$ which procdump
/usr/bin/which: no procdump in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin)
$
$ make install
mkdir -p //usr/bin
cp bin/procdump //usr/bin
mkdir -p //usr/share/man/man1
cp procdump.1 //usr/share/man/man1
$
$ which procdump
/usr/bin/procdump
$
Con la instalación, ProcDump proporciona una página man, a la que puede acceder con man procdump
:
$ man procdump
$
Ejecutar ProcDump
Para volcar la memoria de un proceso, debe proporcionar su ID de proceso (PID) a ProcDump. Puede usar cualquiera de los programas o demonios en ejecución en su máquina. Para este ejemplo, usaré un pequeño programa en C que se repite para siempre. Compile el programa y ejecútelo (para salir del programa, presione Ctrl +C , o si se está ejecutando en segundo plano, use kill
comando con el PID):
$ cat progxyz.c
#include <stdio.h>
int main() {
for (;;)
{
printf(".");
sleep(1);
}
return 0;
}
$
$ gcc progxyz.c -o progxyz
$
$ ./progxyz &
[1] 350498
$
Al ejecutar el programa, puede encontrar su PID usando pgrep
o ps
. Tome nota del PID:
$ pgrep progxyz
350498
$
$ ps -ef | grep progxyz
root 350498 345445 0 03:29 pts/1 00:00:00 ./progxyz
root 350508 347350 0 03:29 pts/0 00:00:00 grep --color=auto progxyz
$
Mientras se ejecuta el proceso de prueba, invoque procdump
y proporcione el PID. La salida indica el nombre del proceso y el PID, informa que un Core dump
fue generado y muestra su nombre de archivo:
$ procdump -p 350498
ProcDump v1.1.1 - Sysinternals process dump utility
Copyright (C) 2020 Microsoft Corporation. All rights reserved. Licensed under the MIT license.
Mark Russinovich, Mario Hewardt, John Salem, Javid Habibi
Monitors a process and writes a dump file when the process exceeds the
specified criteria.
Process: progxyz (350498)
CPU Threshold: n/a
Commit Threshold: n/a
Polling interval (ms): 1000
Threshold (s): 10
Number of Dumps: 1
Press Ctrl-C to end monitoring without terminating the process.
[03:30:00 - INFO]: Timed:
[03:30:01 - INFO]: Core dump 0 generated: progxyz_time_2020-06-24_03:30:00.350498
$
Enumere el contenido del directorio actual y debería ver el nuevo archivo central. El nombre del archivo coincide con el que muestra el procdump
comando, y la fecha, la hora y el PID se le agregan:
$ ls -l progxyz_time_2020-06-24_03\:30\:00.350498
-rw-r--r--. 1 root root 356848 Jun 24 03:30 progxyz_time_2020-06-24_03:30:00.350498
$
$ file progxyz_time_2020-06-24_03\:30\:00.350498
progxyz_time_2020-06-24_03:30:00.350498: ELF 64-bit LSB core file, x86-64, version 1 (SYSV), SVR4-style, from './progxyz', real uid: 0, effective uid: 0, real gid: 0, effective gid: 0, execfn: './progxyz', platform: 'x86_64'
$
Analice el archivo principal con el depurador de proyectos GNU
Para ver si puede leer el archivo proc, invoque el depurador de proyectos GNU (gdb
). Recuerde proporcionar la ruta del binario de prueba para que pueda ver todos los nombres de funciones en la pila. Aquí, bt
(retroceso) muestra que sleep()
la función se estaba ejecutando cuando se realizó el volcado:
$ gdb -q ./progxyz ./progxyz_time_2020-06-24_03\:30\:00.350498
Reading symbols from ./progxyz...(no debugging symbols found)...done.
[New LWP 350498]
Core was generated by `./progxyz'.
#0 0x00007fb6947e9208 in nanosleep () from /lib64/libc.so.6
Missing separate debuginfos, use: yum debuginfo-install glibc-2.28-101.el8.x86_64
(gdb) bt
#0 0x00007fb6947e9208 in nanosleep () from /lib64/libc.so.6
#1 0x00007fb6947e913e in sleep () from /lib64/libc.so.6
#2 0x00000000004005f3 in main ()
(gdb)
¿Qué pasa con gcore?
Los usuarios de Linux señalarán rápidamente que Linux ya tiene un comando llamado gcore
, que viene con la mayoría de las distribuciones de Linux y hace exactamente lo mismo que ProcDump. Este es un argumento válido. Si nunca lo ha usado, intente lo siguiente para volcar el núcleo de un proceso con gcore
. Vuelva a ejecutar el programa de prueba, luego ejecute gcore
y proporcione el PID como argumento:
$ ./progxyz &
[1] 350664
$
$
$ pgrep progxyz
350664
$
$
$ gcore 350664
0x00007fefd3be2208 in nanosleep () from /lib64/libc.so.6
Saved corefile core.350664
[Inferior 1 (process 350664) detached]
$
gcore
imprime un mensaje que dice que ha guardado el núcleo en un archivo específico. Verifique el directorio actual para encontrar este archivo central y use gdb
de nuevo para cargarlo:
$
$ ls -l core.350664
-rw-r--r--. 1 root root 356848 Jun 24 03:34 core.350664
$
$
$ file core.350664
core.350664: ELF 64-bit LSB core file, x86-64, version 1 (SYSV), SVR4-style, from './progxyz', real uid: 0, effective uid: 0, real gid: 0, effective gid: 0, execfn: './progxyz', platform: 'x86_64'
$
$ gdb -q ./progxyz ./core.350664
Reading symbols from ./progxyz...(no debugging symbols found)...done.
[New LWP 350664]
Core was generated by `./progxyz'.
#0 0x00007fefd3be2208 in nanosleep () from /lib64/libc.so.6
Missing separate debuginfos, use: yum debuginfo-install glibc-2.28-101.el8.x86_64
(gdb) bt
#0 0x00007fefd3be2208 in nanosleep () from /lib64/libc.so.6
#1 0x00007fefd3be213e in sleep () from /lib64/libc.so.6
#2 0x00000000004005f3 in main ()
(gdb) q
$
Para gcore
para que funcione, debe asegurarse de que las siguientes configuraciones estén en su lugar. Primero, asegúrese de que ulimit
está configurado para archivos principales; si se establece en 0
, no se generarán archivos principales. En segundo lugar, asegúrese de que /proc/sys/kernel/core_pattern
tiene la configuración adecuada para especificar el patrón principal:
$ ulimit -c
unlimited
$
¿Debería usar ProcDump o gcore?
Hay varios casos en los que podría preferir usar ProcDump en lugar de gcore, y ProcDump tiene algunas funciones integradas que pueden ser útiles en general.
Esperando que se ejecute un binario de prueba
Ya sea que use ProcDump o gcore, el proceso de prueba debe ejecutarse y estar en ejecución para que pueda proporcionar un PID para generar un archivo central. Pero ProcDump tiene una función que espera hasta que se ejecuta un binario específico; una vez que encuentra un binario de prueba en ejecución que coincide con ese nombre dado, genera un archivo central para ese binario de prueba. Se puede habilitar usando -w
argumento y el nombre del programa en lugar de un PID. Esta función puede ser útil en casos en los que el programa de prueba se cierra rápidamente.
Así es como funciona. En este ejemplo, no hay ningún proceso llamado progxyz
corriendo:
$ pgrep progxyz
$
Invocar procdump
con el -w
comando para mantenerlo esperando. Desde otro terminal, invoque el binario de prueba progxyz
:
$ procdump -w progxyz
ProcDump v1.1.1 - Sysinternals process dump utility
Copyright (C) 2020 Microsoft Corporation. All rights reserved. Licensed under the MIT license.
Mark Russinovich, Mario Hewardt, John Salem, Javid Habibi
Monitors a process and writes a dump file when the process exceeds the
specified criteria.
Process: progxyz (pending)
CPU Threshold: n/a
Commit Threshold: n/a
Polling interval (ms): 1000
Threshold (s): 10
Number of Dumps: 1
Press Ctrl-C to end monitoring without terminating the process.
[03:39:23 - INFO]: Waiting for process 'progxyz' to launch...
Luego, desde otra terminal, invoque el binario de prueba progxyz
:
$ ./progxyz &
[1] 350951
$
ProcDump detecta inmediatamente que el binario se está ejecutando y vuelca el archivo central para este binario:
[03:39:23 - INFO]: Waiting for process 'progxyz' to launch...
[03:43:22 - INFO]: Found process with PID 350951
[03:43:22 - INFO]: Timed:
[03:43:23 - INFO]: Core dump 0 generated: progxyz_time_2020-06-24_03:43:22.350951
$
$ ls -l progxyz_time_2020-06-24_03\:43\:22.350951
-rw-r--r--. 1 root root 356848 Jun 24 03:43 progxyz_time_2020-06-24_03:43:22.350951
$
$ file progxyz_time_2020-06-24_03\:43\:22.350951
progxyz_time_2020-06-24_03:43:22.350951: ELF 64-bit LSB core file, x86-64, version 1 (SYSV), SVR4-style, from './progxyz', real uid: 0, effective uid: 0, real gid: 0, effective gid: 0, execfn: './progxyz', platform: 'x86_64'
$
Volcados de varios núcleos
Otra característica importante de ProcDump es que puede especificar cuántos archivos principales generar utilizando el argumento de la línea de comandos -n <count>
. El intervalo de tiempo predeterminado entre los volcados del núcleo es de 10 segundos, pero puede modificarlo usando -s <sec>
argumento. Este ejemplo usa ProcDump para tomar tres volcados del núcleo del binario de prueba:
$ ./progxyz &
[1] 351014
$
$ procdump -n 3 -p 351014
ProcDump v1.1.1 - Sysinternals process dump utility
Copyright (C) 2020 Microsoft Corporation. All rights reserved. Licensed under the MIT license.
Mark Russinovich, Mario Hewardt, John Salem, Javid Habibi
Monitors a process and writes a dump file when the process exceeds the
specified criteria.
Process: progxyz (351014)
CPU Threshold: n/a
Commit Threshold: n/a
Polling interval (ms): 1000
Threshold (s): 10
Number of Dumps: 3
Press Ctrl-C to end monitoring without terminating the process.
[03:45:20 - INFO]: Timed:
[03:45:21 - INFO]: Core dump 0 generated: progxyz_time_2020-06-24_03:45:20.351014
[03:45:31 - INFO]: Timed:
[03:45:32 - INFO]: Core dump 1 generated: progxyz_time_2020-06-24_03:45:31.351014
[03:45:42 - INFO]: Timed:
[03:45:44 - INFO]: Core dump 2 generated: progxyz_time_2020-06-24_03:45:42.351014
$
$ ls -l progxyz_time_2020-06-24_03\:45\:*
-rw-r--r--. 1 root root 356848 Jun 24 03:45 progxyz_time_2020-06-24_03:45:20.351014
-rw-r--r--. 1 root root 356848 Jun 24 03:45 progxyz_time_2020-06-24_03:45:31.351014
-rw-r--r--. 1 root root 356848 Jun 24 03:45 progxyz_time_2020-06-24_03:45:42.351014
$
Volcado de núcleo basado en el uso de memoria y CPU
ProcDump también le permite activar un volcado del núcleo cuando un binario o proceso de prueba alcanza un cierto umbral de CPU o memoria. La página del manual de ProcDump muestra los argumentos de la línea de comandos que se deben usar al invocar a ProcDump:
-C Trigger core dump generation when CPU exceeds or equals specified value (0 to 100 * nCPU)
-c Trigger core dump generation when CPU is less than specified value (0 to 100 * nCPU)
-M Trigger core dump generation when memory commit exceeds or equals specified value (MB)
-m Trigger core dump generation when when memory commit is less than specified value (MB)
-T Trigger when thread count exceeds or equals specified value.
-F Trigger when filedescriptor count exceeds or equals specified value.
-I Polling frequency in milliseconds (default is 1000)
Por ejemplo, puede pedirle a ProcDump que descargue el núcleo cuando el uso de CPU del PID dado supere el 70 %:
procdump -C 70 -n 3 -p 351014
Conclusión
ProcDump es una adición interesante a la larga lista de programas de Windows que se están transfiriendo a Linux. No solo proporciona opciones de herramientas adicionales para los usuarios de Linux, sino que también puede hacer que los usuarios de Windows se sientan más cómodos cuando trabajan en Linux.