Elixir Supervisors——你如何命名一个监督任务
Elixir Supervisors — How do you name a Supervised Task
我真的在与 Elixir supervisors 纠缠不清,想知道如何命名它们以便我可以使用它们。基本上,我只是想启动一个受监督的 Task
,我可以向其发送消息。
所以我有以下内容:
defmodule Run.Command do
def start_link do
Task.start_link(fn ->
receive do
{:run, cmd} -> System.cmd(cmd, [])
end
end)
end
end
项目入口点为:
defmodule Run do
use Application
# See http://elixir-lang.org/docs/stable/elixir/Application.html
# for more information on OTP Applications
def start(_type, _args) do
import Supervisor.Spec, warn: false
children = [
# Define workers and child supervisors to be supervised
worker(Run.Command, [])
]
# See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: Run.Command]
Supervisor.start_link(children, opts)
end
end
在这一点上,我什至不确定我是否使用了正确的东西(具体来说 Task
)。基本上,我想要的只是在应用程序启动时生成一个进程或任务或 GenServer 或任何正确的东西,我可以向其发送消息,这些消息实际上会执行 System.cmd(cmd, opts)
。我希望这个任务或过程受到监督。当我向它发送 {:run, cmd, opts}
消息时,例如 {:run, "mv", ["/file/to/move", "/move/to/here"]}
我希望它产生一个新任务或进程来执行该命令。对于我的使用,我什至不需要从任务中取回响应,我只需要它来执行。任何关于去哪里的指导都会有所帮助。我已经通读了入门指南,但老实说,它让我更加困惑,因为当我尝试做已经完成的事情时,它永远不会像在应用程序中那样。
感谢您的耐心等待。
我只使用 GenServer,设置如下:
defmodule Run do
use Application
def start(_, _) do
import Supervisor.Spec, warn: false
children = [worker(Run.Command, [])]
Supervisor.start_link(children, strategy: :one_for_one)
end
end
defmodule Run.Command do
use GenServer
def start_link do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
end
def run(cmd, opts) when is_list(opts), do: GenServer.call(__MODULE__, {:run, cmd, opts})
def run(cmd, _), do: GenServer.call(__MODULE__, {:run, cmd, []})
def handle_call({:run, cmd, opts}, _from, state) do
{:reply, System.cmd(cmd, opts), state}
end
def handle_call(request, from, state), do: super(request, from, state)
end
然后您可以向 运行 进程发送一个命令来执行,如下所示:
# If you want the result
{contents, _} = Run.Command.run("cat", ["path/to/some/file"])
# If not, just ignore it
Run.Command.run("cp", ["path/to/source", "path/to/destination"])
基本上我们正在创建一个 "singleton" 进程(只能使用一个给定的名称注册一个进程,而我们正在使用模块的名称注册 Run.Command 进程,所以任何在进程为 运行 时连续调用 start_link
将失败。但是,这使得设置可以透明执行命令的 API (run
函数)变得容易在另一个进程中,调用进程不必知道任何关于它的信息。我在这里使用 call
与 cast
,但如果您永远不关心结果并且不想要调用进程阻塞。
对于长运行,这是一个更好的模式。对于一次性的事情,Task
更简单易用,但我个人更喜欢将 GenServer
用于像这样的全局流程。
我真的在与 Elixir supervisors 纠缠不清,想知道如何命名它们以便我可以使用它们。基本上,我只是想启动一个受监督的 Task
,我可以向其发送消息。
所以我有以下内容:
defmodule Run.Command do
def start_link do
Task.start_link(fn ->
receive do
{:run, cmd} -> System.cmd(cmd, [])
end
end)
end
end
项目入口点为:
defmodule Run do
use Application
# See http://elixir-lang.org/docs/stable/elixir/Application.html
# for more information on OTP Applications
def start(_type, _args) do
import Supervisor.Spec, warn: false
children = [
# Define workers and child supervisors to be supervised
worker(Run.Command, [])
]
# See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: Run.Command]
Supervisor.start_link(children, opts)
end
end
在这一点上,我什至不确定我是否使用了正确的东西(具体来说 Task
)。基本上,我想要的只是在应用程序启动时生成一个进程或任务或 GenServer 或任何正确的东西,我可以向其发送消息,这些消息实际上会执行 System.cmd(cmd, opts)
。我希望这个任务或过程受到监督。当我向它发送 {:run, cmd, opts}
消息时,例如 {:run, "mv", ["/file/to/move", "/move/to/here"]}
我希望它产生一个新任务或进程来执行该命令。对于我的使用,我什至不需要从任务中取回响应,我只需要它来执行。任何关于去哪里的指导都会有所帮助。我已经通读了入门指南,但老实说,它让我更加困惑,因为当我尝试做已经完成的事情时,它永远不会像在应用程序中那样。
感谢您的耐心等待。
我只使用 GenServer,设置如下:
defmodule Run do
use Application
def start(_, _) do
import Supervisor.Spec, warn: false
children = [worker(Run.Command, [])]
Supervisor.start_link(children, strategy: :one_for_one)
end
end
defmodule Run.Command do
use GenServer
def start_link do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
end
def run(cmd, opts) when is_list(opts), do: GenServer.call(__MODULE__, {:run, cmd, opts})
def run(cmd, _), do: GenServer.call(__MODULE__, {:run, cmd, []})
def handle_call({:run, cmd, opts}, _from, state) do
{:reply, System.cmd(cmd, opts), state}
end
def handle_call(request, from, state), do: super(request, from, state)
end
然后您可以向 运行 进程发送一个命令来执行,如下所示:
# If you want the result
{contents, _} = Run.Command.run("cat", ["path/to/some/file"])
# If not, just ignore it
Run.Command.run("cp", ["path/to/source", "path/to/destination"])
基本上我们正在创建一个 "singleton" 进程(只能使用一个给定的名称注册一个进程,而我们正在使用模块的名称注册 Run.Command 进程,所以任何在进程为 运行 时连续调用 start_link
将失败。但是,这使得设置可以透明执行命令的 API (run
函数)变得容易在另一个进程中,调用进程不必知道任何关于它的信息。我在这里使用 call
与 cast
,但如果您永远不关心结果并且不想要调用进程阻塞。
对于长运行,这是一个更好的模式。对于一次性的事情,Task
更简单易用,但我个人更喜欢将 GenServer
用于像这样的全局流程。