Elixir shell 中的 Application.stop(...)

Posted

技术标签:

【中文标题】Elixir shell 中的 Application.stop(...)【英文标题】:Application.stop(...) in Elixir shell 【发布时间】:2016-08-22 18:42:07 【问题描述】:

我正在使用 Plug 和 Cowboy 在 Elixir 中编写一个简单的应用程序并进行混合。执行后:

$ iex -S mix

应用程序启动。如果我执行

iex(1)> Application.start(:web)
:error, :already_started, :web

我得到了预期的输出。但是,当我尝试使用以下命令停止应用程序时:

iex(2)> Application.stop(:web)
:ok

我收到了:ok,但随后收到了很多消息,包括以下内容:

iex(3)>
09:36:43.689 [info]  Application web exited: :stopped

09:36:43.691 [error] GenServer #PID<0.189.0> terminating
** (stop) killed
Last message: :EXIT, #PID<0.187.0>, :killed
State: :state, #PID<0.189.0>, :ranch_acceptors_sup


:undefined, 1, 5, [], 0, :ranch_acceptors_sup, [ServeRequests.HTTP, 100, 
:ranch_tcp, [port: 4000]]
09:36:43.691 [error] Failed to start Ranch listener ServeRequests.HTTP in :ranch_tcp:listen([port: 4000]) for reason :eaddrinuse (address already in use)
09:36:43.691 [info]  Application ranch exited: shutdown
nil

我在代码中做错了吗?这是正常行为吗?

mix.exs文件的内容如下:

defmodule Web.Mixfile do
  use Mix.Project

  def project do
    [app: :web,
     version: "0.1.1",
     elixir: "~> 1.2",
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     deps: deps]
  end

  def application do
    [applications:
        [:logger, :cowboy, :plug],
        mod: Web, []
    ]
  end

  defp deps do
  [:cowboy, "~> 1.0.3",
  :plug, "~> 1.1.2"]
  end
end

lib/web.ex的内容如下:

defmodule Web do
  use Application

  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    children = [
      worker(Web.Router, [])
    ]

    opts = [strategy: :one_for_one, name: Web.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

谢谢, 米哈利斯。

【问题讨论】:

请分享您的mix.exs 配置文件。看起来您的应用程序已正确停止而没有错误(第一行),但您的节点尝试在您的操作系统释放端口 4000 之前立即重新启动牧场。如果您可以在 GitHub 上共享您的整个项目,它将允许人们进行挖掘。 包含mix.exs的内容。有没有办法释放4000端口或者让Supervisor稍等一下? @MihalisTsoukalos 你能把lib/web.ex的内容也发一下吗? 我已经检查过,即使使用 start_permanent,应用程序在使用 Application.stop/1 停止时也不应该自动重新启动,所以我不确定是否可以提供帮助。 您可以在github.com/mactsouk/Elixir找到该项目的所有Elixir文件。 【参考方案1】:

这在文档中有一些子文档,我现在也看到我应该在 EiA 中解释这一点(我的错)。要点是您应该使用Plug.Adapters.Cowboy.child_spec 将服务器正确插入到监督树中。然后,服务器将与应用程序一起正确停止。

这是在您的示例中的外观(web.ex):

children = [
  Plug.Adapters.Cowboy.child_spec(:http, Web.Router, [])
]

这样,您可以完全摆脱my_web_startWeb.Router.start_server 函数。

在 shell 中尝试它给了我:

iex(1)> Application.stop(:web)
:ok
16:44:29.929 [info]  Application web exited: :stopped

iex(2)> Application.start(:web)
:ok

然后我可以再次访问该页面。

【讨论】:

我有 EiA,但在那里找不到解决方案。再次感谢!【参考方案2】: 它表示您的地址已被使用 (eaddrinuse)。 尝试重新启动您正在运行的设备或检查您没有两次打开程序。 重新启动将停止并启动可能修复地址的程序 使用。

【讨论】:

为什么应用程序无法正常停止?

以上是关于Elixir shell 中的 Application.stop(...)的主要内容,如果未能解决你的问题,请参考以下文章

将 iex shell 附加到正在运行的 elixir 应用程序

Elixir IEX在显示提示之前停止,并且不接受输入

E1.获取Elixir/Erlang版本信息

为输入 iex shell 着色

如何重新编译 Elixir 项目并从 iex 中重新加载它?

elixir中的truth和true