Previous Entry В избранное Поделиться Next Entry
Архивирование базы в скриптах (Ошибки)
avatar
[info]jsirex
Часто встречаю такие записи в скриптах (кстати, как правило, для бэкапов, что важно):
mysqldump -u root -p123 -a | gzip -9 > /tmp/newdump.gz && echo "Backup Success"

И это не только здесь. Так вот запомните, это может привести вас к проблемам: вы можете получить нерабочие бэкапы фиг знает за какой промежуток времени.
Навеяно очередным продакшен скриптом, который ща исправляю.

Пояснение примером:
sirex@proj-nb-jek:~$ ls /usr/lib | gzip -9 > /tmp/test && echo "all ok"
all ok
sirex@proj-nb-jek:~$ ls /tmp/test
/tmp/test
sirex@proj-nb-jek:~$ ls /usr/not_exist_directory | gzip -9 > /tmp/test && echo "all ok"
ls: невозможно получить доступ к /usr/not_exist_directory: Нет такого файла или каталога
all ok

Объяснение:
Дело в том, что в конвеере mysqldump | gzip результат выполнения программы берётся у gzip.
Т.е. если дамп пофейлился, то gzip ничего не смог сжать (пустые данные) и логично он должен был вернуть ошибку. Но это не так. Gzip действует вполне логично. Ну и что что пришёл пустой файл? Правильно, он его успешно сжал.

Таким образом каждый раз вы проверяете успешность сжатия данных, а не процесс самого дампа.
Конечно, проверять, что всё сжалось тоже нужно (мало ли место кончилось), но не менее важно проверять, что данные вы получили.

Кастыль:
Куда ж без них?
на помощь приходят потоки (streams, хотя по русски это именованные каналы, согласно ману):
TMP=`mktemp`
STATUS="Backup Success"
mkfifo $TMP
(mysqldump -u root -p123 -a > $TMP || STATUS="Unable to dump")&
cat $TMP | gzip -9 > /backup.gz || STATUS="Unable to gzip"
rm $TMP

Надеюсь, идея понятна.

ПС. У меня ещё встречается такое в скриптах, но у меня бэкапы идут в несколько шагов, в том числе на мыло я получаю полный лог, а также размеры бэкапов, что позволяет сразу определить, что что-то не так, хотя и Successful



[info]_adept_ подсказал более правильное решение (которое уже не пахнет костылём): set -o pipefail
Метки: , , ,

вот так бывает.
живёшь живёшь, а какой-то простой штуки не знаешь.
Спасибо огромное. Пойду курить маны по set и чего с ним можно ещё сделать.

ПС. Заметка больше призвана напомнить админу, что используя пайпы он может нарваться на неприятности если забудет про этот нюанс. Уверен, найдутся миллионы бэкап скриптов (особенно классика mysqldump |gzip), которые не будут предусматривать pipefail

так как правильно бэкапить с set -o pipefail ? приведите пример.

Вы читаете журнал [info]jsirex