Можно ли «перевернуть» символическую ссылку на новый файл, не затрагивая никаких открытых дескрипторов файлов?

Приложение, которое я разрабатываю локально, регистрирует его вывод в файлы, отформатированные с текущей временной меткой, такие как app-%Y%m%d.log .

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

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

Возможно ли изменить цель символической ссылки без необходимости перезапуска tail – путем изменения цели дескриптора файла, если tail является более мудрой?

Чтобы автоматизировать задачу «начать новый рабочий день», было бы легко настроить скрипт cron'ed, чтобы указать символическую ссылку в сегодняшнем файле, но, похоже, что существующий tail процесс не имел бы представления о том, что цель изменилась.

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

Обновление: по крайней мере, хвост версии OS X имеет опцию -F, которая будет открывать файл повторно, если он переместился.

Если вы используете современный Linux, вы можете использовать inotifywait , одну из программ командной строки из пакета inotify-tools . Я не сделал этого, но похоже, что inotifywait может использоваться в сценарии оболочки для сброса символической ссылки и остановки и перезапуска tail -f на символической ссылке. Возможно, вы даже захотите избавиться от символической ссылки и просто закроете текущий файл журнала.

Не используя inotify, вы можете написать свою собственную хвостовую программу, которая проверяет, изменился ли номер inode имени файла, с которого он считывается. В этот момент хвостовая программа может закрыть старый файловый дескриптор и получить новый файловый дескриптор для текущего имени файла. Это сложная программа для написания, и она подвержена условиям гонки.

Из вашего описания это звучит так, как ваше конкретное обстоятельство можно решить, сделав работу cron, которая также убила / перезапустила хвостовой процесс. Но в целом, (Mac OS является исключением) хвост будет помнить, где вы находитесь в файле (то есть смещение байта). Кроме того, дескриптор открытого файла указывает на целевой файл, а не на символическую ссылку. Символьная ссылка становится неактуальной для процесса чтения после того, как файл был открыт. Хотя возможно наличие функций, которые снова открывают файл на основе исходного пути, когда что-то меняется, большинство реализаций этого не делают.

Почему бы не войти в файл, current.log, который вы можете связать с содержимым ваших сердец, а затем использовать что-то вроде / usr / sbin / logrotate, чтобы повернуть этот файл. Вы можете указать в config, что вы хотите сделать некоторые команды postrotate, чтобы переименовать старый файл с добавленной датой и т. Д. Он полностью устраняет необходимость в символических ссылках и может также упростить ваш код ведения журнала.

Конечно, logrotate не может быть установлен в системе, для которой вы разрабатываете.

Как только программа открыла файл, он продолжает получать доступ к тому же файлу, даже если файл перемещен или даже удален. (Удаление открытого файла только удаляет его имя, а файл – индексный дескриптор – фактически удаляется, когда процесс не открывается.)

Некоторые программы наблюдают, если что-то происходит с открытым файлом. Например, классический tail -f программы tail -f продолжает печатать строки, прикрепленные к одному и тому же файлу; некоторые современные реализации (GNU, FreeBSD, NetBSD, OSX) имеют tail -F , который обнаруживает, что новый файл с тем же именем перемещен на место и начинает чтение из нового файла. Multitail также может сделать это (запустите его как multitail --retry ).

Вы можете использовать интерфейс Inotify в Linux или его эквивалент на других узлах, чтобы определить, изменился ли файл. В Linux используйте команду inotifywait .

Я предпочитаю использовать короткий скрипт perl вместо /usr/bin/tail -f для этой цели.

См. http://search.cpan.org/~mgrabnar/File-Tail-0.99.3/Tail.pm для подсказок.