dd vs kedi - bu günlerde hala dd alakalı mı?


122

Geçenlerde kullanabileceğimiz fark catkadar ddve bu kadar aslında daha hızlıdd

Bunun dd, blok büyüklüğünün sadece performansta değil, doğrulukta önemli olduğu kasetlerle uğraşırken de faydalı olduğunu biliyorum . Bu günlerde, ddyapamayacağınız bir şeyin catyapamadığı durumlar var mı? (Burada alakasız% 20'den az performans farkı görecektim.)

Somut örnekler iyi olurdu!


1
Somut bir örnek için bu SO soruya bakınız .
camh

Yanıtlar:


156

Görünüşe göre, ddçok nadir kullanılan bazı işlevleri yerine getiren (örneğin günümüzde yaygın bir ihtiyaç olmayan, ASCII'den ASCD'ye dönüşümler veya endianness tersine çevirme gibi) yabancı görünümünü koruyan (parametre geçişi) IBM işletim sisteminden bir araçtır.

Ben düşünürdüm o dddaha hızlı (nedeniyle tamponlama daha verimli kullanılmasına) aynı disk üzerinde büyük veri bloklarını kopyalamak için, ama bu doğru değildir , en azından bugünkü Linux sistemlerinde,.

Bazı ddseçeneklerin kasetlerle uğraşırken, okuma işleminin gerçekten bloklar halinde yapıldığı durumlarda yararlı olduğunu düşünüyorum (manyetik bant sürücüleri, disk ortamında olduğu gibi depolama ortamındaki blokları gizlemez). Ama detayları bilmiyorum.

Bir şey ddyapabilir (kolayca) başka herhangi bir POSIX araç tarafından yapılamaz ilk N bayt alma bir akışın. Pek çok sistem bunu yapabilir head -c 42, ancak head -cortak olsa da POSIX'te değildir (ve bugün örneğin OpenBSD'de mevcut değildir). ( tail -cPOSIX'dir.) Ayrıca, var olsa bile head -c, kaynaktan çok fazla sayıda bayt okuyabilir (dahili olarak stdio arabelleğini kullandığından), bu yalnızca okumanın etkili olduğu özel bir dosyadan okuyorsanız bir sorundur. (Mevcut GNU coreutils ile kesin sayı okunur head -c, ancak FreeBSD ve NetBSD stdio kullanır.)

Daha genel olarak ddUnix araçları arasında tek olan altta yatan dosya API bir arabirim verir: Sadece ddedebilir üzerine veya kesmek bir dosya herhangi bir noktada ya da aramak bir dosyada. (Bu ddeşsiz bir yetenek ve büyük bir yetenek; garip bir şekilde dd, diğer araçların yapabileceği şeyler için en iyi şekilde bilinir.)

  • Çoğu Unix aracı çıktı dosyasının üzerine yazar, yani içeriğini silip sıfırdan başlatır. Bu, >kabuktaki yönlendirmeyi de kullandığınızda olur .
  • Bir dosyanın içeriğini >>, kabuktaki yeniden yönlendirme ile veya ile ekleyebilirsiniz tee -a.
  • Belirli bir noktadan sonra tüm verileri kaldırarak bir dosyayı kısaltmak istiyorsanız , bu truncateişlev temelde yatan çekirdek ve C API tarafından desteklenir , ancak aşağıdakiler dışındadd hiçbir komut satırı aracı tarafından gösterilmez :

    dd if=/dev/null of=/file/to/truncate seek=1 bs=123456  # truncate file to 123456 bytes
    
  • Bir dosyanın ortasındaki verilerin üzerine yazmak istiyorsanız, bu, underling API'sinde dosyayı kesmeden yazmak için açarak (ve lseekgerektiğinde istenen konuma gitmek için çağırarak ) mümkündür, ancak yalnızca dddosyayı açmadan açabilirsiniz. kesiliyor, ekliyor veya kabuğundan araştırıyorsunuz ( daha karmaşık bir örnek ).

    # zero out the second kB block in the file (i.e. bytes 1024 to 2047)
    dd if=/dev/zero of=/path/to/file bs=1024 seek=1 count=1 conv=notrunc
    

Yani… Bir sistem aracı olarak, ddhemen hemen işe yaramaz. Bir metin (veya ikili dosya) işleme aracı olarak, oldukça değerli!


Kabul edildi çünkü bence diğer cevapların ana fikrini açıklıyor ( truncve ondan seekkullanılabilir dd).
kizzx2

2
Bir başka özel kullanım: ddstdio arabelleği nedeniyle okunmamış verileri potansiyel olarak imha etmeden, dikkate alınamayan dosya tanımlayıcılarından ikili verileri okuyabilir. Örnek için buraya bakınız: etalabs.net/sh_tricks.html
R. ..

2
@R ..: Evet. GNU çekirdeklerinde 6.10, head -c Nçağırır readve hiçbir zaman N'nin ötesine geçmez. NetBSD 5.1'de head -cçağırır getc. FreeBSD 7.4'te head -cçağrılar fread.
Gilles,

1
Coreutils ddayrıca, O_DIRECT (vb.) 'İ de benzersiz olduğunu düşündüğüm kabuk komut dosyasına maruz bırakır.
derobert, 16

1
Coreutils truncate, dosyaların kesilmesine veya genişletilmesine izin verir, böylece başka bir kullanımını ortadan kaldırır dd.
dcoles 17:18

22

Bu ddkomut, kedinin barınamadığı LOTS seçeneklerini içerir. Belki de kullanım durumunuzda kedi uygulanabilir bir ikamedir, ancak bir dd ikame değildir.

Bir örnek dd, bir şeyin bir kısmını kopyalamak için kullanmak , her şeyi değil. Belki bir parça görüntüyü ortasından veya bölüm tablosundan cihazdaki bilinen bir yere dayanarak bir sabit diskten çıkarmak istiyorsunuz. İle ddbu işlemlere izin veren start, stop ve miktar seçeneklerini belirleyebilirsiniz.

Bu seçenekler ddince taneli veri işlemesi için vazgeçilmez kılar, oysa cat* sadece tüm dosya nesneleri, aygıtlar veya akışlarda çalışabilir.

* Gilles tarafından yorumlarda belirtildiği gibi cat, bir şeyin parçalarını izole etmek için diğer araçlarla birleştirmek mümkündür , ancak catyine de tüm nesne üzerinde çalışır.


5
ddaslında düşük seviye cihazlarla ilgisi yok /dev, diğerleri gibi bir giriş yapması gerekiyor . Tüm bir bölümü catveya onun bir bölümünü kopyalayabilirsiniz tail +c $(($start+1)) | head -c $count.
Gilles,

16
Tabii ki. ;-) Ve cat | head | tailson birkaç MB'yi almak için bir 1.6TB disk görüntüsünü beslediğimde , disk dönüşü, dünyaya daha yakın olan ayı emecek.
Caleb

2
@Gilles Üzgünüm, "düşük seviye" terimini kullanmamın, cihazlara değil cihazlara ilişkin verilere atıfta bulunmama rağmen, çok iyi bir diksiyon olmadığını kabul etmek istemiştim. Belki de "ince ayarlanmış veri manipülasyonu", "düşük seviyeli veriyi manipüle etmekten" daha iyidir.
Caleb

21

Hiç kimse seyrek dosyalar oluşturmak için dd'yi kullanabileceğinizi ancak yine truncatede aynı amaç için kullanabileceğinizi belirtmedi .

dd if=/dev/zero of=sparse-file bs=1 count=1 seek=10GB

Bu neredeyse anında gerçekleşir ve örneğin geridöngü dosyası olarak kullanılabilecek isteğe bağlı büyük bir dosya oluşturur:

loop=`losetup --show -f sparse-file`
mkfs.ext4 $loop
mkdir myloop
mount $loop myloop

Güzel olan şey, başlangıçta yalnızca tek bir disk alanı kullanması ve daha sonra yalnızca gerektiği kadar büyümesi (10GB'lık bir dosyanın ext4 formatlaması sistemimde 291 MB tüketiyor). duNe kadar disk alanı kullanıldığını görmek için kullanın - lsyalnızca dosyanın büyüyebileceği maksimum boyutu rapor eder.


4
ls -lssize seyrek boyutunu gösterir.
jmtd

2
Komutunuz, dosyaya gereksiz bir bayt yazar. dd of=sparse-file bs=1 count=0 seek=10Geşdeğer olurdu truncate -s 10GB sparse-file. Confusingly yeterli, truncateve ddtam tersi yorumunu var GBvs G...
frostschutz

5
@frostschutz: man dddiyor: MB =1000*1000, M =1024*1024vb. Ve man truncatediyor ki:, MB 1000*1000, M 1024*1024yani hiçbir fark yoktur. Ben ikisini de kullanmak ddve truncateGNU coreutils gelen. Sen de yapmalısın! :-)
erik

@ erik: Düzeltme için teşekkürler. Son zamanlarda değişmediyse, bir şekilde başka bir şeyle karıştırmalıydım.
frostschutz

10

Sabit sürücünün belirli bölümlerini geçersiz kılmak, ortak bir örnektir. Örneğin, bu komutu kullanarak MBR'nizi silmek isteyebilirsiniz:

dd if=/dev/zero of=/dev/sda bs=446 count=1

Ayrıca onunla boş dosyalar oluşturabilirsiniz (döngü diski görüntüleri için söyleyin):

dd if=/dev/zero of=10mb.file bs=1024k count=10

Bir kenara, ikinci komut 10MB'yi kadar kullanmak Bildiğim en hızlı şekilde olduğu gibi
Kevin M

3
@Kevin: Daha hızlı head -c? Lütfen bir kıyaslama paylaşın !
Gilles

9

ddbir sabit sürücünün veya diğer depolama aygıtının ( dd if=/dev/sda of=boot_sector.bin bs=512 count=1) önyükleme kesimini yedeklemek ve daha sonra yeniden yazmak için çok yararlıdır ( dd if=boot_sector.bin of=/dev/sda). Benzer şekilde şifreli birimlerin başlıklarını yedeklemek için de kullanışlıdır.

catBunu yapmak için bükülmüş olabilir, ancak yeniden yazma kısmında buna güvenmezdim. Sadece catbelirli sayıda bayt okumak / yazmak zor .


5

Geçenlerde, linuxing tarihimde ilk kez 100'lerin üzerinde birkaç GB'lik bölümleri klonlamaya neden oldum (cf cp -arveya rsyncbana birçok kez hizmet etti). Tabii ki döndüm dd'çünkü herkes kullandığın şeyin bu olduğunu biliyor ... Birazcık googling birazdan beni yönlendirdi ddrescue, ki şimdi birkaç kez kullandım ve çok iyi çalışıyor (dd'den çok daha hızlı).


1
ddrescueözellikle hatalı disklerden veri almak için harika.
ryenus

5

İşte yıllar boyunca ortaya attığım bazı hileler ..

Düşmanca olmayan veya etkileşimli olmayan modda kes ve yapıştır

EOF / ^ D / ^ F'nin algılanmadığı bir durumdaysanız, metin dosyalarını bir ana bilgisayara aktarmak için dd kullanabilirsiniz. Belirli bir bayt miktarından sonra otomatik olarak okumayı durduracağından.

Bunu, geçen yılki gibi uzak bir ana bilgisayarda tty olmayan mermiler alabildiğimiz ve dosyaları aktarmak için gerekli olan bir güvenlik alıştırması sırasında kullandım.

Aslında, onları kodlayan base64 kullanarak ve yavaş ama güvenilir bir saf-bash base64 kod çözme komut dosyası kullanarak birkaç ikili dosya bile yaptım.

dd of=textfile.txt bs=1 count=<size_of_data_in_paste_buffer>

Süper havalı bir hile şu ki dd çalışırken, eğer bir USR1 sinyali gönderirseniz, o anki durumunu yayar (bayt okundu, saniye başına bayt sayısı ..)

Evrensel geçiş durumu filtresi

Bunu, stdout aracılığıyla veri yayan herhangi bir program için saf bir bash ilerleme filtresi gibi davranması için yazdım. (Not: Hemen hemen her şey stdout aracılığıyla veri yayar - yapmayan programlar için, eğer / dev / stdout'u dosya adı olarak kullanmaktan alıkoymazlarsa hile yapabilirsiniz. bayt miktarı, karma işaretleri yazdır (karma modu açıkken eski okul FTP gibi)

(Not) İlerleme dosyası olayı topal, bu çoğunlukla bir konsept kanıtıydı. Yeniden yazsaydım, sadece bir değişken kullanırdım.

 dd bs=$BLKSZ of=${TMPFILE} 2>&1 \
                | grep --line-buffered -E '[[:digit:]]* bytes' \
                | awk '{ print $1 }' >> ${PROGRESS} &

 while [[ $(pidof dd) -gt 1 ]]; do

        # PROTIP: You can sleep partial seconds
        sleep .5

        # Force dd to update us on it's progress (which gets
        # redirected to $PROGRESS file.    
        pkill -USR1 dd
        local BYTES_THIS_CYCLE=$(tail -1 $PROGRESS)
        local XFER_BLKS=$(((BYTES_THIS_CYCLE-BYTES_LAST_CYCLE)/BLKSZ))

        if [ $XFER_BLKS -gt 0 ]; then
                printf "#%0.s" $(seq 0 $XFER_BLKS)
                BYTES_LAST_CYCLE=$BYTES_THIS_CYCLE
        fi
done

anonim kabuk filehandles kullanarak dilim-ve-zar dosyaları

Kısmi dosya verilerini depolamak için herhangi bir tmp dosyası kullanmadan, anonim bir dosya kilidi üzerinden tar girişi sağlayarak, hatasız ayıklayabileceğiniz imzalı bir tar dosyasına nasıl sahip olabileceğinize dair son derece sahte kod örneği.

generate_hash() {
    echo "yay!"
}

# Create a tar file, generate a hash, append it to the end
tar -cf log.tar /var/log/* 2>/dev/null
TARFILE_SIZE=$(stat -f "%z" log.tar)
SIGNATURE=$(generate_hash log.tar)
echo $SIGNATURE >>log.tar

# Then, later, extract without getting an error..

tar xvf <(dd if=$OLDPWD/log.tar bs=1 count=${TARFILE_SIZE})

Tl; dr: dd'nin inanılmaz derecede faydalı olduğunu düşünüyorum. Ve bunlar kafamın üstünden düşünebildiğim sadece üç örnek.


4

Bazı çıktı içeriğini yönlendirebilirsiniz. Yazmanız gerekirse, özellikle yararlıdır sudo:

echo some_content | sudo dd status=none of=output.txt

Bunun yanında sudoeşdeğerdir:

echo some_content > output.txt

veya buna:

echo some_content | sudo tee output.txt > /dev/null

İyi bir nokta.
Stdout'ta
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.