Tworzę plik 1 TB z losowymi danymi za pomocą dd if=/dev/urandom of=file bs=1M count=1000000
. Teraz sprawdzam kill -SIGUSR1 <PID>
postępy i otrzymuję:
691581+0 Datensätze ein
691580+0 Datensätze aus
725174190080 Bytes (725 GB) kopiert, 86256,9 s, 8,4 MB/s
800950+1 Datensätze ein
800950+0 Datensätze aus
839856947200 Bytes (840 GB) kopiert, 99429,5 s, 8,4 MB/s
dd: warning: partial read (809620 bytes); suggest iflag=fullblock
803432+1 Datensätze ein
803431+1 Datensätze aus
842459273876 Bytes (842 GB) kopiert, 99791,3 s, 8,4 MB/s
Nie mogę zinterpretować ostrzeżenia. Co to mówi? Czy po ostrzeżeniu mój plik jest naprawdę losowy, czy występuje problem? Co +0 +1 lub w 800950+1 Datensätze ein
i 800950+0 Datensätze aus
średnią? Po ostrzeżeniu jest +1. Czy to liczba błędów?
LC_ALL=C
przed poleceniem, na przykładLC_ALL=C dd if=...
Odpowiedzi:
Podsumowanie:
dd
jest 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ą.dd
ma 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.dd
wykonuje pojedyncze wywołanie wywołaniaread
systemowego na blok (zdefiniowane przez wartośćbs
). Nie ma gwarancji, żeread
wywoł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śliread
wywołanie systemowe zwraca mniej niż jeden pełny blok, wówczasdd
przenosi 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
dd
przekazano niepełny blok. W liczeniu bloków+1
oznacza, ż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
dd
wypisują, są bajtami, które odczytały/dev/urandom
. Ale masz mniej bajtów niż oczekiwano.Linux
/dev/urandom
obsługuje dowolne duże żądania (source:extract_entropy_user
indrivers/char/random.c
), więcdd
zwykle jest bezpieczny podczas czytania z niego. Jednak czytanie dużych ilości danych wymaga czasu. Jeśli proces odbierze sygnał,read
wywołanie systemowe powraca przed zapełnieniem bufora wyjściowego. Jest to normalne zachowanie, a aplikacje powinny wywoływać sięread
w pętli;dd
nie robi tego z przyczyn historycznych (dd
pochodzenie 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 dodd
procesu sygnał, który przerywa odczyt. Masz wybór między wiedzą, ile bajtówdd
skopiuje w całości (pamiętaj, aby go nie przerwać - bez sprawdzania postępu, bez zawieszenia) lub wiedząc, ile bajtówdd
skopiowano do tej pory, w takim przypadku nie możesz wiedzieć, ile jeszcze bajtów skopiuje.Wersja
dd
w GNU coreutils (znaleziona w niewbudowanym systemie Linux i na Cygwin) ma flagę,fullblock
która mówi,dd
aby wywoływaćread
w pętli (i to samo dlawrite
), 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ślidd
w ogóle używasz , to znaczy: zwykle są lepsze rozwiązania (patrz poniżej).Innym możliwym sposobem na upewnienie się, co się
dd
stanie, 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 aread
zostanie 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
dd
jest nie używaćdd
. Chociażdd
jest 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/…
,dd
jest 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
:Zrobiłem szybki test porównawczy na mojej maszynie i nie zauważyłem żadnej różnicy w wydajności między
dd
dużym blokiem ahead
.Jeśli musisz pominąć kilka bajtów na początku, potokuj
tail
dohead
:Jeśli chcesz zobaczyć postęp, zadzwoń,
lsof
aby 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.Możesz zadzwonić,
pv
aby uzyskać raport postępu (lepszy niżdd
), kosztem dodatkowego elementu w potoku (pod względem wydajności jest to ledwo zauważalne).źródło
dd
polecenia, o którym nie wiedziałem, że powinienem wiedzieć. Dzięki.dd
może być bezpiecznie używany, dzięki jegofullblock
opcji. Ale jeśli masz jądra GNU, nie potrzebujeszdd
wiele. „Pochodne”,dcfldd
które nie sądd
, nie mają wad konstrukcyjnych, więc moja odpowiedź ich nie dotyczy. Ogromna większość ludzi, którzy używajądd
, nie poświęciła wystarczająco dużo czasu na jej zrozumienie (najwyżej poświęciła czas, by myśleć , że to rozumie), a sposób, w jaki z niego korzystają, prowadzi do utraty danych.Ostrzeżenie pojawia się, gdy
dd
nie można uzyskać wystarczającej ilości danych, aby wypełnić blok w jednym odczycie. Dzieje się tak w przypadku nieregularnych lub wolnych źródeł danych lub źródeł zapisujących dane w mniejszych jednostkach niż żądany rozmiar bloku.Nie ma problemu z integralnością danych, ale problem polega na tym, że
dd
częściowy odczyt nadal jest traktowany jako blok odczytu.Jeśli nie korzystasz z tej
count
opcji, ostrzeżenie nie ma większego znaczenia, to tylko kwestia wydajności. Ale dziękicount
nie uzyskasz żądanej ilości danych. Ze względu na częściowe odczytyof
będą mniejsze niżcount*bs
na końcu.Więc kiedy używasz
count
, technicznie powinieneś zawsze również używaćiflag=fullblock
.+x
Powinna być liczba częściowych bloków.źródło
^ To po prostu zadziała. W przeciwnym razie błędne informacje są oczywiście fałszywe.
dd
Bufory są jawne, więc aby buforować dane wejściowe w celu zliczenia wystąpień, musisz je jawnie buforować. To wszystko. Nie kupuj dziwki.źródło