将正在运行的进程移至 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 仓库中。


本文翻译自:Move a running process to screen