मुझे कैसे पता चलेगा कि अभी भी dd काम कर रहा है?


147

मैंने ddवह सब उपयोग नहीं किया है, लेकिन अभी तक यह मुझे विफल नहीं हुआ है। अभी, मेरे पास dd12 घंटे से अधिक समय के लिए जा रहा है - मैं डिस्क से वापस आई एक छवि लिख रहा हूं - और मैं थोड़ा चिंतित हो रहा हूं, क्योंकि मैं ddडिस्क से छवि के बारे में सक्षम था 7 घंटे।

मैं मैकबुक पर OSX 10.6.6 चला रहा हूं जिसमें 2.1 जीबी / कोर में 4 जीबी रैम के साथ कोर 2 डुओ है। मैं एक 7200rpm हार्ड ड्राइव (बूट ड्राइव) पर एक .dmg से पढ़ रहा हूं, और मैं एक 7200rpm ड्राइव पर SATA-to-USB कनेक्टर से जुड़ा हुआ लिख रहा हूं। मैंने डिफ़ॉल्ट पर रुकावट को छोड़ दिया, और छवि लगभग 160gb है।

EDIT: और, 14 घंटे के शुद्ध तनाव के ddबाद , पूरी तरह से काम किया। अगली बार, हालांकि, मैं इसे चलाने जा रहा हूं pvऔर इसके साथ ट्रैक करूंगा strace। सभी को आपकी मदद के लिए धन्यवाद।


7
आपके प्रश्न का उत्तर नहीं दे रहा है, लेकिन आपका समय काफी उच्च IMO है। क्या आपने डिफ़ॉल्ट 512 बाइट्स के अलावा dd को बड़ा ब्लॉक आकार देना याद किया? dd ... bs=16Mमेरा सुझाव है, आपकी रैम, डिस्क का आकार और गति।
जूलियानो

मैंने नहीं किया, सिर्फ इसलिए कि मैं इसे सुरक्षित खेलना चाहता था। मैं अगली बार कोशिश करूँगा, हालाँकि। धन्यवाद।
एकजा

मेरे अनुभव में, ddमैक ओएस एक्स पर उस बिंदु को स्थिर करने की प्रवृत्ति है जहां मैं प्रक्रिया को नहीं मार सकता, लेकिन सिस्टम को पुनरारंभ करना होगा। मैं तब लिनक्स वीएम पर काम करने का सहारा लेता हूं।
ssc

जवाबों:


174

आप कमांड ddका उपयोग करके एक निश्चित संकेत भेज सकते हैं killताकि यह इसकी वर्तमान स्थिति को आउटपुट कर सके। संकेत INFOबीएसडी सिस्टम (OSX सहित) और USR1लिनक्स पर है। आपके मामले में:

kill -INFO $PID

आप कमांड के $PIDसाथ प्रक्रिया आईडी ( ऊपर) पा सकते हैं ps; या अधिक सुविधाजनक तरीकों के लिए मैक ओएस एक्स पर pgrep और pkill विकल्प देखें ।

अधिक बस के रूप में, AntoineG अपने जवाब में बताते हैं , आप ctrl-Tइसे INFOसंकेत भेजने के लिए dd चलाने वाले शेल में टाइप कर सकते हैं ।

लिनक्स पर एक उदाहरण के रूप में, आप सभी सक्रिय ddप्रक्रियाओं को इस तरह आउटपुट स्थिति बना सकते हैं :

pkill -USR1 -x dd

अपनी स्थिति का उत्पादन करने के बाद, मैथुन ddजारी रहेगा।


9
ओह, बहुत अच्छा। आप उन लोगों के साथ गठजोड़ कर सकते हैंpkill -USR1 -x dd
माइकल Mrozek

9
@kivetros: बीएसडी सिस्टम पर, आपको INFOसिग्नल भेजने की आवश्यकता है । लिनक्स में SIGINFO नहीं है और USR1इसके बजाय उपयोग करता है ।
गाइल्स

5
SIGUSRx सिग्नल एक मानकीकृत अर्थ होने के विपरीत कार्यक्रमों को करने के लिए है जो वे चाहते हैं। उदाहरण के लिए, SIGWINCH को तब उठाया जाता है जब टर्मिनल ने अपना आकार बदल दिया हो और प्रोग्राम को अपनी स्क्रीन को फिर से तैयार करने की आवश्यकता हो। ऑपरेटिंग सिस्टम SIGUSRx को नहीं भेजता है, इसलिए वे कस्टम उपयोग के लिए उपलब्ध हैं।
लॉरेंस

11
USR1 सिग्नल को जल्द ही भेजने के बाद इसे शुरू किया जाना चाहिए (यानी एक bash स्क्रिप्ट में, आपके शुरू करने के बाद की लाइन) वास्तव में इसे समाप्त कर देगा। बीच-बीच में 0.1 सेकंड की नींद लें और यह अपनी प्रगति को ठीक से करेगा। वैसे, USR1 / INFO का परीक्षण करने के लिए एक बहुत अच्छी dd कमांड है dd if=/dev/zero of=/dev/null। :)
लॉरिट्ज वी। थुलो

11
BTW, सभी "सच्चे" BSD SIGINFO को अग्रभूमि प्रक्रिया समूह में भेजते हैं यदि स्थिति वर्ण (डिफ़ॉल्ट रूप से Ctrl + T) टर्मिनल पर भेजा जाता है। लेकिन मुझे नहीं पता कि यह MacOSX के लिए सही है या नहीं।
Nov२

101

ओएस एक्स (लिनक्स पर कोशिश नहीं की गई) के तहत, आप बस टर्मिनल चलाने में Ctrl+ टाइप कर सकते हैं । यह उसी आउटपुट को प्रिंट करेगा , जैसे सीपीयू उपयोग:Tddkill -INFO $PID

load: 1.40  cmd: dd 34536 uninterruptible 3.49u 64.58s
5020305+0 records in
5020304+0 records out
2570395648 bytes transferred in 4284.349974 secs (599950 bytes/sec)

मुझे इस धागे को पढ़ने के बारे में पता चला, और अपने टर्मिनल में एक नया टैब खोलने की कोशिश कर रहा था, लेकिन + के Tसाथ Ctrl+ मिला रहा था T


1
ओह, ठीक है, तो loadCPU उपयोग है?
पीजे

यह इतना बेहतर समाधान था!
Stephn_R

मैंने लिनक्स पर dd में कोशिश की, यह सिर्फ ^Tटर्मिनल को गूँजता है।
म्वफेरेनली

1
सुनिश्चित करें कि आप मैक टर्मिनल में ctrl + shift + T कर रहे हैं
JBaczuk

26

के लिए dd, आप एक संकेत भेज सकते हैं । फ़ाइल में पढ़ने या लिखने वाले अन्य आदेशों के लिए, आप फ़ाइल के साथ उनकी स्थिति देख सकते हैं lsof

lsof -o -p1234    # where 1234 is the process ID of the command
lsof -o /path/to/file

यदि आप पहले से योजना बनाते हैं, तो डेटा को इसके माध्यम से पाइप करें pv


1
pv आश्चर्यजनक लग रहा है - मैं निश्चित रूप से अगली बार उपयोग करने जा रहा हूं। बहुत बहुत धन्यवाद।
एकजा

1
+1 - pvबस टिकट की तरह दिखता है।
बोहेज

17

एक अधिक सामान्य तरीका यह है iotopकि प्रति प्रोग्राम डिस्क पढ़ने / लिखने की वर्तमान मात्रा प्रदर्शित करता है।

संपादित करें: iotop -oकेवल ऐसे कार्यक्रम दिखाएं जो वर्तमान में I / O संचालन करते हैं ( इस टिप्पणी के लिए धन्यवाद जेसन सी )।


1
यह मेरी पसंदीदा त्वरित जांच विधि है। iotop -oउन प्रक्रियाओं को छिपाएगा जो IO नहीं कर रही हैं और एक नज़र में बताना आसान है कि क्या हो रहा है।
जेसन सी

13

मैं आमतौर straceपर इस तरह की रनिंग प्रक्रिया ( -p $PIDविकल्प के साथ ) को यह देखने के लिए संलग्न करता हूं कि क्या यह सिस्टम कॉल में अवरुद्ध रहता है या यदि यह अभी भी सक्रिय है।

या, यदि आप चल रहे dd को एक संकेत भेजने के बारे में घबराहट महसूस करते हैं, तो यह काम करने के लिए मान्य करने के लिए दूसरा dd शुरू करें।


2
आप वास्तव में कैसे संलग्न होंगे strace? इसके अलावा, मैंने एक ddऔर शुरुआत की और उसमें से एक सुझाव दिया संकेतों को भेजने के लिए, और ... इसने इसे मार दिया।
ईकजा

2
यदि आप चल रही dd प्रक्रिया के pid को जानते हैं, तो बस strace -p <pid> करें। आपको प्रक्रिया द्वारा बुलाए गए सभी सिस्टम कॉल्स का लॉग देखना चाहिए (ज्यादातर पढ़े और लिखें)
philfr

11

अगली बार, आप बस pvशुरुआत से उपयोग कर सकते हैं (यदि यह आपके पैकेज प्रबंधक के माध्यम से उपलब्ध है, तो इसे स्थापित करें)। यह आउटपुट और मॉनिटरिंग प्रगति और गति के लिए इनपुट इनपुट के एकमात्र उद्देश्य के साथ एक उपयोगिता है।

फिर, किसी छवि को किसी ड्राइव पर लिखने के लिए, 4MB ब्लॉक आकार के साथ कहें:

pv -ptearb /path/to/image.bin | dd iflag=fullblock of=/dev/whatever bs=4M

प्रारंभिक बफ़रिंग के अलावा (एक अंतिम सिंक द्वारा ऑफ़सेट, जो ddआप चाहें तो कर सकते हैं), यह आपको एक प्रगति बार, औसत गति, वर्तमान गति और ईटीए दिखाएगा।

iflag=fullblockविकल्प बलों के माध्यम से इनपुट का पूरा ब्लॉक हड़पने डीडी pv, अन्यथा आप ब्लॉक आकार के लिए पाइप की दया पर कर रहे हैं।

दूसरे तरीके से जाने के लिए पढ़ने के लिए dd और लिखने के लिए pv का उपयोग करें, हालाँकि आपको स्पष्ट रूप से आकार निर्दिष्ट करना होगा यदि स्रोत एक ब्लॉक डिवाइस है। 4GB डिवाइस के लिए:

dd if=/dev/whatever bs=4M | pv -ptearb -s 4096m > /path/to/image.bin

आप स्वचालित रूप से आकार भी निर्धारित कर सकते हैं, जैसे कुछ:

dd if=/dev/whatever bs=4M | pv -ptearb -s `blockdev --getsize64 /dev/whatever` > /path/to/image.bin

यह वास्तव में मायने नहीं रखता है कि आप किस क्रम में ddऔर किस क्रम pvमें हैं, यह पूरी तरह से प्रदर्शन से संबंधित है - यदि आप जिस डिवाइस को पढ़ रहे हैं या उससे प्राप्त किया गया है, उस डिवाइस को एक्सेस करने के ddबजाय आपके द्वारा उपयोग किए जाने वाले कुछ विशिष्ट अवरोधों के लिए इष्टतम प्रदर्शन pvहै। तुम भी ddदोनों छोरों पर छड़ी कर सकते हैं यदि आप चाहते हैं, या बिल्कुल नहीं अगर आप परवाह नहीं करते हैं:

pv -ptearb /path/to/image.bin > /dev/whatever
sync


5

ddrescue जैसा चल रहा है वैसा ही आपको आँकड़े देगा।

डेमो: http://www.youtube.com/watch?v=vqq9A01geeA#t=144s


3
यह अगली बार के लिए मददगार हो सकता है, लेकिन यह ओपी को यह समझने में मदद नहीं करेगा कि वर्तमान कमांड जमी है या नहीं।
फ्रांसेस्को तुर्को

4

कभी-कभी आप INFO या USR1 सिग्नल का उपयोग करने में सक्षम नहीं हो सकते हैं क्योंकि ddप्रक्रिया की स्टेडर स्ट्रीम सुलभ नहीं है (जैसे कि टर्मिनल जिसमें इसे निष्पादित किया गया था, पहले से ही बंद था)। इस स्थिति में, एक समाधान निम्नलिखित करना है (फ्रीबीएसडी पर परीक्षण किया गया, लिनक्स पर थोड़ा अलग हो सकता है):

  1. iostatलक्ष्य डिवाइस के औसत लिखने की दर (MB / s) का अनुमान लगाने के लिए उपयोग करें , उदाहरण के लिए:

    iostat -d -w30 ada0

    अपने लक्ष्य डिवाइस का नाम ada0यहां रखें, और एक दो परिणाम देने के लिए एक मिनट प्रतीक्षा करें। "डब्ल्यू" पैरामीटर यह निर्धारित करता है कि नमूनों के बीच कितने सेकंड हैं। इसे बढ़ाने से कम विचरण के साथ एक बेहतर औसत अनुमान मिलेगा, लेकिन आपको लंबे समय तक इंतजार करना होगा।

  2. psयह निर्धारित करने के लिए उपयोग करें कि कब ddसे चल रहा है:

    ps -xo etime,command | grep dd

    रनटाइम के कुल सेकंड प्राप्त करने के लिए इसे सेकंड में बदलें।

  3. कुल हस्तांतरित एमबी प्राप्त करने के लिए औसत लेखन दर से रनटाइम के कुल सेकंड को गुणा करें।
  4. एमबी में डिवाइस का आकार प्राप्त करें:

    grep ada0 /var/run/dmesg.boot

    के लिए अपने लक्ष्य डिवाइस का नाम रखें ada0। सेकंड में कुल अंतरण समय प्राप्त करने के लिए औसत लेखन दर से परिणाम को विभाजित करें। शेष समय पाने के लिए अब तक चल रहे समय को घटाएं।

यह रणनीति केवल तभी काम करती है ddजब यह चालू औसत लेखन दर पर लगातार लिख रहा हो। यदि अन्य प्रक्रियाएं CPU या I / O संसाधनों (I / O बस सहित) के लिए प्रतिस्पर्धा कर रही हैं तो यह हस्तांतरण दर को कम कर सकती हैं।


4

मैंने dcfldd (1) का उपयोग करना शुरू कर दिया, जो बेहतर तरीके से dd संचालन दिखाता है।


2

ddनिष्पादित करते समय, मैं इसे रूट के रूप में किसी अन्य टर्मिनल में चलाता हूं:

while pgrep ^dd; do pkill -INFO dd; sleep 1; done

यह मूल टर्मिनल विंडो मेंdd हर 1 सेकंड की स्थिति को प्रिंट करता है, जहां कमांड निष्पादित होता है, और जब कमांड किया जाता है, तो वह क्विट करता है।dd


इतना ठंडा। एल कैपिटान के तहत यहां ठीक काम किया गया
स्टेफानो माटांगू

2

आप उपयोग कर सकते हैं progress, जो विशेष रूप से, एक चलने की प्रगति को दर्शाता है dd। यह उपयोग करता है /proc/$pid/fdऔर /proc/$pid/fdinfo जिसे आप हाथ से भी देख सकते हैं।


1

wcharलाइन (लिखित अक्षर) में /proc/$pid/ioआप के बारे में सटीक जानकारी दे सकते हैं ddप्रक्रिया। जब तक यह बदलता है, तब तक आपका ddकाम जारी है!

यहाँ एक साफ छोटी php स्क्रिप्ट है, जिसे आप लिखित बाइट्स को प्रदर्शित करने के php filename.phpदौरान सहेज सकते हैं और फिर निष्पादित कर सकते हैं dd/proc/$pid/ioओवर देखने का अच्छा लाभ kill -USR1 $(pidof dd)यह है कि आपको टर्मिनलों के बीच स्विच नहीं करना पड़ता है, जो हमेशा एक विकल्प नहीं होता है।

<?php

/** Time between refreshs in seconds */
$refresh = 1;


/**
 * Start of Script 
 */

if (!($pid = exec('pidof dd')))
    exit("no dd running\n");

$history = array();
$break_ms = $refresh * 1000000;
$start_time = exec("ls -ld /proc/$pid --time-style=+\"%s\" | egrep -o [0-9]{10}");


fprintf(STDOUT, "PID: %s\n", $pid);
fprintf(STDOUT, "START TIME: %s\n\n", date("Y-m-d H:i:s", $start_time));


while (true) {
    if (isset($curr))
        array_push($history, $curr);

    if (count($history) > 10) array_shift($history);
    $oldest = reset($history);
    $latest = end($history);

    /**
     * get number of written bytes from /proc/$pid/io
     */
    #if (!($curr = exec("cat /proc/$pid/io | grep ^write_bytes | sed 's/write_bytes: //g'")))
    #    break;

    /* prepare proc_open() parameter */
    $descriptorspec = array(
        0 => array('pipe', 'r'), // stdin
        1 => array('pipe', 'w'), // stdout
        2 => array('pipe', 'w'), // stderr
    );

    $process = proc_open("cat /proc/$pid/io | grep ^write_bytes | sed 's/write_bytes: //g'", $descriptorspec, $pipes);
    if (!is_resource($process)) break;

    $stdout = stream_get_contents($pipes[1]);
    $stderr = stream_get_contents($pipes[2]);
    proc_close($process);

    if (!empty($stderr)) break;
    $curr = trim($stdout);

    /**
     * caculate elapsed time from start */
    $time_elapsed = time() - $start_time;

    /**
     * avg speed since start */
    $avg = $time_elapsed > 0 ? round($curr / $time_elapsed) : 0;

    /**
     * avg speed of last 10 updates */
    if (count($history) > 0)
        $speed = human_file_size(round(($latest - $oldest) / count($history) / $refresh));

    $output = sprintf("\rBYTES WRITTEN: %s [%s]  ::  CURRENT: %s/s  ::  AVERAGE: %s/s  ::  ELAPSED: %s", $curr, human_file_size($curr), isset($speed) ? $speed : 0, human_file_size($avg), gmdate("H:i:s", $time_elapsed));
    printf("%s%s", $output, str_repeat(" ", exec("tput cols") - strlen($output)));

    usleep($break_ms);
}

fprintf(STDOUT, "\ndd has finished!\n\n");

function human_file_size($size,$unit="") {
  if( (!$unit && $size >= 1<<30) || $unit == "GB")
    return number_format($size/(1<<30),2)." GB";
  if( (!$unit && $size >= 1<<20) || $unit == "MB")
    return number_format($size/(1<<20),2)." MB";
  if( (!$unit && $size >= 1<<10) || $unit == "kB")
    return number_format($size/(1<<10),2)." kB";
  return number_format($size)." bytes";
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.