2011-10-20 67 views
1

我有一个守护程序,它可以在整个操作过程中打开一个文件并将其写入(通常每次都是几天)。为了支持日志旋转,我希望能够识别句柄引用的文件位于原始位置的新位置。从Linux中的文件句柄确定文件路径

这可能吗? fstat()不会为这种情况提供任何有用的信息。

我目前的解决方案是在日志写入功能中测试日志文件的存在,如果它不存在,关闭旧的句柄并打开一个新的句柄。这工作,但是是黑客,并有一定的局限性。在我的情况下,我们的系统组使用一个工具进行日志轮换,要求他们在旋出后触摸文件,这导致我的守护进程继续认为它的文件句柄指向正确的位置。

+0

看看这个线程,看看在PHP手册中是否有类似的功能。 http://stackoverflow.com/questions/1188757/getting-filename-from-file-descriptor-in-c – Jake

回答

3

这是一个想法。它不是便携式的,我不完全确定它是否工作或是可靠的,这让我感到有点不安,但你可以在/proc/%d/fd/%d上使用readlink,其中第一个%dgetpid()的结果,第二个是你的文件描述。

虽然这里有一些注意事项。首先,面对同时发生的重新命名,整个“走这条路+做某件事”的方法将具有竞争条件。另外,您的日志文件可能有其他链接。我不知道在面对重命名时,/proc中的链接的行为是什么。

+0

proc文件获取文件描述符;它不会给你一个'fstat'的不同答案# – mkj

+0

@mkj你确定吗?最后我知道'struct stat'没有名称字段。 – asveikau

+0

这不是一个名称字段,它是一个'st_ino'字段,它为您提供inode编号。 – mkj

0

您可以简单地定期重新获取您的文件句柄(模式为a),例如每24小时一次。这允许你继续日志记录,尽管存在虚弱和错误(因为重命名文件和重新触摸它之间存在不可避免的竞态条件)日志轮转实用程序。

0

fstat为您提供了一个inode号码,它将在日志旋转时更改。

http://php.net/manual/en/function.fstat.phphttp://www.php.net/manual/en/function.lstat.php

您可以从fstatlstat inode编号比较节点号码;如果它们不同,请重新打开。

处理这个在过去的Unix守护进程的标准方法已经赶上SIGHUP并把它作为一个信号,重新打开日志文件,并有日志旋转脚本发送SIGHUP

+0

从我的测试中,移动文件时,inode不会改变。由于似乎没有一个好的,可靠的解决方案,我认为处理SIGHUP可能是我最终走向的方式。 – Mark

+0

的确,inode号码在文件移动时不会改变。如果文件描述符中的“fstat”在打开文件时在文件名称上产生了与“lstat”不同的inode编号,则该文件在您打开文件后已被移动或删除。所有这一切说,实施'SIGHUP'处理是Unix方式。检查'lstat'与'fstat'是备份策略,以防有人忘记发送'SIGHUP'。 – mkj