Dd ile rastgele veriler oluşturun ve “kısmi okuma uyarısı” alın. Uyarıdan sonraki veriler gerçekten rastgele mi?


16

Rastgele verilerle 1 TB dosya oluşturuyorum dd if=/dev/urandom of=file bs=1M count=1000000. Şimdi kill -SIGUSR1 <PID>ilerlemeyi kontrol ediyorum ve aşağıdakileri alıyorum :

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

Uyarıyı yorumlayamıyorum. Ne diyor? Uyarıdan sonra dosyam gerçekten rastgele mi yoksa bir sorun mu var? +0 veya +1 ne anlama geliyor 800950+1 Datensätze einve ne 800950+0 Datensätze ausanlama geliyor? Uyarıdan sonra +1 olur. Bir hata hesabı mı?


İletileri İngilizce'ye çevirebilseydiniz bunu yanıtlamak daha kolay olurdu. Ayrıca, "gerçekten rastgele" tanımlayın. Ne düzeyde bir rastgelelik istiyorsunuz, ne için kullanacaksınız?
terdon

İngilizce mesajlar almak LC_ALL=Ciçin komutun önünde kullanın, örneğinLC_ALL=C dd if=...
Volker Siegel

Yanıtlar:


38

Özet: dddoğru kullanımı zor olan huysuz bir araçtır. Size söyleyen çok sayıda öğreticiye rağmen bunu kullanmayın. ddeklenmiş bir "unix sokak kredisi" havası var - ancak ne yaptığınızı gerçekten anlarsanız, 10 metrelik bir direğe dokunmamanız gerektiğini bilirsiniz.

ddreadblok başına sistem çağrısına tek bir çağrı yapar (değeri ile tanımlanır bs). readSistem çağrısının belirtilen arabellek boyutu kadar veri döndürdüğünün garantisi yoktur . Bu normal dosyalar ve blok aygıtlar için çalışma eğilimindedir, ancak borular ve bazı karakter aygıtları için çalışmaz. Bkz . Dd veri kopyalamak için ne zaman uygundur? (veya daha fazla bilgi için okunduğunda () ve yazarken () kısmi) . Eğer readsistem çağrı getiri az bir tam blok, daha sonra ddkısmi blok aktarır. Yine de belirtilen sayıda bloğu kopyalar, bu nedenle aktarılan toplam bayt miktarı istenenden azdır.

“Kısmi okuma” ile ilgili uyarı size tam olarak bunu söyler: okumalardan biri kısaydı, bu yüzden ddeksik bir blok aktarıldı. Blok sayımlarında, +1bir bloğun kısmen okunduğu anlamına gelir; çıktı sayımı olduğundan +0, tüm bloklar okundu olarak yazılmıştır.

Bu, verilerin rasgeleliğini etkilemez: yazılan tüm baytlar ddokuduğu baytlardır /dev/urandom. Ama beklenenden daha az baytınız var.

Linux'un /dev/urandomkeyfi büyük istekleri (kaynak: extract_entropy_userin drivers/char/random.c) barındırdığı için, ddnormalde onlardan okurken güvenlidir. Ancak, büyük miktarda veri okumak zaman alır. İşlem bir sinyal alırsa, readsistem çağrısı çıkış arabelleğini doldurmadan önce geri döner. Bu normal bir davranıştır ve uygulamaların readbir döngü içinde çağrılması gerekir ; ddtarihi nedenlerden dolayı bunu yapmaz ( ddkökenleri bulanıktır, ancak kendine özgü gereksinimleri olan ve asla genel amaçlı bir araç olarak uyarlanmayan bantlara erişmek için bir araç olarak başlamış gibi görünüyor). İlerlemeyi kontrol ettiğinizde, bu ddsürece okuma işlemini kesen bir sinyal gönderir . Kaç bayt olduğunu bilmek arasında bir seçeneğiniz varddtoplam kopyalar (kesintiye uğramamayı unutmayın - ilerleme kontrolü yok, askıya alma yok) veya ddşu ana kadar kaç bayt kopyalandığını bilmek , bu durumda kaç bayt kopyalayacağını bilemezsiniz.

ddGNU coreutils (gömülü olmayan Linux ve Cygwin'de bulunan) sürümü, bir döngüde (ve ditto için ) çağırmayı ve böylece her zaman tam blokları aktarmayı fullblocksöyleyen bir bayrağa sahiptir . Hata iletisi, onu kullanmanızı önerir; çok özel durumlar (çoğunlukla bantlara erişirken) dışında her zaman kullanmalısınız (hem giriş hem de çıkış bayraklarında) - hiç kullanırsanız , yani: genellikle daha iyi çözümler vardır (aşağıya bakın).ddreadwritedd

dd if=/dev/urandom iflag=fullblock oflag=fullblock of=file bs=1M count=1000000

Ne ddyapacağından emin olmanın bir başka olası yolu , 1 blok büyüklüğünü geçmek. Sonra blok sayımından kaç bayt kopyalandığını söyleyebilirsiniz, ancak readilkini okumadan önce a kesilirse ne olacağından emin değilim. bayt (pratikte çok olası değildir, ancak olabilir). Ancak, çalışıyor olsa bile, bu çok yavaş.

Kullanımıyla ilgili genel tavsiye ddolduğunu kullanmayındd . ddGenellikle cihazlara erişmek için düşük seviyeli bir komut olarak ilan edilmesine rağmen , aslında böyle bir şey değildir: cihaz dosyasında (tüm /dev/…) tüm sihir gerçekleşir dd, sadece veri kaybına neden olan yanlış kullanım için yüksek potansiyele sahip sıradan bir araçtır. . Çoğu durumda, en azından Linux'ta istediğinizi yapmanın daha basit ve daha güvenli bir yolu vardır.

Örneğin, bir dosyanın başlangıcında belirli sayıda bayt okumak için şunu çağırmanız yeterlidir head:

head -c 1000000m </dev/urandom >file

Makinemde hızlı bir karşılaştırma yaptım ve ddbüyük bir blok boyutu ile arasında herhangi bir performans farkı gözlemlemedim head.

Eğer başında bazı bayt atlamanız gerekiyorsa, boru tailiçine head:

dd if=input of=output count=C bs=B seek=S
<input tail -c +$((S*B+1)) | head -c $((C*B)) >output

İlerlemeyi görmek istiyorsanız lsof, dosya ofsetini görmek için arayın . Bu, karakter aygıtında değil, yalnızca normal bir dosyada (örneğin çıktı dosyası) çalışır.

lsof -a -p 1234 -d 1
cat /proc/1234/fdinfo/1

Boru hattındaki ek bir kalem pahasına pvbir ilerleme raporu ( dd's'den daha iyi) almak için arayabilirsiniz (performans açısından, zar zor algılanabilir).


2
+1. Bu, StackExchange ağında uzun zamandır okuduğum en iyi araştırılmış yayınlardan biri. Bilmeliyim ddki bilmem gereken komuta ile ilgili tüm detayları (tarihi ve günümüz) özlüdür. Teşekkürler.
Kozmik Ossifrage

4
Üzgünüm ama dd "doğru kullanımı zor huysuz bir araç" ve "dd kullanmayın" iddiasına katılmıyorum. Anlamak için zaman ayıran biri tarafından doğru kullanıldığında mükemmel bir yardımcı programdır. Gerçekten de disk adli araç takımlarının neredeyse tamamı dd'ye veya dcfldd gibi bir türeve bağlıdır.
fpmurphy

1
@ fpmurphy1 GNU dd, fullblockseçeneği sayesinde güvenle kullanılabilir . Ancak GNU coreutils'iniz varsa ddçok fazla ihtiyacınız yoktur . “Türev” gibi dcflddolan değil dd cevabım kendileri için geçerli değildir bu yüzden onlar, kendi tasarım kusurları muzdarip değildir. Kullanan insanların büyük ve büyük bir çoğunluğu ddbunu anlamak için yeterli zaman almadı (en çok, anladıklarını düşünmek için zaman ayırdılar) ve kullanma şekilleri veri kaybına yol açar.
Gilles 'SO- kötü olmayı kes'

1
@Gilles Yani kötüye kullanma potansiyelinin "echo" b / c'sini kullanmamalıyız (sudo echo hello world> / dev / sda)?
whitey04

2
@ whitey04 Nitrogliserin varillerine dokunmamanızı tavsiye ederim. Kibrit kullanmamalısın demedim.
Gilles 'SO- kötü olmayı bırak

9

Uyarı, ddtek bir okumada bir bloğu dolduracak kadar veri alınamadığı zaman oluşur . Bu, düzensiz veya yavaş veri kaynaklarında veya istediğiniz blok boyutundan daha küçük birimlerde veri yazan kaynaklarda olur.

Veri bütünlüğüyle ilgili bir sorun yoktur, ancak sorun, ddkısmi bir okumayı hala bir okuma bloğu olarak saymasıdır.

countSeçeneği kullanmıyorsanız, uyarı pek önemli değildir, bu sadece bir performans konusudur. Ancak count, istediğiniz veri miktarını alamazsınız. Kısmi okumalar nedeniyle, sondan ofdaha küçük olacaktır count*bs.

Bu nedenle count, teknik iflag=fullblockolarak her zaman da kullanmalısınız .

+xKısmi blok sayısı olmalıdır.


-3
< /dev/urandom \
dd ibs=4k obs=64k |
dd bs=64k count=16000000 >file

^ Sadece işe yarayacak. Aksi takdirde burada yanlış bilgi olması açıkça yanlıştır. ddadlı kullanıcının arabellekleri açıktır ve bu nedenle, girdileri araları saymak için arabelleğe almak için açıkça arabelleğe almanız gerekir. Hepsi bu. Yumuşaklığı satın alma.

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.