3
votes

Is it possible to write to stdin of external process In Elixir? Is NIF the only option right now?

The process that started from Elixir, blocks and wait for user input:

pid = spawn(fn ->
   System.cmd("sh", [
    Path.join([System.cwd, "sh", "wait_for_input"]),
   "Hello world"
  ])
end)

I would like to achieve something like that

IO.write pid, "Hello"
IO.write pid, "Hello again"

And this is the script

#!/bin/sh
while read data
do
  echo $data >> file_output.txt
done
1
Check out Ports: elixir-lang.org/docs/stable/elixir/Port.html. Specifically, Port.open/2 and Port.command/3.Dogbert
@Stratus3D I'm looking for the opposite, to write into stdin.LemmonMaxwell
@Dogbert when I run the command it sends the data, but I don't see it writes to stdin for the external process.LemmonMaxwell
@LemmonMaxwell can you post a simplified version of the script you're executing with sh and writing data to so I can reproduce the error? Port.command should work: iex(1)> port = Port.open({:spawn, "sh"}, []); Port.command(port, "echo 1\n"); iex(2)> flush {#Port<0.1348>, {:data, '1\n'}}.Dogbert

1 Answers

8
votes

You can use Port for this. Note that the read builtin of sh will only get data when a newline character is sent to sh, so you need to add that whenever you want the buffered data to be sent to read.

$ cat wait_for_input
while read data
do
  echo $data >> file_output.txt
done
$ iex
iex(1)> port = Port.open({:spawn, "sh wait_for_input"}, [])
#Port<0.1260>
iex(2)> Port.command port, "foo\n"
true
iex(3)> Port.command port, "bar\n"
true
iex(4)> Port.close(port)
true
$ cat file_output.txt
foo
bar