[英]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进程并终止/bin/sh
is terminated, so that the ngrok process can't be wait(2)
ed for /bin/sh
已终止,因此 ngrok 进程不能wait(2)
编辑/bin/sh
may kill ngrok with a SIGHUP signal/bin/sh
可能会用 SIGHUP 信号杀死 ngrok 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.