次のように構成された Elixir アプリケーションがあります。
Application --> Supervisor --> Worker
アプリケーション モジュールは非常に単純でuse Application
、
def start(_type, _args)
MyApp.Supervisor.start_link()
end
Supervisor はもう少し複雑です。
def start_link() do
{:ok, pid} = Supervisor.start_link(__MODULE__, [], name: __MODULE__)
halt_exit(wait_for_child())
{:ok, pid}
end
def init(data) do
children =
[
worker(MyApp.Worker, [], restart: :transient)
]
Supervisor.init(children, [strategy: :one_for_one])
end
wherehalt_exit(pid)
は aProcess.sleep(100)
を実行し、プロセス pid がまだ生きていることがわかるたびに自分自身を呼び出し (または pid がもう生きていない場合は単に nil を返します)、wait_for_child
Worker モジュールの pid を見つけます (開始されるまで待たなければならない可能性があることを考慮して) .
私の Worker モジュールは、 と を使用してユーザーと対話しIO.puts
ますIO.gets
。なぜこのような複雑で不必要なロジックが必要なのですか? のようだ
- mix run を使用し、halting exit を省略すると、アプリケーションがすぐに終了する
- mix release (distillery) を使用し
myapp.bat console
て cmd から実行し、停止中の終了を省略すると、アプリケーションが起動し、すぐに終了し、iex が起動します - mix release を使用し
myapp.bat console
、halting exit を含めると、アプリは正しく出力されますが、入力を受け取ることができません (これは、werl.exe のウィンドウに入力できないことを意味します)。 - mix release w/ を使用
myapp.bat foreground
すると、アプリが起動し、バッチ ファイルにエラーが発生します(システムはファイル `%get_pid_cmd%` を見つけることができません。エラー: 検索フィルターを認識できません。'@call' は認識されません)。内部コマンドまたは外部コマンド、操作可能なプログラムまたはバッチ ファイルとして。) その時点でアプリが終了します。 - mix run --no-halt (アプリ内に exit-halting ロジックがない) を使用すると、アプリが起動し、すぐに終了し、erlang VM は cmd ウィンドウで実行されたままになります
- run と include を混在させた場合にのみ
halt_exit/1
、アプリが期待どおりに動作します
これらすべてから、私は次のように結論付けました。1) アプリケーション モジュールがstart/2
戻った瞬間に、アプリはシャットダウンされます。Elixir は、アプリケーションのメイン以外ではなく、他のプロセスに負荷をかけるアプリケーション向けに設計されているため、あまり意味がありません。モジュール。2) 入力はメイン アプリケーション モジュールのプロセスを介して行われます (ただし、何らかの理由で別の werl.exe ウィンドウで実行された場合のみ、mix run で正常に動作するようです)、blocking-until-work-finished を配置できません。ユーザー入力が必要な場合は、そこにロジックがあります。
どうすればこれを解決できますか? 同様に重要なことに (将来の問題を回避できるように)、どのような動作が問題を引き起こしているのでしょうか? mixとErlang VMがインストールされていないコンピューターでこれを実行できる必要があるため、私の唯一のオプションは、生成されたdistilleryパッケージで動作させることですが、現時点ではできません。
いくらグーグルで調べても、人為的に終了を停止するための同様の戦術に私を導いたことはなく、私が見つけたフォーラム/チュートリアルでは、この「早期終了」の問題について言及していないので、これを解決する正しい方法は、どうにかしてそれを望ましくないものにすることだと思いますプロセスの実行中に終了します。