我在linux上写了一个logger。
记录器在init上打开一个文件。
并在程序运行时写入该文件描述符。
如果在创建文件描述符之后将删除日志文件,
将检测不到异常/错误。
我曾尝试:
out.fail()
!out.is_open()
我google了一下,找到了这篇文章。
http://www.daniweb.com/forums/thread23244.html
所以我现在明白了,即使该文件被删除使用rm.it仍然存在,它只是被取消链接。
处理这个问题的最好方法是什么?
1.这是一个日志应用程序,因此性能是一个问题,我不想在每次写入时使用stat()
2.我不在乎日志文件中的某些行是否会在开始时丢失
3.用户被允许删除日志文件,重新开始.日志记录器应该重新打开文件.
4条答案
按热度按时间e37o9pze1#
文件是
rm
的'unlinked'。一个文件可以有很多名字。当它没有名字时,没有人打开它,那么它就被文件系统回收,它占用的空间可以重新使用。
Linux有一个名为
inotify
的“监视”文件的API,但这会带来复杂性和竞争条件。所以更大的问题是,还有谁在运行时删除了这个文件,为什么?说服他们不要这样做!
trnvg8h32#
您已经在注解中声明了这样做的原因是允许用户删除日志文件,在这种情况下,您希望应用程序开始在其位置写入新的日志文件。
传统的UNIX机制是让你的程序安装一个信号处理器(通常是
SIGHUP
,因为这对守护进程来说没有意义)。信号处理器包含了让程序关闭并重新打开日志文件的代码。然后,用户被指示在他们删除日志文件之后,他们需要向程序发送
SIGHUP
。szqfcxe23#
处理这种情况的唯一明智的方法是尝试写入日志。(大多数情况下不会)然后你需要找出原因。在这一点上,你可以做一些事情,比如使用stat来查看日志是否仍然存在-如果是,你有某种磁盘已满或权限错误,这可能很难或不可能恢复,如果不是,重新打开并重试写入。
tv6aics14#
这是一个较老的线程,但它仍然弹出时,我有同样的问题,所以我想我贡献了一个更现代的答案,为我工作。
我使用的是std::filesystem::exists函数(C17的特性,在experimental_filesystem中用于C14)。如果文件存在,它返回TRUE,如果文件不存在,它返回FALSE,即使文件存在并且被rm“取消链接”,它也会返回FALSE。
所以我的程序在写入文件之前总是会检查文件是否存在。在我的例子中,它不会产生任何明显的cpu开销,我以20到255字节的批量写入大约每秒50KB,它有时会每秒检查500次。测试了很多次,从来没有出现过问题。
总的来说,c++17的文件系统库是非常棒的,它消除了C遗留代码所产生的许多令人头痛的问题。
干杯