如何在用户登录时运行尚未运行的命令

如何在用户登录时运行尚未运行的命令

当我通过 ssh 连接到我的无头服务器时,我经常运行一系列的穷人守护进程。一到监控我桶里的啤酒和一到从网络浏览器监控服务器本身

我通过在以下位置运行两者来做到这一点screen

screen -d -m psdash
screen -d -m kegbot runserver xxx.xx.x.xxx:8008

屏幕外的这两个命令往往会以stdout这样的方式占据主导地位,使得ssh会话的其余部分无法使用。而且,它们也会随着会话而终止ssh,所以我发现 screen 是最好的选择。

我的问题是:有没有办法.profile或其他方法让这些命令在登录时运行,但如果它们已经在运行,则不运行?最后一点让我无法理解。

答案1

我建议将 PID(在$!启动进程后的 bash 中)写入您正在启动的两个进程的文件中(psdashkegbot)。

然后您可以使用它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

这是一种解决方案,如果kegbotfork到后台等但是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 文件的第一个测试的目的。

相关内容