I've just spent 3 hours trying to figure out why open_port isn't working.
I had this command that I would spawn that would output a line of text from time to time. What I wanted to do is turn those lines of text into some form of events, in Erlang. Something like:
run() ->
Port = open_port({spawn, "my-long-running-command"},
[exit_status, {line, 1024}]),
loop().
loop() ->
receive {data, {eol, Line}}} -> we_have_an_event(Line) end,
loop().
But the problem was that Erlang was not getting anything from that command - even though it was printing when testing it separately.
So I spent a lot of time trying all the possible combinations of options for open_port - thinking that I'm not using it correctly.
At some point I discovered a curious thing. If I did "my-long-running-command | tee a.txt" nothing would show up in a.txt when running the command in open_port - but it would if I ran it in a terminal.
So it finally struck me. The command's output was being buffered somehow only when it was run in Erlang.
So the solution was to make all the buffers zero, like so:
Port = open_port({spawn, "stdbuf -i0 -o0 -e0 my-long-running-command"},
[exit_status, {line, 1024}])
This way I received each line the moment it was printed out by the program.
No comments:
Post a Comment