Bagaimana saya tahu jika dd masih berfungsi?

147

Saya belum terlalu ddbanyak menggunakan, tapi sejauh ini belum gagal saya. Saat ini, saya sudah ddberjalan selama lebih dari 12 jam - saya menulis gambar kembali ke disk asalnya - dan saya sedikit khawatir, karena saya dapat dddari disk ke gambar sekitar 7 jam.

Saya menjalankan OSX 10.6.6 pada MacBook dengan Core 2 Duo di 2.1ghz / core dengan RAM 4GB. Saya membaca dari .dmg pada hard drive 7200rpm (drive boot), dan saya menulis ke drive 7200rpm yang terhubung melalui konektor SATA-to-USB. Saya meninggalkan blocksize secara default, dan gambar sekitar 160gb.

EDIT: Dan, setelah 14 jam stres murni, ternyata ddberhasil dengan baik. Namun lain kali, saya akan menjalankannya pvdan melacaknya strace. Terima kasih untuk semua orang atas semua bantuan Anda.

eckza
sumber
7
Tidak menjawab pertanyaan Anda, tetapi waktu Anda IMO cukup tinggi. Apakah Anda ingat untuk meneruskan ukuran blok yang lebih besar ke dd selain dari 512 byte default? dd ... bs=16Madalah saran saya, mengingat RAM Anda, ukuran dan kecepatan disk.
Juliano
Saya tidak melakukannya, hanya karena saya ingin bermain aman. Saya akan mencobanya lain kali. Terima kasih.
eckza
Dalam pengalaman saya, ddpada Mac OS X memiliki kecenderungan untuk membeku ke titik di mana saya bahkan tidak dapat mematikan proses, tetapi harus me-restart sistem. Saya resor untuk melakukan pekerjaan pada VM Linux.
ssc

Jawaban:

173

Anda dapat mengirim ddsinyal tertentu menggunakan killperintah untuk membuatnya mengeluarkan statusnya saat ini. Sinyal ada INFOdi sistem BSD (termasuk OSX) dan USR1di Linux. Dalam kasus Anda:

kill -INFO $PID

Anda dapat menemukan id proses (di $PIDatas) dengan psperintah; atau lihat pgrep dan pkill alternatif di mac os x untuk metode yang lebih mudah.

Lebih sederhana, seperti yang ditunjukkan AntoineG dalam jawabannya , Anda dapat mengetikkan ctrl-Tshell yang menjalankan dd untuk mengirimkan INFOsinyal.

Sebagai contoh di Linux, Anda dapat membuat semua ddstatus keluaran proses aktif seperti ini:

pkill -USR1 -x dd

Setelah mengeluarkan statusnya, ddakan terus mengatasi.

Caleb
sumber
9
Oh, sangat keren. Anda dapat menggabungkannya denganpkill -USR1 -x dd
Michael Mrozek
9
@kivetros: Pada sistem BSD, Anda perlu mengirim INFOsinyal. Linux tidak memiliki SIGINFO dan menggunakan USR1sebagai gantinya.
Gilles
5
Sinyal SIGUSRx adalah untuk program melakukan apa yang mereka inginkan, sebagai lawan dari memiliki makna standar. SIGWINCH, misalnya, dinaikkan ketika terminal telah mengubah ukurannya dan program mungkin perlu menggambar ulang layarnya. Sistem operasi tidak mengirimkan SIGUSRx sehingga tersedia untuk penggunaan khusus.
LawrenceC
11
Mengirimkan dd sinyal USR1 terlalu cepat setelah dimulai (yaitu dalam skrip bash, baris setelah Anda memulainya) sebenarnya akan menghentikannya. Letakkan 0,1 detik di antaranya dan itu akan menampilkan kemajuan dengan benar. Omong-omong, perintah dd yang sangat bagus untuk menguji USR1 / INFO aktif dd if=/dev/zero of=/dev/null. :)
Lauritz V. Thaulow
11
BTW, semua BSD "benar" mengirim SIGINFO ke grup proses latar depan jika karakter status (Ctrl + T secara default) dikirim ke terminal. Tapi saya tidak tahu apakah itu benar untuk MacOSX.
Netch
100

Di bawah OS X (tidak mencoba di Linux), Anda cukup mengetik Ctrl+ Tdi terminal yang berjalan dd. Ini akan mencetak output yang sama dengan kill -INFO $PID, ditambah penggunaan CPU:

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)

Saya mengetahui tentang hal itu membaca utas ini, dan mencoba membuka tab baru di terminal saya tetapi mencampur + Tdengan Ctrl+ T.

AntoineG
sumber
1
Oh, oke, jadi loadapakah penggunaan CPU?
pje
ini adalah solusi yang jauh lebih baik!
Stephn_R
Saya mencoba di dd di Linux, itu hanya bergema ^Tke terminal.
mwfearnley
1
pastikan Anda melakukan ctrl + shift + T di terminal mac
JBaczuk
26

Sebab dd, Anda bisa mengirim sinyal . Untuk perintah lain yang sedang membaca atau menulis ke file, Anda dapat melihat posisinya di file lsof.

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

Jika Anda berencana terlebih dahulu, pipa data melalui pv.

Gilles
sumber
1
pv terlihat luar biasa - saya pasti akan menggunakannya lain kali. Terima kasih banyak.
eckza
1
+1 - pvsepertinya hanya tiket.
boehj
17

Cara yang lebih umum adalah menggunakan iotopyang menampilkan jumlah disk saat ini membaca / menulis per program.

EDIT: iotop -ohanya tampilkan program yang melakukan operasi I / O saat ini (terima kasih Jason C untuk komentar ini).

Jofel
sumber
1
Ini juga metode pemeriksaan cepat pilihan saya. iotop -oakan menyembunyikan proses yang tidak melakukan IO dan membuatnya lebih mudah untuk mengetahui apa yang sedang terjadi.
Jason C
13

Saya biasanya melampirkan straceproses yang berjalan (dengan -p $PIDopsi) untuk melihat apakah tetap diblokir dalam panggilan sistem atau jika masih aktif.

Atau, jika Anda merasa gugup mengirim sinyal ke dd berjalan, mulai dd lain untuk memvalidasi jika ini berfungsi.

philfr
sumber
2
Bagaimana tepatnya Anda akan melampirkan strace? Juga, saya memang memulai yang lain dddan mengirim salah satu sinyal yang disarankan untuk itu, dan ... itu membunuhnya.
eckza
2
Jika Anda tahu pid dari proses menjalankan dd, lakukan saja strace -p <pid>. Anda akan melihat log semua panggilan sistem yang dipanggil oleh proses (kebanyakan membaca dan menulis)
philfr
11

Untuk waktu berikutnya, Anda bisa menggunakannya pvdari awal (jika tersedia melalui manajer paket Anda, instal). Ini adalah utilitas dengan tujuan tunggal menyalurkan input ke output dan memantau kemajuan dan kecepatan.

Kemudian, untuk menulis gambar ke drive, katakan dengan ukuran blok 4MB:

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

Selain dari penyangga awal (diimbangi dengan sinkronisasi akhir, yang dapat dilakukan melalui ddjika Anda mau), ini akan menampilkan bilah kemajuan, kecepatan rata-rata, kecepatan saat ini, dan ETA.

The iflag=fullblockpasukan pilihan dd untuk mengambil blok penuh masukan melalui pv, jika Anda pada belas kasihan dari pipa untuk ukuran blok.

Untuk ke arah lain gunakan dd untuk membaca dan pv untuk menulis, meskipun Anda harus secara eksplisit menentukan ukuran jika sumbernya adalah perangkat blok. Untuk perangkat 4GB:

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

Anda juga dapat menentukan ukuran secara otomatis, seperti:

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

Tidak masalah apa pun urutan dddan urutannya pv, ini sepenuhnya terkait dengan kinerja - jika perangkat yang Anda baca memiliki atau dari memiliki kinerja optimal untuk ukuran blok tertentu yang ingin Anda gunakan ddalih-alih pvmengakses perangkat itu. Anda bahkan dapat menempelkannya dddi kedua ujungnya jika Anda mau, atau tidak sama sekali jika Anda tidak peduli:

pv -ptearb /path/to/image.bin > /dev/whatever
sync
Jason C
sumber
10

Pada coreutilsv8.24, ddmemiliki dukungan asli untuk menunjukkan kemajuan. Cukup tambahkan opsi status=progress.

Contoh:

dd if=arch.iso of=/dev/sdb bs=4M status=progress

Sumber

Chirag Bhatia - chirag64
sumber
5

ddrescue akan memberi Anda statistik saat sedang berjalan.

demo: http://www.youtube.com/watch?v=vqq9A01geeA#t=144s

Ben Preston
sumber
3
Ini mungkin membantu untuk waktu berikutnya, tetapi tidak akan membantu OP untuk memahami apakah perintah saat ini dibekukan atau tidak.
Francesco Turco
4

Kadang-kadang Anda mungkin tidak dapat menggunakan sinyal INFO atau USR1 karena aliran ddproses stderr tidak dapat diakses (misalnya karena terminal di mana ia dieksekusi sudah ditutup). Dalam hal ini, solusinya adalah dengan melakukan hal berikut (diuji pada FreeBSD, mungkin sedikit berbeda di Linux):

  1. Gunakan iostatuntuk memperkirakan tingkat penulisan rata-rata (MB / s) ke perangkat target, misalnya:

    iostat -d -w30 ada0

    Gantilah nama perangkat target Anda di ada0sini, dan tunggu sebentar hingga hasilnya beberapa. Parameter "w" menentukan berapa detik antar sampel. Menambahnya akan memberikan perkiraan rata-rata yang lebih baik dengan varians yang lebih sedikit, tetapi Anda harus menunggu lebih lama.

  2. Gunakan psuntuk menentukan berapa lama ddtelah berjalan:

    ps -xo etime,command | grep dd

    Konversikan ke detik untuk mendapatkan runtime total detik.

  3. Kalikan total detik runtime dengan rata-rata tingkat penulisan untuk mendapatkan MB total yang ditransfer.
  4. Dapatkan ukuran perangkat dalam MB dengan:

    grep ada0 /var/run/dmesg.boot

    Ganti nama perangkat target Anda dengan ada0. Bagi hasil dengan rata-rata tingkat penulisan untuk mendapatkan total waktu transfer dalam detik. Kurangi waktu yang sudah berjalan sejauh ini untuk mendapatkan sisa waktu.

Strategi ini hanya berfungsi jika ddtelah menulis terus menerus pada tingkat menulis rata-rata saat ini sejak dimulai. Jika proses lain bersaing untuk sumber daya CPU atau I / O (termasuk bus I / O) maka dapat mengurangi kecepatan transfer.

D Coetzee
sumber
4

Saya mulai menggunakan dcfldd (1), yang menunjukkan operasi dd dengan cara yang lebih baik.

Kartik M
sumber
2

Ketika ddsedang mengeksekusi, saya menjalankan ini di terminal lain sebagai root:

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

Ini mencetak ddstatus setiap 1 detik di jendela terminal asli tempat ddeksekusi, dan berhenti ketika perintah dilakukan.

ccpizza
sumber
Keren abis. Bekerja dengan baik di sini di bawah El Capitan
Stefano Mtangoo
2

Anda dapat menggunakan progressyang, khususnya, menunjukkan progres lari dd. Ini menggunakan /proc/$pid/fddan /proc/$pid/fdinfo yang Anda juga dapat memonitor dengan tangan.

Jofel
sumber
1

The wcharline (karakter yang ditulis) dalam /proc/$pid/iodapat memberikan informasi yang tepat tentang ddproses. Selama itu berubah, Anda ddmasih bekerja!

Berikut ini adalah skrip php kecil yang rapi, yang dapat Anda simpan dan kemudian jalankan dengan php filename.phpselama dduntuk menampilkan byte yang ditulis. Manfaat bagus menonton /proc/$pid/iolebih kill -USR1 $(pidof dd)adalah bahwa Anda tidak perlu beralih di antara terminal, yang tidak selalu pilihan.

<?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";
}
Leon Kramer
sumber