是否可以使对命名管道的seek()操作成功返回?


12

有什么方法可以使程序在尝试对seek()命名管道执行操作时成功返回(但就像管道是空文件一样)而不是“非法查找”吗?

我在系统上的所有最后一点记录都存储在SQLite数据库中,而我在任何地方都没有文件。但是,有些程序对此有麻烦。有2种具体情况;

  • 程序要写入syslog-ng作为命名管道创建并正在读取的日志文件。程序seek()由于某种原因想要执行a ,然后失败。
  • 程序(例如denyhosts或fail2ban)想要从syslog-ng创建为命名管道并正在写入的日志文件中读取。该程序要对其执行操作seek()并失败。

理想情况下,我希望这些搜索的行为就像命名管道只是一个空文件一样。我看不到任何原因为什么写日志的程序仍然需要执行查找,它应该只打开文件进行追加并开始写。我可以看到为什么要读取程序,以便它可以从其最后一个位置恢复,所以我希望它的行为就像文件是空的(就像被截断一样)。

那么,可以在命名管道上设置一些选项来使它们以这种方式运行吗?如果没有,那么在syslog-ng打开管道以使其具有这种行为时可以设置一种模式(我愿意进行代码更改)?还是我在一条小河上?

Answers:


10

已经为Linux内核提出了可寻求的管道,但是我不知道实现它们的有效补丁。

您可以使用LD_PRELOAD'ed库来覆盖lseek对特定文件的调用。我不知道为此目的有任何现成的包装器。Shadowfs可能有助于编写一个。


1
我将尝试LD_PRELOAD路由。不是最大的解决方案,但应该可行。
Patrick

顺便说一句,是否有必要使用可寻找的管道来减少与管道跟踪文件相同的管道跟踪?我是在关注使用较少的管道的情况下问的问题(您可能希望在此处回答)。
Piotr Dobrogost,2015年

@PiotrDobrogost在F更少的命令上下文中,如果在一秒钟左右没有任何输出,刷新屏幕就足够了。使管道可搜索是无济于事的:相应的区别是F到达文件的末尾,然后等待数据显示在末尾之后—但是对于管道,文件的末尾仅在编写者关闭文件时才会到来。
吉尔(Gilles)“所以,别再邪恶了”

1

如果应用程序正在调用seek,则它可能已损坏,或者不打算在管道上工作。如果是前者,则需要固定。如果是后者,则它期望搜索实际上有效,因此在无效时撒谎并声称其有效几乎可以肯定会导致错误操作。

同样,如果日志文件被命名管道替换,则一次只能读取一个进程。它应该是一个套接字。


2
不打算在管道上工作并不意味着不能在管道上工作。如果应用程序只是简单地执行SEEK_END以到达文件末尾怎么办?或执行SEEK_CUR以查找当前位置。如果我向程序撒谎有关搜索结果的话,这些都不会引起任何问题。唯一会中断的地方是,如果应用程序试图返回并覆盖已经写入的数据,而该数据不应该与日志文件一起使用。是的,我知道每管道一进程的限制。这不会有问题。
Patrick

1
如果它所做的只是寻找附加的末尾,那么它应该只是以附加模式打开文件,因此它属于损坏的类别。除非他们需要能够找到其他位置,然后返回到当前位置,否则应用程序不会尝试找到当前位置,因此它属于“您将通过静默失败来破坏它”类别。这是非常不可能的程序调用求,但并不真正需要它的工作(如果确实如此,它落在破类别)。
psusi 2012年

1
不对。万一有其他程序自上次写入文件以来,许多应用程序都在文件的末尾查找。否则,将其写入当前位置将破坏其他程序的更改。而且,如果从文件中读取数据,则可能要使用SEEK_CUR来获取其当前位置,以便在程序启动时备份,可以从上次中断的地方继续执行。
Patrick

1
@Patrick,对于前者,如果要追加,则应以追加模式重新打开文件。在这种情况下,您正在谈论读取,在这种情况下,跳过尚未读取的新数据是没有意义的(并且默默地忽略寻道会破坏这一点)。对于后者,如果它试图在关闭并重新打开文件后尝试使用seek返回到相同的位置,如果您默默地忽略了seek,则该文件将在管道上中断,因为在关闭管道时,服务器会收到SIGPIPE,大概使其重置,以便下一个打开管道的客户端从头开始。
psusi'2
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.