简体   繁体   English

Rails:系统进程不会在 Rails 服务器中启动,但会在 Rails 控制台中启动

[英]Rails: system process won't start in rails server, but will in rails console

I want to start a ngrok process when server starts.我想在服务器启动时启动一个ngrok进程。 To achieve this, I coded a ngrok.rb lib and I call it within an initializer为此,我编写了一个 ngrok.rb 库,并在初始化程序中调用它

app/lib/ngrok.rb应用程序/lib/ngrok.rb

require "singleton"
class Ngrok
    include Singleton

    attr_accessor :api_url, :front_url


    def start
        if is_running?
            return fetch_urls
        end

        authenticate
        started = system("ngrok start --all -log=stdout > #{ENV['APP_ROOT']}/log/ngrok.log &")
        system("sleep 1")
        if !started
            return { api: nil, front: nil }
        end

        urls = fetch_urls
        sync_urls(urls["api_url"], urls["front_url"])
        return urls
    end

    def sync_urls(api_url, front_url)
        NgrokSyncJob.perform_later(api_url, front_url)
    end

    def is_running?
        return system("ps aux | grep ngrok")
    end
    def restart
        stop
        return start
    end
    def stop
        return system("pkill ngrok")
    end

    def authenticate
        has_file = system("ls ~/.ngrok2/ngrok.yml")
        if has_file
            return true
        else
            file_created = system("ngrok authtoken #{ENV['NGROK_TOKEN']}")
            if file_created
                return system("cat " + ENV['APP_ROOT'] + '/essentials/ngrok/example.yml >> ~/.ngrok2/ngrok.yml')
            else
                return false
            end
        end
    end

    def fetch_urls
        logfile = ENV['APP_ROOT'] + '/log/ngrok.log'

        file = File.open logfile
        text = file.read

        api_url = nil
        front_url = nil

        text.split("\n").each do |line|
            next if !line.include?("url=") || !line.include?("https")

            if line.split("name=")[1].split(" addr=")[0] == "ncommerce-api"
                api_url = line.split("url=")[1]
            elsif line.split("name=")[1].split(" addr=")[0] == "ncommerce"
                front_url = line.split("url=")[1]
            end
        end

        file.close

        self.api_url = api_url
        self.front_url = front_url

        res = {}
        res["api_url"] = api_url
        res["front_url"] = front_url

        return res
    end
end

config/initializers/app-init.rb配置/初始化程序/app-init.rb

module AppModule
    class Application < Rails::Application
        config.after_initialize do
            puts "XXXXXXXXXXXXXXXXXXXXXXX"
            Ngrok.instance.start
            puts "XXXXXXXXXXXXXXXXXXXXXXX"

        end
    end
end

When I type rails serve , here is a sample of the output当我键入rails serve时,这里是 output 的示例

在此处输入图像描述

So we know for sure my initializer is being called, but when I look at rails console if it's running, it's not!所以我们肯定知道我的初始化程序被调用了,但是当我查看 Rails 控制台是否正在运行时,它没有!

在此处输入图像描述

But when I type Ngrok.instance.start in rails console, here's the output:但是当我在 Rails 控制台中键入Ngrok.instance.start时,这里是 output:

在此处输入图像描述

And it starts!它开始了!

在此处输入图像描述

So, my question is: WHY ON EARTH is system("ngrok start --all -log=stdout > #{ENV['APP_ROOT']}/log/ngrok.log &") NOT working on rails serve, but it is on rails console?所以,我的问题是:为什么system("ngrok start --all -log=stdout > #{ENV['APP_ROOT']}/log/ngrok.log &")在 rails serve 上不工作,但它是在 Rails 控制台上?

UPDATE更新

If I use 'byebug' within ngrok.rb and use rails serve, when I exit byebug with "continue", the ngrok process is created and works如果我在 ngrok.rb 中使用“byebug”并使用 rails serve,当我使用“continue”退出 byebug 时,ngrok 进程将被创建并运行

You're creating an orphaned process in the way that you use system() to start the ngrok process in the background:您正在以使用system()在后台启动 ngrok 进程的方式创建一个孤立进程

system("ngrok start --all -log=stdout > #{ENV['APP_ROOT']}/log/ngrok.log &")

Note the & at the end of the commandline.请注意命令行末尾的&

I'd need more details about your runtime environment to tell precisely which system policy kills the orphaned ngrok process right after starting it (which OS? if Linux, is it based on systemd? how do you start rails server, from a terminal or as a system service?).我需要有关您的运行时环境的更多详细信息,以准确地告诉您哪个系统策略在启动后立即杀死孤立的 ngrok 进程(哪个操作系统?如果是 Linux,它是基于 systemd 的吗?您如何启动 rails 服务器,从终端或作为系统服务?)。

But what's happening is this:但是发生的事情是这样的:

  • system() starts an instance of /bin/sh to interpret the commandline system()启动/bin/sh的一个实例来解释命令行
  • /bin/sh starts the ngrok process in the background and terminates /bin/sh在后台启动ngrok进程并终止
  • ngrok is now "orphaned", meaning that its parent process /bin/sh is terminated, so that the ngrok process can't be wait(2) ed for ngrok 现在是“孤立的”,这意味着它的父进程/bin/sh已终止,因此 ngrok 进程不能wait(2)编辑
  • depending on the environment, the terminating /bin/sh may kill ngrok with a SIGHUP signal根据环境,终止/bin/sh可能会用 SIGHUP 信号杀死 ngrok
  • or the OS re-parents ngrok, normally to the init-process (but this depends)或操作系统 re-parents ngrok,通常到 init-process(但这取决于)

When you use the rails console or byebug, in both cases you're entering an interactive environment, which prepares "process groups", "session ids" and "controlling terminals" in a way suitable for interactive execution.当您使用 Rails 控制台或 byebug 时,在这两种情况下您都进入了一个交互式环境,它以适合交互式执行的方式准备“进程组”、“会话 ID”和“控制终端”。 These properties are inherited by child processes, like ngrok.这些属性由子进程继承,例如 ngrok。 This influences system policies regarding the handling of the orphaned background process.这会影响有关处理孤立后台进程的系统策略。

When ngrok is started from rails server, these properties will be different (depending on the way rails server is started).当 ngrok 从 rails server 启动时,这些属性会有所不同(取决于 rails server 的启动方式)。

Here's a nice article about some of the OS mechanisms that might be involved: https://www.jstorimer.com/blogs/workingwithcode/7766093-daemon-processes-in-ruby这是一篇关于可能涉及的一些操作系统机制的好文章: https://www.jstorimer.com/blogs/workingwithcode/7766093-daemon-processes-in-ruby

You would probably have better success by using Ruby's Process.spawn to start the background process, in combination with Process.detach in your case.通过使用 Ruby 的Process.spawn启动后台进程,结合您的情况Process.detach ,您可能会取得更好的成功。 This would avoid orphaning the ngrok process.这将避免孤立 ngrok 进程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM