Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Elixir GenServer强制转换和启动链接_Elixir_Otp_Gen Server - Fatal编程技术网

Elixir GenServer强制转换和启动链接

Elixir GenServer强制转换和启动链接,elixir,otp,gen-server,Elixir,Otp,Gen Server,这是我的前两个小时的长生不老药,所以这可能是一个不切实际的问题,但我在生成GenServer并使用它时遇到了一些问题。我正在使用这个模块,它监视系统中某个文件的更改,每次在该文件中添加一个新条目时,我都希望将日志转换到gen服务器,该服务器将对日志进行分析,并根据结果执行任何应该执行的操作 以下是监视更改的模块: defmodule Test.Watcher do use ExFSWatch, dirs: ["/var/log/"] import Test.Receiver,

这是我的前两个小时的长生不老药,所以这可能是一个不切实际的问题,但我在生成
GenServer
并使用它时遇到了一些问题。我正在使用这个模块,它监视系统中某个文件的更改,每次在该文件中添加一个新条目时,我都希望将日志转换到gen服务器,该服务器将对日志进行分析,并根据结果执行任何应该执行的操作

以下是监视更改的模块:

defmodule Test.Watcher do
    use ExFSWatch, dirs: ["/var/log/"]

    import Test.Receiver, only: [analyze_log: 2]

    def callback(file_path, actions) do
        if file_path == "/var/log/syslog" do
            if :modified in actions do
                #~~~~ WHERE DO I GET THIS pid FROM?
                analyze_log pid, get_log
            end
        end
    end

    def get_log do
        {log, _} = System.cmd("tail", ["-n", "1", "/var/log/syslog"])
        log
    end
end
watcher工作得很好,它接收到了新的日志,但是我遇到了使用
GenServer
Test.Receiver
的问题

我的第一个问题是…我从哪里启动这个gen服务器
ExFSWatch
有自己的
start
方法,我无法覆盖它。每次有新日志传入时,我是否会调用
start\u link
(我对此表示怀疑,但我不得不问)

所有我读过的例子我都应该从其他地方开始,抓住它的
pid
,并将它作为参数传递给
analyze\u log
方法,如果我是对的,我唯一剩下的问题是找到一个好地方来启动
Test.Receiver
Genserver并获取它的pid,这样我就可以在
回调
方法中使用它

defmodule Test.Receiver do
    use GenServer

    def start_link do
        GenServer.start_link(__MODULE__, :ok, [])
    end

    def analyze_log(pid, log) do
        GenServer.cast(pid, {:analyze_log, log})
    end

    def init(:ok) do
        {:ok, %{}}
    end

    def handle_cast({:analyze_log, log}, state) do
        IO.puts log
        {:noreply, state}
    end
end

好的,为了扩展@Dogbert的答案并为其他开始使用长生不老药的人澄清它,我将为我提供解决方案。这可能不是最优雅的一个,因为我缺乏知识,但工作

正如Dogbert所说,您需要用一个名称注册您的
GenServer
,并用该名称调用它。所以我转到我的主文件,生成了一个监听器,让这些监听器保持活跃,就像这样:

defmodule Test do
    use Application

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

        Fail2ban.Watcher.start

        children = [
            # ... I have more here but let's keep it simple
            supervisor(Test.Receiver, [Test.Receiver]),
        ]

        opts = [strategy: :one_for_one, name: Test.Supervisor]
        Supervisor.start_link(children, opts)
    end
end
如您所见,传递到supervisor调用的第二个参数是我要注册此模块的名称。我想这可能是你喜欢的任何东西,因为我对此不是很确定。第二个参数进入我的接收器的
start\u链接
,并以该名称注册:

def start_link(name \\ nil) do
    GenServer.start_link(__MODULE__, nil, [name: name])
end
现在,记住接收器上的这个方法,我在pid方面遇到了问题,我不知道从哪里得到:

defmodule Test.Watcher do
    use ExFSWatch, dirs: ["/var/log/"]

    import Test.Receiver, only: [analyze_log: 2]

    def callback(file_path, actions) do
        if file_path == "/var/log/syslog" do
            if :modified in actions do
                # Instead of the pid, pass the name under which it was registered
                analyze_log Test.Receiver, get_log
            end
        end
    end

    def get_log do
        {log, _} = System.cmd("tail", ["-n", "1", "/var/log/syslog"])
        log
    end
end

对我来说很有用,欢迎讨论和改进。这是我使用长生不老药的第二天,我开始掌握它的滴答声。来自Python、Ruby和PHP的我,一直以参数和状态的形式获取和传递信息有点困难,但是..我现在看到太阳了。

大多数具有这种回调接口的模块也有一个额外的“状态”参数携带此类信息,但由于某种原因,
ExFSWatch
似乎没有。除此之外,我能想到的最简单的方法是生成并用名称注册接收方进程,然后按名称调用它。谢谢