【问题标题】:Can a standalone ruby script (windows and mac) reload and restart itself?独立的 ruby​​ 脚本(windows 和 mac)可以重新加载并重新启动吗?
【发布时间】:2010-04-13 23:17:32
【问题描述】:

我有一个 master-workers 架构,其中 worker 的数量每周都在增长。不能再期望我通过 ssh 或远程控制台进入每台机器来杀死工作人员、进行源代码控制同步并重新启动。我希望能够让主人在网络上发布一条消息,告诉每台机器同步并重新启动。

这就是我遇到障碍的地方。如果我使用任何健全的平台,我可以这样做:

exec('ruby', __FILE__)

...然后就完成了。但是,我做了以下测试:

p Process.pid
sleep 1
exec('ruby', __FILE__)

...在 Windows 上,每次调用 exec 都会获得一个 ruby​​ 实例。在我在有问题的窗口上按 ^C 之前,它们都不会死。在我尝试过的每个平台上,它每次都在执行文件的新版本,我通过在测试进行时对测试脚本进行简单的编辑来验证这一点。

我打印 pid 的原因是为了仔细检查我看到的行为。在 Windows 上,每次执行我都会得到一个不同的 pid - 这是我所期望的,因为我在每次运行的任务管理器中都看到了一个新进程。 mac 的行为正确:每个系统调用的 pid 都是相同的,我已经用 dtrace 验证了每次运行都触发了对 execve 系统调用的调用。

所以,简而言之,有没有办法让 Windows ruby​​ 脚本重新开始执行,这样它就可以运行在执行期间发生变化的任何代码(包括自身)?请注意,这不是一个 Rails 应用程序,尽管它使用了 activerecord。

【问题讨论】:

  • 如果我理解正确的话,有两个问题,一是你无法向 Windows 上的主进程发出信号来重启自身。第二个是当执行“exec”时,没有获取更新的代码。你能确认一下吗?

标签: windows ruby exec reload restart


【解决方案1】:

在尝试了许多解决方案(包括 Byron Whitlock 提交的解决方案,最终让我走上了圆满的道路)后,我决定:

IO.popen("start cmd /C ruby.exe #{$0} #{ARGV.join(' ')}")
sleep 5

我发现,如果我在 popen 之后根本不睡觉,只是退出,那么 spawn 会经常(>50% 的时间)失败。这显然不是跨平台的,因此为了在 mac 上具有相同的行为:

IO.popen("xterm -e \"ruby blah blah blah\"&")

【讨论】:

  • 我让它在 Ubuntu 上工作:IO.popen("kill #{Process.pid} && ruby server.rb&")。我认为如果您从 popen 中终止进程,则不需要 xterm/sleep 部分。
【解决方案2】:

重新启动程序的经典方法是编写另一个为您执行此操作的程序。所以你生成一个进程到restart.exe <args>,然后死亡或退出; restart.exe 等到调用脚本不再运行,然后再次启动脚本。

【讨论】:

  • 我希望尽可能避免这种情况。有问题的脚本已经是执行实际工作的脚本的重启器。面对调用其他应用程序(如 Visual Studio)的脚本,这对于绕过 Windows 上的 ruby​​ 的线程限制是必要的。如果我可以避免让启动器调用调用工作器的启动器,我会很更快乐。此外 - 这并不能完全解决问题:如果我更改顶级启动器的代码会发生什么?我只是将问题上移了一层而没有真正解决它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-16
  • 2011-12-16
  • 2012-03-14
  • 2023-04-06
  • 1970-01-01
相关资源
最近更新 更多