【问题标题】:Execute command and stream results执行命令并流式传输结果
【发布时间】:2018-03-02 08:46:49
【问题描述】:

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

我能否以某种方式让 System.cmd 流式传输结果而不是等到它完成?

或者,我可以将输出写入文件并从那里流式传输正在附加的内容吗?

【问题讨论】:

    标签: elixir


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      可以使用以下命令覆盖输出:

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

      结果:

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

      docs

      编辑:

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

      【讨论】:

      • 我试过了,但没用。 System.cmd 似乎仍在等待它完成。这就是我跑的:gist.github.com/Linuus/1a5ca235650cc2ba0b9a
      • 我的意思是,IO.stream(:stdio, :line) 只是将它打印到应用程序标准输出。对吗?
      • sobolevn:我不太明白。你能给我一个完整的例子和 System.cmd 吗?
      • sobolevn:它似乎不起作用:试试这个 System.cmd("git", ["clone", "--progress", git_uri, "docker-test"], stderr_to_stdout:是的,进入: IO.stream(:stdio, :line)) |> Stream.map(fn(line) -> IO.inspect("FOO") end) 永远不会调用 IO.inspect("FOO")。一切都只是打印到标准输出。我想将每一行捕获为流并在 Phoenix 通道中发送给客户端。
      【解决方案3】:

      如果你不想使用Porcelain,它有一个go可执行依赖,你可以使用port,像这样:

        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
      

      【讨论】:

        猜你喜欢
        • 2016-06-20
        • 1970-01-01
        • 2016-03-21
        • 1970-01-01
        • 1970-01-01
        • 2015-01-07
        • 1970-01-01
        • 2013-01-31
        • 2013-07-16
        相关资源
        最近更新 更多