Linux 版の Sysinternals ProcDump を試す (1)

先のエントリで書いたように最近は Windows も触っていて 主に Sysinternals ツールを使って Windows 探検をしている

hiboma.hatenadiary.jp

その流れで ProcDump の使い方を調べていた.

f:id:hiboma:20190217165143p:plain

Sysinternals の ProcDump

technet.microsoft.com

Windows 版の詳細は上記のリンクを辿って自分でご覧になって欲しい。その中で、CPU 使用率やメモリ使用量(コミットチャージ) をコアダンプ生成のトリガーにできるのが目に留まった

-c 
    CPU しきい値を指定します。このしきい値に達すると、プロセスのダンプが作成されます。

-m 
    メモリ コミットのしきい値を MB 単位で指定します。このしきい値に達すると、プロセスのダンプが作成されます。

gdb もこんな風に扱えたら便利かな〜??? と思っていたところ、ふと Linux 版の存在があるのを思い出したのだった!

Linux 版 🐧

下記のリポジトリで ProcDump の Linux 版が公開されている

github.com

ディストリビューション向けのパッケージが配布されており、インストールの手順はREADME.md に書かれている

CLI インタフェースを調べる

手順通りに Ubuntu Xenial にインストールして、man を読み何ができるのかをざっと調べる

man(8)                                                                                     procdump manpage                                                                                     man(8)

NAME
       procdump - generate coredumps based off performance triggers.

SYNOPSIS
       procdump [OPTIONS...] TARGET
             -C   CPU threshold at which to create a coredump of the process from 0 to 100 * nCPU
             -c   CPU threshold below which to create a coredump of the process from 0 to 100 * nCPU
             -M   Memory commit threshold in MB at which to create a coredump
             -m   Trigger when memory commit drops below specified MB value
             -n   Number of dumps to write before exiting
             -s   Consecutive seconds before dump is written (default is 10)
         TARGET must be exactly one of these:
             -p   pid of the process

DESCRIPTION
       procdump  is  a  Linux reimagining of the class ProcDump tool from the Sysinternals suite of tools for Windows. Procdump provides a convenient way for Linux developers to create core dumps of
       their application based on performance triggers.

1.0.1                                                                                         12/18/2017                                                                                        man(8)

Linux 版でも CPU使用率 やメモリ使用量をトリガーにしてコアダンプできる。コアダンプを採取する回数を指定できたり、採取の間隔を指定できる

アーキテクチャに依存しないエッセンスとなるオプションだけを実装した感じで、Windows 版よりだいぶ簡素かな?

検証(1): メモリの使用量を閾値にしてコアダンプを採取流 🔍

以下のようなテストプロセスを起動して、ProcDump でコアダンプを採取する

  1. 100MB の仮想メモリmalloc(3) するa
  2. 1 の仮想メモリでマイナーページフォルトを起こす
  3. 1 の仮想メモリを free(3) する
  4. 3秒スリープする
  5. 1-4 を3回繰り返す

さて、上記のプロセスを ProcDump したのを GIF 動画でにした

f:id:hiboma:20190217121748g:plain

コアダンプが合計3回採取されているのがわかるだろうか?

ソース 📖

上記のデモで使ったソースは下記の通り

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void malloc_and_free() { 
    size_t size = 100 * 1024 * 1024;

    char *p = malloc(size);
    if (p == NULL) { 
        perror("failed to malloc");
        exit(1);
    }

    // memset でもええねん
    for (size_t i = 0; i < size; i++)  { 
        p[i] = '@';
    }
   
    sleep(3);
    free(p);
}

int main() { 
    sleep(5);
    malloc_and_free();
    malloc_and_free();
    malloc_and_free();
}

注意: ProcDump の動作を確認するためのコードなので、コアダンプを採取しても面白いことはなにもない

使ってみよう(2): CPU 使用率を閾値にする 🔍

CPU 使用率を監視してダンプを採取する GIF 動画が ProcDump のリポジトリにのっているので、引用として掲載する

f:id:hiboma:20190217121836g:plain

Source: GitHub - Microsoft/ProcDump-for-Linux: A Linux version of the ProcDump Sysinternals tool

採取したコアダンプを調査することで CPU 使用率が高い時のバックトレースを調べていくことができるだろう

ユースケース

網を張って気長に待つようなデバッグに向いてるだろう

長時間実行した際に特定の負荷のパターンでうごくプロセスがいるとして、そのようなケースで作業を半自動化できて便利だろう. ( 例: たまーに CPU時間が10数秒スパイクするプロセスがいて調査したいが、再現するタイミングがよくわからない )

Windows Sysinternals徹底解説 改訂新版』でもそのようなトラブルシューティングの例を出している

まとめ

  • ProcDump を使うと CPU使用率やメモリ使用量をトリガーにしてコアダンプをとれる
  • プロセスのリソースを見張ってトリガーにする単体のコマンドがあれば、コアダンプの採取以外にも使えて便利な気がする
  • コアダンプのサイズは大きくなりがちなので、バックトレースだけ取れたら十分かなという気もする

次回のエントリでは Procump の実装を見ていく