it-swarm-id.com

dd vs cat - apakah hari ini masih relevan?

Baru-baru ini saya menyadari bahwa kita dapat menggunakan cat sebanyak dd, dan itu sebenarnya lebih cepat dari dd

Saya tahu bahwa dd berguna dalam menangani kaset yang ukuran bloknya benar dalam kebenaran, bukan hanya kinerja. Namun, pada hari-hari ini, adakah situasi di mana dd dapat melakukan sesuatu cat tidak bisa? (Di sini saya akan menganggap perbedaan kinerja kurang dari 20% tidak relevan.)

Contoh nyata akan lebih baik!

129
kizzx2

Dalam penampilan, dd adalah alat dari sistem operasi IBM yang mempertahankan penampilan asingnya (parameter passing-nya), yang melakukan beberapa fungsi yang sangat jarang digunakan (seperti EBCDIC ke ASCII konversi atau pembalikan endianness ... bukan kebutuhan umum saat ini).

Saya dulu berpikir bahwa dd lebih cepat untuk menyalin blok data yang besar pada disk yang sama (karena penggunaan buffering yang lebih efisien), tetapi ini tidak benar , setidaknya pada sistem Linux saat ini.

Saya pikir beberapa pilihan dd berguna ketika berhadapan dengan kaset, di mana pembacaan benar-benar dilakukan dalam blok (driver tape tidak menyembunyikan blok pada media penyimpanan seperti yang dilakukan oleh driver disk). Tapi saya tidak tahu secara spesifik.

Satu hal dd dapat melakukan itu tidak dapat (dengan mudah) dilakukan oleh alat POSIX lainnya adalah mengambil N byte pertama dari aliran. Banyak sistem dapat melakukannya dengan head -c 42, Tetapi head -c, Sementara umum, tidak ada dalam POSIX (dan tidak tersedia hari ini di mis. OpenBSD). (tail -c Adalah POSIX.) Juga, bahkan di mana head -c Ada, mungkin membaca terlalu banyak byte dari sumber (karena menggunakan stdio buffering secara internal), yang merupakan masalah jika Anda membaca dari file khusus di mana hanya membaca berpengaruh. (Saat ini GNU coreutils membaca jumlah pasti dengan head -c, Tetapi FreeBSD dan NetBSD menggunakan stdio.)

Secara umum, dd memberikan antarmuka ke file API yang mendasarinya yang unik di antara alat Unix: hanya dd dapat menimpa atau memotong file pada titik mana saja atau seek dalam file. (Ini adalah kemampuan unik dd, dan ini adalah yang besar; anehnya dd terkenal karena hal-hal yang dapat dilakukan oleh alat lain.)

  • Sebagian besar alat Unix menimpa file output mereka, yaitu menghapus isinya dan memulainya dari awal. Inilah yang terjadi ketika Anda menggunakan pengalihan > Di Shell juga.
  • Anda dapat menambahkan konten file dengan >> Pengalihan di Shell, atau dengan tee -a.
  • Jika Anda ingin mempersingkat file dengan menghapus semua data setelah titik tertentu, ini didukung oleh kernel dan C API yang mendasarinya melalui truncate berfungsi, tetapi tidak diekspos oleh alat baris perintah apa pun kecuali dd :

    dd if=/dev/null of=/file/to/truncate seek=1 bs=123456  # truncate file to 123456 bytes
    
  • Jika Anda ingin menimpa data di tengah file, sekali lagi, ini dimungkinkan dalam underyling API dengan opening file untuk ditulis tanpa memotong (dan memanggil lseek untuk pindah ke posisi yang diinginkan jika perlu), tetapi hanya dd dapat membuka file tanpa memotong atau menambahkan, atau mencari dari Shell ( contoh yang lebih kompleks misalnya ).

    # 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
    

Jadi ... Sebagai alat sistem, dd tidak berguna. Sebagai alat pengolah teks (atau file biner), itu cukup berharga!

Perintah dd mencakup BANYAK opsi yang tidak dapat diakomodasi oleh kucing. Mungkin dalam kasus penggunaan Anda kucing adalah pengganti yang bisa diterapkan, tetapi itu bukan pengganti dd.

Salah satu contoh akan menggunakan dd untuk menyalin bagian dari sesuatu tetapi tidak semuanya. Mungkin Anda ingin merobek beberapa bit dari tengah gambar iso atau tabel partisi dari hard drive berdasarkan lokasi yang diketahui pada perangkat. Dengan dd Anda dapat menentukan opsi mulai, berhenti dan jumlah yang memungkinkan tindakan ini.

Opsi dd ini membuatnya sangat diperlukan untuk manipulasi data berbutir halus sedangkan cat * hanya dapat beroperasi pada objek, perangkat, atau aliran file secara keseluruhan.

* Sebagaimana dicatat oleh Gilles dalam komentar, dimungkinkan untuk menggabungkan cat dengan alat lain untuk mengisolasi bagian dari sesuatu, tetapi cat masih beroperasi pada seluruh objek.

22
Caleb

Belum ada yang menyebutkan bahwa Anda dapat menggunakan dd untuk membuat file jarang , meskipun truncate juga dapat digunakan untuk tujuan yang sama.

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

Ini hampir instan dan membuat file besar sembarang yang dapat digunakan sebagai file loopback misalnya:

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

Yang menyenangkan adalah bahwa awalnya hanya menggunakan satu blok ruang disk, dan setelah itu tumbuh hanya sesuai kebutuhan (format ext4 dari file 10GB mengkonsumsi 291 MB pada sistem saya). Gunakan du untuk melihat seberapa banyak ruang disk yang sebenarnya digunakan - ls hanya melaporkan ukuran maksimum file yang mungkin tumbuh.

21

Mengganti segmen tertentu dari hard drive dengan sesuatu adalah contoh umum. Misalnya Anda mungkin ingin menghapus MBR Anda menggunakan perintah ini:

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

Anda juga dapat membuat file kosong dengan itu (katakan untuk gambar loop disk):

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

dd sangat berguna untuk mencadangkan sektor boot dari hard drive atau perangkat penyimpanan lainnya (dd if=/dev/sda of=boot_sector.bin bs=512 count=1) dan kemudian menulis ulang (dd if=boot_sector.bin of=/dev/sda). Ini juga berguna untuk membackup header volume terenkripsi.

cat mungkin bisa dipelintir untuk melakukan itu tetapi saya tidak akan mempercayainya pada bagian penulisan ulang. Sulit untuk mendapatkan cat hanya membaca/menulis sejumlah byte.

9
LawrenceC

Saya baru-baru ini memiliki alasan untuk mengkloning beberapa partisi 100-an-GB untuk pertama kalinya dalam sejarah linuxing saya (c.f cp -ar atau rsync yang telah membantu saya berkali-kali). Tentu saja saya beralih ke dd karena semua orang tahu itu yang Anda gunakan ... dan sangat terkejut dengan performanya. Sedikit googling segera membawa saya ke ddrescue , yang saya gunakan beberapa kali sekarang dan bekerja dengan sangat baik (jauh lebih cepat daripada dd).

5
timday

Berikut adalah beberapa trik yang saya buat selama bertahun-tahun ..

Potong-dan-Tempel pada mode bty tty atau non-interaktif

Jika Anda berada dalam situasi di mana EOF/^ D/^ F tidak terdeteksi, Anda dapat menggunakan dd untuk mentransfer file teks ke Host. Karena itu akan berhenti membaca setelah jumlah byte yang ditentukan secara otomatis.

Saya menggunakan ini baru-baru ini tahun lalu selama latihan keamanan di mana kami bisa mendapatkan kerang non-tty pada Host jarak jauh dan diperlukan untuk mentransfer file.

Bahkan, saya bahkan melakukan beberapa file biner dengan base64 mengkodekannya dan menggunakan script decoding pure-bash base64 murni yang lambat.

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

Trik super keren adalah ketika dd sedang berjalan, jika Anda mengirimkan sinyal USR1, itu akan mengeluarkan statusnya saat ini (byte baca, byte per detik ..)

Filter status throughput universal

Saya menulis ini untuk bertindak sebagai filter kemajuan bash murni untuk setiap program yang memancarkan data melalui stdout. (Catatan: Hampir semua hal akan memancarkan data melalui stdout - untuk program yang tidak, Anda dapat menipu jika mereka tidak menganggap Anda menggunakan/dev/stdout sebagai nama file. Tetapi idenya pada dasarnya, setiap kali Anda mendapatkan X jumlah byte, cetak tanda pagar (seperti FTP sekolah lama saat mode hash Anda aktif)

(Catatan) Berkas progresnya payah, ini sebagian besar merupakan bukti konsep. Jika saya redid, saya hanya akan menggunakan variabel.

 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

file slice-and-dadu menggunakan filehandles Shell anonim

Berikut adalah contoh kode sangat pseudo tentang bagaimana Anda dapat memiliki file tar yang ditandatangani yang dapat Anda ekstrak tanpa kesalahan dengan memberikan input tar melalui penanganan file anonim - tanpa menggunakan file tmp apa pun untuk menyimpan data file parsial.

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 adalah: Saya menemukan dd sangat berguna. Dan ini hanya tiga contoh yang bisa saya pikirkan dari atas kepala saya.

5
synthesizerpatel

Anda dapat mengarahkan beberapa konten keluaran. Ini sangat berguna, jika Anda perlu menulis dengan Sudo:

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

Selain Sudo itu setara dengan:

echo some_content > output.txt

atau ini:

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