Dd'nin hala çalışıp çalışmadığını nasıl bilebilirim?


147

Bunları ddpek kullanmadım, ama şu ana kadar henüz başarısız olmadı. Şu anda, dd12 saatten fazla bir süredir devam ettim - Geldiği diske bir görüntü yazıyorum - ve dddiskten görüntüye kadar alabildiğim için biraz endişeliyim. 7 saat.

4 gb RAM ile 2.1 gh / çekirdek Core 2 Duo'lu bir MacBook'ta OSX 10.6.6 kullanıyorum. 7200rpm sabit sürücüdeki (önyükleme sürücüsü) bir .dmg'den okuyorum ve SATA-USB konektörüne bağlı 7200rpm sürücüye yazıyorum. Blok boyutunu varsayılan olarak bıraktım ve görüntü yaklaşık 160 gb.

EDIT: 14 saatlik saf stresten sonra, sonuçta ddmükemmel şekilde çalıştı. Bir dahaki sefere, yine de içinden geçip pvtakip edeceğim strace. Tüm yardımlarınız için herkese teşekkürler.


7
Sorunuza cevap vermemekle birlikte, zamanınız oldukça yüksek IMO. Varsayılan 512 bayttan daha büyük bir blok boyutunu gg'ye geçirmeyi hatırladınız mı? dd ... bs=16Mbenim önerim, RAM'inizi, disk boyutunu ve hızını verir.
Juliano

Yapmadım, çünkü güvenli bir şekilde oynamak istedim. Yine de bir dahaki sefere deneyeceğim. Teşekkürler.
eckza

Tecrübelerime göre, ddMac OS'de X, süreci bile öldüremediğim bir noktaya donma eğiliminde, ancak sistemi yeniden başlatmak zorunda. O zaman Linux VM'de çalışmak için başvuruyorum.
ssc

Yanıtlar:


173

Komutu ddkullanarak killgeçerli durumunu göstermek için belirli bir sinyal gönderebilirsiniz . Sinyal INFOBSD sistemlerinde (OSX dahil) ve USR1Linux'ta. Senin durumunda:

kill -INFO $PID

İşlem kimliğini ( $PIDyukarıda) pskomut ile bulabilirsiniz; veya daha uygun yöntemler için mac os x üzerindeki pgrep ve pkill alternatiflerine bakın .

Daha basit bir şekilde, AntoineG'nin cevabında işaret ettiğictrl-T gibi, INFOsinyal göndermek için gd çalışan kabuk yazabilirsiniz .

Linux'ta bir örnek olarak, tüm aktif ddişlemlerin çıkış durumunu şöyle yapabilirsiniz :

pkill -USR1 -x dd

Durumunu verdikten sonra ddbaşa çıkmaya devam edecek.


9
Oh, çok havalı. Bunları birleştirebilirsinizpkill -USR1 -x dd
Michael Mrozek

9
@ kivetros: BSD sistemlerinde, INFOsinyali göndermeniz gerekir . Linux'un bir SIGINFO'su yoktur ve USR1onun yerine kullanır .
Gilles

5
SIGUSRx sinyalleri, standartlaştırılmış bir anlama sahip olmalarının aksine, programların istediklerini yapmaları içindir. Örneğin SIGWINCH, terminal boyutunu değiştirdiğinde yükseltilir ve programın ekranını yeniden çizmesi gerekebilir. İşletim sistemi SIGUSRx'leri göndermiyor, bu yüzden özel kullanım için uygunlar.
LawrenceC

11
USR1 sinyalini başladıktan hemen sonra (örneğin bir bash betiğinde, başlattıktan sonraki satır) dd göndermek aslında onu sonlandıracaktır. Arada 0,1 saniyelik bir uyku koyun ve ilerlemesini düzgün bir şekilde yapacaktır. Bu arada, USR1 / INFO'yu test etmek için çok güzel bir dd komutu var dd if=/dev/zero of=/dev/null. :)
Lauritz V. Thaulow 14:11

11
BTW, tüm "true" BSD'ler, durum karakteri (varsayılan olarak Ctrl + T) terminale gönderilirse, SIGINFO'yu ön plan işlem grubuna gönderir. Ama MacOSX için doğru olup olmadığını bilmiyorum.
Netch

100

OS X altında (Linux'ta denemedi), basitçe terminal çalışmasında Ctrl+ yazabilirsiniz . CPU çıkışı ile aynı çıktıyı yazdıracaktır :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)

Bu konuyu okuduğunu ve terminalimde yeni bir sekme açmaya çalışarak + Tile Ctrl+ karıştırmayı öğrendim T.


1
Oh, tamam, loadCPU kullanımı da öyle mi?
pje

bu çok daha iyi bir çözüm oldu!
Stephn_R

Linux’ta dd’de denedim, sadece ^Tterminalde yankılanıyor .
mwfearnley

1
mac terminalinde ctrl + shift + T yaptığınızdan emin olun
JBaczuk

26

İçin ddşunları yapabilirsiniz sinyal gönderecek . Bir dosyayı okuyan veya yazan diğer komutlar için, dosyadaki konumlarını ile izleyebilirsiniz lsof.

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

Önceden planlıyorsanız, verileri iletin pv.


1
pv harika görünüyor - kesinlikle bir dahaki sefere kullanacağım. Çok teşekkür ederim.
eckza

1
+1 - pvsadece bilet gibi görünüyor.
boehj

17

iotopProgram başına geçerli okuma / yazma miktarını gösteren daha genel bir yol kullanmaktır .

EDIT: iotop -oyalnızca şu anda G / Ç işlemleri gerçekleştiren programları göster ( bu yorum için Jason C'ye teşekkürler ).


1
Bu benim de tercih ettiğim hızlı kontrol yöntemim. iotop -oGÇ yapmayan işlemleri gizler ve neler olduğunu bir bakışta anlatmayı kolaylaştırır.
Jason C

13

Genellikle , sistem çağrısında engellenip engellenmediğini veya hala etkin olup olmadığını görmek straceiçin böyle bir işleme ( -p $PIDseçeneğe bağlı) eklerim.

Veya, çalışan gg'ye bir sinyal gönderme konusunda gerginseniz, bunun işe yarayıp yaramadığını doğrulamak için başka bir gg başlatın.


2
Tam olarak nasıl takılırsın strace? Ayrıca, bir başkasına başladım ddve önerilen sinyallerden birini gönderdim ve ... onu öldürdü.
eckza

2
Sürmekte olan dd sürecinin pidini biliyorsanız, sadece strace -p <pid> yapın. Sürecin çağırdığı tüm sistem çağrılarının kayıtlarını görmelisiniz (çoğunlukla okuma ve yazma)
philfr

11

Bir dahaki sefere, sadece pvbaştan kullanabilirsiniz (eğer paket yöneticiniz tarafından mevcutsa kurun). Bu, ilerlemenin ve hızın çıktısını almak ve izlemek için yalnızca boru girişinin amaçlandığı bir yardımcı programdır.

Ardından, bir sürücüye bir resim yazmak için, 4 MB blok boyutunda:

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

İlk arabelleğe almanın yanı sıra ( ddisterseniz isterseniz yapılabilecek bir son senkronizasyonla dengeleme ), bu size bir ilerleme çubuğu, ortalama hız, geçerli hız ve ETA gösterecektir.

iflag=fullblockSeçenek kuvvetleri aracılığıyla girdisinin tüm blokları kapmak için dd pvaksi takdirde blok boyutları için borunun insafına konum.

Diğer yoldan gitmek için, okumak için dd'yi, yazmak için pv'yi kullanın; ancak, kaynak bir blok aygıtı ise, boyutu açıkça belirtmeniz gerekir. 4GB'lık bir cihaz için:

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

Ayrıca, boyutu otomatik olarak belirleyebilirsiniz:

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

Gerçekten ne yapmak sırası önemli değildir ddve pvsize ya da bir okuduğunuz cihaz kullanmak istediğiniz belirli bloktadır için optimum performans varsa - görüntü, tamamı performansla ilgili olduğunu ddyerine pvo cihaza erişmek için. İsterseniz ddher iki uca da takabilirsiniz , umursamıyorsanız bile:

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

10

coreutilsV8.24 itibariyle, ddilerlemeyi göstermek için yerel desteğe sahiptir. Sadece seçeneği ekleyin status=progress.

Örnek:

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

Kaynak



4

Bazen, INFO veya USR1 sinyalini kullanamayabilirsiniz, çünkü ddişlemin stderr akışı erişilebilir değildir (örneğin, yürütüldüğü terminal zaten kapalı olduğu için). Bu durumda, bir geçici çözüm aşağıdakileri yapmaktır (FreeBSD'de test edilmiştir, Linux'ta biraz farklı olabilir):

  1. iostatHedef cihaza ortalama yazma oranını (MB / s) tahmin etmek için kullanın , örneğin:

    iostat -d -w30 ada0

    Hedef cihaz adınızı ada0burada değiştirin ve birkaç sonuç vermesi için bir dakika bekleyin. "W" parametresi örnekler arasında kaç saniye olduğunu belirler. Artırılması, daha az varyansla daha iyi bir ortalama tahmini sağlayacaktır;

  2. psNe kadar süre ddçalıştığını belirlemek için kullanın :

    ps -xo etime,command | grep dd

    Toplam çalışma süresinin saniyesini elde etmek için bunu saniyeye dönüştürün.

  3. Toplam aktarılan MB'yi elde etmek için çalışma süresinin toplam saniyesini ortalama yazma oranıyla çarpın.
  4. Cihazın boyutunu MB ile al:

    grep ada0 /var/run/dmesg.boot

    Hedef cihazınızın adını değiştirin ada0. Toplam aktarım süresini saniye cinsinden almak için sonucu ortalama yazma hızına bölün. Kalan süre almak için şu ana kadar çalıştığı zamanı çıkarın.

Bu strateji dd, başladığından beri sürekli olarak mevcut ortalama yazma hızında yazıyorsa işe yarar . CPU veya G / Ç kaynakları için diğer işlemler (G / Ç veriyolu dahil) rekabet ediyorsa, aktarım hızını düşürebilir.


4

Dd işlemlerini daha iyi gösteren dcfldd (1) kullanmaya başladım.


2

İken ddyürütülüyor, ben root olarak başka terminalde bu çalıştırın:

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

Bu baskılar dddurumunu her 1 saniyede orjinal terminal penceresindedd yapılırken, ve komut yapıldığında çıkar.


Çok havalı. Burada El Capitan
Stefano Mtangoo

2

progressÖzellikle koşu koşularının ilerleyişini gösterenleri kullanabilirsiniz dd. Kullanır /proc/$pid/fdve /proc/$pid/fdinfo el ile de izleyebilirsiniz.


1

İçindeki wcharçizgi (yazılı karakterler) /proc/$pid/io, ddişlem hakkında size kesin bilgi verebilir . Değiştiği sürece dd, hala çalışıyor!

Burada kaydetmek ve daha sonra yürütebileceği bir temiz küçük php komut dosyası vardır php filename.phpsırasında ddyazılı bayt görüntülemek için. İzlerken güzel bir yararı /proc/$pid/ioüzerinde kill -USR1 $(pidof dd)her zaman bir seçenek değildir terminalleri arasında geçiş yapmak zorunda kalmamasıdır.

<?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";
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.