GNU/Linux >> Linux の 問題 >  >> Linux

ProcDumpを使用してLinuxをデバッグする

Linuxとオープンソースに対するMicrosoftの評価の高まりは秘密ではありません。同社は、ソフトウェアやツールの一部をLinuxに移植するなど、過去数年間でオー​​プンソースへの貢献を着実に増やしてきました。 2018年後半、MicrosoftはSysinternalsツールの一部をオープンソースとしてLinuxに移植すると発表し、ProcDumpforLinuxがそのような最初のリリースでした。

デバッグやトラブルシューティングでWindowsに取り組んだことがある場合は、おそらくSysinternalsについて聞いたことがあるでしょう。これは、システム管理者、開発者、ITセキュリティ専門家がWindows環境を監視およびトラブルシューティングするのに役立つ「スイスアーミーナイフ」ツールセットです。

その他のLinuxリソース

  • Linuxコマンドのチートシート
  • 高度なLinuxコマンドのチートシート
  • 無料のオンラインコース:RHELの技術概要
  • Linuxネットワーキングのチートシート
  • SELinuxチートシート
  • Linuxの一般的なコマンドのチートシート
  • Linuxコンテナとは何ですか?
  • 最新のLinux記事

Sysinternalsで最も人気のあるツールの1つは、ProcDumpです。その名前が示すように、実行中のプロセスのメモリをディスク上のコアファイルにダンプするために使用されます。次に、このコアファイルをデバッガーを使用して分析し、ダンプが取得されたときのプロセスの状態を理解できます。以前にSysinternalsを使用したことがあるので、ProcDumpのLinuxポートを試してみたいと思いました。

ProcDumpforLinuxの使用を開始する

Linux用のProcDumpを試すには、ツールをダウンロードしてコンパイルする必要があります。 (私はRed Hat Enterprise Linuxを使用していますが、これらの手順は他のLinuxディストリビューションでも同じように機能するはずです):

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

まず、ProcDumpforLinuxリポジトリのクローンを作成します。

 $ git clone https://github.com/microsoft/ProcDump-for-Linux.git 
'ProcDump-for-Linux'へのクローン作成...
リモート:オブジェクトの列挙:40、
リモート:オブジェクトのカウント:100%(40/40)、完了。
リモート:オブジェクトの圧縮:100%(33/33)、完了。
リモート:合計414(デルタ14)、再利用14(delta 6)、パック再利用374
オブジェクトの受信:100%(414/414)、335.28 KiB | 265.00 KiB / s、完了。
デルタの解決:100%(232/232)、完了。
$
$ cd ProcDump-for-Linux /
$
$ ls
azure-pipelines.yml CONTRIBUTING.md docs INSTALL.md Makefile procdump.gif src
CODE_OF_CONDUCT.md dist dist pre tests 次に、makeを使用してプログラムをビルドします 。ソースファイルのコンパイルに必要な正確なGCCコマンドラインインターフェイスを出力します。

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

コンパイルにより、2つの新しいディレクトリが作成されます。最初はobj/です ディレクトリ。コンパイル中に作成されたオブジェクトファイルを保持します。 2番目の(そしてより重要な)ディレクトリはbin/です 、コンパイルされたprocdumpがここにあります プログラムが保存されます。また、ProcDumpTestApplicationと呼ばれる別のテストバイナリをコンパイルします :

 $ ls obj / 
CoreDumpWriter.o Handle.o ProcDumpConfiguration.o ProcDumpTestApplication.o TriggerThreadProcs.o
Events.o Logging.o Procdump.o
$
$ ls bin /
procdump ProcDumpTestApplication
$
$ file bin / procdump
bin / procdump:ELF 64ビットLSB実行可能ファイル、x86-64、バージョン1(SYSV)、動的リンク、インタープリター/lib64/ld-linux-x86-64.so.2、GNU / Linux 3.2.0の場合、BuildID [sha1] =6e8827db64835ea0d1f0941ac3ecff9ee8c06e6b、debug_infoあり、ストリップされていない
$
$ file bin / ProcDumpTestApplication
bin / ProcDumpTestApplication:ELF 64ビットLSB実行可能ファイル、x86-64、バージョン1(SYSV)、動的リンク、インタープリター/lib64/ld-linux-x86-64.so。 2、GNU / Linux 3.2.0の場合、BuildID [sha1] =c8fd86f53c07df142e52518815b2573d1c690e4e、debug_infoを使用、削除されない
$

この設定では、procdumpを実行するたびに ユーティリティの場合、bin/に移動する必要があります フォルダ。システム内のどこからでも利用できるようにするには、make installを実行します 。これにより、バイナリが通常のbin/にコピーされます。 シェルの$PATHの一部であるディレクトリ :

 $ which procdump 
/ usr / bin / which:procdumpがありません(/ 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
$

インストールすると、ProcDumpはmanページを提供します。このページには、man procdumpでアクセスできます。 :

 $ man procdump 
$

ProcDumpを実行

プロセスのメモリをダンプするには、そのプロセスID(PID)をProcDumpに提供する必要があります。マシン上で実行中のプログラムまたはデーモンのいずれかを使用できます。この例では、永久にループする小さなCプログラムを使用します。プログラムをコンパイルして実行します(プログラムを終了するには、 Ctrlを押します + C 、またはバックグラウンドで実行されている場合は、killを使用します PIDを使用したコマンド):

 $ cat progxyz.c 
#include

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

プログラムを実行すると、pgrepのいずれかを使用してそのPIDを見つけることができます。 またはps 。 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
$

テストプロセスの実行中に、procdumpを呼び出します PIDを提供します。出力には、プロセスの名前とPIDが示され、Core dumpが報告されます。 が生成され、そのファイル名が表示されます:

 $ procdump -p 350498 

ProcDump v1.1.1-Sysinternalsプロセスダンプユーティリティ
Copyright(C)2020MicrosoftCorporation。全著作権所有。 MITライセンスの下でライセンス供与されています。
MarkRussinovich、Mario Hewardt、John Salem、Javid Habibi
プロセスを監視し、プロセスが
指定された基準を超えるとダンプファイルを書き込みます。

プロセス:progxyz(350498)
CPUしきい値:n / a
コミットしきい値:n / a
ポーリング間隔(ms):1000
しきい値(s):10
ダンプの数:1

Ctrl-Cを押して、プロセスを終了せずに監視を終了します。

[03:30:00-INFO]:時間指定:
[03:30:01-情報]:コアダンプ0が生成されました:progxyz_time_2020-06-24_03:30:00.350498
$

現在のディレクトリの内容を一覧表示すると、新しいコアファイルが表示されます。ファイル名は、procdumpで示されているものと一致します コマンド、および日付、時刻、PIDが追加されます:

 $ ls -l progxyz_time_2020-06-24_03 \:30 \:00.350498 
-rw-r--r--。 1ルートルート3568486月24日03:30progxyz_time_2020-06-24_03:30:00.350498
$
$ファイルprogxyz_time_2020-06-24_03\:30 \:00.350498
progxyz_time_2020-06-24_03: 30:00.350498:ELF 64ビットLSBコアファイル、x86-64、バージョン1(SYSV)、SVR4スタイル、「。/ progxyz」から、実数uid:0、有効uid:0、実数gid:0、有効gid :0、execfn:'./progxyz'、プラットフォーム:'x86_64'
$

GNUプロジェクトデバッガーを使用してコアファイルを分析します

procファイルを読み取れるかどうかを確認するには、GNU Project Debugger(gdb)を呼び出します。 )。スタック上のすべての関数名を確認できるように、テストバイナリのパスを指定することを忘れないでください。ここでは、bt (バックトレース)は、sleep() ダンプが取られたときに関数が実行されていました:

 $ gdb -q ./progxyz ./progxyz_time_2020-06-24_03 \:30 \:00.350498 
./progxyzからのシンボルの読み取り...(デバッグシンボルが見つかりません)...完了。
[新しいLWP350498]
コアは`./progxyz'によって生成されました。
#0 0x00007fb6947e9208 in nanosleep()from /lib64/libc.so.6
個別のデバッグ情報がない場合は、以下を使用してくださいyum debuginfo-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)

gcoreはどうですか?

Linuxユーザーは、Linuxにはすでにgcoreというコマンドがあることをすぐに指摘できます。 、ほとんどのLinuxディストリビューションに同梱されており、ProcDumpとまったく同じことを行います。これは有効な引数です。使用したことがない場合は、次の手順を実行して、プロセスのコアをgcoreでダンプしてください。 。テストプログラムを再度実行してから、gcoreを実行します 、引数としてPIDを指定します:

 $ ./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 コアを特定のファイルに保存したことを示すメッセージを出力します。現在のディレクトリをチェックしてこのコアファイルを見つけ、gdbを使用します もう一度ロードするには:

 $ 
$ ls -l core.350664
-rw-r--r--。 1ルートルート356846Jun24 03:34 core.350664
$
$
$ file core.350664
core.350664:ELF 64ビットLSBコアファイル、x86-64 、バージョン1(SYSV)、SVR4スタイル、'./progxyz'から、実数uid:0、有効uid:0、実数gid:0、有効gid:0、execfn:'./progxyz'、プラットフォーム:'x86_64 '
$
$ gdb -q ./progxyz ./core.350664
./progxyzからのシンボルの読み取り...(デバッグシンボルが見つかりません)...完了。
[新しいLWP350664]
コアは`./progxyz'によって生成されました。
#0 0x00007fefd3be2208 in nanosleep()from /lib64/libc.so.6
個別のdebuginfoがない場合、使用:yum debuginfo-インストール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
$

gcoreの場合 動作させるには、次の設定が行われていることを確認する必要があります。まず、ulimitを確認します コアファイル用に設定されています。 0に設定されている場合 、コアファイルは生成されません。次に、/proc/sys/kernel/core_pattern コアパターンを指定するための適切な設定があります:

 $ ulimit -c 
unlimited
$

ProcDumpとgcoreのどちらを使用しますか?

gcoreの代わりにProcDumpを使用したい場合がいくつかあり、ProcDumpには一般的に役立つ可能性のあるいくつかの組み込み機能があります。

テストバイナリの実行を待機しています

ProcDumpまたはgcoreのどちらを使用する場合でも、コアファイルを生成するためのPIDを提供できるように、テストプロセスを実行して実行状態にする必要があります。ただし、ProcDumpには、特定のバイナリが実行されるまで待機する機能があります。その指定された名前に一致する実行中のテストバイナリが見つかると、そのテストバイナリのコアファイルが生成されます。 -wを使用して有効にできます PIDの代わりに引数とプログラム名。この機能は、テストプログラムがすぐに終了する場合に役立ちます。

仕組みは次のとおりです。この例では、progxyzという名前のプロセスはありません。 実行中:

 $ pgrep progxyz 
$

procdumpを呼び出す -wを使用 それを待たせるコマンド。別の端末から、テストバイナリprogxyzを呼び出します :

 $ procdump -w progxyz 

ProcDump v1.1.1-Sysinternalsプロセスダンプユーティリティ
Copyright(C)2020MicrosoftCorporation。全著作権所有。 MITライセンスの下でライセンス供与されています。
MarkRussinovich、Mario Hewardt、John Salem、Javid Habibi
プロセスを監視し、プロセスが
指定された基準を超えるとダンプファイルを書き込みます。

プロセス:progxyz(保留中)
CPUしきい値:n / a
コミットしきい値:n / a
ポーリング間隔(ミリ秒):1000
しきい値(秒):10
ダンプの数:1

Ctrl-Cを押して、プロセスを終了せずに監視を終了します。

[03:39:23-情報]:プロセスを待機しています起動する「progxyz」...

次に、別の端末から、テストバイナリprogxyzを呼び出します。 :

 $ ./progxyz&
[1] 350951
$

ProcDumpは、バイナリが実行中であることをすぐに検出し、このバイナリのコアファイルをダンプします。

 [03:39:23-INFO]:プロセス'progxyz'が起動するのを待っています...
[03:43:22-INFO]:PID350951のプロセスが見つかりました
[03: 43:22-情報]:時間指定:
[03:43:23-情報]:コアダンプ0が生成されました:progxyz_time_2020-06-24_03:43:22.350951
$


$ ls -l progxyz_time_2020-06-24_03 \:43 \:22.350951
-rw-r--r--。 1ルートルート3568486月24日03:43progxyz_time_2020-06-24_03:43:22.350951
$
$ファイルprogxyz_time_2020-06-24_03\:43 \:22.350951
progxyz_time_2020-06-24_03: 43:22.350951:ELF 64ビットLSBコアファイル、x86-64、バージョン1(SYSV)、SVR4スタイル、「。/ progxyz」から、実数uid:0、有効uid:0、実数gid:0、有効gid :0、execfn:'./progxyz'、プラットフォーム:'x86_64'
$
複数のコアダンプ

もう1つの重要なProcDump機能は、コマンドライン引数-n <count>を使用して、生成するコアファイルの数を指定できることです。 。コアダンプ間のデフォルトの時間ギャップは10秒ですが、これは-s <sec>を使用して変更できます。 口論。この例では、ProcDumpを使用して、テストバイナリの3つのコアダンプを取得します。

 $ ./progxyz&
[1] 351014
$
$ procdump -n 3 -p 351014

ProcDumpv1.1.1-Sysinternalsプロセスダンプユーティリティ
Copyright(C)2020MicrosoftCorporation。全著作権所有。 MITライセンスの下でライセンスされています。
MarkRussinovich、Mario Hewardt、John Salem、Javid Habibi
プロセスを監視し、プロセスが
指定された基準を超えるとダンプファイルを書き込みます。

プロセス:progxyz(351014)
CPUしきい値:n / a
コミットしきい値:n / a
ポーリング間隔(ms):1000
しきい値(s):10
ダンプの数:3

Ctrl-Cを押して、プロセスを終了せずに監視を終了します。

[03:45:20-情報]:時間指定:
[03:45:21-情報]:コアダンプ0が生成されました:progxyz_time_2020-06-24_03:45:20.351014
[03:45:31-情報]:時間指定:
[03: 45:32-情報]:コアダンプ1が生成されました:progxyz_time_2020-06-24_03:45:31.351014
[03:45:42-情報]:時間指定:
[03:45:44-情報] :生成されたコアダンプ2:progxyz_time_2020-06-24_03:45:42.351014
$
$ ls -l progxyz_time_2020-06-24_03 \:45 \:*
-rw-r--r -。 1ルートルート3568486月24日03:45progxyz_time_2020-06-24_03:45:20.351014
-rw-r--r--。 1ルートルート3568486月24日03:45progxyz_time_2020-06-24_03:45:31.351014
-rw-r--r--。 1ルートルート3568486月24日03:45progxyz_time_2020-06-24_03:45:42.351014
$

CPUとメモリの使用量に基づくコアダンプ

ProcDumpを使用すると、テストバイナリまたはプロセスが特定のCPUまたはメモリのしきい値に達したときにコアダンプをトリガーすることもできます。 ProcDumpのマニュアルページには、ProcDumpを呼び出すときに使用するコマンドライン引数が表示されます。

 -C CPUが指定値(0〜100 * nCPU)以上の場合にコアダンプ生成をトリガーします
-c CPUが指定値(0〜100 * nCPU)未満の場合にコアダンプ生成をトリガーします
-Mメモリコミットが指定値(MB)以上の場合にコアダンプ生成をトリガーします
-mメモリコミットが指定値(MB)未満の場合にコアダンプ生成をトリガーします
-Tスレッドカウント時にトリガーします指定された値以上。
-Fファイル記述子の数が指定された値以上になったときにトリガーされます。
-Iポーリング頻度(ミリ秒)(デフォルトは1000)

たとえば、指定されたPIDのCPU使用率が70%を超えたときに、コアをダンプするようにProcDumpに要求できます。

 procdump -C 70 -n 3 -p 351014 
結論

ProcDumpは、Linuxに移植されているWindowsプログラムの長いリストへの興味深い追加です。 Linuxユーザーに追加のツールオプションを提供するだけでなく、WindowsユーザーがLinuxで作業しているときに自宅にいるように感じることもできます。


Linux
  1. Linuxでのripgrep(rg)コマンドの使用

  2. 50 UNIX / Linux システム管理者チュートリアル

  3. Linux Deploy を使用した Android 上の Kali Linux

  1. checksecを使用してLinuxのセキュリティプロパティを特定する

  2. Linux での dmsetup コマンドの使用例

  3. Linux でシグナルを使用した IPC

  1. Linuxでprocファイルシステムを使用してトラブルシューティングする

  2. gdbを使用してLinuxでCプログラムをデバッグする方法

  3. Linux – LinuxでサスペンドからRAMへの問題をデバッグする方法は?