我有一个由poolboy worker产生的功能
基本概述:
我遇到的问题是,当我运行ExUnit测试时,它会很好地完成生成的进程,并且可以输出数据(使用IO.inspect)。
当我运行System.cmd时(" wget" ....当ExUnit测试运行时,我看到终端中的wget输出,所以命令实际上正在运行,但随后我做了什么在那个命令没有运行之后。
所以在我的工作人员中,如果我这样做:
Product Serial #
然后我看到IO.puts "hello"
System.cmd("wget", opts)
IO.puts "world"
我看到了wget的输出,但我看不到hello
如果我做其他事情:
world
然后我看到IO.puts "hello"
File.write("/tmp/temp.txt", "test")
IO.puts "world"
和hello
,并且写了一个文件。
我是否遗漏了导致此情况发生的world
具体内容?它不能在单独的进程中运行时工作正常,因此它是进程和System.cmd的组合。
有什么想法吗?谢谢!
答案 0 :(得分:5)
您已输入标记为Elixir的部分
"这里是龙"
System.cmd
只是Port
的一个简单包装,Port
主要是。port
Erlang System.cmd
函数的未记录的包装器。
http://www.erlang.org/doc/man/erlang.html#open_port-2
底层的Erlang BEAM进程调度程序是基于它的假设而构建的 可以"交换"以非常短的时间间隔进行处理。如果你只使用Erlang / Exilir 代码,它都被设计为在BEAM VM中工作。任何可能阻止或挂起系统调用的代码都需要在驱动程序中运行。这是一个特殊的 连接到Erlang VM,将Erlang调度程序与可以挂起系统调用的任何进程隔离开来。
设置Ports驱动程序以处理对外部程序的调用。
do_cmd Port.open({:spawn_executable, cmd}, opts), initial, fun
最终调用
do_cmd
端口在单独的进程中运行,System.cmd
例程运行接收
循环,直到它从底层的Erlang端口接收退出状态。所以
System.cmd将"阻止"那个特定的BEAM进程直到wget unix
进程退出。
然而,其余的Elixir BEAM流程将以他们的快乐方式进行。 我对PoolBoy不太熟悉,知道是否存在某种超时 对你的工人进行监控或心跳。但是,如果有和wget命令 超过此超时,工作进程可能会在wget命令之前退出 完成。
Porcelain
并未真正设置为处理可能需要很长时间的命令的所有问题。我建议您查看grep(c(pattern1, pattern2, pattern3), ...)
模块,作为围绕Erlang端口相当复杂的主题的一个很好的包装器。
https://github.com/alco/porcelain
或者由于您正在进行简单的wget,因此使用Elixir或Erlang HTTP客户端模块可能会在BEAM框架内更好地工作。
答案 1 :(得分:0)
我遇到了同样的问题,并且能够通过使用-q选项运行wget命令来回避它。
System.cmd("wget", ["-q", url])
这似乎可以通过静音wget的输出来阻止进程卡住。