我有一个 Elixir 应用程序,其结构如下:
Application --> Supervisor --> Worker
应用程序模块相当简单,它有一个use Application
和一个
def start(_type, _args)
MyApp.Supervisor.start_link()
end
主管有点复杂:
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(考虑到它可能必须等到它启动) .
IO.puts
我的 Worker 模块使用和与用户交互IO.gets
。为什么所有这些复杂的不必要的逻辑?看起来
- 当使用 mix run 并省略停止退出时,应用程序立即死亡
- 当使用 mix release (distillery) 并
myapp.bat console
从 cmd 运行并省略停止退出时,我的应用程序启动,立即死亡,然后 iex 启动 - 当使用带有
myapp.bat console
停止退出的混合版本时,我的应用程序输出正确,但无法接收任何输入(我的意思是我无法在 werl.exe 的窗口中输入) - 使用 mix release w/ 时
myapp.bat foreground
,我的应用程序启动,然后批处理文件中出现错误(系统找不到文件 `%get_pid_cmd%`。错误:无法识别搜索过滤器。无法识别 '@call'作为内部或外部命令、可运行程序或批处理文件。)此时我的应用程序终止。 - 当使用 mix run --no-halt (应用程序内没有退出暂停逻辑)时,我的应用程序启动,立即终止,并且 erlang VM 仍然在 cmd 窗口中运行
- 只有当我混合运行和包含时
halt_exit/1
,我的应用程序才能按预期工作
综上所述,我得出的结论是 1)当我的应用程序模块start/2
返回时,应用程序就关闭了,这没有多大意义,因为 Elixir 是为那些将负载放在其他进程而不是在应用程序的 main之外的应用程序而设计的模块。2)输入是通过主应用程序模块的进程完成的(但由于某种原因,仅在单独的 werl.exe 窗口中运行时,似乎可以正常运行混合运行),所以我不能放置任何阻塞直到工作完成如果我想要我的用户输入,那里有逻辑。
我该如何解决这个问题,同样重要的是(这样我可以避免将来出现问题)是什么行为导致了我的问题?我需要能够在没有安装 mix 和 Erlang VM 的计算机上运行它,所以我唯一的选择是让它与生成的 distillery 包一起工作,目前我不能。
没有多少谷歌搜索导致我采取类似的策略来人为地停止退出,而且我发现没有论坛/教程提到这个“提前退出”的问题,所以我想解决这个问题的正确方法是以某种方式让它不想要在任何进程运行时退出。