फाइल करने के लिए एक linux प्रोसेस की मेमोरी डंप करें


52

क्या किसी फ़ाइल के लिए (PID द्वारा) प्रक्रिया के लिए आवंटित वर्तमान मेमोरी को डंप करना संभव है? या इसे किसी तरह पढ़ा?



1
तुम भी पढ़ने के लिए चाहते हो सकता है superuser.com/questions/236390/... और बदले gcore का उपयोग करें।
साइमन ए। यूगस्टर

जवाबों:


46

मुझे यकीन नहीं है कि आप बार-बार ऐसा किए बिना किसी फ़ाइल को सभी मेमोरी कैसे डंप करते हैं (अगर किसी को पता है कि यह करने के लिए gdb प्राप्त करने के लिए एक स्वचालित तरीका है, तो कृपया मुझे बताएं), लेकिन निम्नलिखित में से किसी एक मेमोरी के बैच के लिए काम करता है जिसे आप जानते हैं पिड:

$ 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

फिर स्ट्रिंग्स कमांड के साथ विश्लेषण / रूट / आउटपुट, कम आप अपनी स्क्रीन पर PuTTY चाहते हैं।


1
क्या बिना gdb के सिर्फ bash / sh में ऐसा करने का कोई तरीका है?
प्रोग्रामिंग 4

3
@ Programming4life gcore (1)
julian

51

मैंने एक स्क्रिप्ट बनाई है जो इस कार्य को पूरा करती है।

यह विचार जेम्स लॉरी के उत्तर और इस पोस्ट से आता है: 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

इसे एक फ़ाइल में डालें (उदाहरण के लिए। "dip-all-memory-of-pid.sh") और इसे क्रियान्वित करें

उपयोग: ./dump-all-memory-of-pid.sh [pid]

आउटपुट नामों के साथ फाइल में प्रिंट किया गया है: pid-startaddress-stopaddress.dump

निर्भरता: gdb


2
बहुत बढ़िया! बस इसका उपयोग यह पता लगाने के लिए किया गया था कि कौन सी स्क्रिप्ट एक रहस्यमय बैश उदाहरण चल रही थी।
टोबिया

आप केवल rw-pअनुमतियों के लिए रेंजिंग और डंपिंग क्यों कर रहे हैं ?
mxmlnkn

@mxmlnkn यह डेटा ( rw-p) है, अन्य श्रेणियां कोड ( r-xp) के लिए हैं। यदि आप दोनों को डंप करना चाहते हैं, तो आगे बढ़ें और grepउदाहरण के लिए विनिमय करें cat
ए। निल्सन

39

प्रयत्न, कोशिश

    gcore $pid

जहां $pidपिड की वास्तविक संख्या है; अधिक जानकारी के लिए देखें:info gcore

डंप होने के लिए कुछ समय लग सकता है, और कुछ मेमोरी पढ़ने योग्य नहीं हो सकती है, लेकिन यह काफी अच्छा है ... इस बात से भी अवगत रहें कि यह बड़ी फाइल बना सकती है, मैंने अभी एक 2GB फाइल बनाई है जिस तरह से ।।


1
है gcoreस्पार्स फ़ाइल डंपिंग?
CMCDragonkai

3

आदमी खरीद कहते हैं:

/ proc / [pid] / mem इस फ़ाइल को ओपन (2), रीड (2), और लेसेक (2) के माध्यम से प्रक्रिया की मेमोरी के पेज तक पहुँचने के लिए उपयोग किया जा सकता है।

शायद यह आपकी मदद कर सके


1
यह पर्याप्त नहीं है, एक अन्य प्रक्रिया को पढ़ने के लिए / proc / <pid> / {mem, * map}, ptrace, और लक्ष्य प्रक्रिया को लटकाने से बचने के लिए कुछ सिग्नल हैंडलिंग के संयोजन की आवश्यकता है।
तोबू


3

मैंने पूरी प्रक्रिया मेमोरी को डंप करने के लिए अपना खुद का प्रोग्राम बनाया, यह सी में है इसलिए इसे एंड्रॉइड पर क्रॉस-संकलित किया जा सकता है, जिसे इसकी आवश्यकता है।

आप आईपी पता और टीसीपी पोर्ट भी निर्दिष्ट कर सकते हैं। स्रोत कोड यहाँ


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

उपयोग: procdump पीआईडी

एक क्लीनर डंप के लिए:

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 का नाकाबंदी अस्वीकार्य धीमी गति से बैंडविड्थ की ओर जाता है ~ 30kB / s पृष्ठ आकार (मेरे लिए 4096) के बराबर एक अवरोधक का उपयोग करने की तुलना में जिसके लिए मुझे ~ 100MB / s मिलता है! देखें यहाँgetconf PAGESIZEका उपयोग पृष्ठ का आकार प्राप्त करने के लिए किया जाता है और फिर इसके द्वारा पते और गणना को विभाजित किया जाता है।
mxmlnkn

1

मानक आउटपुट, पीसीएटी / मेमडंप में प्रक्रिया को डंप करने का उपकरण:


यह अप्रचलित है (अनुरक्षक के अनुरोध पर हटा दिया गया है); मैंने वैसे भी पुराने पैकेज को स्थापित किया और यह "इनपुट / आउटपुट त्रुटि के साथ विफल रहा? क्या आपने किसी अन्य मशीन की हेडर फ़ाइलों के साथ जीसीसी का उपयोग किया?"।
तोबू


0

यदि आप विशाल कोर फ़ाइल (गर्क के साथ कहना) के बिना चल रही प्रक्रिया के एक अलग मेमोरी सेगमेंट को डंप करना चाहते हैं, तो आप यहां से एक छोटे टूल का उपयोग कर सकते हैं । README में एक-लाइनर भी है यदि आप सभी पठनीय खंडों को अलग-अलग फाइलों में डंप करना चाहते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.