使用像 bash 管道这样的操作系统进程:发送 STDIN 并获取其 STDOUT

Ada*_*hip 7 stdin ipc stdout message-passing elixir

我正在尝试使用读取 STDIN 并写入 STDOUT 的外部进程。

我想在 Elixir 中编写与此等效的代码,而不使用外部库或包装脚本:

$ echo foo | nkf
foo
Run Code Online (Sandbox Code Playgroud)

即发送数据到标准输入,并从标准输出nkf返回转换后的结果,知道它已经完成了流的处理。nkf

我试图用端口来做到这一点,但问题是单个发送的消息可以在多个接收到的消息中返回,因此无法判断何时到达消息末尾(简化的示例,实际上"foo"是一个整个文件):

iex(1)> port = Port.open({:spawn, "nkf -u"}, [:binary])
#Port<0.7>
iex(2)> Port.command(port, "foo")
true
iex(3)> flush
{#Port<0.7>, {:data, "fo"}}
{#Port<0.7>, {:data, "o"}}
:ok
Run Code Online (Sandbox Code Playgroud)

如何在 Elixir 中获得与 Ports 相同的 bash 管道行为?

Ada*_*hip 2

Beam 当前不提供关闭进程的流并等待进程中的流完成发送的方法。使用端口,关闭端口也会关闭来自外部进程的流,即使该进程尚未完成数据发送。因此,目前不可能仅使用内置功能 - 有必要寻求外部工具的帮助,例如瓷器erlexec