Добавление суммы 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 помог мне существенно написать этот скрипт.