当从 Erlang 调用 shell 脚本时,我通常需要它们的退出状态(0 或其他),所以我使用这个函数运行它们:
%% 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.
这工作得很好,直到我用它来启动一个分叉程序并退出的脚本:
#!/bin/sh
FILENAME=$1
eog $FILENAME &
exit 0
(在实际用例中,还有很多参数,并且在将它们传递给程序之前进行了一些按摩)。从终端运行时,它会按预期显示图像并立即退出。
但是从 Erlang 运行,它没有。在日志文件中,我看到它开始正常:
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
并eog
出现窗口。但我不明白
22/Mar/2011 13:47:14.709 Info: Starting player finished successfully
直到终止eog
进程(kill
关闭或关闭窗口),这不适合我的要求。为什么行为上的差异?有没有办法解决它?