GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Debuggen Sie Linux mit ProcDump

Microsofts wachsende Wertschätzung für Linux und Open Source ist kein Geheimnis. Das Unternehmen hat seine Beiträge zu Open Source in den letzten Jahren stetig erhöht, einschließlich der Portierung einiger seiner Software und Tools auf Linux. Ende 2018 kündigte Microsoft an, einige seiner Sysinternals-Tools als Open Source auf Linux zu portieren, und ProcDump für Linux war die erste derartige Version.

Wenn Sie an Windows beim Debuggen oder der Fehlerbehebung gearbeitet haben, haben Sie wahrscheinlich schon von Sysinternals gehört. Es ist ein "Schweizer Taschenmesser"-Toolset, das Systemadministratoren, Entwicklern und IT-Sicherheitsexperten hilft, Windows-Umgebungen zu überwachen und Fehler zu beheben.

Weitere Linux-Ressourcen

  • Spickzettel für Linux-Befehle
  • Spickzettel für fortgeschrittene Linux-Befehle
  • Kostenloser Online-Kurs:RHEL Technical Overview
  • Spickzettel für Linux-Netzwerke
  • SELinux-Spickzettel
  • Spickzettel für allgemeine Linux-Befehle
  • Was sind Linux-Container?
  • Unsere neuesten Linux-Artikel

Eines der beliebtesten Tools von Sysinternals ist ProcDump. Wie der Name schon sagt, wird es verwendet, um den Speicher eines laufenden Prozesses in eine Kerndatei auf der Festplatte zu kopieren. Diese Kerndatei kann dann mit einem Debugger analysiert werden, um den Status des Prozesses zu verstehen, als der Dump erstellt wurde. Nachdem ich zuvor Sysinternals verwendet hatte, war ich neugierig, die Linux-Portierung von ProcDump auszuprobieren.

Erste Schritte mit ProcDump für Linux

Um ProcDump für Linux auszuprobieren, müssen Sie das Tool herunterladen und kompilieren. (Ich verwende Red Hat Enterprise Linux, obwohl diese Anweisungen auf anderen Linux-Distributionen genauso funktionieren sollten):

$ cat /etc/redhat-release 
Red Hat Enterprise Linux release 8.2 (Ootpa)
$
$ uname -r
4.18.0-193.el8.x86_64
$

Klonen Sie zuerst das ProcDump für Linux-Repository:

$ 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
$

Als nächstes erstellen Sie das Programm mit make . Es gibt die exakte GCC-Befehlszeilenschnittstelle aus, die zum Kompilieren der Quelldateien benötigt wird:

$ 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
$

Die Kompilierung erstellt zwei neue Verzeichnisse. Zuerst ist ein obj/ Verzeichnis, das die während der Kompilierung erstellten Objektdateien enthält. Das zweite (und wichtigere) Verzeichnis ist bin/ , wo sich der kompilierte procdump befindet Programm gespeichert. Es kompiliert auch eine weitere Test-Binärdatei namens 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
$

Mit diesem Setup jedes Mal, wenn Sie procdump ausführen müssen Sie in den bin/ verschieben Mappe. Um es von überall im System verfügbar zu machen, führen Sie make install aus . Dies kopiert die Binärdatei in den üblichen bin/ Verzeichnis, das Teil des $PATH Ihrer Shell ist :

$ 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
$

Bei der Installation stellt ProcDump eine Manpage zur Verfügung, auf die Sie mit man procdump zugreifen können :

$ man procdump
$

ProcDump ausführen

Um den Arbeitsspeicher eines Prozesses zu sichern, müssen Sie seine Prozess-ID (PID) an ProcDump übermitteln. Sie können alle laufenden Programme oder Daemons auf Ihrem Computer verwenden. Für dieses Beispiel werde ich ein winziges C-Programm verwenden, das sich endlos wiederholt. Kompilieren Sie das Programm und führen Sie es aus (um das Programm zu beenden, drücken Sie Strg +C , oder wenn es im Hintergrund läuft, verwenden Sie den kill Befehl mit der PID):

$ cat progxyz.c 
#include <stdio.h>

int main() {
        for (;;)
        {
                printf(".");
                sleep(1);
        }
        return 0;
}
$
$ gcc progxyz.c -o progxyz
$
$ ./progxyz &
[1] 350498
$

Wenn Sie das Programm ausführen, können Sie seine PID entweder mit pgrep finden oder ps . Notieren Sie sich die 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
$

Während der Testprozess läuft, rufen Sie procdump auf und geben Sie die PID an. Die Ausgabe gibt den Namen des Prozesses und die PID an, meldet, dass es sich um einen Core dump handelt wurde generiert und zeigt den Dateinamen:

$ 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
$

Listen Sie den Inhalt des aktuellen Verzeichnisses auf, und Sie sollten die neue Kerndatei sehen. Der Dateiname stimmt mit dem von procdump angezeigten überein Befehl, und Datum, Uhrzeit und PID werden daran angehängt:

$ 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'
$

Analysieren Sie die Core-Datei mit dem GNU Project Debugger

Um zu sehen, ob Sie die proc-Datei lesen können, rufen Sie den GNU Project Debugger (gdb ). Denken Sie daran, den Pfad der Testbinärdatei anzugeben, damit Sie alle Funktionsnamen auf dem Stack sehen können. Hier, bt (Backtrace) zeigt, dass sleep() Funktion wurde ausgeführt, als der Dump erstellt wurde:

$ 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)

Was ist mit gcore?

Linux-Benutzer werden schnell darauf hinweisen, dass Linux bereits einen Befehl namens gcore hat , das mit den meisten Linux-Distributionen ausgeliefert wird und genau dasselbe tut wie ProcDump. Dies ist ein gültiges Argument. Wenn Sie es noch nie verwendet haben, versuchen Sie Folgendes, um den Kern eines Prozesses mit gcore zu sichern . Führen Sie das Testprogramm erneut aus und führen Sie dann gcore aus , und geben Sie die PID als Argument an:

$ ./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 druckt eine Nachricht, die besagt, dass der Kern in einer bestimmten Datei gespeichert wurde. Überprüfen Sie das aktuelle Verzeichnis, um diese Kerndatei zu finden, und verwenden Sie gdb erneut, um es zu laden:

$ 
$ 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
$

Für gcore Um zu funktionieren, müssen Sie sicherstellen, dass die folgenden Einstellungen vorhanden sind. Stellen Sie zuerst das ulimit sicher ist für Core-Dateien gesetzt; wenn es auf 0 gesetzt ist , Kerndateien werden nicht generiert. Stellen Sie zweitens sicher, dass /proc/sys/kernel/core_pattern hat die richtigen Einstellungen, um das Kernmuster anzugeben:

$ ulimit -c
unlimited
$

Sollten Sie ProcDump oder gcore verwenden?

Es gibt mehrere Fälle, in denen Sie die Verwendung von ProcDump anstelle von gcore bevorzugen könnten, und ProcDump hat einige eingebaute Funktionen, die im Allgemeinen nützlich sein könnten.

Warten auf die Ausführung einer Testbinärdatei

Unabhängig davon, ob Sie ProcDump oder gcore verwenden, muss der Testprozess ausgeführt werden und sich in einem laufenden Zustand befinden, damit Sie eine PID zum Generieren einer Kerndatei bereitstellen können. Aber ProcDump hat eine Funktion, die wartet, bis eine bestimmte Binärdatei ausgeführt wird; Sobald es eine laufende Testbinärdatei findet, die mit diesem angegebenen Namen übereinstimmt, generiert es eine Kerndatei für diese Testbinärdatei. Es kann mit dem -w aktiviert werden Argument und den Namen des Programms anstelle einer PID. Diese Funktion kann in Fällen nützlich sein, in denen das Testprogramm schnell beendet wird.

So funktioniert das. In diesem Beispiel gibt es keinen Prozess namens progxyz läuft:

$ pgrep progxyz 
$

Rufen Sie procdump auf mit dem -w Befehl, es warten zu lassen. Rufen Sie von einem anderen Terminal aus die Testbinärdatei progxyz auf :

$ 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...

Rufen Sie dann von einem anderen Terminal aus die Testbinärdatei progxyz auf : 

$ ./progxyz &
[1] 350951
$

ProcDump erkennt sofort, dass die Binärdatei ausgeführt wird, und gibt die Kerndatei für diese Binärdatei aus:

[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'
$

Mehrere Core-Dumps

Eine weitere wichtige ProcDump-Funktion besteht darin, dass Sie angeben können, wie viele Kerndateien generiert werden sollen, indem Sie das Befehlszeilenargument -n <count> verwenden . Der standardmäßige Zeitabstand zwischen den Core-Dumps beträgt 10 Sekunden, aber Sie können dies mit -s <sec> ändern Streit. Dieses Beispiel verwendet ProcDump, um drei Core-Dumps der Test-Binärdatei zu erstellen:

$ ./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
$

Core-Dump basierend auf CPU- und Speichernutzung

Mit ProcDump können Sie auch einen Core-Dump auslösen, wenn eine Testbinärdatei oder ein Prozess einen bestimmten CPU- oder Speicherschwellenwert erreicht. Die Manpage von ProcDump zeigt die Befehlszeilenargumente, die beim Aufrufen von ProcDump zu verwenden sind:

-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)

Beispielsweise können Sie ProcDump auffordern, den Kern zu entleeren, wenn die CPU-Auslastung der angegebenen PID 70 % überschreitet:

procdump -C 70 -n 3 -p 351014

Schlussfolgerung

ProcDump ist eine interessante Ergänzung der langen Liste von Windows-Programmen, die auf Linux portiert werden. Es bietet Linux-Benutzern nicht nur zusätzliche Tooloptionen, sondern kann auch dafür sorgen, dass sich Windows-Benutzer bei der Arbeit unter Linux besser zu Hause fühlen.


Linux
  1. Identifizieren Sie Sicherheitseigenschaften unter Linux mit checksec

  2. Fehlerbehebung mit dem proc-Dateisystem unter Linux

  3. Beispiel für die Verwendung von getnstimeofday im Linux-Kernel

  4. IPC mit Signalen unter Linux

  5. Linux-Warteschlangensystem

So erstellen Sie einen CS:GO-Server auf einem Linux-VPS

So zeigen Sie Benutzer in MySQL mit Linux an

Ablenkungsfreies Schreiben unter Linux mit FocusWriter

Installieren Sie MongoDB mit Vagrant unter Linux

Verwenden des Watch-Befehls unter Linux

Cut auf Linux Terminal verwenden