Как безопасно конвертировать файл .gz в файл .xz

3722
pythonic metaphor

У меня есть несколько огромных файлов, которые в настоящее время разархивированы, и я бы хотел их сохранить. Я хочу настроить скрипт для этого, но я хочу быть осторожным, чтобы не потерять данные, то есть я никогда не должен удалять версию gzipped, если версия xz не была определенно создана правильно. Поскольку это большие файлы, я бы также предпочел не разархивировать файл на диск. Я думал, что труба set -o pipefail; gzip -dc file.gz | xz > file.xz && rm file.gzможет быть близко к тому, что я хочу. Какой правильный способ сделать это? Гарантируется ли это перехват всех сбоев, произошедших до удаления окончательного файла?

4
Я думаю, что вы должны использовать `&&` not `||` в вашем `&& rm file.gz`. В противном случае с `||` файл `file.gz` будет удален, даже если произойдет сбой` xz`, чего вы не хотите. Dan D. 10 лет назад 0
@ Дэн Д. Конечно, ты прав, исправлено pythonic metaphor 10 лет назад 0

1 ответ на вопрос

8
Horn OK Please

Добавление суммы SHA1 (которая математически гарантирует до невероятно высокой степени уверенности в том, что файлы либо совпадают, когда совпадают хэши, и хэши не совпадают, когда файлы не совпадают), добавляет меру целостности данных для защиты от случаев, когда дисковая подсистема могла сделать (тихую) ошибку во время записи. Безмолвная коррупция редка, но коварна, когда это происходит.

Конечно, вы все равно могли бы получить ошибочные результаты, если у вас возникли случайные ошибки при чтении, но в этом случае суммы не будут совпадать в любом случае, с чрезвычайно высокой степенью достоверности. Другими словами, если система повреждена (либо ОЗУ, либо диск, производящий неправильные биты / перевернутые биты / поврежденные данные), то это не удастся, когда простое &&может быть успешно выполнено, и шансы на попадание в rmстроку с поврежденными данными исчезают. маленький (поскольку большинство ошибок имеют тенденцию повреждать данные случайным образом, шансы случайного изменения, вызывающего столкновение хеша в SHA1 во время обратного чтения, невероятно малы).

#!/bin/bash set -e set -o pipefail ORIGSUM=$(gzip -dc file.gz | tee >(xz > file.xz) | sha1sum) NEWSUM=$(unxz -c file.xz | sha1sum) if [ "$" = "$" ]; then rm file.gz; fi 

set -eДелает выход сценария оболочки, как только любая строка скрипта возвращает ненулевой код завершения.

Затем мы используем teeкоманду, чтобы скопировать распакованный вывод файла как в xzкомпрессор, так и в sha1sumпрограмму. sha1sumвычисляет сумму SHA1 исходных данных, содержащихся в архиве gzip, временно распаковывая их в программу sha1sum, которая считывает данные для вычисления суммы и затем отбрасывает данные. При использовании teeнам нужно только заплатить ЦПУ за разархивирование файла один раз.

Затем мы выполняем дополнительный вычислительно-дорогой шаг (для супер-дополнительной проверки) и удаляем сжатие xz для файла (временно, в поток) и направляем его в sha1sum, чтобы получить нашу сумму SHA1 «нового файла».

Затем мы сравниваем две суммы, и если они не являются равными строками или если одна или обе из них имеют нулевую длину, мы либо получим ошибку сценария (которая завершается, спасибо set -e), либо файл не будет удален. Вы можете реализовать elseпредложение для удобной обработки ошибок, если хотите, но этот существенный сценарий как есть будет чрезвычайно безопасным, хотя и не очень информативным для пользователя, выполняющего команду в интерактивном режиме.

В конце концов, file.gzзавещание будет разорвано только тогда и только тогда, когда несжатое содержимое file.gzи file.xzбудет точно идентичным в момент времени, когда были вычислены хеш-значения, с астрономически высокой степенью достоверности (вероятность того, что что-то будет не так, будет неправильной) как 1 в 1 с 300 нулями после него). На этом этапе вам нужно беспокоиться только о повреждении данных после завершения работы этого скрипта. ;)


Спектакль

Этот сценарий будет работать почти с той же скоростью, что и исходный сценарий в вопросе, за исключением части, которая выполняется unxz. К счастью, распаковка из LZMA происходит чрезвычайно быстро, почти так же быстро, как обычная Zip, и примерно на порядок быстрее, чем сжатие в LZMA. Если у вас есть быстрый процессор, а файлы достаточно малы, это не следует добавлять слишком много времени выполнения для сценария, но если вы дорожите целостность данных по производительности, это чистая победа.


Кредит, где кредит должен

Этот ответ на StackOverflow помог мне существенно написать этот скрипт.

Это действительно хороший способ убедиться, что сжатие сработало правильно, и время выполнения примерно одинаково. И да, я планировал некоторые из этих операций, и шаг xz был на порядок медленнее, чем шаг unxz, поэтому я не беспокоюсь об этой части. pythonic metaphor 10 лет назад 0
Я должен добавить, что в системе с ECC RAM и запущенной файловой системой со встроенными проверками целостности, такими как `btrfs` или` zfs`, операционная система и аппаратное обеспечение * уже * работают вместе, чтобы сделать что-то очень похожее на мой Тест sha1sum, поэтому, если вы работаете в такой конфигурации, риск удаления проверки sha1sum из этого сценария довольно незначителен. С другой стороны, если у вас есть оперативная память не-ECC и файловая система, которая не обладает встроенной целостностью, это сделает ваш сценарий * значительно * более безопасным. Horn OK Please 10 лет назад 0