将正在运行的进程移至 screen
用 ssh
连接远程服务器时,如果连接断开,那么当前的进程就会被杀死。运行系统备份或 ftp 传输这样耗时较长的任务,ssh
不方便一直挂着,那该怎么办呢?这种情况的应对方法是 GNU Screen,一款由 GNU 计划开发的用于命令行终端切换的自由软件。用户可以通过该软件同时连接多个本地或远程的命令行会话,并在其间自由切换。
在执行快速和简单的任务时,往往不会使用 screen
,因为这没有必要。但是,如果发现正在运行的任务花费的时间比预期的要长得多,或者只是单纯地忘记了在执行命令前进入 screen
,该怎么办呢?这时退出 ssh
就会导致前功尽弃。在这种情况下,我们剩下三个选择:
- 一直保持
ssh
连接,但不知道要等到什么时候 - 退出当前进程,丢失所有未保存的工作,并可能浪费大量的时间来处理,或者
- 将正在运行的进程移至新的
screen
中。这是笔者将在后文中描述的解决方案。
操作步骤如下。
挂起进程
我们需要做的第一件事是通过按 Ctrl+Z 挂起当前的进程。
这会向进程发送一个 TSTP 信号 —— 停止执行进程,并且内核将不再为该进程安排更多的 CPU 时间。
在后台恢复进程
输入 bg
命令。这会将 SIGCONT 信号发送到该进程,现在它会在后台欢快地运行起来。
disown
进程
现在,我们像这样运行 disown
命令:1
disown %1
disown
从活动作业表中删除该进程,从本质上允许该进程被另一个会话接管。
新开 screen
执行 screen
即可,进入一个新的 screen
会话中。
查找进程的 PID
现在,我们需要找到要接管的进程的 PID。笔者使用和推荐的方法是 pgrep
。例如,如果我们的进程称为 myprogram
,则可以运行 pgrep myprogram
命令,该命令将返回其 PID。
使用 reptyr
接管进程
最后,我们将 PID 传递给 reptyr
来接管该进程。如果 pgrep
给我们的 PID 为 1234,我们现在可以使用以下命令:1
reptyr 1234
最后两步也可以合在一起:1
reptyr $(pgrep myprogram)
如果提示找不到 reptyr
命令,可以用包管理工具安装一下。reptyr
的源码在这个 GitHub 仓库中。