我正在本地开发的应用程序将其输出记录到使用当前时间戳格式化的文件,例如app-%Y%m%d.log
.
为了使能够在终端窗口中跟踪当前日志变得简单,我有一个名为 的符号链接,current.log
它指向今天的日志。
每天开始工作时,我需要终止尾部进程,将符号链接指向今天的文件,然后重新运行命令到tail -f current.log
.
是否可以tail
通过更改文件句柄的目标而不需要重新启动来更改符号链接的目标tail
?
要自动执行此“新工作日开始”任务,可以很容易地设置一个 cron'ed 脚本来将符号链接指向今天的文件,但现有tail
进程似乎不知道目标已更改。
答案1
我认为这是不可能的,除非您可以定期关闭并重新打开文件。一个尾部(或任何其他程序)打开一个文件,它获取该文件的索引节点的句柄。那时,不再参考文件名和链接。这就是为什么您可以从文件系统中删除文件,并且任何打开该文件的程序都将继续工作。只有当 ;ast 程序关闭文件时,它才真正从磁盘中删除。
更新:至少 OS X 上的版本尾部有一个 -F 选项,如果文件已移动,它将重新打开该文件。
答案2
如果您使用的是现代 Linux,您可以使用inotifywait
,来自inotify 工具包裹。我还没有这样做,但它看起来inotifywait
可以在 shell 脚本中使用来重置符号链接并tail -f
在符号链接上停止和重新启动。您甚至可以处理符号链接,只跟踪当前日志文件。
如果不使用inotify,则可以编写自己的类似尾部的程序来检查其读取的文件名的索引节点号是否已更改。此时,类似尾部的程序可以关闭其旧文件描述符,并为现在不同的文件名获取新的文件描述符。这是一个编写起来很棘手的程序,并且很容易出现竞争条件。
答案3
从您的描述来看,您的具体情况似乎可以通过执行 cron 作业来解决,该作业也杀死/重新启动了尾部进程。但一般来说,(Mac OS 除外)tail 会记住您在文件中的位置(即字节偏移量)。此外,打开的文件句柄指向目标文件,而不是符号链接。一旦文件被打开,符号链接就与读取过程无关。尽管可以具有在某些内容发生更改时根据原始路径重新打开文件的功能,但大多数实现不会这样做。
答案4
一旦程序打开文件,即使文件被移动甚至删除,它也会继续访问同一文件。 (删除打开的文件只会删除其名称;该文件 —索引节点— 一旦没有进程打开它,实际上就会被删除。)
有些程序会监视它们打开的文件是否发生问题。例如,经典程序tail -f
将打印行附加到同一文件中;一些现代实现(GNU、FreeBSD、NetBSD、OSX)具有tail -F
,它会检测是否有同名的新文件被移动到位并开始从新文件中读取。多尾也可以这样做(运行它multitail --retry
)。
您可以使用通知Linux 上的接口或其他 unice 上的等效接口,用于检测文件是否已更改。在 Linux 上,使用inotifywait
命令。