解决XShell退出后,后台进程关闭

问题描述

利用 XShell 登录远程 Unix 服务器,启动后台进程,如下所示。

$ command &

当关闭 XShell 后,后台进程就会一起终止。

问题原因

在查看 Bash 的使用手册后,发现如下一段描述:

The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP to all jobs, running or stopped. Stopped jobs are sent SIGCONT to ensure that they receive the SIGHUP.

由此可以知道后台进程退出是由于登陆 shell 收到了 SIGHUP 信号后在退出前将 SIGHUP 转发给所有的作业(jobs)。jobs 由于收到 SIGHUP 而终止运行。

解决方案

如果我们不想因为关闭 XShell 而导致自己的后台进程结束。一般有以下几种方法。

使用 nohup 运行命令

iZbp16mnrxv8swew70ltcdZ# nohup python3 csdn1.py > /dev/null &
[1] 8467
iZbp16mnrxv8swew70ltcdZ# nohup: ignoring input and redirecting stderr to stdout
iZbp16mnrxv8swew70ltcdZ# jobs
[1]  + running    nohup python3 csdn1.py > /dev/null
iZbp16mnrxv8swew70ltcdZ# ps -o pid,ppid,pgid,sid,cmd
  PID  PPID  PGID   SID CMD
 8220  8197  8220  8220 -zsh
 8467  8220  8467  8220 python3 csdn1.py
 8470  8220  8470  8220 ps -o pid,ppid,pgid,sid,cmd
iZbp16mnrxv8swew70ltcdZ# fg 
[1]  + running    nohup python3 csdn1.py > /dev/null
^Z
zsh: suspended  nohup python3 csdn1.py > /dev/null

关闭 XShell 窗口并重新登录。


iZbp16mnrxv8swew70ltcdZ# ps -aux | grep csdn1.py
root      8467  3.2  5.7 116352 58256 ?        SN   13:27   0:29 python3 csdn1.py
root      8560  0.0  0.0  14224  1000 pts/0    S+   13:42   0:00 grep csdn1.py

发现重新登录后前台和后台进程都还运行着但父进程变成了init。

使用 setpid 运行命令

iZbp16mnrxv8swew70ltcdZ# setsid python3 csdn1.py > /dev/null &
[1] 8584
iZbp16mnrxv8swew70ltcdZ# 
[1]  + done       setsid python3 csdn1.py > /dev/null
iZbp16mnrxv8swew70ltcdZ# ps
  PID TTY          TIME CMD
 8546 pts/0    00:00:00 zsh
 8587 pts/0    00:00:00 ps
iZbp16mnrxv8swew70ltcdZ# ps -aux | grep csdn1
root      8585 20.6  5.5 115340 56796 ?        SNs  13:45   0:04 python3 csdn1.py
root      8589  0.0  0.0  14224   984 pts/0    S+   13:45   0:00 grep csdn1

关闭 XShell 窗口并重新登录。

Last login: Sun Feb  9 13:41:21 2020 from 115.226.144.198
iZbp16mnrxv8swew70ltcdZ# ps -aux | grep csdn1
root      8585 21.3  5.6 115492 57276 ?        SNs  13:45   0:12 python3 csdn1.py
root      8619  0.0  0.0  14224   892 pts/1    S+   13:46   0:00 grep csdn1

使用 disown 运行命令

### 先运行脚本,在用ctrl+z挂起脚本,通过jobs查看,脚本确实处于suspended状态 ###
iZbp16mnrxv8swew70ltcdZ# python3 csdn1.py > /dev/null
^Z
zsh: suspended  python3 csdn1.py > /dev/null
iZbp16mnrxv8swew70ltcdZ# jobs
[1]  + suspended  python3 csdn1.py > /dev/null

### 使用bg命令将挂起的任务转到后台运行 ###
iZbp16mnrxv8swew70ltcdZ# bg %1
[1]  + continued  python3 csdn1.py > /dev/null
iZbp16mnrxv8swew70ltcdZ# jobs
[1]  + running    python3 csdn1.py > /dev/null

### 使用disown命令,再次利用job查看发现后台任务变成daemon了 ###
iZbp16mnrxv8swew70ltcdZ# disown %1   
iZbp16mnrxv8swew70ltcdZ# jobs
iZbp16mnrxv8swew70ltcdZ# ps -aux | grep csdn1
root      8628 14.9  5.5 114524 56596 pts/1    S    13:49   0:19 python3 csdn1.py
root      8631  0.0  0.0  14224   952 pts/1    S+   13:51   0:00 grep csdn1

关闭 XShell 窗口并重新登录。

Last login: Sun Feb  9 13:46:15 2020 from 115.226.144.198
iZbp16mnrxv8swew70ltcdZ# jobs
iZbp16mnrxv8swew70ltcdZ# ps -aux | grep csdn1.py
root      8628 19.6  5.9 118648 60508 ?        S    13:49   1:05 python3 csdn1.py
root      8684  0.0  0.0  14224   996 pts/0    S+   13:55   0:00 grep csdn1.py

Catch SIGHUP 信号

如果是shell脚本,则在脚本中加上下面的一条语句就行了。(备注,这个命令测试没有成功

# trap "" SIGHUP

如果是C程序,则使用signal函数对SIGHUP进行屏蔽就行了。

signal(SIGHUP, SIG_IGN);

 

### 如何配置 Xshell退出时自动停止运行中的容器 为了实现当关闭 Xshell 会话时能够同时停止 Docker 容器的功能,可以通过设置 Xshell 的 `logout` 脚本或者利用 SSH 登录后的挂起命令来触发容器的停止操作。以下是具体的解决方案: #### 方法一:通过 SSH 配置文件设置 logout 命令 可以在远程服务器上的 `.bash_logout` 文件中添加一条用于停止容器的脚本命令。这样,在用户退出终端会话时,该命令会被执行。 ```bash #!/bin/bash # 获取所有正在运行的容器 ID 并停止它们 docker stop $(docker ps -q) ``` 上述脚本的作用是从当前运行的所有容器中获取其 ID 列表并逐一调用 `docker stop` 来优雅地终止这些容器[^1]。 如果仅希望针对特定名称或标签的容器,则可以修改此脚本如下所示: ```bash #!/bin/bash # 使用过滤条件指定要停止的目标容器 docker stop $(docker ps --filter name=your_container_name_prefix* -q) ``` #### 方法二:借助 nohup 或 screen 工具保持后台进程独立性 另一种方法是在启动容器时将其作为守护程序运行,并确保即使父 shell 关闭也不会影响到它。然而,这种方法本身并不能满足题目需求——即在断开连接的同时销毁容器实例;因此需要额外编写清理逻辑配合使用。 例如,创建一个新的 Bash 函数定义于用户的环境变量加载路径下(如 ~/.profile 或者 ~/.bashrc 中): ```bash function start_and_auto_stop() { CONTAINER_NAME=$1 trap 'echo Stopping container... && docker stop $CONTAINER_NAME' EXIT docker run -d --name "$CONTAINER_NAME" your_image_command_here } ``` 这里我们引入了一个名为 `trap` 的内置 Shell 功能,用来监听特殊信号事件的发生时刻,比如这里的 `EXIT` 表示的是当前脚本即将结束前一刻的动作处理函数注册过程[^3]。 #### 注意事项 需要注意的是,以上两种方案各有优缺点。前者简单直接但可能误杀其他无关的服务型长期存活类容器;后者更加灵活可控却增加了复杂度以及潜在风险隐患。实际应用过程中应当权衡利弊做出合理选择。 ```python import os os.system('docker stop $(docker ps -q)') ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的老周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值