执行命令和流结果

时间:2015-12-08 20:31:27

标签: elixir

我想执行系统命令(git clone)并通过Phoenix中的频道将输出流式传输给用户?

我能不能以某种方式使System.cmd流成为结果,而不是等到它完成?

或者,我可以将输出写入文件并从中传输内容,因为它正在追加?

3 个答案:

答案 0 :(得分:2)

可以用以下方式覆盖输出:

System.cmd "git", ["clone", "YOUR_GIT"], into: IO.stream(:stdio, :line)

结果:

  

克隆到'YOUR_GIT'... remote:计数对象:1665,完成。                                        remote:压缩对象:0%(1/979)remote:压缩对象:100%(979/979),完成。                                                     接收物体:0%(1/166远程:总计1665(delta 855),重复使用1331(delta 597)                                                          接收物体:92%(接收物体:100%(1665/1665),5.25 MiB | 376.00   KiB / s,完成了。                                                                      解决delResolving增量:100%(855/855),完成。                                          检查连接...完成。
  {%IO.Stream {device :: standard_io,line_or_bytes :: line,raw:false},0}

docs

编辑:

为了帮助您完成特定任务,将本地标准流重定向到外部标准流,有一个库porcelainhandles it perfectly

答案 1 :(得分:2)

我建议使用瓷器。具体检查https://github.com/alco/porcelain#messages

您可以使用Porcelain.spawn_shell使用out: {:send, self()}选项运行命令,并实施匹配的handle_info回调。

答案 2 :(得分:0)

如果您不想使用具有go可执行依赖性的Porcelain,您可以使用端口,如下所示:

  def long do
    port = Port.open({:spawn_executable, /path/to/command"}, [:stderr_to_stdout, :binary, :exit_status, args: ["arg1"]])
    stream_output(port)
  end

  defp stream_output(port) do
    receive do
      {^port, {:data, data}} ->
        Logger.info(data) # send to phoenix channel
        stream_output(port)
      {^port, {:exit_status, 0}} ->
        Logger.info("Command success")
      {^port, {:exit_status, status}} ->
        Logger.info("Command error, status #{status}")
    end
  end