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

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

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

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

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

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

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

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

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

Спасибо

0
задан 21 March 2020 в 14:49
1 ответ

Ваш текущий сценарий 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 не будет выполнен, если подписчик выходит с ошибкой.

0
ответ дан 30 March 2020 в 01:28

Теги

Похожие вопросы