Назад | Перейти на главную страницу

Гарантированное переименование файла журнала ПОСЛЕ того, как файл журнала больше не записывается

У меня есть следующая настройка.

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

Есть одна особенность моей ситуации, из-за которой знакомое мне решение не работает: файл журнала содержит данные моментального снимка и поток дельт. Следствием этого является то, что я не могу просто выполнить лог-ротацию файла журнала, потому что в начале следующего файла журнала будет отсутствовать моментальный снимок. Сейчас я с этим справляюсь: вручную останавливать подписчика и перезапускать его из сценария .sh. Сценарий .sh перенаправит stdout в следующий файл журнала с датой. Для моих целей отсутствие данных в течение нескольких секунд между перезапусками не является проблемой. Что ЯВЛЯЕТСЯ проблемным, так это наличие файла журнала, в котором отсутствует его первоначальный снимок.

Итак, мой вопрос: как правильно автоматизировать этот ручной процесс?

У меня есть частичное решение, которое мне не нравится.

Даже если бы я узнал, как сделать последний шаг, мне не нравится решение, потому что я никогда не видел такого надежного конвейера, построенного на основе cronjobs.

Итак, если кто-то знает надежный способ сделать это, что это такое? А если нет, как я могу гарантировать, что .log.part файл переименован в .log когда абонент умирает?

Спасибо

Ваш текущий сценарий cron, вероятно, выглядит примерно так:

setsid subscriber > subscriber.date.log &

Вы хотите, чтобы оболочка ожидала выхода подписчика, а затем переименовывала его вывод. Что-то вроде этого подойдет:

log_date_str=`date ...`

watcher()
{
        subscriber > subscriber.${log_date_str}.log.part
        mv subscriber.${log_date_str}.log.part subscriber.${log_date_str}.log
}

killall subscriber
setsid watcher &

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

Есть пара подводных камней:

Если подписчик уходит в фоновый режим, как демон, и не подключается к сценарию оболочки, вам нужно выяснить, как предотвратить это (обычно используется -d). Это маловероятно, так как было бы странно выводить на стандартный вывод и сам форк.

Во-вторых, если ваша оболочка не имеет встроенного setid, вам придется разделить часы на собственный сценарий оболочки и вызвать его вместо функции.

Я бы рекомендовал использовать pstree, чтобы увидеть отношения между родительскими и дочерними элементами.

Кроме того, убедитесь, что вы не выполняете set -e в своем скрипте (или отключите его в наблюдателе), иначе mv не будет выполняться, когда подписчик выходит с ошибкой.