Linuxプロセスのメモリをファイルにダンプします


52

プロセスに割り当てられた現在のメモリを(PIDで)ファイルにダンプすることはできますか?それとも何とか読む?



1
superuser.com/questions/236390/…を読んで、代わりにgcoreを使用することもできます
サイモンA.エグスター14

回答:


46

これを繰り返し行わずにすべてのメモリをファイルにダンプする方法はわかりません(gdbにこれを行う自動化された方法を知っている人がいる場合はお知らせください) PID:

$ cat /proc/[pid]/maps

これは次の形式になります(例)。

00400000-00421000 r-xp 00000000 08:01 592398                             /usr/libexec/dovecot/pop3-login
00621000-00622000 rw-p 00021000 08:01 592398                             /usr/libexec/dovecot/pop3-login
00622000-0066a000 rw-p 00622000 00:00 0                                  [heap]
3e73200000-3e7321c000 r-xp 00000000 08:01 229378                         /lib64/ld-2.5.so
3e7341b000-3e7341c000 r--p 0001b000 08:01 229378                         /lib64/ld-2.5.so

メモリのバッチを1つ選択し(たとえば00621000-00622000)、gdbをルートとして使用してプロセスにアタッチし、そのメモリをダンプします。

$ gdb --pid [pid]
(gdb) dump memory /root/output 0x00621000 0x00622000

次に、文字列コマンドで/ root / outputを分析します。画面全体にPuTTYが必要な場合は少なくなります。


1
gdbなしでbash / shだけでこれを行う方法はありますか?
Programming4life

3
@ Programming4life のgcore(1)
ジュリアン

51

このタスクを実行するスクリプトを作成しました。

アイデアはジェームズ・ローリーの答えとこの投稿から来ていますhttp : //www.linuxforums.org/forum/programming-scripting/52375-reading-memory-other-processes.html#post287195

#!/bin/bash

grep rw-p /proc/$1/maps \
| sed -n 's/^\([0-9a-f]*\)-\([0-9a-f]*\) .*$/\1 \2/p' \
| while read start stop; do \
    gdb --batch --pid $1 -ex \
        "dump memory $1-$start-$stop.dump 0x$start 0x$stop"; \
done

これをファイル(例: "dump-all-memory-of-pid.sh")に入れて実行可能にします

使用法: ./dump-all-memory-of-pid.sh [pid]

出力は、次の名前のファイルに出力されます。 pid-startaddress-stopaddress.dump

依存関係: gdb


2
驚くばかり!それを使用して、謎のbashインスタンスが実行されているスクリプトを検出しました。
トビア

なぜあなたはパーミッションで範囲をgrepしてダンプするだけなのrw-pですか?
mxmlnkn

@mxmlnknそれはデータrw-pr-xp)です。他の範囲はコード()です。両方のダンプが必要な場合はgrep、たとえばに交換してくださいcat
A.ニルソン

39

試してみる

    gcore $pid

$pidpidの実際の番号はどこですか。詳細については、以下を参照してください。info gcore

ダンプが発生するまでに時間がかかることがあり、一部のメモリは読み取り可能ではないかもしれませんが、十分です...大きなファイルを作成できることに注意してください、私はちょうど2GBのファイルをそのように作成しました。


1
されたgcoreスパースファイルをダンプ?
CMCDragonkai

3

man procのコメント:

/ proc / [pid] / memこのファイルは、open(2)、read(2)、およびlseek(2)を介してプロセスのメモリのページにアクセスするために使用できます。

たぶんそれはあなたを助けることができる


1
それだけでは不十分です。別のプロセスを読み込むには、/ proc / <pid> / {mem、* maps}、ptrace、およびターゲットプロセスのハングを回避するためのシグナル処理の組み合わせが必要です。
東武


3

プロセスメモリ全体もダンプする独自のプログラムを作成しました。これはCであるため、Androidにクロスコンパイルできます。これが必要なことです。

IPアドレスとTCPポートを指定することもできます。ソースコードはこちら


2

純粋なbashソリューション:

procdump () 
{ 
    cat /proc/$1/maps | grep "rw-p" | awk '{print $1}' | ( IFS="-"
    while read a b; do
        count=$(( bd-ad ))
        ad=$(printf "%llu" "0x$a")
        bd=$(printf "%llu" "0x$b")
        dd if=/proc/$1/mem bs=1 skip=$ad count=$count of=$1_mem_$a.bin
    done )
}

使用法:procdump PID

よりクリーンなダンプの場合:

procdump () 
{ 
    cat /proc/$1/maps | grep -Fv ".so" | grep " 0 " | awk '{print $1}' | ( IFS="-"
    while read a b; do
        ad=$(printf "%llu" "0x$a")
        bd=$(printf "%llu" "0x$b")
        dd if=/proc/$1/mem bs=1 skip=$ad count=$(( bd-ad )) of=$1_mem_$a.bin
    done )
}

だから、私が理解していることから、クリーナーダンプの背後にある考え方は、サイズが0である実際のアプリケーションメモリとは対照的に、インメモリファイルのみがメモリ領域にサイズを持っているということです(実際に使用されているサイズはOS)。
mxmlnkn

このスクリプトでの問題の1つは、ブロックサイズが1であるために、ページサイズ(私にとっては4096)に等しいブロックサイズを使用する場合と比較して、許容できないほど低速の〜30kB / sの帯域幅になることです!こちらをご覧くださいgetconf PAGESIZEは、ページサイズを取得するために使用され、アドレスとカウントはそれによって分割されます。
mxmlnkn

1

プロセスを標準出力pcat / memdumpにダンプするツール:


これは廃止されました(メンテナの要求により削除されます)。とにかく古いパッケージをインストールしましたが、「入出力エラー。別のマシンのヘッダーファイルでGCCを使用しましたか?」で失敗しました。
東武


0

巨大なコアファイルを作成せずに(たとえばgcoreを使用して)実行中のプロセスの個別のメモリセグメントをダンプする場合は、ここから小さなツールを使用できます。すべての読み取り可能なセグメントを個別のファイルにダンプする場合は、READMEに1行のライナーもあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.