Вивантажте пам'ять процесу Linux


52

Чи можна скинути в файл поточну пам'ять, виділену для процесу (PID)? Або читати якось?


Ви можете використовувати мій сценарій перевірки концепції, який читається /proc/$pid/mem.
Жил 'ТАК - перестань бути злим'

1
Ви також можете прочитати superuser.com/questions/236390/… і використовувати натомість gcore.
Саймон А. Югстер

Відповіді:


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 як корінь для приєднання до процесу та скидання цієї пам'яті:

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

Потім проаналізуйте / root / output за допомогою команди рядків, менше, ніж вам потрібно PuTTY на всьому екрані.


1
Чи є спосіб зробити це просто в bash / sh без gdb?
Programming4life

3
@ Programming4life gcore (1)
липень

51

Я зробив сценарій, який виконує це завдання.

Ідея походить від відповіді Джеймса Лоурі і цього повідомлення: http://www.linuxforums.org/forum/programming-scripting/52375-reading-memory-other-process.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.
Tobia

Чому ви лише захоплюєтесь та скидаєте діапазони з rw-pдозволами?
mxmlnkn

@mxmlnkn Це дані ( rw-p), інші діапазони - для коду ( r-xp). Якщо ви хочете скинути обидва, тоді продовжуйте обмін grepна напр cat.
А. Нільссон

39

спробуйте

    gcore $pid

де $pidфактична кількість піда; для отримання додаткової інформації див:info gcore

це може зайняти деякий час, щоб дамп трапився, і деяка пам'ять може бути нечитабельною, але досить хороша ... пам'ятайте також, що вона може створювати великі файли, я просто створив файл 2 Гб таким чином ..


1
Чи gcoreзберігається розріджений файл?
CMCDragonkai

3

man proc каже:

/ proc / [pid] / mem Цей файл можна використовувати для доступу до сторінок пам'яті процесу через open (2), read (2) та lseek (2).

Можливо, це може вам допомогти


1
Це недостатньо, для читання іншого процесу потрібна комбінація / proc / <pid> / {mem, * maps}, ptrace та деякої обробки сигналів, щоб уникнути вивішування цільового процесу.
Тобу


3

Я створив власну програму для скидання всієї пам’яті процесів, вона знаходиться в C, щоб її можна було перекомпілювати на Android, і це те, що мені потрібно.

Ви також можете вказати IP-адресу та порт tcp. Вихідний код тут .


2

Чистий розчин башмаку:

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

Використання: продати 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

Одне з проблем із цим сценарієм полягає в тому, що розмір блоку 1 призводить до пропускної здатності неприпустимо повільного ~ 30 кБ / с порівняно з використанням блочного розміру, рівного розміру сторінки (4096 для мене), за який я отримую ~ 100 Мб / с! Дивіться тут . getconf PAGESIZEвикористовується для отримання розміру сторінки, а потім адреси та підрахунки поділяються на неї.
mxmlnkn

1

Інструмент для скидання процесу до стандартного виводу, pcat / memdump:


Ця застаріла (видаляється на вимогу технічного обслуговування); Я встановив старий пакет в будь-якому випадку, і він не вдався до "Помилка вводу / виводу; ти використовував GCC з файлами заголовка іншої машини?".
Тобу


0

Якщо ви хочете скинути окремий сегмент пам'яті запущеного процесу , не створюючи величезний файл ядра (скажімо , з gcore), ви можете використовувати невеликий інструмент з тут . У README також є однолінійний шрифт, якщо ви хочете скинути всі читані сегменти в окремі файли.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.