Executing commands and stream results

I want to execute a system command (git clone) and pass the result to the user through a channel in Phoenix?

Can I somehow get System.cmd to pass the results, rather than wait until it ends?

Or, can I write the output to a file and transfer the contents from there, as it is added?

+5
source share
3 answers

You can override the output with:

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

Result:

Cloning to 'YOUR_GIT' ... remote: counting objects: 1665, done. remote: Object compression: 0% (1/979) remote: Object compression: 100% (979/979), done. Receiving objects: 0% (1 / 166remote: Total 1665 (delta 855), reuse 1331 (delta 597) Receiving objects: 92% (Receiving objects: 100% (1665/1665), 5.25 MiB | 376.00 KiB / s, done. DelResolving deltur resolution: 100% (855/855), done. Connection check ... done.
{% IO.Stream {device :: standard_io, line_or_bytes :: string, raw: false}, 0}

docs

Edit:

To help you achieve your specific task by redirecting a local standard stream to an external one, there is a porcelain library that handles fine .

+2
source

I would advise using Porcelain for this. In particular, check out https://github.com/alco/porcelain#messages .

You can use Porcelain.spawn_shell to run your command with the out: {:send, self()} option out: {:send, self()} and implement the corresponding handle_info .

+2
source

If you do not want to use Porcelain, which has an executable dependency, you can use a port, for example:

  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 
0
source

Source: https://habr.com/ru/post/1237688/


All Articles