Podsumowanie: ddjest zepsutym narzędziem, które jest trudne w użyciu poprawnie. Nie używaj go, pomimo licznych samouczków, które ci to mówią. ddma w sobie klimat „unix street cred” - ale jeśli naprawdę rozumiesz, co robisz, będziesz wiedział, że nie powinieneś dotykać go 10-metrowym drągiem.
ddwykonuje pojedyncze wywołanie wywołania readsystemowego na blok (zdefiniowane przez wartość bs). Nie ma gwarancji, że readwywołanie systemowe zwróci tyle danych, ile podany rozmiar bufora. Zwykle działa to na zwykłe pliki i urządzenia blokujące, ale nie na potoki i niektóre urządzenia znakowe. Zobacz Kiedy dd nadaje się do kopiowania danych? (lub, gdy są czytane () i write () częściowe), aby uzyskać więcej informacji. Jeśli readwywołanie systemowe zwraca mniej niż jeden pełny blok, wówczas ddprzenosi blok częściowy. Nadal kopiuje określoną liczbę bloków, więc całkowita liczba przesłanych bajtów jest mniejsza niż wymagana.
Ostrzeżenie o „częściowym odczycie” mówi dokładnie to: jeden z odczytów był częściowy, więc ddprzekazano niepełny blok. W liczeniu bloków +1oznacza, że jeden blok został częściowo odczytany; ponieważ liczba wyjść jest taka +0, wszystkie bloki zostały zapisane jako przeczytane.
Nie wpływa to na losowość danych: wszystkie bajty, które ddwypisują, są bajtami, które odczytały /dev/urandom. Ale masz mniej bajtów niż oczekiwano.
Linux /dev/urandomobsługuje dowolne duże żądania (source: extract_entropy_userin drivers/char/random.c), więc ddzwykle jest bezpieczny podczas czytania z niego. Jednak czytanie dużych ilości danych wymaga czasu. Jeśli proces odbierze sygnał, readwywołanie systemowe powraca przed zapełnieniem bufora wyjściowego. Jest to normalne zachowanie, a aplikacje powinny wywoływać się readw pętli; ddnie robi tego z przyczyn historycznych ( ddpochodzenie jest niejasne, ale wydaje się, że zaczęło się jako narzędzie dostępu do taśm, które mają specyficzne wymagania i nigdy nie zostało przystosowane do tego, by być narzędziem ogólnego zastosowania). Gdy sprawdzasz postęp, wysyła do ddprocesu sygnał, który przerywa odczyt. Masz wybór między wiedzą, ile bajtówddskopiuje w całości (pamiętaj, aby go nie przerwać - bez sprawdzania postępu, bez zawieszenia) lub wiedząc, ile bajtów ddskopiowano do tej pory, w takim przypadku nie możesz wiedzieć, ile jeszcze bajtów skopiuje.
Wersja ddw GNU coreutils (znaleziona w niewbudowanym systemie Linux i na Cygwin) ma flagę, fullblockktóra mówi, ddaby wywoływać readw pętli (i to samo dla write), a zatem zawsze przenosić pełne bloki. Komunikat o błędzie sugeruje jego użycie; powinieneś zawsze go używać (zarówno w flagach wejściowych, jak i wyjściowych), z wyjątkiem bardzo szczególnych okoliczności (głównie podczas uzyskiwania dostępu do taśm) - jeśli ddw ogóle używasz , to znaczy: zwykle są lepsze rozwiązania (patrz poniżej).
dd if=/dev/urandom iflag=fullblock oflag=fullblock of=file bs=1M count=1000000
Innym możliwym sposobem na upewnienie się, co się ddstanie, jest przekazanie bloku o rozmiarze 1. Następnie możesz powiedzieć, ile bajtów zostało skopiowanych z liczby bloków, chociaż nie jestem pewien, co się stanie, jeśli a readzostanie przerwane przed przeczytaniem pierwszego bajt (co w praktyce jest mało prawdopodobne, ale może się zdarzyć). Jednak nawet jeśli to działa, jest to bardzo powolne.
Według opinii na temat używania ddjest nie używaćdd . Chociaż ddjest często reklamowany jako polecenie niskiego poziomu dostępu do urządzeń, w rzeczywistości nie ma takiej rzeczy: cała magia dzieje się w części pliku urządzenia /dev/…, ddjest zwykłym narzędziem o wysokim potencjale niewłaściwego użycia powodującego utratę danych . W większości przypadków istnieje prostszy i bezpieczniejszy sposób robienia tego, co chcesz, przynajmniej w systemie Linux.
Na przykład, aby odczytać określoną liczbę bajtów na początku pliku, wystarczy wywołać head:
head -c 1000000m </dev/urandom >file
Zrobiłem szybki test porównawczy na mojej maszynie i nie zauważyłem żadnej różnicy w wydajności między dddużym blokiem a head.
Jeśli musisz pominąć kilka bajtów na początku, potokuj taildo head:
dd if=input of=output count=C bs=B seek=S
<input tail -c +$((S*B+1)) | head -c $((C*B)) >output
Jeśli chcesz zobaczyć postęp, zadzwoń, lsofaby zobaczyć przesunięcie pliku. Działa to tylko na zwykłym pliku (plik wyjściowy na twoim przykładzie), a nie na urządzeniu znakowym.
lsof -a -p 1234 -d 1
cat /proc/1234/fdinfo/1
Możesz zadzwonić, pvaby uzyskać raport postępu (lepszy niż dd), kosztem dodatkowego elementu w potoku (pod względem wydajności jest to ledwo zauważalne).