障碍
最近需要在一台 remote 的 gpu 机器上跑 training 的脚本,terminal 不可能一直开着,所以肯定都是要以 daemon 方式来跑。
众所周知,最简单的 daemon 运行的方式就是在命令后加 &,再配合将输出重定向到一个 log 文件,这样就可以实现即以 daemon 跑,也能随时查看 output 和error 相关的信息。比如
./run.sh > output.log &
不过最近几天,我发现每次到公司查看昨晚上的任务情况,都发现进程在我下班后不久就被干掉,output.log 中也没有任何的错误信息。实在是相当诡异。
求索
google 了一番,没什么有建设性的意见,一开始以为是不是 & 方式的 daemon 天生有缺陷,还研究半天怎么用 python fork 出 daemon process。但越试越感觉,可能这个不是主要原因,在玩了几次 python-daemon 之后,还是决定回到源头尝试解决。
其中有一个回答提到了可能因为脚本占用内存过大导致被系统 kill 掉(OOM),这个时候脚本本身是不会输出错误的。于是就去 /var/log/system.log 里边儿翻 OOM,结果 OOM 没翻到到翻到了一个 "Received SIGRTMIN+24 from PID 27041 (kill)." , 继续 google 了一下发现。这是系统进程 systemd 发出的信号,(systemd 可以理解为调度 daemon process 的进程)。
为什么 systemd 没事儿会来干我的脚本呢? 因为 systemd 默认会在一个 user detach 的时候,干掉这个 user 启动的所有 process,不管你是不是 daemon。所以当我的本地电脑休眠超过一定时间时,远程的机器自动 logout user, 然后触发 systemd 干掉了我的脚本,即便我的脚本有 & 加持。
解题
知道问题的原因那就简单了,简单 google 一下就能知道, 我们只需要修改 /etc/systemd/logind.conf 中,将 KillUserProcesses=no 反 comment 即可。代表让 systemd 不要干掉 user process。