在不同的执行过程中保持FIFO可读

我从来没有使用过一个命名pipe道,最近才意识到这正是我所需要的。

我正在运行一个使用gnu parallel的程序,这个程序可能会产生为mySQL上的一个数据库格式化的输出(GB到1TB,现在很难知道)。

我发现我可以打开两个terminal:terminal1得到如下的东西:

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

在哪里pipe道是由mkfifo制成的fifo。

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

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

有用…

但是,这很笨拙…如果我理解正确,第一个过程结束时会产生一个EOF,导致pipe道closures。

理想情况下,我想在不同参数的循环中运行第一个进程。 每次迭代可能需要很长时间,我需要进行合理性检查,所以我不会松懈一周,以查明是否有错误或逻辑错误。

我想知道如何以标准的方式使用FIFO这种程序。

如果我理解正确,第一个进程结束时会生成一个EOF,导致管道关闭。

有点。 还有一点比这个还要多 – 从技术上讲,第一道工序结束后管道关闭是不正确的。

相反,当管道中没有更多数据时,管道和FIFO将返回EOF,并且不会打开任何进程的写入。

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

在你的情况下,这是不可能的,因为你没有持续运行的永久进程(也就是说,你没有相当于服务器进程)。 您基本上需要某种“持久性写入器”,即在不同的迭代过程中保持管道打开以供写入的过程。

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

所以,简而言之,你:

  1. 创建FIFO: mkfifo /home/pipe
  2. 启动一个打开FIFO的后台作业: cat >/home/pipe &
  3. 不管你想要运行你的程序,需要多少次迭代。 忽略关于正在停止的后台作业的shell消息。 你可以像这样离开,因为即使作业已经停止,管道仍然是打开的。
  4. 当你完成后,通过把它带到前台并发送SIGINT(通常是Ctrl + C)或kill PID来杀死后台cat

请注意,通过这样做读者进程(在这种情况下,mysql)将永远不知道什么时候输入结束。 它会一直阻塞更多的输入,除非你在杀死mysql之前杀死后台cat