elixir - How to capture each line from System.cmd output? -
how capture each line written in console when run commands system.cmd
or other approach?
i want capture final results displayed in console in case similar to: cloning 'myrepo'... remote: counting objects: 3271, done.
, send each line via channels:
case system.cmd("git", ["clone", "git@github.com:#{vault}/#{repo}.git"], cd: repo) {results, 0} -> myapp.endpoint.broadcast("app:setup", "new:line", results) {_, code} -> raise runtimeerror, "`git clone` failed code #{code}" end
i haven't found solution, there similar issues without clear answer: question or question
so, there couple approaches here, , i'm going try sum , have able make sense of previous answers in other questions.
first of all, should know handling stuff in detail, need learn how use :erlang.open_port/2
. can pass {:line, max_length}
options 1 message per line. output git
seeing stuff being written stderr
, , can pass :stderr_to_stdout
redirect come in 1 line per message. can loop using receive
until receive eof
message, , can see docs more details on when eof
message emitted.
bitwalker's answer in second link want modification:
defmodule shell def exec(exe, args, opts \\ [:stream]) when is_list(args) port = port.open({:spawn_executable, exe}, opts ++ [{:args, args}, :binary, :exit_status, :hide, :use_stdio, :stderr_to_stdout]) handle_output(port) end def handle_output(port) receive {^port, {:data, data}} -> io.inspect(data) # replace appropriate broadcast handle_output(port) {^port, {:exit_status, status}} -> status end end end
now, while can redirect stderr stdout, 1 of problems here git detect redirected stream , adjust how streams accordingly. want compare output of these calls:
gitcmd = system.find_executable("git") shell.exec(gitcmd, ["clone","--progress",url], [{:line, 4096}])
this prints out 1 message each "\n" finds in stream. notice junk \r? that's how progress comes out. can remove --progress
args, , you'll 1 or 2 boring lines. if want everything, need stream results, , split line-ish output yourself.
shell.exec(gitcmd, ["clone","--progress",url], [:stream])
you can see using :stream
instead of :line
we'll it's being flush'd other side. you'll have clean dangling \r
, \n
yourself, , may want plan receiving part of line, think should onto journey.
this redirecting stderr stdout, if need retain difference between stderr
, stdout
, , if want ability kill process, rather depend on closing after close stdin
, you're going have rely on porcelain manages well-behaved process "manage" other process you.
Comments
Post a Comment