88 votes

Dump de la mémoire d'un processus linux vers un fichier

Est-il possible de vider la mémoire actuelle allouée à un processus (par PID) dans un fichier ? Ou de la lire d'une manière ou d'une autre ?

0 votes

Vous pouvez utiliser mon preuve de concept script qui se lit comme suit /proc/$pid/mem .

2 votes

Vous pouvez également lire superuser.com/questions/236390/ et utiliser gcore à la place.

82voto

A. Nilsson Points 793

J'ai créé un script qui accomplit cette tâche.

L'idée vient de la réponse de James Lawrie et de ce 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

mettez cela dans un fichier (par exemple "dump-all-memory-of-pid.sh") et rendez-le exécutable.

l'usage : ./dump-all-memory-of-pid.sh [pid]

La sortie est imprimée dans des fichiers portant les noms : pid-startaddress-stopaddress.dump

Dépendances : gdb

2 votes

Génial ! Je viens de l'utiliser pour découvrir quel script une mystérieuse instance de bash exécutait.

1 votes

Pourquoi ne cherchez-vous que des plages de dumping avec rw-p des permissions ?

2 votes

@mxmlnkn Ce sont des données ( rw-p ), les autres plages sont pour le code ( r-xp ). Si vous voulez une décharge des deux, alors allez-y et échangez grep par exemple cat .

77voto

James L Points 5835

Je ne suis pas sûr de savoir comment vider toute la mémoire dans un fichier sans le faire de manière répétée (si quelqu'un connaît un moyen automatisé pour que gdb le fasse, merci de me le faire savoir), mais ce qui suit fonctionne pour n'importe quel lot de mémoire en supposant que vous connaissez le pid :

$ cat /proc/[pid]/maps

Ce sera dans le format (exemple) :

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

Choisissez un lot de mémoire (par exemple 00621000-00622000) puis utilisez gdb en tant que root pour vous attacher au processus et vider cette mémoire :

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

Ensuite, analysez /root/output avec la commande strings, à moins que vous ne vouliez que le PuTTY soit partout sur votre écran.

4 votes

Existe-t-il un moyen de faire cela en bash/sh sans gdb ?

3 votes

@Programming4life gcore(1)

0 votes

Donc lire directement /proc/<PID>/mem n'est pas une option ? J'obtiens une erreur de lecture si j'essaie d'ouvrir le 'fichier' dans un éditeur.

54voto

Aquarius Power Points 731

Essayez

    gcore $pid

$pid est le numéro réel du pid ; pour plus d'informations, voir : info gcore

Cela peut prendre un certain temps pour que le dump se produise, et une partie de la mémoire peut ne pas être lisible, mais c'est suffisant... soyez aussi conscient que cela peut créer de gros fichiers, je viens de créer un fichier de 2GB de cette façon...

1 votes

Est gcore vidage d'un fichier épars ?

3 votes

@CMCDragonkai utiliser gcore -a PID

18voto

Zibri Points 281

Solution purement bash :

procdump() 
( 
    cat /proc/$1/maps | grep "rw-p" | awk '{print $1}' | ( IFS="-"
    while read a b; do
        dd if=/proc/$1/mem bs=$( getconf PAGESIZE ) iflag=skip_bytes,count_bytes \
           skip=$(( 0x$a )) count=$(( 0x$b - 0x$a )) of="$1_mem_$a.bin"
    done )
)

Utilisation : procdump PID

pour un filtre de décharge plus propre *.so les bibliothèques partagées mappées en mémoire et les plages de mémoire vides :

procdump()
( 
    cat /proc/$1/maps | grep -Fv ".so" | grep " 0 " | awk '{print $1}' | ( IFS="-"
    while read a b; do
        dd if=/proc/$1/mem bs=$( getconf PAGESIZE ) iflag=skip_bytes,count_bytes \
           skip=$(( 0x$a )) count=$(( 0x$b - 0x$a )) of="$1_mem_$a.bin"
    done )
)

0 votes

Donc, d'après ce que j'ai compris, l'idée derrière le dump plus propre est que seuls les fichiers en mémoire ont une taille attachée à la région de mémoire, contrairement à la mémoire réelle de l'application, qui a une taille 0 (car la taille réellement utilisée est inconnue du système d'exploitation).

2 votes

Un problème que j'ai avec ce script est que la taille de bloc de 1 conduit à une bande passante d'une lenteur inacceptable ~30kB/s par rapport à l'utilisation d'une taille de bloc égale à la taille de la page (4096 pour moi) pour laquelle j'obtiens ~100MB/s ! Voir aquí . getconf PAGESIZE est utilisé pour obtenir la taille de la page, puis les adresses et les comptes sont divisés par celle-ci.

0 votes

@mxmlnkn c'était paresseux de ma part, n'hésitez pas à corriger ma réponse.

5voto

Tal Aloni Points 171

J'ai fait mon propre programme pour vider toute la mémoire du processus, il est en C et peut donc être compilé pour Android, ce qui est ce dont j'avais besoin.

Vous pouvez également spécifier l'adresse IP et le port tcp. Code source aquí .

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X