如何避免Java进程退出时杀死启动它的父Bash监控脚本
问题根因
- 首次安装时通过SSH远程执行命令,启动的后台进程默认和SSH会话绑定,SSH断开时系统会向会话关联的所有进程发送
SIGHUP挂起信号,导致监控脚本被终止;而开机启动的进程由系统init进程托管,不会绑定到用户会话,因此重启后问题消失。 - 原SSH安装命令存在语法错误(
bash install.sh &;; exit中多了一个多余分号),导致添加nohup后命令无法正常执行。 - 监控脚本自身健壮性不足:首次运行时
Server.pid文件不存在,source命令执行失败可能导致脚本直接退出。
修复方案
1. 修正SSH远程安装命令
将原安装命令替换为以下内容,解决语法错误同时确保进程完全脱离SSH会话:
cd /home/UserName; unzip -u -o Server.zip; chmod 777 install.sh; nohup bash install.sh >/dev/null 2>&1 & disown; exit
nohup会忽略SIGHUP信号- 输出重定向到
/dev/null避免占用SSH会话输出 disown将进程从当前shell的作业列表中移除,彻底脱离会话关联
2. 加固install.sh启动逻辑
修改install.sh中启动监控脚本的行,确保完全脱离父进程:
# 替换原行:nohup bash $INSTALL_DIR/service-start.sh & nohup bash $INSTALL_DIR/service-start.sh < /dev/null > $INSTALL_DIR/logs/service-start-boot.log 2>&1 & disown
3. 修复监控脚本健壮性问题
在service-start.sh中添加两处修改:
- 脚本开头(
#!/bin/bash之后)添加忽略SIGHUP信号的逻辑,双重保险避免被会话信号终止 - 读取pid文件前先判断文件是否存在,避免首次运行报错退出
修改后的监控脚本关键部分如下:
#!/bin/bash # 新增:忽略SIGHUP信号 trap '' HUP JAVA_HOME=/usr/lib/jvm/java-16-openjdk-amd64 WORKING_DIR=~/Data LOG=$WORKING_DIR/logs/Bash.log rm $LOG echo "Script started" > $LOG while true; do # 新增:判断pid文件存在才读取,否则默认AppPID为空 AppPID="" if [ -f $WORKING_DIR/Server.pid ]; then source $WORKING_DIR/Server.pid fi # 新增:2>/dev/null 避免进程不存在时输出错误日志 if ! kill -0 $AppPID 2>/dev/null; then # 后续原有逻辑保持不变 # ... fi sleep 5 echo "5 seconds idle passed" >> $LOG done
验证方法
修改完成后执行安装,断开SSH会话后重新连接,执行ps aux | grep service-start.sh确认监控进程正常运行,触发更新测试即可确认流程正常,无需重启设备。
内容的提问来源于stack exchange,提问作者Leone Shamoth
相关产品推荐
相关产品推荐

