Автор статьи — Крис Зибенманн, системный администратор Unix в университете Торонто
Время от времени в моей работе происходит нечто странное, что заставляет задуматься. Даже если сразу непонятно, какие следуют выводы. Недавно я упомянул, что мы нашли ошибку в GNU Tar, и история о том, как это произошло, — один из таких случаев.
Для бэкапа файл-серверов мы используем Amanda и GNU Tar. В течение долгого времени у нас периодически возникала довольно редкая проблема, когда tar сходил с ума при резервном копировании файловой системы с каталогом
(Из-за этого мне стало интересно, появляются ли нулевые байты естественным образом у людей в почтовых ящиках. Оказалось, что поиск нулевых байтов в текстовых файлах не такой простой и да, они там есть).
Недавно мы перенесли файловую систему с
С помощью
Несколько месяцев назад мы столкнулись с проблемой NFS в Alpine. Работая над этим багом, я сделал трассировку процесса Alpine и заметил, среди прочего, что для изменения размера почтовых ящиков он использует
(Это даже объясняет, почему tar иногда восстанавливается; если позже в ящик вдруг пришла новая почта, тот возвращается к ожидаемому размеру, и tar больше не сталкивается с неожиданным завершением файла).
Я немного повозился в GDB на отладочных символах Ubuntu и исходном коде пакета tar, который я получил, и смог воспроизвести ошибку, хотя она несколько отличалась от моей первоначальной теории. Оказалось, что
(За исключением случаев, когда файл разрежен только в конце и сжимается только в этом месте. В таком случае всё в порядке).
Мне подумалось, что всё то же самое я мог проверить много лет назад на наших файл-серверах OmniOS. Там есть способы трассировки системных вызовов программы и аналоги
(Дело не только в инструментах и окружении; мы ещё автоматически предположили, что на OmniOS стоит какая-то старая неподдерживаемая версия GNU Tar, которую нет смысла исследовать, ведь проблему конечно же решили в более новой версии).
P.S.: Наверное, в качестве быстрого исправления мы просто запретим Amanda использовать параметр tar
P.P.S.: Я не пытался сообщить о баге разработчикам GNU Tar, потому что обнаружил его только в пятницу, а университет сейчас на зимних каникулах. Не стесняйтесь сделать это раньше меня.
Время от времени в моей работе происходит нечто странное, что заставляет задуматься. Даже если сразу непонятно, какие следуют выводы. Недавно я упомянул, что мы нашли ошибку в GNU Tar, и история о том, как это произошло, — один из таких случаев.
Для бэкапа файл-серверов мы используем Amanda и GNU Tar. В течение долгого времени у нас периодически возникала довольно редкая проблема, когда tar сходил с ума при резервном копировании файловой системы с каталогом
/var/mail
, производя огромное количество выходных данных. Обычно этот процесс уходил в бесконечность и приходилось убивать дамп; в других случаях он всё-таки завершался, выдав терабайт(ы) данных, которые вроде бы отлично сжимались. Когда мне в очередной раз попался такой гигантский файл tar, я подверг его проверке — и выяснил, что он частично состоит из нулевых байтов, которые очень не нравятся команде тестирования tar -t
, после чего всё возвращается в норму.(Из-за этого мне стало интересно, появляются ли нулевые байты естественным образом у людей в почтовых ящиках. Оказалось, что поиск нулевых байтов в текстовых файлах не такой простой и да, они там есть).
Недавно мы перенесли файловую систему с
/var/mail
на новые файловые серверы Linux под Ubuntu 18.04 и поэтому перешли на более позднюю и более стандартную версию GNU Tar, чем стоит на машинах OmniOS. Мы надеялись, что это решит наши проблемы, но почти сразу произошёл такой же инцидент. На этот раз GNU Tar работал на машине Ubuntu, где я хорошо знаком со всеми доступными инструментами отладки, так что я проверил запущенный процесс tar
. Проверка показала, что tar
выдаёт бесконечный поток read()
, возвращающих 0 байт:read(6, "", 512) = 0
read(6, "", 512) = 0
[...]
read(6, "", 512) = 0
write(1, "\0\0\0\0\0"..., 10240) = 10240
read(6, "", 512) = 0
[...]
lsof
сказал, что файловый дескриптор 6 является чьим-то почтовым ящиком.С помощью
apt-get source tar
я загрузил исходный код и начал искать в нём системные вызовы read()
, которые не проверяют завершение файла. Разобрав несколько уровней косвенной адресации, я нашёл очевидное место, где вроде бы такая проверка опущена, а именно в функции sparse_dump_region
из файла sparse.cs. И тут я кое-что вспомнил.Несколько месяцев назад мы столкнулись с проблемой NFS в Alpine. Работая над этим багом, я сделал трассировку процесса Alpine и заметил, среди прочего, что для изменения размера почтовых ящиков он использует
ftruncate()
; иногда он расширяет их, временно создавая разреженный раздел файла, пока не заполнит его, и, возможно, иногда сжимает его. Казалось, это совпадало с нынешней ситуацией: разреженные области связаны, а сокращение размера файла с помощью ftruncate()
создаёт ситуацию, когда tar неожиданно для себя сталкивается с завершением файла.(Это даже объясняет, почему tar иногда восстанавливается; если позже в ящик вдруг пришла новая почта, тот возвращается к ожидаемому размеру, и tar больше не сталкивается с неожиданным завершением файла).
Я немного повозился в GDB на отладочных символах Ubuntu и исходном коде пакета tar, который я получил, и смог воспроизвести ошибку, хотя она несколько отличалась от моей первоначальной теории. Оказалось, что
sparse_dump_region
не сбрасывает разреженные области файла, а сбрасывает не разреженные (ну конечно), и используется для всех файлов (разреженные или нет), если вы запускаете tar с аргументом --sparse
. Таким образом, фактическая ошибка заключается в том, что если вы запускаете GNU Tar с аргументом --sparse
и файл сжимается в процессе его чтения, tar не может правильно обработать конец файла, полученный ранее, чем ожидалось. Если файл снова увеличивается, tar восстанавливает работу.(За исключением случаев, когда файл разрежен только в конце и сжимается только в этом месте. В таком случае всё в порядке).
Мне подумалось, что всё то же самое я мог проверить много лет назад на наших файл-серверах OmniOS. Там есть способы трассировки системных вызовов программы и аналоги
lsof
, и я мог бы найти и посмотреть исходный код своей версии GNU Tar и запустить его с отладчиком OmniOS (хотя там у нас вроде не установлена GDB), и так далее. Но я этого не сделал. Вместо этого мы пожали плечами и двинулись дальше. Потребовалось переместить файловую систему под Ubuntu, чтобы я пошевелил пальцем и разобрался в проблеме.(Дело не только в инструментах и окружении; мы ещё автоматически предположили, что на OmniOS стоит какая-то старая неподдерживаемая версия GNU Tar, которую нет смысла исследовать, ведь проблему конечно же решили в более новой версии).
P.S.: Наверное, в качестве быстрого исправления мы просто запретим Amanda использовать параметр tar
--sparse
при резервном копировании. Почтовые ящики не должны быть разреженными, а если такое случится, мы всё равно сжимаем бэкапы файловой системы, так что все эти нулевые байты хорошо сожмутся.P.P.S.: Я не пытался сообщить о баге разработчикам GNU Tar, потому что обнаружил его только в пятницу, а университет сейчас на зимних каникулах. Не стесняйтесь сделать это раньше меня.
Комментарии (12)
selivanov_pavel
28.12.2018 00:02Написал на bug-tar@gnu.org
Но вообще, я даже не уверен, что архиватор должен уметь корректно работать с изменяющимся во время архивации файлом.
Arris
28.12.2018 00:56+3Как я нашел баг в TAR…
… и ничего не сделал, чтобы его исправить, потому что «университет на зимних каникулах».
Какой странный дядя.Mingun
28.12.2018 14:57Пожалуй недоумение вызывает уже сам факт того, что для того, чтоб зарепортить баг нужен кто-то, кто не на "зимних каникулах" O_o
tbl
28.12.2018 15:02К моменту публикации перевода на хабре фикс уже был готов:
git.savannah.gnu.org/cgit/tar.git/commit/?id=c15c42c
gecube
Два замечания
Я очень ценю труд пользователя m1rko Статьи реально полезные и выходят достаточно часто. Но можно попросить чуточку более аккуратно относиться к переводу (знаки препинания, ну, конечно, и орфография)
Во-вторых, статья вообще о чём? Что парни нашли баг в tar'е? Да вообще молодцы — видимо про lvm snapshot не слышали. Я уж не говорю о том, что бекапить каталоги и файлы, пока в них пишут — верх слабоумия. Очень двойственное впечатление. С одной стороны — да, действительно tar с ключом sparse должен работать предсказуемо, а с другой — бекап через одно место
saege5b
Некоторые товарищи запуститли апгрейд(типа того) системы совместно с резайзом картинок.
Была недавно статья на тему как гарантированно уронить систему и мучительно её поднимать, сидя на удалёнке за много-много милионов километров.
От тех самых товарищей.
gecube
Спасибо за ссылку. Прям мощь. Чуть было не потеряли космический аппарат. На этот раз повезло и помогли профессионализм и хладнокровие инженеров.
psycho-coder
Пользуясь случаем, оставлю ссылку на сервис проверки грамматики) (правда сам редко им пользуюсь)
languagetool.org/ru