Skip to main content

实用工具:Terminal Multiplexers

· 9 min read
one

使用实验室集群时,我们可能偶尔会遇到断开连接的情况,可能是主动断开SSH,也可能是网络不稳定。无论怎样,重新连接后不会自动恢复上一次的工作(所在的路径、环境变量、打开的文件等)。

为了保存工作,便于重连后继续,我们可以让自己的程序或者 shell 在后台一直运行。保持程序后台运行的方式/工具有很多,本文简单介绍以下几种:

  • nohup&
  • screen
  • tmux

后台运行程序:nohup 和 &

参考:

Linux上常用的后台执行程序的命令是 nohup,它的功能是无视 hangup 信号,也就是在 shell 退出时不会自动被挂断。该命令默认会把原本到标准输出的东西重定向到一个文件。

$ nohup ping nodedata
nohup: ignoring input and appending output to ‘nohup.out’

执行该命令后,退出 shell 不会中断它。实际上,它已经不再依赖于任何 pts 了。不过,我们直接在当前shell执行后(foreground),把自己的 shell 也阻塞了,因此我们要把程序放在后台(background)。

$ ping nodedata &

执行该命令后,会产生一个 subshell 来执行 ping nodedata,输出仍然是标准输出,所以会出现这样的情况:屏幕不断地打印东西出来,但自己还是能正常敲其他命令。

作为后台运行的进程,直接用组合键 Control + c 是无法终止的。通常有两种方法用于终止一个后台执行的程序:

  • ps 找到进程号,用 kill 直接发送终止信号;
  • fg 把后台程序调到到前面,再 Control + c 终止。

了解 nohup& 以后,我们可以组合两者,实现后台运行一个不依赖于当前 shell 的程序。

$ nohup ping nodedata &

执行该命令后,仍然可以在当前shell做其他事情,因为 & 把程序转入后台,而 nohup 重定向了输出。也可以立马退出,因为 nohup 会无视SIGHUP信号。

Terminal multiplexers

参考:

终端多路复用器(terminal multiplexers)就是一种创建多个伪终端(会话)的程序,达到类似于“多路复用”的状态。相比于 nohup 通常只用于跑单个程序,我们使用 multiplexer 可以很容易地在一个登录的终端中管理大量会话,每个会话都有自己的shell。

一个会话通常有 attacheddetached 两种状态,attached 表示有某个 shell 正在使用它(可以同时从多个 shell 进入同一会话),detached 表示它没被使用。

处于一个会话中时,通常要使用组合键来向 multiplexer 发送命令,见后续介绍。在会话中,用户可以使用的组合键通常都非常丰富,可以实现在同一会话中创建多个窗口、分屏等操作。

screen

screen 是Linux通常会带的 multiplexer。创建并进入会话后,所有发给 screen 的命令都由组合键 Control + a 开头。例如:

组合键功能
Control + a + ?查看在screen会话中可使用的key bindings
Control + a + ddetach,把当前会话挂在后台

实际操作的例子如下:

## 以detached模式创建一个有名字的会话
$ screen -dmS test

## 创建另一个有名字的会话,并立即使用(attach)
$ screen -S develop

## 列出所有存在的会话和状态
$ screen -ls
There are screens on:
26426.develop (Attached)
26348.test (Detached)
2 Sockets in /var/run/screen/S-one.

## detach当前会话,退回到最初的shell
Control + a + d

## 进入另一个会话(reattach)
$ screen -r test

## 假设网络突然中断,又或者我们想在另一台电脑上继续之前的工作
## 只需要登录后执行
$ screen -r develop

tmux

参考:

tmux 是一个比 screen 功能更全面的 multiplexer,但它们的基本用法差不多。创建并进入会话后,所有发给 screen 的命令都由组合键 Control + b 开头。例如:

组合键功能
Control + b + ?查看在tmux会话中可使用的key bindings和命令
Control + b + ddetach,把当前会话挂在后台
Control + b + :发送命令到tmux,每个组合键的功能都可以用命令完成
Control + b + c在当前会话创建新的window
Control + b + n/p切换到前一个/后一个window
Control + b + w列出现存的windows,可用键盘上/下键选择

实际操作的例子如下:

## 以detached模式创建一个有名字的会话
$ tmux new-session -ds test

## 创建另一个有名字的会话,并立即使用(attach)
$ tmux new-session -s develop

## 列出所有存在的会话和状态
$ tmux ls
test: 1 windows
develop: 1 windows (attached)

## detach当前会话,退回到最初的shell
Control + b + d

## 进入另一个会话(reattach)
$ tmux attach -t test

## 假设网络突然中断,又或者我们想在另一台电脑上继续之前的工作
## 只需要登录后执行
$ tmux attach -t develop

保持SSH或SFTP连接

当我们使用集群时,使用 screentmux 这样的程序能让我们保存当前的工作以便下次继续。如果出于某种理由我们不希望反复登录集群(比如需要动态口令),那就需要保存已登录的 shell,也就是在 multiplexer 打开的会话里面登录集群。

例如,我们想在实验室机器上创建会话,在这个会话里面打开一个SSH和一个SFTP到某超算S。假设超算域名是 s.example.cn,端口是 12345,我的用户名是 hpcer

## 首先从自己电脑登录实验室集群
$ ssh hpcer@ssh.hpcer.dev

## 创建一个tmux会话用于SSH
$ tmux new-session -s myssh

## 在myssh会话中连接超算S
$ ssh -o ServerAliveInterval=60 -p 12345 hpcer@s.example.cn

## 用组合键detach当前会话
Control + b + d

## 创建另一个tmux会话用于SFTP
$ tmux new-session -s mysftp

## 在mysftp会话中连接超算S
$ sftp -o ServerAliveInterval=60 -P 12345 hpcer@s.example.cn

## 用组合键detach当前会话
Control + b + d

创建了上述两个会话后,只要实验室集群到超算S的连接不断开,我们随时都可以通过 tmux 会话回到超算S,不需要反复登录。如果实验室集群到超算S的连接也不稳定,可以换其他不在校园网的机器。