2011-10-04

tail -F

Кто бы мог подумать, что у меня будут претензии к coreutils: а именно, к небезызвестной tail.

Суть проблемы в следующем - в процессе перемещения нашей системы с etch на squeeze (или, с 4 на 6 версию Debian), был получен непонятный глюк, связанный с потерей данных при ротейте файлов. Оказалось, что дело в tail! Схема использования выглядит так:

1. Есть основная программа, которая непрерывно пишет в некий file, в ней есть обработчик сигнала (допустим, USR1).
2. Есть tail, который запущен в режиме следования за именем файла:
tail --follow=name --retry file.

И есть простейший скрипт ротейта, который работает в два приема:

1. Переименовывает файл (допустим, в file.прошло_секунд_с_1970-01-01). Сам файл, естественно, продолжает увеличиваться и после переименовывания.
2. Посылает основной программе сигнал USR1, который заставляет ее закрыть текущий дескриптор и открыть по-новой файл file.

При таких обстоятельствах, tail в режиме следования за именем файла бросает следить за старым и пересаживается на новый. Таким образом, по идее, обеспечивается непрерывность потока данных во время ротейтов.

Так вот - поведение "старого" tail-а 5.95 из etch однозначно - он будет "сосать" данные из  переименованного файла до тех пор, пока снова не появится файл со старым именем - и лишь тогда переключится на него. А вот "новый" tail 8.5 (а по факту, его поведение изменилось уже в версиях 6.x), как только файл переименован, бросает его и тупо ждет появления файла со старым именем. В итоге, данные, которые успели записаться в "старый" файл до момента обработки основной программой сигнала USR1, игнорируются tail-ом, образуя некую "дыру" в потоке - обычно пара секунд данных таким образом безвозвратно теряется.

Первым делом хочется увеличить время сна tail-а, чтобы переоткрывание все-таки успело произойти. Но потом понимаешь, что это обычный sleep, и вероятность, что tail проснется в неподходящий момент, сохраняется. 

Именно поэтому пришлось делать специальный пакет со "старым" tail-ом - бы было чуть больше времени, сделал бы значение ключа --follow=descritpor_than_name или что-то в этом духе. 

Комментариев нет: