When calling shell scripts from Erlang, I generally need their exit status (0 or something else), so I run them using this function:
%% in module util
os_cmd_exitstatus(Action, Cmd) ->
?debug("~ts starting... Shell command: ~ts", [Action, Cmd]),
try erlang:open_port({spawn, Cmd}, [exit_status, stderr_to_stdout]) of
Port ->
os_cmd_exitstatus_loop(Action, Port)
catch
_:Reason ->
case Reason of
badarg ->
Message = "Bad input arguments";
system_limit ->
Message = "All available ports in the Erlang emulator are in use";
_ ->
Message = file:format_error(Reason)
end,
?error("~ts: shell command error: ~ts", [Action, Message]),
error
end.
os_cmd_exitstatus_loop(Action, Port) ->
receive
{Port, {data, Data}} ->
?debug("~ts... Shell output: ~ts", [Action, Data]),
os_cmd_exitstatus_loop(Action, Port);
{Port, {exit_status, 0}} ->
?info("~ts finished successfully", [Action]),
ok;
{Port, {exit_status, Status}} ->
?error("~ts failed with exit status ~p", [Action, Status]),
error;
{'EXIT', Port, Reason} ->
?error("~ts failed with port exit: reason ~ts",
[Action, file:format_error(Reason)]),
error
end.
This worked fine, until I used this to start a script which forks off a program and exits:
#!/bin/sh
FILENAME=$1
eog $FILENAME &
exit 0
(In the actual usecase, there are quite a few more arguments, and some massaging before they are passed to the program). When run from the terminal, it shows the image and exits immediately, as expected.
But running from Erlang, it doesn't. In the log file I see that it starts fine:
22/Mar/2011 13:38:30.518 Debug: Starting player starting... Shell command: /home/aromanov/workspace/gmcontroller/scripts.dummy/image/show-image.sh /home/aromanov/workspace/media/images/9e89471e-eb0b-43f8-8c12-97bbe598e7f7.png
and the eog
window appears. But I don't get
22/Mar/2011 13:47:14.709 Info: Starting player finished successfully
until killing the eog
process (with kill
or just closing the window), which isn't suitable for my requirements. Why the difference in behavior? Is there a way to fix it?