it-swarm-tr.com

DD vs Cat - DD bugünlerde hala geçerli mi?

Son zamanlarda cat'yi dd kadar kullanabileceğimizi fark ettim ve aslında dd

dd'ın sadece performansın değil, blok boyutunun gerçekten doğrulukta önemli olduğu bantlarla uğraşmada yararlı olduğunu biliyorum. Ancak bu günlerde dd'nin cat'nin yapamayacağı bir şey yapabileceği durumlar var mı? (Burada% 20'den az performans farkının önemsiz olduğunu düşünürüm.)

Somut örnekler güzel olurdu!

129
kizzx2

Görünüşte, dd , çok nadiren kullanılan bazı işlevleri (EBCDIC - ASCII dönüşümler veya endianitenin tersine çevrilmesi… günümüzde yaygın bir ihtiyaç değildir).

Ben düşünmek için kullanılırdd aynı diskteki büyük veri bloklarını kopyalamak için daha hızlıydı (arabelleğe almanın daha verimli kullanılması nedeniyle), ancak bu doğru değil , en azından bugünün Linux sistemlerinde.

Ben dd 'seçeneklerinden bazıları okuma gerçekten bloklar halinde gerçekleştirilir kasetlerle uğraşırken yararlı olduğunu düşünüyorum (teyp sürücüleri disk sürücüleri gibi depolama ortamında blokları gizlemek yok). Ama detayları bilmiyorum.

dd başka bir POSIX aracı tarafından yapılamayan bir şey , ilk N baytını almaktır. Akış. Birçok sistem bunu head -c 42 İle yapabilir, ancak head -c Yaygın olsa da POSIX'te değildir (ve bugün OpenBSD'de mevcut değildir). (tail -c POSIX'tir.) Ayrıca, head -c Mevcut olsa bile, kaynaktan çok fazla bayt okuyabilir (çünkü dahili olarak stdio arabelleğe alma kullandığından), bu da okuyorsanız bir sorundur sadece okumanın etkili olduğu özel bir dosyadan. (Geçerli GNU coreutils head -c İle tam sayıyı okuyor, ancak FreeBSD ve NetBSD stdio kullanıyor.)

Daha genel olarak, dd temel dosya API'sına Unix araçları arasında benzersiz olan bir arabirim verir: yalnızca dd üzerine yazabilir veya kesebilir herhangi bir noktada bir dosya veya bir dosyada arayın. (Bu dd 'ın benzersiz yeteneğidir ve büyük bir yetenektir; garip bir şekilde dd en iyi diğer araçların yapabileceği şeyler için bilinir.)

  • Çoğu Unix aracı çıktı dosyalarının üzerine yazar, yani içeriğini silin ve sıfırdan başlatın. Kabuk'ta da > Yönlendirmesini kullandığınızda olan şey budur.
  • Kabuktaki >> Yeniden yönlendirmesiyle veya tee -a İle bir dosyanın içeriğine ekleyebilirsiniz.
  • Bir dosyayı tüm verileri kaldırarak kısaltmak istiyorsanız belirli bir noktadan sonra, bu temel çekirdek ve C API'sı ile truncate işlevi, ancak herhangi bir komut satırı aracı tarafından gösterilmiyor dd hariç:

    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 yine alt çizgi API'sında open dosyayı kesmeden yazmak için (ve lseek gerekiyorsa istenen konuma gitmek için), ancak yalnızca dd bir dosyayı kesmeden veya eklemeden açabilir veya Kabuktan seek açabilir ( daha karmaşık ö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, dd neredeyse işe yaramaz. Bir metin (veya ikili dosya) işleme aracı olarak oldukça değerlidir!

dd komutu, kedinin barınamadığı çok sayıda seçenek içerir. Belki kullanım durumlarınızda kedi uygulanabilir bir alternatiftir, ancak bir dd yedeği değildir.

Bir örnek, bir şeyin bir kısmını kopyalamak için değil, dd kullanmaktır. Belki de bir parça görüntünün ortasından bazı bitleri veya bölüm tablosunu, aygıttaki bilinen bir konuma göre sabit sürücüden çıkarmak isteyebilirsiniz. dd ile bu eylemlere izin veren başlatma, durdurma ve miktar seçeneklerini belirleyebilirsiniz.

Bu dd seçenekleri ince taneli veri manipülasyonu için vazgeçilmez kılarken, cat * yalnızca tüm dosya nesneleri, aygıtlar veya akışlarda çalışabilir.

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

22
Caleb

Henüz hiç kimse seyrek dosyalar oluşturmak için dd'yi kullanabileceğinizden bahsetmedi, ancak truncate aynı amaç için de kullanılabilir.

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

Bu neredeyse anında gerçekleşir ve örneğin, geri döngü dosyası olarak kullanılabilen rastgele 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ı bloğu kullanması ve daha sonra yalnızca gerektiği gibi büyümesidir (10GB'lık bir dosyanın ext4 biçimlendirmesi sistemimde 291 MB tüketir). Ne kadar disk alanı kullanıldığını görmek için du kullanın - ls yalnızca dosyanın büyüyebileceği maksimum boyutu bildirir.

21

Bir sabit sürücünün belirli bölümlerini bir şeyle geçersiz kılmak yaygın 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 deyin):

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

dd, bir sabit sürücünün veya başka bir depolama aygıtının önyükleme kesimini yedeklemek için çok kullanışlıdır (dd if=/dev/sda of=boot_sector.bin bs=512 count=1) ve daha sonra yeniden yazıyor (dd if=boot_sector.bin of=/dev/sda). Aynı şekilde şifrelenmiş birimlerin başlıklarını yedeklemek için de kullanışlıdır.

cat bunu yapmak için bükülmüş olabilir, ancak yeniden yazma bölümünde güvenmezdim. cat öğesinin yalnızca belirli sayıda baytı okuması/yazması zor.

9
LawrenceC

Son zamanlarda linuxing geçmişimde ilk defa 100'lerin GB'lık bölümlerini klonlama nedenim vardı (c.f cp -ar veya rsync). Tabii ki dd 'ya döndüm çünkü herkes bunu kullandığını biliyor ... ve performanstan dehşete düşmüştü. Biraz googling beni yakında ddrescue olarak yönlendirdi.

5
timday

İşte yıllar boyunca ortaya koyduğum bazı hileler ..

Düşmanca tty veya etkileşimli olmayan mod bash üzerinde Kes ve Yapıştır

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

Bunu geçtiğimiz yıl kadar uzak bir Ana Makinede tty olmayan kabuklar alabildiğimiz ve dosyaları aktarmamız gereken bir güvenlik tatbikatında kullandım.

Aslında, onları kodlayan 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 bir hile, dd çalışırken, bir USR1 sinyali gönderirseniz, mevcut durumunu (bayt okundu, saniye başına bayt ..) gönderir.

Evrensel işlem durumu filtresi

Bunu, stdout yoluyla veri yayan herhangi bir program için saf bir bash ilerleme filtresi olarak görev yaptım. (Not: Hemen hemen her şey stdout aracılığıyla veri yayar - olmayan programlar için/dev/stdout'u dosya adı olarak kullanarak size engel olmuyorlarsa hile yapabilirsiniz.Ancak fikir, her X aldığınızda bayt miktarı, yazdırma karması işaretleri (karma modunuz açıkken eski okul FTP'si gibi)

(Not) İlerleme dosyası şey topal, bu çoğunlukla bir kavram kanıtıydı. Eğer redid edersem, 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 Shell dosya tanıtıcıları kullanarak dilim ve zar dosyaları

Burada, kısmi dosya verilerini depolamak için herhangi bir tmp dosyası kullanmadan, anonim bir dosya tanıtıcısı aracılığıyla tar girdisi sağlayarak hatasız bir şekilde ayıklayabileceğiniz imzalı bir tar dosyasına nasıl sahip olabileceğinize dair son derece sahte bir 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'yi inanılmaz faydalı buluyorum. Ve bunlar sadece kafamın üstünde düşünebileceğim üç örnek.

5
synthesizerpatel

Bazı çıktı içeriklerini yeniden yönlendirebilirsiniz. Sudo ile yazmanız gerekiyorsa özellikle kullanışlıdır:

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

Sudo yanında:

echo some_content > output.txt

veya buna:

echo some_content | Sudo tee output.txt > /dev/null
5
Alexey