维护跨不同执行的 FIFO 可读

Maintaining a FIFO readable across different executions

我以前从未使用过命名管道,最近才意识到这正是我所需要的。

我正在 运行使用 gnu parallel 生成大量(GB 到 1TB,现在很难知道)针对 mySQL 上的数据库格式化的输出。

我发现我可以打开两个终端: 1 号航站楼得到类似:

find . -type f -name "*.h" | parallel --jobs 12 'cprogram {}' > /home/pipe

其中 pipe 是用 mkfifo 制作的 fifo。

在第二个终端上,我 运行 类似这样的命令:

mysql DataBaseName -e "LOAD DATA LOCAL INFILE '/home/pipe' INTO TABLE tableName";

有效...

但这很糟糕...如果我理解正确,当第一个进程结束导致管道关闭时会生成一个 EOF。

理想情况下,我希望 运行 具有不同参数的循环中的第一个进程。每次迭代都可能需要很长时间,我需要进行健全性检查,这样我就不会浪费一周的时间来发现我有错误或错误的逻辑。

我想知道如何以标准方式将 FIFO 用于此类过程。

If I understand correctly, there's an EOF generated when the first process ends causing the pipe to close.

有点。还有一点比这更重要 - 从技术上讲管道在第一个进程结束后立即关闭是不正确的。

取而代之的是管道和 FIFO return EOF,当管道中没有更多的数据并且没有被任何进程打开进行写入时。

通常,这可以通过让 reader 进程打开 FIFO 进行读取和写入来解决,即使它永远不会写入 - 例如,通过从 FIFO 读取来接受本地客户端的服务器可以打开 FIFO 进行读写,这样当没有活动的客户端时,服务器就不必处理 EOF 的特殊情况。这是 "standard" 处理它的方法,如 UNIX 环境中的高级编程 关于 IPC 机制的章节中所述。

但在您的情况下,这实际上是不可能的,因为您没有保持 运行 的永久进程(也就是说,您没有服务器进程的等价物)。您基本上需要某种 "persistent writer",即在不同迭代期间保持管道打开以进行写入的过程。

我能想到的一个解决方案是在后台cat标准输入到FIFO。这确保 cat 打开 FIFO 进行写入,因此始终有一个活动的写入器,但通过将其保留在后台,您实际上不会向它提供任何输入,它也永远不会写入 FIFO。请注意,一旦 cat 尝试从 stdin 读取(后台进程组中的进程 运行,作业将被 shell 停止(但不会终止)通常会发送 SIGTTIN 并在它们尝试从 stdin 读取时停止,因为它们在被带到前台之前没有控制终端)。不管怎样,只要你不给它任何输入,你就很好——进程处于停止状态,但 FIFO 仍然打开以进行写入。只要后台作业没有终止,您就永远不会在管道上看到 EOF。

所以,简而言之,你:

  1. 创建 FIFO:mkfifo /home/pipe
  2. 启动打开 FIFO 进行写入的后台作业:cat >/home/pipe &
  3. 运行 你想要的程序,你想要多少次迭代。忽略有关后台作业停止的 shell 消息。您可以这样保留它,因为即使作业已停止,管道仍处于打开状态以进行写入。
  4. 完成后,通过将其置于前台并发送 SIGINT(通常为 Ctrl+C)或使用 kill PID.
  5. 来终止后台 cat

请注意,通过这样做,reader 进程(在本例中为 mysql)将永远不知道输入何时结束。它总是会阻止更多的输入,除非你在杀死 mysql.

之前杀死背景 cat