4

Erlangからシェルスクリプトを呼び出すときは、通常、終了ステータス(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ウィンドウを閉じるか、ウィンドウを閉じるだけ)、これは私の要件には適していません。なぜ行動の違い?それを修正する方法はありますか?

4

2 に答える 2

3

通常、シェルスクリプトを使用してバックグラウンドでコマンドを実行し&、シェルスクリプトがコマンドの前に終了すると、コマンドは孤立します。erlangがopen_portで孤立したプロセスを防止しようとしeog、終了するのを待っている可能性があります。通常、シェルスクリプト中にバックグラウンドで何かを実行する場合waitは、スクリプトの最後にを入れて、バックグラウンドプロセスが終了するのを待つ必要があります。しかし、これはまさにあなたがやりたくないことです。

シェルスクリプトで次のことを試してみてください。

#!/bin/sh

FILENAME=$1

daemon eog $FILENAME

# exit 0 not needed: daemon returns 0 if everything is ok

オペレーティングシステムにdaemonコマンドがある場合。FreeBSDにチェックインしたところ、daemon(8)が1つあります。

これは、すべてのUnixライクなシステムで使用できるコマンドではありませんが、オペレーティングシステムで同じことを行う別のコマンドが存在する可能性があります。

デーモンユーティリティは、それ自体を制御端末から切り離し、引数で指定されたプログラムを実行します。

これで問題が解決するかどうかはeogわかりませんが、制御端末の一種としてstdin/stdouに接続されたままになっているのではないかと思います。とにかく試してみる価値があります。

これにより、ジョブ制御が誤ってオンになり、問題を引き起こす可能性のある問題も解決されるはずです。通常は終了するのでdaemon、シェルビューにはバックグラウンドジョブがないため、シェルは終了時にバックグラウンドジョブを待機できません。

こう言ったのですが、eog実行中はErlangでポートを開いたままにしておかないのはなぜですか?

それを開始します:

#!/bin/sh

FILENAME=$1

exec eog $FILENAME

で呼び出すとexecフォークされません。buはシェルプロセスを。に置き換えますeog。Erlangに表示される終了ステータスはeog、終了時のステータスになります。また、必要に応じて、ポートを閉じてeogErlangで終了することもできます。

于 2011-03-22T15:19:30.107 に答える
1

/bin/shインタラクティブに実行されていない場合、おそらくジョブ制御をサポートしていませんか?少なくとも私のUbuntuシステムの/bin/sh(実際にはdash(1)!)は次のように述べています:

      -m monitor       Turn on job control (set automatically
                       when interactive).

ターミナルからスクリプトを実行すると、シェルはおそらく、スクリプトがインタラクティブに実行されていることを認識し、ジョブ制御をサポートします。シェルスクリプトをポートとして実行すると、シェルはおそらくジョブ制御なしで実行されます。

于 2011-03-22T12:01:01.803 に答える