У меня есть следующие настройки.
На удаленной машине у меня постоянно работает процесс, который подписывается на некоторые данные и записывает их в stdout (позволяет вызвать процесс подписчика). Я вызываю подписчика из сценария .sh, который перенаправляет stdout в файл, содержащий дату в имени, позволяет называть это файлом журнала. В целом, я хочу разбить эти файлы журналов на разные даты, чтобы я мог перенести их с удаленного компьютера на свой локальный.
Есть одна особенность моей ситуации, которая делает решение, с которым я знаком не работает: файл журнала содержит данные моментального снимка плюс поток дельт. Следствием этого является то, что я не могу просто выполнить лог-ротацию файла журнала, потому что в начале следующего файла журнала будет отсутствовать моментальный снимок. Сейчас я с этим справляюсь: вручную останавливать подписчика и перезапускать его из сценария .sh. Сценарий .sh перенаправит stdout в следующий файл журнала с датой. Для моих целей отсутствие данных в течение нескольких секунд между перезапусками не является проблемой. Что ЯВЛЯЕТСЯ проблемой, если в файле журнала отсутствует исходный снимок.
Итак, мой вопрос: как правильно автоматизировать этот ручной процесс?
У меня есть частичное решение, которое мне не нравится.
.log
, назовите его .log.part
, вдохновившись этим ответом . .log.part
переименовывается в .log
, сигнализируя, что этот файл журнала доступен для перемещения .log
. Даже если бы я узнал, как сделать последний шаг, мне не нравится решение, потому что я никогда не видел грабителя Такой конвейер построен на основе 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 не будет выполнен, если подписчик выходит с ошибкой.