重启Golang Gin的dbagent服务时避免误杀Java子服务的方案咨询
问题:systemctl重启Golang服务时,关联的Java进程被意外终止
环境与现状
- 基于Golang Gin开发的
dbagent服务,由systemd管理 - 服务启动链路:Golang进程执行
start-a.sh脚本,该脚本调用不可修改的start-b.sh启动Java服务 - 异常现象:执行
systemctl restart dbagent时,Java进程会被一并杀死;从systemctl status输出可见,Java进程属于dbagent的CGroup组
Golang执行脚本的初始代码
exec.Command("bash", "/etc/start-a.sh").Start()
start-a.sh 内容
nohup /etc/start-b.sh 1>/dev/null 2>&1 &
start-b.sh 内容(不可修改)
nohup java -jar xxxx 2>&1 &
systemctl状态输出
[root@core03 bin]# systemctl status dbagent-server ● dbagent-server.service - "Database Agent Server" Loaded: loaded (/etc/systemd/system/dbagent-server.service; enabled; vendor preset: disabled) Active: active (running) since Thu 2023-06-29 12:22:09 CST; 29min ago Main PID: 1905 (dbagent-server) CGroup: /system.slice/dbagent-server.service ├─1905 /usr/local/dbagent-server/dbagent-server ├─2795 /usr/java/jdk1.8.0_301-amd64/bin/java -Xmx1500m -X
已尝试的无效方案
- 设置Golang进程
SysProcAttr:cmd := exec.Command("bash", "/etc/start-a.sh") cmd.SysProcAttr = &syscall.SysProcAttr{ Setsid: true, //Setpgid也尝试过 } cmd.Start() - 使用
setsid直接执行脚本:cmd := exec.Command("setsid", "/etc/start-a.sh") cmd.Start() - 结合
disown命令:cmd := exec.Command("bash", "/etc/start-a.sh & disown") - 修改
start-a.sh为:setsid /etc/start-b.sh
可行解决方案
方案1:修改systemd服务配置(推荐)
编辑/etc/systemd/system/dbagent-server.service,在[Service]段添加:
KillMode=process
执行以下命令使配置生效:
systemctl daemon-reload systemctl restart dbagent-server
原理:systemd默认KillMode=control-group会杀死CGroup下所有进程,设置为process后仅终止主PID对应的进程,避免连带杀死Java进程。
方案2:修改Java进程的CGroup归属
修改start-a.sh内容,在启动Java服务后将其移至系统默认CGroup:
nohup /etc/start-b.sh 1>/dev/null 2>&1 & # 匹配Java进程PID(需根据实际参数调整匹配规则) JAVA_PID=$(pgrep -f "java -jar xxxx") # 将进程移至system.slice CGroup echo $JAVA_PID > /sys/fs/cgroup/system.slice/tasks
注意:需确保dbagent进程具备写入对应CGroup文件的权限。
方案3:用systemd独立托管Java服务
修改start-a.sh,使用systemd-run启动Java服务:
systemd-run --unit=java-dbagent-service /etc/start-b.sh
原理:Java服务会以独立的systemd单元运行,完全脱离dbagent的CGroup,不受其重启影响。
内容的提问来源于stack exchange,提问作者First Rain
相关产品推荐
相关产品推荐

