我有两个应用程序用于传输数据:
应用程序1 | 应用程序2
基本上,应用程序 1 会生成一个日志,其中包含应用程序 2 处理的事件。问题是我经常更新应用程序 2。这意味着,我需要停止这些更新,更新二进制文件,然后重新启动它。在那段短暂的时间内,应用程序 1 可能会丢失数据。
我读到过有关使用命名管道的文章mkfifo
,并认为这可能是一个理想的解决方案。保持应用程序 1 运行,并让它写入文件支持的命名管道,这样当应用程序更新时不会丢失数据,并且一旦应用程序 2 启动,它就会获取数据。
测试cat
模拟读取器/写入器是否有效,直到不再有读取器。这是意料之外的。
另一种方法是使用实际文件,但存在问题:
- 它保留在磁盘上,不像 FIFO 那样运行
- 它需要某种形式的轮换来防止文件变得过大
- 据我所知,当读取器位于末尾(尾部?)时,如果文件大小增加,则需要在计时器后面进行探测,从而增加处理延迟
我控制着阅读器,目前的行为是它会自动重启,但我无法控制写入器。我只能将其输出通过管道传输到其他地方。
- 是否可以以某种方式配置命名管道以使其持久?
- 我读到过作者关于“固定”到管道的内容,但我无法让它发挥作用
- 一旦读者退出,我可以防止管道关闭吗?
- 有没有像管道一样运作的替代品?
解决方案https://unix.stackexchange.com/a/784153/585995有效!
mkfifo /tmp/mypipe
writerapp 1<>/tmp/mypipe
当我重新启动阅读器时,编写器继续运行:
readerapp </tmp/mypipe
顺便说一句,你可以自己使用以下方法测试一下cat
您可以将命名管道视为要创建的常规管道的锚点。
之上:
shell 执行
open("fifo", O_WRONLY)
。它将open()
阻塞,直到另一个进程(或同一个进程)执行open("fifo", O_RDONLY)
¹:此时,一个管道(与 创建的未命名管道非常相似
pipe()
)被实例化。如果
application2
终止,则该管道的读取端将关闭,成为损坏的管道,并且application1
在下次尝试写入时会收到 SIGPIPE 信号。为了避免这种情况,您需要确保管道保持活动状态,例如,通过另一个进程在管道上打开一个 fd 进行读取,或者您可以以模式¹
application1
打开它,以便它本身成为该管道的写入者和读取者,即使它实际上不会从中读取。fifo
O_RDWR
和:
标准输出在 O_RDWR 中打开,管道立即实例化。
application1
将开始写入管道,直到管道缓冲区已满。如果它愿意,application1
可以从其标准输出 fd读取并使用它之前写入的内容,但应用程序通常不会从其标准输出读取。然后,你这样做:
application2
将成为该管道的另一个读取者。如果它终止,管道不会损坏,因为仍然有一个读取者 (application1
),您可以启动新版本的application2
as:,application2 < fifo
它将从上一次运行离开的地方继续。使用未命名管道,您还可以执行以下操作:
您将在其中提供
application2
as²的新版本new-application2
,它会自动重命名并循环运行。application2
当或失败时,循环停止,mv
此时管道将会中断,并且application1
在下次尝试写入时将收到 SIGPIPE。¹ IIRC,这并不适用于所有的 Unices,但我无法告诉你它不适用于哪些 Unices。
² 您需要确保
new-application2
它看起来完整(例如,通过从以前的名称/位置重命名它)以避免在未完全创建时执行的风险。是的,这取决于您对耐用性的定义。
mkfifo
创建 fifo 或命名管道,并且它会一直保留在那里,直到您删除它。不知道你的意思。但是,如果你无法控制作者,那么这不是一个解决方案。
你可以
tail -f
在 fifo 上使用,而不是cat
。或者甚至tail -n +1 -f fifo_name | command
一些附加信息:当
cat
遇到文件结尾时,它会退出。因此,如果你这样做在另一个终端
你从 获得跳跃
cat
,然后猫退出。如果你的作家然后它会一直挂起,直到
cat fifootje
发出新的为止。tail -f
(“跟随”或“永远”)只是等待,直到添加一些行,并且直到被杀死才会退出。所以,在写入器终端中:
或者,您可以:
是的,插座。