У меня есть следующая настройка.
На удаленной машине у меня постоянно работает процесс, который подписывается на некоторые данные и записывает их в 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 не будет выполняться, когда подписчик выходит с ошибкой.