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!
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ır
dd 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.)
>Yönlendirmesini kullandığınızda olan şey budur.
>>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.
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.
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
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.
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.
İşte yıllar boyunca ortaya koyduğum bazı hileler ..
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.
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
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.
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