通过screen解决终端模拟器断开连接之后丢失会话的问题

当使用Xshell、putty、SecureCRT等终端模拟器远程连接至Linux服务器时,如果需要执行一个耗时很长的命令或脚本,在尚未执行完毕之前,客户端突然断开网络连接,或者终端模拟器发生死锁,此时客户端便会失去先前和Linux服务器建立的会话。由于不能实时查看脚本或命令的执行日志,因此也就很难判断它们的执行状态,应该如何解决这个问题呢?

使用screen工具可以解决这个问题!screen是Linux系统的一种多重窗口管理器。当终端模拟器通过telnet或ssh远程登录至Linux服务器时,如果网络连接非正常中断,那么客户端可以通过screen工具重新连接至Linux服务器,恢复先前的网络会话。screen具有以下三个主要功能:

  • 会话恢复
    只要screen自身没有终止,在其内部运行的会话都可以恢复。这一点对于远程登录的用户特别有用 —— 即使网络连接中断,用户也不会失去对已经打开的命令行会话的控制。只要再次登录到主机上执行screen -r命令就可以恢复先前会话的运行。同样在暂时离开的时候,也可以执行分离命令detach,在保证里面的程序正常运行的情况下让screen挂起(切换到后台)。这一点和图形界面下的VNC很相似。

  • 多重窗口
    在screen环境下,所有的会话都会独立运行,并且拥有各自的编号、输入、输出和窗口缓存。用户可以通过快捷键在不同的窗口之间切换,并且可以自由地重定向各个窗口的输入和输出。screen实现了基本的文本操作,如复制和粘贴等;还提供了类似滚动条的功能,可以查看窗口状况的历史记录。窗口还可以被分区和命名,还可以监视后台窗口的活动。

  • 会话共享
    screen可以让一个或多个用户从不同终端多次登录同一个会话,并共享会话的所有特性(比如可以看到完全相同的输出)。它同时提供了窗口访问权限的机制,可以对窗口进行密码保护。

一、环境描述

  • 操作系统:CentOS 6.6 x86_64 Minimal
  • YUM源:CentOS官方镜像源
  • screen版本:4.00.03
  • 终端模拟器:Xshell 5 (Build 1019)

二、用法和参数

1. 使用方法

screen具有两种使用方式:

1.1 新建会话
  1. screen [-opts] [cmd [args]]

其中,opts是可选参数,cmd是可选的待执行命令,args是待执行命令的参数。

1.2 恢复会话
  1. screen -r [host.tty]

其中,host.tty是先前建立的会话名称。

2. 可选参数

screen具有以下的可选参数:

  • -4:使用IPv4协议。
  • -6:使用IPv6协议。
  • -a:将所有的功能强制包含在每个窗口的termcap之中。
  • -A -[r|R]:将所有的窗口适配于新的显示宽度和高度。
  • -c file:读取/etc/screenrc配置文件,而不是$HOME/.screenrc文件。
  • -d (-r):分离在别处运行的screen会话,然后在此处重新连接。
  • -dmS name:以守护程序的方式启动screen工具,screen会话处于分离模式。
  • -D (-r):分离和登出远程的screen会话,然后在此处重新连接。
  • -D -RR:执行能够获取screen会话的所有必需的操作。
  • -e xy:修改命令字符。
  • -f:开启流控功能。
  • -fn:关闭流控功能。
  • -fa:系统自动决定是否使用流控功能。
  • -h lines:设置回滚历史缓冲区的大小,lines参数指定行数。
  • -i:当开启流控时,立即中断输出。
  • -l:开启登录模式(更新/var/run/utmp文件)。
  • -ln:关闭登录模式。
  • -list或-ls:什么都不做,仅仅列出SockDir的内容。
  • -L:开启输出日志。
  • -m:忽略$STY变量,强制创建一个新的screen会话。
  • -O:选择最优化的输出方式,而不是精确地模拟vt100终端。
  • -p window:预选具有名称的窗口(window参数指定),如果存在的话。
  • -q:静默启动。如果不成功,则返回非零值。
  • -r:重新连接至一个已分离的screen会话。
  • -R:重新连接至指定的screen会话,若不存在,则建立新会话。
  • -s shell:指定建立新窗口时,需要执行的shell。
  • -S sockname:将screen会话的名称指定为<pid>.sockname,而不是<pid>.<tty>.<host>。
  • -t title:设置窗口的标题名称。
  • -T term:使用term作为窗口的$TERM变量,而不是使用“screen”。
  • -U:指定screen工具使用UTF-8编码。
  • -v:输出screen工具的版本号。
  • -wipe:什么都不做,仅仅清除SockDir目录。
  • -x:连接至一个未分离的screen会话(多重显示模式)。
  • -X: 当执行screen命令时,在指定的会话中同时执行<cmd>指定的命令。

3. 快捷键

在每个screen会话中,所有的命令都以ctrl+aC-a) 开始:

  • C-a ?
    显示所有的快捷键信息。
  • C-a c
    创建一个新的运行shell的窗口,并切换到该窗口。
  • C-a n
    切换到下一个窗口。
  • C-a p
    切换到前一个窗口。
  • C-a 0..9
    切换到第0..9个窗口。
  • C-a [Space]
    由窗口0循序切换到窗口9。
  • C-a x
    锁定当前的窗口,需要用户密码解锁。
  • C-a d
    暂时离开当前的会话,将当前的screen会话(可能含有多个窗口) 切换至后台执行,并且回到尚未进入screen会话时的状态。此时,在screen会话里,每个窗口内运行的进程(无论是前台/后台)都在继续执行,即使登出系统也不会受影响。
  • C-a z
    把当前的screen会话切换至后台执行,用shell的fg命令则可以切换回去。
  • C-a w
    显示所有窗口列表。
  • C-a t
    显示当前的时间和系统的负载状态。
  • C-a k
    强行关闭当前的窗口。

screen会话还有一种特殊的工作模式,叫做拷贝模式(copy mode)。在 拷贝模式中,可以进行回滚、搜索、复制等操作,就像用使用vi一样:

  • C-a [
    进入拷贝模式。
  • C-b Backward
    在拷贝模式中,向上翻页。
  • C-f Forward
    在拷贝模式中,向下翻页。
  • H
    在拷贝模式中,将光标移至左上角。
  • L
    在拷贝模式中,将光标移至左下角。
  • 0
    在拷贝模式中,将光标移至行首。
  • $
    在拷贝模式中,将光标移至行末。
  • w
    在拷贝模式中,光标以字为单位往前移。
  • b
    在拷贝模式中,光标以字为单位往后移。
  • Space
    在拷贝模式中,第一次按设置标记区起点,第二次按设置标记区终点。
  • Esc
    在拷贝模式中,退出拷贝模式。
  • C-a ]
    粘贴先前在拷贝模式选择的内容。

三、使用示例

1. 安装screen

CentOS的官方镜像源自带screen工具,可以通过以下命令安装:

  1. yum install -y screen

安装完成之后,检查screen版本,如下图所示:

检查screen版本

2. 创建新窗口

运行以下命令就可以进入一个指定名称的screen会话:

  1. screen -S <session_name>

其中,session_name就是指定的会话名称。进入screen会话时,会创建第一个窗口,也就是“screen 0”,并且打开系统默认的Shell,一般是Bash。因此,在执行上述命令之后,会立刻又返回至命令提示符,就好像什么都没有发生,但实际上已经进入screen会话了。

另外,在执行screen命令时,还可以直接打开指定的程序:

  1. screen <cmd [args]>

其中,cmd是指定的待执行程序名,args是待执行程序的参数。screen会创建一个执行指定程序的单窗口会话,退出这个程序就会退出相应的窗口/会话。

3. 会话的分离与恢复

当在screen会话的窗口中执行耗时较长的程序时,可以不中断正在运行的程序而暂时离开(detach)screen会话,稍后还可以重新连接(attach)该会话,重新控制会话窗口中运行的程序。

例如,打开一个screen窗口,更新整个系统的组件:

  1. screen yum update -y

这个命令的执行时间较长,此时如果需要处理别的事情,那么就需要暂时退出这个screen窗口,只需要按下快捷键“C-a d”,screen就会给出会话分离的提示,如下图所示:

从screen会话分离

在事情处理完毕之后,找到这个screen会话:

  1. screen -ls

上述命令会列出所有的screen会话,如下图所示:

列出所有可用的screen会话

此时,便可以重新连接screen会话:

  1. screen -r 2122

先前在screen窗口中执行命令的状态依然可见,如下图所示:

重新连接至会话

4. 清除dead会话

如果由于某种原因,某个会话死掉了(例如:手动杀掉该会话的进程),这时screen -ls命令便会显示该会话为dead状态。可以使用screen -wipe命令清除dead会话:

清除已死锁的会话

5. 关闭窗口

在screen窗口中输入exit命令便会退出当前的screen窗口,当screen会话中的所有窗口都退出时,便会退出这个screen会话。也可以使用C-a k快捷键退出当前的screen窗口。

如果某个程序随同screen命令同时执行,那么在这个程序运行结束时,也会自动退出相应的screen会话。

6. 会话共享

当在一个终端模拟器中进入screen会话时,在另一个终端模拟器中也可以连接至这个screen会话,运行以下命令:

  1. screen -x [session_name]

其中,session_name就是想要连接的screen会话的名称。这个命令的效果相当于让两个人坐在同一个显示器前面,一个人的操作会同步演示给另一个人,反之亦然。

7. 会话锁定和解锁

screen允许使用快捷键C-a s锁定会话。会话锁定之后,再进行任何输入屏幕都不会再有反应了。但是要注意虽然屏幕上看不到反应,但是输入都会被screen中的进程接收到。快捷键C-a q可以解锁一个会话。

另外,还可以使用C-a x锁定会话。不同的是,这样锁定之后,会话会被screen所属用户的密码保护,需要输入密码才能继续访问这个会话。

8. 发送命令到screen会话

在终端模拟器中,可以通过screen命令在一个已存在的screen会话中执行指定的命令,例如:

  1. screen -S test -X screen ping www.baidu.com

这个命令会在一个名为test的screen会话中创建一个新窗口,并在其中运行ping命令。

9. 屏幕分割

有时候需要在同一个终端模拟器窗口中,一边执行程序,一边监控系统系统性能,这时可以将屏幕分割成不同的区域,分别显示不同的screen窗口。

例如,首先创建和进入一个名为test-screen的会话:

  1. screen -S test-screen

然后,运行top命令,再使用快捷键C-a S,将屏幕水平分割,如下图所示:

分割screen屏幕

由上图可知,屏幕已经分为上下两个部分,上半部分运行top命令,下半部分是空白的。此时,使用C-a TAB快捷键,将光标切换至下半部分,再使用C-a c快捷键,在下半部分新建一个screen窗口,运行Bash Shell。最后,在下半部分的screen窗口中运行fdisk -l命令,如下图所示:

在不同的屏幕区块中运行不同的命令

可以使用C-a X快捷键关闭光标当前所在的屏幕区块,也可以使用C-a Q快捷键关闭除当前区块之外的其他所有区块。关闭的区块中的screen窗口并不会关闭,还可以通过窗口切换找到它。