0x00 引言
当你在ssh登录远程机器,并执行程序后,如果再退出ssh会话,可能会遇到进程被杀死的情况。本文将解释该现象产生的原因,并提供一些解决方案。
0x01 基础知识
1 | 1 SIGTERM和SIGKILL区别 |
1、SIGTERM 和 SIGKILL区别
SIGTERM(信号编号15): SIGTERM是一个可捕获的信号,用于请求进程正常终止。当进程接收到SIGTERM信号时,它可以选择捕获该信号并执行清理操作,然后自行退出。这样的行为通常被称为优雅退出。进程可以使用信号处理机制来捕获SIGTERM信号,编写相应的处理代码。
SIGKILL(信号编号9): SIGKILL是一个不可捕获的信号,用于强制终止进程。当进程接收到SIGKILL信号时,它无法捕获或忽略该信号,而是立即终止。SIGKILL信号可以通过系统工具(如kill命令)或在命令行中使用kill -9发送。
2、sshd服务KillMode配置
sshd服务分为两种启动方式:
- sshd服务(主进程为远程连接生成的bash):systemd服务管理文件为/lib/systemd/system/sshd.service,启动命令为systemctl start sshd
- systemd-socket-proxyd服务(主进程为systemd):systemd服务管理文件为/lib/systemd/system/sshd@.service,systemd单元服务文件为/lib/systemd/system/sshd.socket,启动命令为systemctl start sshd.socket
当你通过ssh登录远程机器时,其会为你创建一个会话并分配一个伪终端。当你退出ssh会话时,伪终端也随之关闭,从而导致与之关联的进程被终止。
并且通过配置sshd的KillMode项,可以改变会话退出时对控制组里进程的对应操作:
- control-group(默认值):当前控制组里面的所有子进程,都会被杀掉
- process:只杀主进程
- mixed:主进程将收到 SIGTERM 信号,子进程收到 SIGKILL 信号
- none:没有进程会被杀掉,只是执行服务的 stop 命令
上述两种服务方式在执行kill的时候不同点在于,sshd服务只会kill掉对应bash进程拉起的所有子进程,systemd-socket-proxyd服务会kill掉systemd下由远程连接拉起的所有子进程。
0x02 解决方案
1 | 1 方案一 修改sshd配置 |
1、方案一 修改sshd配置
在 /lib/systemd/system/sshd@.service 配置文件的[Service]下追加KillMode=process
2、方案二 nohup
使用nohup命令在ssh会话中启动进程,会将进程与终端断开关联,并将输出重定向到一个文件,从而使进程在终端关闭后继续在后台运行。这样即使退出ssh会话,进程也会继续运行。
1 | # 使用nohup拉起进程 |
3、方案三 setsid
setsid函数调用成功后,返回新的会话的ID,调用setsid函数的进程成为新的会话的领头进程,并与其父进程的会话组和进程组脱离。
1 |
|