ДД проти котів - чи актуально сьогодні ДД?


122

Нещодавно я зрозумів, що ми можемо використати catстільки ж dd, і це насправді швидше, ніжdd

Я знаю, що ddбуло корисно в роботі зі стрічками, де розмір блоку насправді мав значення в правильності, а не просто у виконанні. Хоча в ці дні існують ситуації, коли ddзробити щось catнеможливо? (Тут я вважаю, що різниця в продуктивності менше ніж 20%.)

Конкретні приклади були б непогані!


1
Дивіться це питання ПУ на одному конкретному прикладі.
camh

Відповіді:


156

На вигляд, ddце інструмент операційної системи IBM, який зберіг свій зовнішній вигляд (передача його параметрів), який виконує деякі дуже рідко використовувані функції (наприклад, перетворення EBCDIC в ASCII або перетворення ендіансів… в даний час не є загальною потребою).

Раніше я думав, що ddце швидше для копіювання великих блоків даних на той же диск (за рахунок більш ефективного використання буферизації), але це неправда , принаймні в сучасних системах Linux.

Я думаю, що деякі з ddваріантів корисні для роботи із стрічками, де читання справді виконується блоками (драйвери стрічок не приховують блоки на носії інформації, як це роблять драйвери диска). Але я не знаю конкретики.

ddМожна зробити одне , що неможливо (легко) зробити будь-який інший інструмент POSIX - це взяти перші N байт потоку. Багато систем можуть це робити head -c 42, але head -c, хоча це звичайно, немає в POSIX (і сьогодні недоступний, наприклад, на OpenBSD). ( tail -cце POSIX.) Крім того, навіть там, де head -cіснує, він може прочитати занадто багато байтів із джерела (оскільки він використовує внутрішню буферизацію stdio), що є проблемою, якщо ви читаєте із спеціального файлу, де саме читання має ефект. (Поточні ядра GNU читають точний підрахунок head -c, але FreeBSD і NetBSD використовують stdio.)

Загалом, ddнадає інтерфейс базового файлового API, який є унікальним серед інструментів Unix: лише ddможна перезаписати або врізати файл у будь-якій точці або шукати файл. (Це ddунікальна здатність, і вона велика; як не дивно, ddце найкраще відомо для речей, які можуть робити інші інструменти.)

  • Більшість інструментів Unix перезаписують вихідний файл, тобто стирають його вміст і запускають його з нуля. Це те, що відбувається, коли ви також використовуєте >перенаправлення в оболонці.
  • Ви можете додати вміст файлу з >>перенаправленням в оболонку або з tee -a.
  • Якщо ви хочете скоротити файл, видаливши всі дані після певного моменту , це підтримується базовим ядром та API API через truncateфункцію, але не піддається впливу будь-якого інструменту командного рядка, крімdd :

    dd if=/dev/null of=/file/to/truncate seek=1 bs=123456  # truncate file to 123456 bytes
    
  • Якщо ви хочете перезаписати дані в середину файлу, це повторно можливо, в API-інтерфейсі, що відкриває файл, відкриваючи файл для запису без обрізання (і за необхідності закликаючи lseekперейти на потрібну позицію), але лише ddможна відкрити файл без обрізати або додавати, або шукати з оболонки ( більш складний приклад ).

    # 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
    

Отже… Як системний інструмент, ddв значній мірі марний. Як інструмент для обробки тексту (або двійкового файлу), він досить цінний!


Прийнято тому, що, на мою думку, це пояснює суть інших відповідей ( truncі seekїх можна використовувати dd).
kizzx2

2
Ще одне особливе використання: ddможе читати бінарні дані з нерозбірливих дескрипторів файлів, не потенційно знищуючи непрочитані дані через буферизацію stdio. Дивіться тут приклад: etalabs.net/sh_tricks.html
R ..

2
@R ..: Так. У GNU coreutils 6.10 head -c Nдзвінки readі ніколи не виходять за межі N. У NetBSD 5.1 head -cвиклики getc. У FreeBSD 7.4 head -cдзвінки fread.
Жиль

1
Coreutils ddтакож виставляє O_DIRECT (тощо) сценаріїв оболонок, що, на мою думку, також унікальне.
дероберт

1
Coreutils truncateдозволяє обрізати або розширювати файли, тим самим виключаючи інше використання dd.
dcoles

22

ddКоманда включає в себе безліч опцій , які кішка не в змозі вмістити. Можливо, у ваших випадках використання кішка є працездатною заміною, але це не заміна DD.

Одним із прикладів може бути ddкопіювання частини чогось, але не всієї справи. Можливо, ви хочете вирвати деякі біти з середини ізо-зображення або таблиці розділів з жорсткого диска на основі відомого місця на пристрої. За допомогою нього ddможна вказати параметри початку, зупинки та кількості, які дозволяють виконувати ці дії.

Ці параметри ddроблять його незамінним для маніпулювання дрібнозернистими даними, тоді як cat* може працювати лише на цілих файлових об'єктах, пристроях або потоках.

* Як зазначив Гілль у коментарях, можна catвиділити інші інструменти для ізоляції частин чогось, але catвсе-таки діють на весь об’єкт.


5
ddнасправді не має нічого спільного з пристроями низького рівня, йому потрібен запис, /devяк і інші. Ви можете скопіювати цілий розділ cat, або частину його за допомогою tail +c $(($start+1)) | head -c $count.
Жиль

16
Звичайно. ;-) І коли я ввожу зображення диска 1,6 Тб, cat | head | tailщоб отримати останні кілька МБ, диск розгортається, висмоктує місяць ближче до землі.
Калеб

2
@Gilles Вибачте, що я мав на увазі, що я використовував термін "низький рівень" не дуже вдала дикція, хоча я мав на увазі дані на пристроях, а не на пристроях. Можливо, "точне налаштування маніпулювання даними" було б краще, ніж "маніпулювання даними низького рівня".
Калеб

21

Ще ніхто не згадував, що ви можете використовувати dd для створення розріджених файлів , хоча truncateвони також можуть бути використані з тією ж метою.

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

Це майже миттєво і створює довільний великий файл, який може використовуватися, наприклад, як файл зворотного зв'язку:

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

Приємно те, що спочатку він використовує лише один блок дискового простору, а потім зростає лише в міру необхідності (форматування ext4 файлу 10 Гб в моїй системі витрачає 291 Мб). Використовуйте duдля того, щоб побачити, скільки фактично використовується дискового простору - lsповідомляє лише про максимальний розмір, до якого може зростати файл.


4
ls -lsпоказує вам розріджений розмір.
jmtd

2
Ваша команда записує у файл марний байт. dd of=sparse-file bs=1 count=0 seek=10Gбуло б рівнозначно truncate -s 10GB sparse-file. Досить truncateddGBG
заплутано

5
@frostschutz: man ddкаже: MB =1000*1000, M =1024*1024і так далі. І man truncateкаже: MB 1000*1000, M 1024*1024так що різниці немає. Я використовую як ddі truncateGNU coreutils. Ви повинні зробити це теж! :-)
Ерік

@erik: Дякую за виправлення. Якщо вона не була змінена нещодавно, я, мабуть, якось переплутав її з чимось іншим.
frostschutz

10

Переопределення конкретних сегментів жорсткого диска з чимось є загальним прикладом. Наприклад, ви можете видалити MBR за допомогою цієї команди:

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

Також ви можете створювати порожні файли за допомогою нього (скажімо, для зображень циклу):

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

Як осторонь, ця друга команда - це найшвидший спосіб, який я знаю, щоб використати 10 Мб
Кевін М

3
@Kevin: Швидше head -c? Будь ласка, поділіться орієнтиром !
Жиль

9

ddдуже корисно для резервного копіювання завантажувального сектора жорсткого диска або іншого пристрою зберігання даних ( dd if=/dev/sda of=boot_sector.bin bs=512 count=1), а потім для подальшого його перезапису ( dd if=boot_sector.bin of=/dev/sda). Це також корисно для резервного копіювання заголовків зашифрованих томів.

catМожливо, це вдасться скрутити, але я б не довіряв цьому на частині переписування. Важко дістатись catлише до читання / запису певної кількості байтів.


5

Нещодавно у мене вперше в моїй історії linuxing було клонування декількох розділів на 100 ГБ (див. cp -arАбо rsyncякі мені служили багато разів). Звичайно, я звернувся до dd«тому, що всі знають, що це ви використовуєте ... і був вражений виставою. Трохи гуґолінг незабаром привів мене до цього ddrescue, яким я користувався вже кілька разів і працює чудово (набагато швидше, ніж ДД).


1
ddrescueчудово, особливо для отримання даних з несправних дисків.
ryenus

5

Ось декілька хитрощів, які я придумав протягом багатьох років.

Вирізати та вставити на недружній тти або неінтерактивний режим гри

Якщо ви знаходитесь у ситуації, коли EOF / ^ D / ^ F не виявлено, ви можете використовувати dd для передачі текстових файлів хосту. Оскільки він автоматично припинить читання після заданої кількості байтів.

Я використовував це нещодавно, як минулого року, під час навчань із безпеки, де нам вдалося отримати невід’ємні оболонки на віддаленому хості та потрібні для передачі файлів у.

Насправді я навіть зробив пару бінарних файлів, кодуючи їх base64 і використовуючи повільний, але надійний сценарій декодування base-bash bas64.

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

Супер класна хитрість полягає в тому, що під час запуску dd, якщо ви надсилаєте йому сигнал USR1, він видаватиме його поточний статус (читання байтів, байтів в секунду ..)

Універсальний фільтр стану пропускної здатності

Я написав це, щоб діяти як чистий фільтр прогресу для будь-якої програми, яка випромінює дані через stdout. (Примітка: майже що-небудь передаватиме дані через stdout - для програм, які цього не роблять, ви можете обдурити, якщо вони не поспішають на вас, використовуючи / dev / stdout як ім'я файлу. Але ідея полягає в основному кожен раз, коли ви отримуєте X кількість байтів, друкуйте хеш-позначки (наприклад, старі шкільні FTP, коли увімкнено хеш-режим)

(Примітка) Справа у файлі прогресу кульгава, це було переважно доказом концепції. Якби я його повторно використав, я просто використав би змінну.

 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

файли з нарізаними кубиками за допомогою анонімних файлів оболонок

Ось надзвичайно псевдокодовий приклад того, як ви можете мати підписаний файл tar, який ви можете витягти без помилок, надаючи вкладку tar через анонімний файл файлового файлу - не використовуючи жодних tmp-файлів для зберігання часткових файлових даних.

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: я вважаю, що ДД є надзвичайно корисним. І це лише три приклади, які я можу придумати з вершини голови.


4

Ви можете перенаправити деякий вихідний вміст. Це особливо корисно, якщо вам потрібно писати з sudo:

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

Крім того, sudoце еквівалентно:

echo some_content > output.txt

або до цього:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.