Dump della memoria di un processo linux su file


Risposte:


46

Non sono sicuro di come scaricare tutta la memoria su un file senza farlo ripetutamente (se qualcuno conosce un modo automatizzato per fare in modo che gdb lo faccia, per favore fatemelo sapere), ma quanto segue funziona per ogni singolo lotto di memoria supponendo che lo sappiate il pid:

$ cat /proc/[pid]/maps

Questo sarà nel formato (esempio):

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

Scegli un batch di memoria (quindi ad esempio 00621000-00622000) quindi usa gdb come root per collegarti al processo e scaricare quella memoria:

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

Quindi analizza / root / output con il comando stringhe, meno vuoi PuTTY su tutto lo schermo.


1
C'è un modo per farlo in solo bash / sh senza gdb?
Programming4life

3
@ Programming4life gcore (1)
giuliano

51

Ho realizzato una sceneggiatura che compie questo compito.

L'idea nasce dalla risposta di James Lawrie e da questo post: 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

mettilo in un file (es. "dump-all-memory-of-pid.sh") e rendilo eseguibile

utilizzo: ./dump-all-memory-of-pid.sh [pid]

L'output viene stampato su file con i nomi: pid-startaddress-stopaddress.dump

dipendenze: gdb


2
Eccezionale! L'ho usato solo per scoprire quale script era in esecuzione una misteriosa istanza bash.
Tobia,

Perché stai solo cercando e scaricando intervalli con rw-pautorizzazioni?
mxmlnkn,

@mxmlnkn Questo è data ( rw-p), gli altri intervalli sono per code ( r-xp). Se vuoi una discarica di entrambi, vai avanti e scambia grepper es cat.
A. Nilsson,

39

provare

    gcore $pid

dove $pidè il numero effettivo del pid; per maggiori informazioni vedi:info gcore

potrebbe volerci un po 'di tempo prima che si verifichi il dump e un po' di memoria potrebbe non essere leggibile, ma è abbastanza buona ... attenzione anche che può creare file di grandi dimensioni, ho appena creato un file da 2 GB in quel modo ..


1
Il gcoredumping è un file sparso?
CMCDragonkai,

3

man proc dice:

/ proc / [pid] / mem Questo file può essere utilizzato per accedere alle pagine della memoria di un processo tramite open (2), read (2) e lseek (2).

Forse ti può aiutare


1
Ciò non è sufficiente, la lettura di un altro processo richiede una combinazione di / proc / <pid> / {mem, * maps}, ptrace e una certa gestione del segnale per evitare di bloccare il processo di destinazione.
Tobu

@Tobu Infatti . Ho scritto una sceneggiatura di prova .
Gilles 'SO- smetti di essere malvagio' il

3

Ho creato il mio programma per scaricare anche l'intera memoria di processo, è in C, quindi può essere compilata su Android, che è ciò di cui avevo bisogno.

È inoltre possibile specificare l'indirizzo IP e la porta tcp. Codice sorgente qui .


2

Soluzione bash pura:

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

Utilizzo: procdump PID

per una discarica più pulita:

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

Quindi, da quello che ho capito, l'idea alla base del dump più pulito è che solo i file in memoria hanno una dimensione collegata alla regione di memoria in contrasto con la memoria effettiva dell'applicazione, che ha dimensione 0 (poiché la dimensione effettivamente utilizzata è sconosciuta al OS).
mxmlnkn,

Un problema che ho con questo script è che la dimensione a blocchi di 1 porta a una larghezza di banda di ~ 30kB / s inaccettabilmente lenta rispetto all'utilizzo di una dimensione a blocchi pari alla dimensione della pagina (4096 per me) per la quale ottengo ~ 100 MB / s! Vedi qui . getconf PAGESIZEviene utilizzato per ottenere le dimensioni della pagina e quindi gli indirizzi e i conteggi vengono divisi per essa.
mxmlnkn,



0

Se vuoi scaricare un segmento di memoria separato del processo in esecuzione senza creare un enorme file core (diciamo con gcore), puoi usare un piccolo strumento da qui . C'è anche una riga in README se desideri scaricare tutti i segmenti leggibili in file separati.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.