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