Kết xuất bộ nhớ của quy trình linux vào tập tin


52

Có thể kết xuất bộ nhớ hiện tại được phân bổ cho một quá trình (bởi PID) vào một tệp không? Hoặc đọc nó bằng cách nào đó?


Bạn có thể sử dụng kịch bản bằng chứng của tôi để đọc /proc/$pid/mem.
Gilles 'SO- ngừng trở nên xấu xa'

1
Bạn cũng có thể muốn đọc superuser.com/questions/236390/ và thay vào đó sử dụng gcore.
Simon A. Eugster

Câu trả lời:


46

Tôi không chắc chắn làm thế nào bạn đổ tất cả bộ nhớ vào một tệp mà không làm điều này nhiều lần (nếu có ai biết cách tự động để có gdb để làm điều này xin vui lòng cho tôi biết), nhưng cách sau đây hoạt động cho bất kỳ một bộ nhớ nào giả sử bạn biết pid:

$ cat /proc/[pid]/maps

Điều này sẽ ở định dạng (ví dụ):

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

Chọn một lô bộ nhớ (ví dụ 00621000-00622000), sau đó sử dụng gdb làm gốc để đính kèm vào quy trình và kết xuất bộ nhớ đó:

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

Sau đó phân tích / root / output bằng lệnh chuỗi, bạn không muốn PuTTY trên màn hình của mình.


1
Có cách nào để làm điều này chỉ trong bash / sh mà không có gdb không?
Lập


51

Tôi đã tạo ra một kịch bản hoàn thành nhiệm vụ này.

Ý tưởng bắt nguồn từ câu trả lời của James Lawrie và bài đăng này: 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

đặt cái này vào một tập tin (ví dụ: "dump-all-memory-of-pid.sh") và làm cho nó có thể thực thi được

sử dụng: ./dump-all-memory-of-pid.sh [pid]

Đầu ra được in ra các tệp có tên: pid-startaddress-stopaddress.dump

Phụ thuộc: gdb


2
Tuyệt vời! Chỉ cần sử dụng nó để khám phá tập lệnh bash bí ẩn nào đang chạy.
Tobia

Tại sao bạn chỉ grepping cho và đổ phạm vi với rw-pquyền?
mxmlnkn

@mxmlnkn Đó là dữ liệu ( rw-p), các phạm vi khác dành cho mã ( r-xp). Nếu bạn muốn một bãi rác của cả hai, sau đó tiếp tục và trao đổi grepví dụ cat.
A. Nilsson

39

thử

    gcore $pid

nơi $pidlà con số thực tế của pid; để biết thêm thông tin xem:info gcore

có thể mất một chút thời gian để kết xuất xảy ra và một số bộ nhớ có thể không đọc được, nhưng đủ tốt ... hãy lưu ý rằng nó có thể tạo các tệp lớn, tôi chỉ tạo một tệp 2GB theo cách đó ..


1
gcorebán phá giá một tập tin thưa thớt?
CMCDragonkai

3

người đàn ông nói:

/ Proc / [pid] / mem Tập tin này có thể được sử dụng để truy cập các trang của bộ nhớ của quá trình thông qua mở (2), đọc (2) và lseek (2).

Có lẽ nó có thể giúp bạn


1
Điều đó là không đủ, đọc một quy trình khác cần kết hợp / Proc / <pid> / {mem, * maps}, ptrace và một số xử lý tín hiệu để tránh treo quá trình đích.
Tobu


3

Tôi cũng đã tạo chương trình của riêng mình để kết xuất toàn bộ bộ nhớ tiến trình, nó ở C để nó có thể được biên dịch chéo sang Android, đây là điều tôi cần.

Bạn cũng có thể chỉ định địa chỉ IP và cổng tcp. Mã nguồn ở đây .


2

Dung dịch bash nguyên chất:

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 )
}

Cách sử dụng: procdump PID

cho một bãi chứa sạch hơn:

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 )
}

Vì vậy, theo những gì tôi hiểu, ý tưởng đằng sau kết xuất sạch hơn là chỉ các tệp trong bộ nhớ có kích thước được gắn vào vùng nhớ trái ngược với bộ nhớ ứng dụng thực tế, có kích thước 0 (vì kích thước thực sự được sử dụng là không xác định HĐH).
mxmlnkn

Một vấn đề tôi gặp phải với tập lệnh này là kích thước khối 1 dẫn đến băng thông chậm không thể chấp nhận ~ 30kB / giây so với sử dụng kích thước khối bằng với kích thước trang (4096 đối với tôi) mà tôi nhận được ~ 100MB / s! Xem tại đây . getconf PAGESIZEđược sử dụng để có được kích thước trang và sau đó các địa chỉ và số lượng được chia cho nó.
mxmlnkn

1

Công cụ kết xuất quá trình thành đầu ra tiêu chuẩn, pcat / memdump:


Cái này đã lỗi thời (loại bỏ theo yêu cầu của người bảo trì); Dù sao tôi cũng đã cài đặt gói cũ và nó không thành công với "Lỗi đầu vào / đầu ra; bạn có sử dụng GCC với các tệp tiêu đề của máy khác không?".
Tobu


0

Nếu bạn muốn kết xuất một phân đoạn bộ nhớ riêng của quá trình đang chạy mà không tạo tệp lõi lớn (nói với gcore), bạn có thể sử dụng một công cụ nhỏ từ đây . Ngoài ra còn có một lớp lót trong README nếu bạn muốn kết xuất tất cả các phân đoạn có thể đọc được thành các tệp riêng biệt.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.