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 ?
Génial ! Je viens de l'utiliser pour découvrir quel script une mystérieuse instance de bash exécutait.
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 ?
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
Génial ! Je viens de l'utiliser pour découvrir quel script une mystérieuse instance de bash exécutait.
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.
Essayez
gcore $pid
où $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...
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 )
)
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).
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.
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.
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.