使用Supervisor时,如何获取start_link/3启动进程的PID?
获取被Supervisor监控的Slack Bot进程PID的方法
不用额外加一层监督就能搞定!这里有几个简单的方案,既能拿到进程的引用(或者PID),又能保持Supervisor对它的监控:
方案1:给Slack Bot进程注册一个全局名字
这是最省心的方法——直接在启动Slack.Bot的时候给它指定一个注册名,之后不管进程重启多少次,你都可以用这个名字直接发消息,完全不用管PID变化。
修改你的子进程配置:
children = [ %{ id: Slack.Bot, # 在start_link的第四个参数(opts)里添加name选项 start: {Slack.Bot, :start_link, [MyBot, [], "api_token", [name: :my_slack_bot]]} } ] opts = [strategy: :one_for_one, name: MyBot.Supervisor] Supervisor.start_link(children, opts)
之后发送自定义事件的时候,直接用这个注册名就行:
send(:my_slack_bot, {:custom_event, "hello"})
Slack.Bot会把这个消息传递给你的MyBot.handle_info/3回调处理,完美!
方案2:通过Supervisor查找子进程
如果不想给进程注册名字,你可以利用Supervisor的API来根据子进程ID查找它的PID。因为你已经给子进程设置了id: Slack.Bot,所以可以用以下方式获取:
# 查找子进程PID case Supervisor.lookup_child(MyBot.Supervisor, Slack.Bot) do {:ok, pid} -> # 拿到PID后发送消息 send(pid, {:custom_event, "hello"}) :error -> # 处理进程不存在的情况(比如还没启动或者已经崩溃) IO.puts("Slack Bot进程不存在") end
或者用Supervisor.which_children/1列出所有子进程再筛选:
for {id, pid, _type, _modules} <- Supervisor.which_children(MyBot.Supervisor), id == Slack.Bot do send(pid, {:custom_event, "hello"}) end
注意点
- 因为Supervisor会在进程崩溃后重启它,所以PID可能会变化。如果你的代码需要频繁发送消息,建议用方案1的注册名,它会自动绑定到重启后的新PID,不用每次都查。
- 两种方案都不会破坏Supervisor的监控机制——子进程依然由
MyBot.Supervisor管理,崩溃后会按配置的策略重启。
内容的提问来源于stack exchange,提问作者Adam Millerchip
相关产品推荐
相关产品推荐

