设想
我们使用基于 Vagrant 的虚拟机运行 Ubuntu 12.04 LTS 来开发三个 Node.JS 服务器,这些服务器使用以下方式启动:永远的. 我们在用户下运行服务vagrant
,并将项目从主机挂载到虚拟机作为共享文件夹。
使用 启动脚本时forever
,它会在启动后分叉到后台,维护所有正在运行的脚本的中央列表(每个用户)。对于使用不同名称的脚本,您可以通过名称以及数字索引来引用它们。
然后使用该命令管理脚本(启动、重新启动、停止等)forever
。
Upstart 配置
我已经为每个服务创建了类似的 upstart conf 文件,如下所示:
description "Control server.js"
chdir /vagrant/server
start on vagrant-mounted
stop on runlevel [016]
expect fork
pre-start script
test -d /vagrant/server
end script
exec sudo su vagrant -c "/usr/local/bin/forever start server.js"
问题 — 关机时挂起
一旦 vagrant 共享文件夹挂载,upstart 即可成功启动服务。但是,关闭虚拟机(即vagrant halt
)会挂起,直到超时并强制关闭虚拟机。
我认为这是因为它不知道如何停止永久服务,因为它forever
仅仅是一个界面我真正想要停止的服务。
我唯一的尝试没有成功(它确实停止了服务,但是 Vagrant 挂起了超时):
pre-stop script
forever stop server.js
end script
节点服务不需要正常终止:我很高兴看到任何可以终止脚本但不会导致 Vagrant 在关闭时挂起的场景。
此外,删除该stop on runlevel
线似乎没有效果。
答案1
首先,您的问题似乎是 fork 跟踪不正确。为了解决这个问题,我将对您的 upstart 配置进行一些调整:
- 首先,不要使用 su 来更改用户。su 不应用于守护进程,只应用于普通用户(它会导致触发 pam 的问题),并且(更相关的是)它会将进程分叉到后台(Upstart 更难跟踪和杀死您的守护进程)。我们将
setuid vagrant
在 upstart 配置中改用。 下一个问题是永远将进程分叉到后台和将自身分叉到后台。这样 Upstart 就会跟踪一些可能不再存在的随机 pid。解决方案是使用 Upstart 的自动重生功能。我将在下面通过示例进行演示。
description "server.js" start on vagrant-mounted stop on runlevel [016] chdir /vagrant/server setuid vagrant respawn respawn limit unlimited exec server.js
请注意,您不需要检查 /vagrant/server 是否是一个目录,因为 upstart 会根据 chdir 节自动创建它。