=Start=
缘由:
我经常会碰到这样的问题,用 ssh 登录了远程的 Linux 服务器,运行了一些耗时较长的任务,结果却由于网络的不稳定导致任务中途失败。如何让命令提交后不受本地关闭终端窗口、网络断开连接的干扰呢?总结下来主要有以下3点需求:
- 想让进程在断开连接后依然保持运行?
- 如果该进程已经开始运行了该如何补救?
- 如果有大量这类需求如何简化操作?
下面主要针对以上这3点需求进行解答,内容基本上照搬「Linux 下让进程在后台可靠运行的几种方法」,略有精简。
正文:
0x0.为什么SSH断开后你运行的进程会退出呢?
因为所有进程都得有个父进程。当你ssh到一个服务器上时,打开的shell就是你所有执行命令的父进程。
当你断开ssh连接时,你的命令的父进程就没了。如果处理不当,这些进程就会收到SIGTERM信号,全被干掉了。
0x1.如何让进程在断开SSH连接后依然保持运行?
nohup 无疑是我们首先想到的办法。顾名思义,nohup 的用途就是让提交的命令忽略 hangup 信号。
nohup 的使用是十分方便的,只需在要处理的命令前加上 nohup 即可,标准输出和标准错误缺省会被重定向到 nohup.out 文件中。一般我们可在结尾加上”&”来将命令同时放入后台运行,也可用”>filename 2>&1″来更改缺省的重定向文件名。
nohup 无疑能通过忽略 HUP 信号来使我们的进程避免中途被中断,但如果我们换个角度思考,如果我们的进程不属于接受 HUP 信号的终端的子进程,那么自然也就不会受到 HUP 信号的影响了。setsid 就能帮助我们做到这一点。
setsid 的使用也是非常方便的,也只需在要处理的命令前加上 setsid 即可。
将一个或多个命名包含在“()”中就能让这些命令在子 shell 中运行中,同时将”&“也放入“()”内之后,我们就会发现新提交的进程的父ID(PPID)为1(init 进程的 PID),并不是当前终端的进程ID。因此并不属于当前终端的子进程,所以能躲过 HUP 信号的影响。
0x2.如果该进程已经开始运行了该如何补救?
只能通过 作业调度(CTRL-z/fg/bg) 和 disown 来解决这个问题。
0x3.如果有大量这类需求如何简化操作?
在 screen/tmux/byobu 中任选一个。screen/tmux/byobu都是虚拟多终端的工具。这些工具可以完成:
- 虚拟多个终端在一个ssh连接中;
- 断线后的恢复。
这里我们需要的是第2个功能。
总结:
nohup/setsid 无疑是临时需要时最方便的方法,disown 能帮助我们来事后补救当前已经在运行了的作业,而 screen/tmux 则是在大批量操作时不二的选择了。
参考链接:
- Linux 下让进程在后台可靠运行的几种方法
- http://www.linuxprobe.com/process-run-background/
- https://www.ibm.com/developerworks/cn/linux/l-cn-nohup/
- http://seanlook.com/2014/02/20/linux-process-running-background-screen/
- Linux ssh状态下如何后台运行程序?
- Linux 进程前后台切换|管理
=END=
《 “Linux下让进程在后台可靠运行的几种方法” 》 有 6 条评论
Stitch — 基于 Python 的远程控制工具(RAT)
https://github.com/nathanlopez/Stitch
Puppy RAT – Python 语言编写的跨平台的远控工具
https://github.com/n1nj4sec/pupy
Tmux使用手册
http://louiszhai.github.io/2017/09/30/tmux/
Undistract-me:当长时间运行的终端命令完成时获取通知
https://linux.cn/article-9174-1.html
https://www.ostechnix.com/undistract-get-notification-long-running-terminal-commands-complete/
https://github.com/jml/undistract-me
如何通过CRIU CHECKPOINT/RESTORE应用
http://reborncodinglife.com/2018/05/29/checkpoint-restore-linux-application-by-criu/
https://criu.org/Main_Page
`
criu 是Linux平台在用户空间实现checkpoint/restore功能的工具软件。通过该工具,可以冻结正在运行的应用程序或者其中的一部分,并将应用程序的执行状态以文件形式保存在磁盘上,然后通过这些快照文件,可以将应用程序从冻结的时间点恢复回来继续运行。借助该软件,可以实现应用的实时迁移、应用快照和远程调试等功能。criu最显著的特点是在用户空间实现checkpoint/restore,不需要修改应用程序的代码或者修改操作系统,并且也是内核中功能最丰富和最活跃的。
`
用tmux分享内网里的终端
https://briteming.blogspot.com/2018/05/tmux.html
`
在一台服务器上直接共享服务器上的 tmux 会话的例子已经有很多了, 实际操作可以参考使用 tmux 结对编程、 Remote Pair Programming Made Easy with SSH and tmux。
如果要分享 NAT 内部的机器终端给不同 NAT 背后的电脑操作或者观看,可以实现吗? 考虑到一位来自远古时期的开发者 Alice,她只在终端上开发,突然一天要转行做网红程序员了,就可能会有直播写代码的需求,而且她希望操作的是自己本地电脑的开发环境终端,直播分享给遍布全世界的拥趸观看。这时上面介绍的分享公网服务器上 tmux 会话的操作就行不通了。
我对这类位于不同 NAT 内部的机器共享终端的问题想了下,发现结合 tmux 和反向 shell 是可以解决的,再对期间可能出现的权限问题进行分析,利用在跳板机新增一个中间用户及 tmux 的只读模式的方法,可以实现分享出去的终端对其余用户只能观看,无法获取写的操作权限,从而保证分享者主机的安全。
首先,简单说下一些常用的反向 shell 的方法,它是分享 NAT 内网终端的前提。
`
tmux 分享内网终端
https://hmgle.github.io/misc/2018/04/30/tmux-live.html
在一台服务器上直接共享服务器上的 tmux 会话的例子已经有很多了, 实际操作可以参考:
使用 tmux 结对编程
https://pityonline.gitbooks.io/tmux-productive-mouse-free-development_zh/content/book-content/Chapter5.html
Remote Pair Programming Made Easy with SSH and tmux
https://www.hamvocke.com/blog/remote-pair-programming-with-tmux/