shahryarjb
How to send line by line of System.cmd to LiveView when a task is running
Hi friend,
I run 3 or 4 different command with System.cmd, so users wait for these tasks are done and after getting status 0 can do another jobs, but I need a way to show them System.cmd log line by line when is running not show all the log at the end.
System.cmd(operation, [command], into: IO.stream(), stderr_to_stdout: true, env: [{"MIX_ENV", "#{Mix.env()}"}])
And if this feature is available at any time, it will be very attractive. For example, from the middle of the log, if requested, show not the whole log or sending any line to PubSub to the channel.
Thank you
Marked As Solved
Also Liked
ruslandoga
You might be able to do that with Port.open and then receive messages coming from it and send them to the liveview process.
port.exs
defmodule Command do
def exec(cmd, args) do
path = System.find_executable(cmd)
port = Port.open({:spawn_executable, path}, [:binary, :exit_status, args: args, line: 1000])
loop(port)
end
defp loop(port) do
receive do
{^port, {:data, data}} ->
IO.inspect(data: data)
loop(port)
{^port, {:exit_status, exit_status}} ->
IO.inspect(exit_status: exit_status)
end
end
end
Command.exec("cat", ["port.exs"])
> elixir port.exs
[data: {:eol, "defmodule Command do"}]
[data: {:eol, " def exec(cmd, args) do"}]
[data: {:eol, " path = System.find_executable(cmd)"}]
[
data: {:eol,
" port = Port.open({:spawn_executable, path}, [:binary, :exit_status, args: args, line: 1000])"}
]
[data: {:eol, " loop(port)"}]
[data: {:eol, " end"}]
[data: {:eol, ""}]
[data: {:eol, " defp loop(port) do"}]
[data: {:eol, " receive do"}]
[data: {:eol, " {^port, {:data, data}} ->"}]
[data: {:eol, " IO.inspect(data: data)"}]
[data: {:eol, " loop(port)"}]
[data: {:eol, ""}]
[data: {:eol, " {^port, {:exit_status, exit_status}} ->"}]
[data: {:eol, " IO.inspect(exit_status: exit_status)"}]
[data: {:eol, " end"}]
[data: {:eol, " end"}]
[data: {:eol, "end"}]
[data: {:eol, ""}]
[data: {:eol, "Command.exec(\"cat\", [\"port.exs\"])"}]
[exit_status: 0]
ruslandoga
There’re some on OS Process Manager for Erlang VM
axelson
I’d recommend looking into exexec | Hex (which wraps the erlexec Erlang library) especially if the command you want to run are not written to conform to the behavior that Port expects.
ruslandoga
Port.open({:spawn_executable, path}, env: [{'MIX_ENV', 'dev'}])
Note that Mix.env() is not always available at runtime.







