it-swarm.it

Come faccio a sapere se dd funziona ancora?

Non ho usato molto dd, ma finora non mi ha ancora deluso. In questo momento, ho avuto un dd per oltre 12 ore - sto scrivendo un'immagine sul disco da cui proveniva - e mi sto preoccupando un po ', dato che sono stato in grado di dd dal disco all'immagine in circa 7 ore.

Sto eseguendo OSX 10.6.6 su un MacBook con un Core 2 Duo a 2.1ghz/core con 4 GB di RAM. Sto leggendo da un .dmg su un disco rigido a 7200 rpm (l'unità di avvio) e sto scrivendo su un'unità a 7200 rpm collegata tramite un connettore SATA-USB. Ho lasciato la dimensione di blocco predefinita e l'immagine è di circa 160 GB.

EDIT: E, dopo 14 ore di puro stress, il dd ha funzionato perfettamente dopo tutto. La prossima volta, però, lo eseguirò attraverso pv e lo seguirò con strace. Grazie a tutti per tutto il vostro aiuto.

150
eckza

Puoi inviare dd un certo segnale usando il comando kill per fare in modo che emetta il suo stato attuale. Il segnale è INFO su sistemi BSD (incluso OSX) e USR1 su Linux. Nel tuo caso:

kill -INFO $PID

È possibile trovare l'ID processo ($PID sopra) con il comando ps; oppure vedi alternative a pgrep e pkill su mac os x per metodi più convenienti.

Più semplicemente, come AntoineG sottolinea in la sua risposta , puoi digitare ctrl-T alla Shell che esegue dd per inviargli il segnale INFO.

Ad esempio su Linux, è possibile rendere tutti i processi attivi dd output in questo modo:

pkill -USR1 -x dd

Dopo aver emesso il suo stato, dd continuerà a far fronte.

176
Caleb

Sotto OS X (non ho provato su Linux), puoi semplicemente digitare Ctrl+T nel terminale che esegue dd. Stampa lo stesso output di kill -INFO $PID, oltre all'utilizzo della 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)

L'ho scoperto leggendo questo thread e provando ad aprire una nuova scheda nel mio terminale ma mescolando +T con Ctrl+T.

104
AntoineG

Per dd, puoi inviare un segnale . Per altri comandi che stanno leggendo o scrivendo su un file, puoi vedere la loro posizione nel file con lsof .

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

Se pianifichi in anticipo, reindirizza i dati attraverso pv .

Un modo più generale è usare iotop che mostra la quantità corrente di lettura/scrittura del disco per programma.

MODIFICARE: iotop -o mostra solo i programmi che eseguono attualmente operazioni di I/O (grazie Jason C per questo commento).

17
jofel

Di solito allego strace a tale processo in esecuzione (con il -p $PID opzione) per vedere se rimane bloccato in una chiamata di sistema o se è ancora attivo.

Oppure, se ti senti nervoso per l'invio di un segnale al dd in esecuzione, avvia un altro dd per confermare se funziona.

13
philfr

Per la prossima volta, puoi semplicemente utilizzare pv dall'inizio (se è disponibile tramite il gestore pacchetti, installalo). Questa è una utility con il solo scopo di convogliare l'input all'output e monitorare i progressi e la velocità.

Quindi, per scrivere un'immagine su un'unità, dire con una dimensione di blocco di 4 MB:

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

A parte il buffering iniziale (compensato da una sincronizzazione finale, che può essere eseguita tramite dd se lo desideri), questo ti mostrerà una barra di avanzamento, velocità media, velocità corrente ed ETA.

Il iflag=fullblock L'opzione forza dd a prendere interi blocchi di input attraverso pv, altrimenti sei in balia del tubo per le dimensioni dei blocchi.

Per andare dall'altra parte usa dd per leggere e pv per scrivere, anche se devi specificare esplicitamente la dimensione se l'origine è un dispositivo a blocchi. Per un dispositivo da 4 GB:

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

Puoi anche determinare automaticamente le dimensioni, qualcosa del tipo:

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

In realtà non importa in quale ordine fai dd e pv, è interamente legato alle prestazioni - se il dispositivo che stai leggendo o da cui ha prestazioni ottimali per determinati blocchi che desideri usa dd invece di pv per accedere a quel dispositivo. Puoi anche attaccare un dd su entrambe le estremità se vuoi, o per niente se non ti interessa:

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

A partire da coreutils v8.24, dd ha il supporto nativo per mostrare i progressi. Aggiungi solo l'opzione status=progress.

Esempio:

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

Source

ddrescue ti darà le statistiche mentre è in esecuzione.

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

5
Ben Preston

Ho iniziato a usare dcfldd (1), che mostra le operazioni dd in un modo migliore.

4
Kartik M

A volte potresti non essere in grado di utilizzare il segnale INFO o USR1 perché il flusso stderr del processo dd non è accessibile (ad esempio perché il terminale in cui è stato eseguito era già chiuso). In questo caso, una soluzione alternativa consiste nel fare quanto segue (testato su FreeBSD, potrebbe essere leggermente diverso su Linux):

  1. Utilizzare iostat per stimare la velocità di scrittura media (MB/s) sul dispositivo di destinazione, ad es .:

    iostat -d -w30 ada0

    Sostituisci il nome del tuo dispositivo di destinazione con ada0 qui, e attendi un minuto per dare un paio di risultati. Il parametro "w" determina quanti secondi tra i campioni. Aumentandolo si otterrà una stima media migliore con una minore varianza, ma dovrai aspettare più a lungo.

  2. Usa ps per determinare da quanto tempo dd è in esecuzione:

    ps -xo etime,command | grep dd

    Converti questo in secondi per ottenere secondi totali di runtime.

  3. Moltiplicare i secondi totali di runtime per la velocità di scrittura media per ottenere MB totali trasferiti.
  4. Ottieni le dimensioni del dispositivo in MB con:

    grep ada0 /var/run/dmesg.boot

    Sostituisci il nome del tuo dispositivo di destinazione con ada0. Dividi il risultato per la velocità di scrittura media per ottenere il tempo di trasferimento totale in secondi. Sottrai il tempo che è stato eseguito finora per ottenere il tempo rimanente.

Questa strategia funziona solo se dd ha continuato a scrivere alla velocità di scrittura media corrente dall'inizio. Se altri processi competono per le risorse CPU o I/O (incluso il bus I/O), è possibile che la velocità di trasferimento venga ridotta.

4
D Coetzee

Puoi usare progress che, in particolare, mostra l'avanzamento di un dd in esecuzione. Utilizza /proc/$pid/fd e /proc/$pid/fdinfo che puoi anche monitorare manualmente.

3
jofel

Durante l'esecuzione di dd, eseguo questo in un altro terminale come root:

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

Stampa lo stato dd ogni 1 secondo nella finestra del terminale originale dove sta eseguendo dd e si chiude al termine del comando.

2
ccpizza

La riga wchar (caratteri scritti) in /proc/$pid/io Può darti informazioni precise sul processo dd. Finché cambia, il tuo dd funziona ancora!

Ecco un piccolo script php pulito, che puoi salvare e quindi eseguire con php filename.php Durante il dd per visualizzare i byte scritti. Il vantaggio di guardare /proc/$pid/io Su kill -USR1 $(pidof dd) è che non è necessario passare da un terminale all'altro, il che non è sempre un'opzione.

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