将linux进程的内存转储到文件


Answers:


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

选择一批内存(例如00621000-00622000),然后使用gdb作为root附加到进程并转储该内存:

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

然后,使用strings命令分析/ root / output,从而减少整个屏幕上的PuTTY。


1
有没有办法在没有gdb的bash / sh中做到这一点?
Programming4life

3
@ Programming4life gcore(1)
julian

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实例正在运行哪个脚本。
托比亚

为什么只在rw-p权限范围内查找和丢弃范围?
mxmlnkn

@mxmlnkn这是数据(rw-p),其他范围用于代码(r-xp)。如果您想两者都转储,则继续grep进行例如的交换cat
尼尔森

39

尝试

    gcore $pid

$pidpid的实际编号在哪里;有关更多信息,请参见:info gcore

可能需要一些时间才能进行转储,并且某些内存可能不可读,但是足够好...还要注意,它可以创建大文件,我只是这样创建了一个2GB的文件。


1
正在gcore转储稀疏文件吗?
CMCDragonkai '16


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(因为实际使用的大小未知)操作系统)。
mxmlnkn

我与该脚本有关的一个问题是,与使用等于页面大小(对于我而言为4096)的块大小(对于我而言为〜100MB / s)相比,将块大小为1导致的带宽达到令人无法接受的慢〜30kB / s!看这里getconf PAGESIZE用于获取页面大小,然后将地址和计数除以它。
mxmlnkn



0

如果要转储正在运行的进程的单独内存段而不创建巨大的核心文件(例如使用gcore),则可以从此处使用一个小工具。如果您希望将所有可读段都转储到单独的文件中,则自述文件中也有一个衬里。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.