当我通过 ssh 连接到我的无头服务器时,我经常运行一系列的穷人守护进程。一到监控我桶里的啤酒和一到从网络浏览器监控服务器本身。
我通过在以下位置运行两者来做到这一点screen
:
screen -d -m psdash
screen -d -m kegbot runserver xxx.xx.x.xxx:8008
屏幕外的这两个命令往往会以stdout
这样的方式占据主导地位,使得ssh
会话的其余部分无法使用。而且,它们也会随着会话而终止ssh
,所以我发现 screen 是最好的选择。
我的问题是:有没有办法.profile
或其他方法让这些命令在登录时运行,但如果它们已经在运行,则不运行?最后一点让我无法理解。
答案1
我建议将 PID(在$!
启动进程后的 bash 中)写入您正在启动的两个进程的文件中(psdash
和kegbot
)。
然后您可以使用它ps --pid $(cat your.pid) | tr -s ' ' | sed 1d | cur -d' ' -f4
来查看该进程是否实际正在运行。
.pid
顺便说一句,在对其进行操作之前,您应该始终检查文件内的 PID 是否有效!
当程序停止时,无论您使用什么机制删除文件.pid
(通常是程序本身的一部分,或者 shellscript 包装器),都可能会失败,并且文件中存在“错误”的 PID .pid
。如果.pid
文件在重新启动后仍然存在,最坏的情况将是您要执行操作的其他进程的 PID。
好的,这是一个可能的解决方案,以kegbot
作为示例:
首先您需要一个包装脚本。为了简单起见,我们假设一切都发生在您的$HOME
.
因此,一个简单的包装器 ( run_kegbot.sh
) 是:
#!/bin/zsh
kegbot runserver xxx.xx.x.xxx:8008
echo $! > kegbot.pid
wait
rm -rf kegbot.pid
这是一种解决方案,如果kegbot
fork到后台等但是fork后PID是有效的。我不知道是否kegbot
能够自己处理PID文件,这会减轻你自己处理PID文件的麻烦。或者,也许您可以kegbot
不分叉到后台,然后使用 shell 本身(通过&
在第 2 行末尾添加 a )来写入 PID 文件并等待其完成。
不管怎样,一旦你完成了 PID 文件 malarkey,你就需要在你的.profile
:
[ -e kegbot.pid ] && {
PID=$(cat kegbot.pid)
COMM=$(ps -p $PID -o comm=)
[ "x$COMM" != "xkegbot" ] && rm -f kegbot.pid
}
[ -e kegbot.pid ] || screen -d -m ./run_kegbot.sh
再说一次,这只是一问题的解决方案,但总体思路是使用进程的 PID 来检查它是否正在运行,上面是一种方法。
一些守护进程将其 PID 文件保存在 中/var/run/
,如果kegbot
和/或psdash
这样做,您显然不需要包装脚本等,因为您可以直接使用这些 PID 文件。
您肯定需要检查 PID 文件中的 PID 是否实际上是它所属的进程。恶意重启和/或守护进程崩溃可能会留下僵尸化的 PID 文件等。这就是上面 PID 文件的第一个测试的目的。