Riepilogo: ddè uno strumento irritabile che è difficile da usare correttamente. Non usarlo, nonostante i numerosi tutorial che lo dicono. ddha un'atmosfera da “unix street cred”, ma se capisci veramente cosa stai facendo, saprai che non dovresti toccarlo con un palo da 10 piedi.
ddeffettua una singola chiamata alla chiamata di readsistema per blocco (definita dal valore di bs). Non vi è alcuna garanzia che la readchiamata di sistema restituisca tutti i dati della dimensione del buffer specificata. Questo tende a funzionare per file regolari e dispositivi a blocchi, ma non per pipe e alcuni dispositivi a caratteri. Vedi Quando dd è adatto alla copia dei dati? (o, quando sono read () e write () parziale) per ulteriori informazioni. Se la readchiamata di sistema restituisce meno di un blocco completo, quindi ddtrasferisce un blocco parziale. Copia ancora il numero specificato di blocchi, quindi la quantità totale di byte trasferiti è inferiore a quella richiesta.
L'avvertimento su una "lettura parziale" dice esattamente questo: una delle letture era parziale, quindi ddtrasferito un blocco incompleto. Nel conteggio dei blocchi, +1significa che un blocco è stato letto parzialmente; poiché il conteggio delle uscite è +0, tutti i blocchi sono stati scritti come letti.
Ciò non influisce sulla casualità dei dati: tutti i byte che vengono ddscritti sono byte da cui vengono letti /dev/urandom. Ma hai meno byte del previsto.
Linux /dev/urandomaccetta richieste arbitrarie di grandi dimensioni (fonte: extract_entropy_userin drivers/char/random.c), quindi ddè normalmente sicuro quando si legge da esso. Tuttavia, la lettura di grandi quantità di dati richiede tempo. Se il processo riceve un segnale, la readchiamata di sistema ritorna prima di riempire il buffer di output. Questo è un comportamento normale e le applicazioni dovrebbero chiamare readin un ciclo; ddnon lo fa, per ragioni storiche ( ddle origini sono oscure, ma sembra essere nato come uno strumento per accedere ai nastri, che hanno requisiti particolari, e non è mai stato adattato per essere uno strumento generico). Quando si controlla l'avanzamento, questo invia al ddprocesso un segnale che interrompe la lettura. Puoi scegliere tra sapere quanti byteddcopierà in totale (assicurati di non interromperlo - nessun controllo di avanzamento, nessuna sospensione), o sapendo quanti byte ddha copiato finora, nel qual caso non puoi sapere quanti più byte copierà.
La versione di ddin GNU coreutils (come si trova su Linux non incorporato e su Cygwin) ha un flag fullblockche dice dddi chiamare readin un ciclo (e idem per write) e quindi trasferire sempre blocchi completi. Il messaggio di errore suggerisce che lo usi; dovresti sempre usarlo (in entrambi i flag di input e output), tranne in circostanze molto speciali (soprattutto quando accedi ai nastri) - se lo usi ddaffatto, cioè: di solito ci sono soluzioni migliori (vedi sotto).
dd if=/dev/urandom iflag=fullblock oflag=fullblock of=file bs=1M count=1000000
Un altro modo possibile per essere sicuri di cosa ddfarà è passare una dimensione del blocco di 1. Quindi puoi dire quanti byte sono stati copiati dal conteggio dei blocchi, anche se non sono sicuro di cosa accadrà se a readviene interrotto prima di leggere il primo byte (che non è molto probabile in pratica ma può accadere). Tuttavia, anche se funziona, è molto lento.
Il consiglio generale sull'uso ddè di non usaredd . Sebbene ddsia spesso pubblicizzato come un comando di basso livello per accedere ai dispositivi, in realtà non è una cosa del genere: tutta la magia accade nel file del dispositivo (la /dev/…) parte, ddè solo uno strumento normale con un alto potenziale di uso improprio con conseguente perdita di dati . Nella maggior parte dei casi, esiste un modo più semplice e sicuro di fare ciò che vuoi, almeno su Linux.
Ad esempio, per leggere un certo numero di byte all'inizio di un file, basta chiamare head:
head -c 1000000m </dev/urandom >file
Ho fatto un rapido benchmark sulla mia macchina e non ho osservato alcuna differenza di prestazioni tra ddcon un blocco di grandi dimensioni e head.
Se è necessario saltare alcuni byte all'inizio, eseguire il pipe tailin head:
dd if=input of=output count=C bs=B seek=S
<input tail -c +$((S*B+1)) | head -c $((C*B)) >output
Se vuoi vedere i progressi, chiama lsofper vedere l'offset del file. Funziona solo su un file normale (il file di output sul tuo esempio), non su un dispositivo a caratteri.
lsof -a -p 1234 -d 1
cat /proc/1234/fdinfo/1
È possibile chiamare pvper ottenere un rapporto sullo stato di avanzamento (meglio di quello dd), a spese di un elemento aggiuntivo in cantiere (dal punto di vista delle prestazioni, è appena percettibile).