我有一些 Upstart 配置,用于启动一些前台和阻塞进程,让它们在后台作为某种“守护进程”运行,尤其是那些进程无论如何都不会分叉。我想要的是,如果它们因任何未知原因退出,则自动重新启动它们,因此我配置了respawn
,但由于这些进程不会分叉,我没有配置expect
。这似乎按预期工作,但最近我改变了一些东西,今天在新贵食谱这又让我感到疑惑……
如果您未指定 expect 节,Upstart 将跟踪它在 exec 或 script 节中执行的第一个 PID 的生命周期。
我确实使用了一个script
节来为我的“守护进程”构建类路径,并且最近exec
在该节中添加了一些等待 Postgres 和/或一些 Web 应用程序准备就绪并在之后使用该script
节执行我的进程的内容。对于等待,我使用ps
和之类的工具curl
,因为我忘记了“第一个 PID 事情”,并且似乎将 Upstartsexec
与执行 的 shell混淆了script
。
一个示例配置:
script
waitForPostgres()
{
while [ true ]
do
# http://superuser.com/questions/597549/grep-fails-in-upstart-script
if ps ax | grep "[p]ostgres: wal writer process" > /dev/null
then
break
fi
sleep 10s
done
}
waitForPostgres
cd "$basePath"
CLASSPATH=$basePath/lib
for i in `ls $basePath/lib/*.jar`
do
CLASSPATH=$CLASSPATH:$i
done
export CLASSPATH
exec java [...]
end script
这些waitForPostgres
东西是新的,据我所知,其他一切都是 shell 内置的,没有waitForPostgres
第一个执行的,因此跟踪的进程应该是java
。但是对于我的附加功能,我怀疑 Upstart 会进行跟踪ps
,这显然不是我想要的。
那么,在这个例子中跟踪哪个 PID,是ps
,grep
还是java
,为什么?
如果没有java
被跟踪,有什么解决方法可以跟踪最后一个 PID 而不是第一个 PID?
谢谢!
答案1
我发现答案使用一些略有不同的搜索词:expect stop
不幸的是,这意味着 Upstart 将 sed 的第一次调用检测为第一个 PID
此外,解决方法就在附近,pre-start
它正是为此目的而设计的。虽然我之前在文档中读过,但我没想到这一点……
我还发现了一个有趣的提议:可以明确指定要跟踪哪个 PID
由于我的某项服务存在一些问题,我再次查看了它与 Upstart 的运行情况,并发现了以下问题:我的“脚本”节仍在调用“dirname”、“readlink”和“ls”等二进制文件,因此无需对某些工作目录进行硬编码,构建某些 Java 类路径等。重要的是,这些不是 shell 内置程序,因此应该由 Upstart 跟踪,因为“readlink”是“start”中执行的第一个二进制文件。但事实并非如此,这些 PID 似乎被忽略了,而 Upstart 反而跟踪了“exec java ...”命令的 PID,我真正想看到的是跟踪。我通过调用“service ... status”并将输出与“ps axf | grep ...”进行比较来验证这一点,两个 PID 都匹配。我可以正确重新启动服务,并且前一个找到的 PID 被删除,然后启动服务,ps 和 service ... status 再次报告相同的 PID。
两种可能的解释:由于“dirname”和 Co. 用作命令替换,Upstart 通过其自己为“script”节创建的 shell 识别创建的子 shell,并故意忽略这些 PID。否则“exec”可能会返回一个覆盖任何以前识别的 PID 的 PID。我怀疑后者,并认为子 shell 只是被忽略了,这是一个非常好的功能。