DUICUO

Microsoft の ProcDump を使用した Linux のデバッグ

[[338713]]

プロセス情報を取得するには、この Microsoft オープンソース ツールを使用してください。

MicrosoftがLinuxとオープンソースへの関心をますます高めていることは周知の事実です。ここ数年、同社はオープンソースへの貢献を着実に増やしており、自社のソフトウェアやツールの一部をLinuxに移植しています。2018年末、MicrosoftはSysinternalsツールの一部をオープンソースとしてLinuxに移植すると発表しました。その最初の移植となるのがProcDumpのLinux版です。

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

Sysinternalsの最も人気のあるツールの一つがProcDumpです。名前の通り、実行中のプロセスのメモリをディスク上のカーネルファイルにダンプするツールです。このカーネルファイルはデバッガで解析することで、ダンプ時のプロセスの状態を把握できます。以前Sysinternalsを使ったことがあるので、ProcDumpのLinux版もぜひ試してみたいと思います。

Linux で ProcDump を使い始める

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

  1. $ cat / etc / redhat - release
  2. Red Hat Enterprise Linux release 8.2 ( Ootpa )
  3. $
  4. $ uname - r
  5. 4.18 . 0 - 193.el8.x86 _64
  6. $

まず、ProcDump リポジトリの Linux バージョンのクローンを作成します。

  1. $ git clone https : //github.com/microsoft/ProcDump-for-Linux.git
  2. Cloning into 'ProcDump-for-Linux' ...
  3. remote : Enumerating objects : 40 , done .
  4. remote : Counting objects : 100 % ( 40 / 40 ), done .
  5. remote : Compressing objects : 100 % ( 33 / 33 ), done .
  6. remote : Total 414 ( delta 14 ), reused 14 ( delta 6 ), pack - reused 374
  7. Receiving objects : 100 % ( 414 / 414 ), 335.28 KiB | 265.00 KiB / s , done .
  8. Resolving deltas : 100 % ( 232 / 232 ), done .
  9. $
  10. $ cd ProcDump - for - Linux /
  11. $
  12. $ ls
  13. azure - pipelines . yml CONTRIBUTING . md docs INSTALL . md Makefile procdump . gif src
  14. CODE_OF_CONDUCT . md dist include LICENSE procdump . 1 README . md tests
  15. $

次に、 make使ってプログラムをビルドします。これにより、ソースファイルのコンパイルに必要な GCC コマンドライン引数が正確に出力されます。

  1. $ make
  2. rm - rf obj
  3. rm - rf bin
  4. rm - rf / root / ProcDump - for - Linux / pkgbuild
  5. gcc - c - g - o obj / Logging . o src / Logging . c - Wall - I ./ include - pthread - std = gnu99
  6. gcc - c - g - o obj / Events . o src / Events . c - Wall - I ./ include - pthread - std = gnu99
  7. gcc - c - g - o obj / ProcDumpConfiguration . o src / ProcDumpConfiguration . c - Wall - I ./ include - pthread - std = gnu99
  8. gcc - c - g - o obj / Handle . o src / Handle . c - Wall - I ./ include - pthread - std = gnu99
  9. gcc - c - g - o obj / Process . o src / Process . c - Wall - I ./ include - pthread - std = gnu99
  10. gcc - c - g - o obj / Procdump . o src / Procdump . c - Wall - I ./ include - pthread - std = gnu99
  11. gcc - c - g - o obj / TriggerThreadProcs . o src / TriggerThreadProcs . c - Wall - I ./ include - pthread - std = gnu99
  12. gcc - c - g - o obj / CoreDumpWriter . o src / CoreDumpWriter . c - Wall - I ./ include - pthread - std = gnu99
  13. 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
  14. gcc - c - g - o obj / ProcDumpTestApplication . o tests / integration / ProcDumpTestApplication . c - Wall - I ./ include - pthread - std = gnu99
  15. gcc - o bin / ProcDumpTestApplication obj / ProcDumpTestApplication . o - Wall - I ./ include - pthread - std = gnu99
  16. $

コンパイル中に、2つの新しいディレクトリが作成されます。1つ目はobj/ディレクトリで、コンパイル中に作成されたオブジェクトファイルが格納されます。2つ目は(そしてより重要な) bin/ ` ディレクトリで、コンパイルされたprocdumpプログラムが格納されます。また、 ProcDumpTestApplicationという別のテストバイナリファイルもコンパイルされます。

  1. $ ls obj /
  2. CoreDumpWriter . o Handle . o ProcDumpConfiguration . o ProcDumpTestApplication . o TriggerThreadProcs . o
  3. Events . o Logging . o Procdump . o Process . o
  4. $
  5. $
  6. $ ls bin /
  7. procdump ProcDumpTestApplication
  8. $
  9. $ file bin / procdump
  10. 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
  11. $
  12. $ file bin / ProcDumpTestApplication
  13. 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
  14. $

この場合、 procdumpユーティリティを実行するたびに、これをbin/フォルダに移動する必要があります。システム上の任意の場所で使用できるようにするには、 make installを実行します。これにより、バイナリが通常のbin/ディレクトリ(シェルの$PATHに含まれる)にコピーされます。

  1. $ which procdump
  2. / usr / bin / which : no procdump in ( /usr/ local / sbin : /usr/ local / bin : /usr/ sbin : /usr/ bin )
  3. $
  4. $ make install
  5. mkdir - p //usr/bin
  6. cp bin / procdump //usr/bin
  7. mkdir - p //usr/share/man/man1
  8. cp procdump . 1 //usr/share/man/man1
  9. $
  10. $ which procdump
  11. / usr / bin / procdump
  12. $

インストール中に、ProcDump はマニュアル ページを提供します。このページには、 man procdumpを使用してアクセスできます。

  1. $ man procdump
  2. $

ProcDumpを実行する

プロセスのメモリをダンプするには、ProcDump にプロセス ID (PID) を指定する必要があります。マシン上で実行中の任意のプログラムまたはデーモンを使用できます。この例では、無限ループする小さな C プログラムを使用します。このプログラムをコンパイルして実行します(プログラムを終了するにはCtrl+Cを押します。プログラムがバックグラウンドで実行されている場合は、 killコマンドを使用して PID を入力してください)。

  1. $ cat progxyz . c
  2. # include < stdio . h >
  3. int main () {
  4.         for (;;)
  5.         {
  6.                 printf ( "." );
  7.                 sleep ( 1 );
  8.         }
  9.         return 0 ;
  10. }
  11. $
  12. $ gcc progxyz . c - o progxyz
  13. $
  14. $ ./ progxyz &
  15. [ 1 ] 350498
  16. $

プログラムを実行した後、 pgrepまたはpsを使って PID を確認できます。PID をメモしておいてください。

  1. $ pgrep progxyz
  2. 350498
  3. $
  4. $ ps - ef | grep progxyz
  5. root 350498   345445   0 03 : 29 pts / 1     00 : 00 : 00 ./ progxyz
  6. root 350508   347350   0 03 : 29 pts / 0     00 : 00 : 00 grep -- color = auto progxyz
  7. $

テストプロセスの実行中にprocdumpが呼び出され、PIDが提供されます。次の出力はプロセス名とPIDを示し、コアダンプファイルが生成されたことを報告し、そのファイル名も表示しています。

  1. $ procdump - p 350498
  2. ProcDump v1 . 1.1 - Sysinternals process dump utility
  3. Copyright ( C ) 2020 Microsoft Corporation . All rights reserved . Licensed under the MIT license .
  4. Mark Russinovich , Mario Hewardt , John Salem , Javid Habibi
  5. Monitors a process and writes a dump file when the process exceeds the
  6. specified criteria .
  7. Process : progxyz ( 350498 )
  8. CPU Threshold : n / a
  9. Commit Threshold : n / a
  10. Polling interval ( ms ):   1000
  11. Threshold ( s ):   10
  12. Number of Dumps :         1
  13. Press Ctrl - C to end monitoring without terminating the process .
  14. [ 03 : 30 : 00 - INFO ]: Timed :
  15. [ 03 : 30 : 01 - INFO ]: Core dump 0 generated : progxyz_time_2020 - 06 - 24 _03 : 30 : 00.350498
  16. $

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

  1. $ ls - l progxyz_time_2020 - 06 - 24 _03\: 30 \: 00.350498
  2. - rw - r -- r --. 1 root root 356848 Jun 24 03 : 30 progxyz_time_2020 - 06 - 24 _03 : 30 : 00.350498
  3. $
  4. $ file progxyz_time_2020 - 06 - 24 _03\: 30 \: 00.350498
  5. 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'
  6. $

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

ダンプファイルが読み込めるかどうかを確認するには、GNUプロジェクトデバッガ( gdb )を起動します。スタック上のすべての関数名を確認できるように、テストバイナリへのパスを指定することを忘れないでください。ここで、 bt (バックトラック)は、ダンプがキャプチャされたときにsleep()関数が実行されていたことを示しています。

  1. $ gdb - q ./ progxyz ./ progxyz_time_2020 - 06 - 24 _03\: 30 \: 00.350498
  2. Reading symbols from ./ progxyz ...( no debugging symbols found )... done .
  3. [ New LWP 350498 ]
  4. Core was generated by `./progxyz'.
  5. #0 0x00007fb6947e9208 in nanosleep () from /lib64/libc.so.6
  6. Missing separate debuginfos, use: yum debuginfo-install glibc-2.28-101.el8.x86_64
  7. (gdb) bt
  8. #0 0x00007fb6947e9208 in nanosleep () from /lib64/libc.so.6
  9. #1 0x00007fb6947e913e in sleep () from /lib64/libc.so.6
  10. #2 0x00000000004005f3 in main ()
  11. (gdb)

gcoreはどうですか?

Linuxユーザーは、Linuxにはすでにgcoreというコマンドがあり、ほとんどのLinuxディストリビューションで利用可能で、`ProcDump`と全く同じ機能を実行することをすぐに指摘するでしょう。その通りです。もしまだ使ったことがないなら、 gcoreを使ってプロセスのコアをダンプしてみてください。テストプログラムを再度実行し、PIDを引数としてgcoreを実行してください。

  1. $ ./ progxyz &
  2. [ 1 ] 350664
  3. $
  4. $
  5. $ pgrep progxyz
  6. 350664
  7. $
  8. $
  9. $ gcore 350664
  10. 0x00007fefd3be2208 in nanosleep () from / lib64 / libc . so . 6
  11. Saved corefile core . 350664
  12. [ Inferior 1 ( process 350664 ) detached ]
  13. $

gcore 、コアファイルを特定のファイルに保存したというメッセージを出力します。現在のディレクトリを確認し、コアファイルを見つけて、 gdbを使用して再度ロードしてください。

  1. $
  2. $ ls - l core . 350664
  3. - rw - r -- r --. 1 root root 356848 Jun 24 03 : 34 core . 350664
  4. $
  5. $
  6. $ file core . 350664
  7. 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'
  8. $
  9. $ gdb - q ./ progxyz ./ core . 350664
  10. Reading symbols from ./ progxyz ...( no debugging symbols found )... done .
  11. [ New LWP 350664 ]
  12. Core was generated by `./progxyz'.
  13. #0 0x00007fefd3be2208 in nanosleep () from /lib64/libc.so.6
  14. Missing separate debuginfos, use: yum debuginfo-install glibc-2.28-101.el8.x86_64
  15. (gdb) bt
  16. #0 0x00007fefd3be2208 in nanosleep () from /lib64/libc.so.6
  17. #1 0x00007fefd3be213e in sleep () from /lib64/libc.so.6
  18. #2 0x00000000004005f3 in main ()
  19. (gdb) q
  20. $

gcoreを動作させるには、以下の設定が適切であることを確認する必要があります。まず、カーネルファイルにulimitが設定されていることを確認してください。ulimit が0に設定されていると、カーネルファイルは生成されません。次に、 /proc/sys/kernel/core_patternカーネルモードを指定するための正しい設定がされていることを確認してください。

  1. $ ulimit - c
  2. unlimited
  3. $

ProcDump と gcore のどちらを使うべきでしょうか?

gcore よりも ProcDump を使用する方が適している状況はいくつかあります。ProcDump には、特定の状況で役立つ組み込み機能がいくつかあります。

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

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

仕組みは以下のとおりです。この例では、 progxyzというプロセスは実行されていません。

  1. $ pgrep progxyz
  2. $

procdump -wパラメータ付きで呼び出して待機させます。別のターミナルでテストバイナリprogxyzを呼び出します。

  1. $ procdump - w progxyz
  2. ProcDump v1 . 1.1 - Sysinternals process dump utility
  3. Copyright ( C ) 2020 Microsoft Corporation . All rights reserved . Licensed under the MIT license .
  4. Mark Russinovich , Mario Hewardt , John Salem , Javid Habibi
  5. Monitors a process and writes a dump file when the process exceeds the
  6. specified criteria .
  7. Process : progxyz ( pending )
  8. CPU Threshold : n / a
  9. Commit Threshold : n / a
  10. Polling interval ( ms ):   1000
  11. Threshold ( s ):   10
  12. Number of Dumps :         1
  13. Press Ctrl - C to end monitoring without terminating the process .
  14. [ 03 : 39 : 23 - INFO ]: Waiting for process 'progxyz' to launch ...

次に、別のターミナルからテストバイナリprogxyz呼び出します。

  1. $ ./ progxyz &
  2. [ 1 ] 350951
  3. $

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

  1. [ 03 : 39 : 23 - INFO ]: Waiting for process 'progxyz' to launch ...
  2. [ 03 : 43 : 22 - INFO ]: Found process with PID 350951
  3. [ 03 : 43 : 22 - INFO ]: Timed :
  4. [ 03 : 43 : 23 - INFO ]: Core dump 0 generated : progxyz_time_2020 - 06 - 24 _03 : 43 : 22.350951
  5. $
  6. $ ls - l progxyz_time_2020 - 06 - 24 _03\: 43 \: 22.350951
  7. - rw - r -- r --. 1 root root 356848 Jun 24 03 : 43 progxyz_time_2020 - 06 - 24 _03 : 43 : 22.350951
  8. $
  9. $ file progxyz_time_2020 - 06 - 24 _03\: 43 \: 22.350951
  10. 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'
  11. $

複数のコアダンプ

ProcDumpのもう一つの重要な機能は、コマンドライン引数-n <count> 」を使用して、生成するコアファイルの数を指定できることです。コアダンプのデフォルトの時間間隔は10秒ですが、 -s <sec>パラメータを使用して変更できます。この例では、ProcDumpを使用してテストバイナリで3つのコアダンプを実行します。

  1. $ ./ progxyz &
  2. [ 1 ] 351014
  3. $
  4. $ procdump - n 3 - p 351014
  5. ProcDump v1 . 1.1 - Sysinternals process dump utility
  6. Copyright ( C ) 2020 Microsoft Corporation . All rights reserved . Licensed under the MIT license .
  7. Mark Russinovich , Mario Hewardt , John Salem , Javid Habibi
  8. Monitors a process and writes a dump file when the process exceeds the
  9. specified criteria .
  10. Process : progxyz ( 351014 )
  11. CPU Threshold : n / a
  12. Commit Threshold : n / a
  13. Polling interval ( ms ):   1000
  14. Threshold ( s ):   10
  15. Number of Dumps :         3
  16. Press Ctrl - C to end monitoring without terminating the process .
  17. [ 03 : 45 : 20 - INFO ]: Timed :
  18. [ 03 : 45 : 21 - INFO ]: Core dump 0 generated : progxyz_time_2020 - 06 - 24 _03 : 45 : 20.351014
  19. [ 03 : 45 : 31 - INFO ]: Timed :
  20. [ 03 : 45 : 32 - INFO ]: Core dump 1 generated : progxyz_time_2020 - 06 - 24 _03 : 45 : 31.351014
  21. [ 03 : 45 : 42 - INFO ]: Timed :
  22. [ 03 : 45 : 44 - INFO ]: Core dump 2 generated : progxyz_time_2020 - 06 - 24 _03 : 45 : 42.351014
  23. $
  24. $ ls - l progxyz_time_2020 - 06 - 24 _03\: 45 \: *
  25. - rw - r -- r --. 1 root root 356848 Jun 24 03 : 45 progxyz_time_2020 - 06 - 24 _03 : 45 : 20.351014
  26. - rw - r -- r --. 1 root root 356848 Jun 24 03 : 45 progxyz_time_2020 - 06 - 24 _03 : 45 : 31.351014
  27. - rw - r -- r --. 1 root root 356848 Jun 24 03 : 45 progxyz_time_2020 - 06 - 24 _03 : 45 : 42.351014
  28. $

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 を要求できます。

  1. procdump - C 70 - n 3 - p 351014

結論は

ProcDumpは、Linuxに移植されたWindowsプログラムの長いリストに加わった興味深いツールです。Linuxユーザーに新たなツールオプションを提供するだけでなく、WindowsユーザーにとってLinuxでの作業をより身近なものにしてくれます。