一、开始

在实际工作中,我们ssh等到远程的Linux上,运行一个程序,但是当我们关闭掉我们的连接终端断开ssh后,刚才运行着的程序也会自动被中断结束。当ssh连接断开后,如何让我们的程序继续在后台运行呢,我们可以使用nohup让程序在后台继续运行

比如

1
nohup ping baidu.com > ping.log &

通过命令 jobs 可以看到程序在后台运行

可以通过命令恢复前台工作

1
2
#恢复1号工作
fg %1

如果此时突然ssh断开了,那么再登陆到系统的时候,执行 jobs 就不会发现刚才的 job 的编号了。但是 job 脚本会继续执行,直到完成脚本的内容

另外,没有使用nohup,单独的&也可以让命令后台运行的,但是如果ssh会话断掉,&的命令也会自动退出。

Screen

Screen是一款由GNU计划开发的用于命令行终端切换的自由软件。用户可以通过该软件同时连接多个本地或远程的命令行会话,并在其间自由切换。GNU Screen可以看作是窗口管理器的命令行界面版本。它提供了统一的管理多个会话的界面和相应的功能。

在Screen环境下,所有的会话都独立的运行,并拥有各自的编号、输入、输出和窗口缓存。用户可以通过快捷键在不同的窗口下切换,并可以自由的重定向各个窗口的输入和输出。

简单来说,Screen是一个可以在多个进程之间多路复用一个物理终端的窗口管理器,用户可以创建多个 screen 会话,每个 screen 会话又可以创建多个窗口,同时关闭终端连接并不会使任务停止运行。

安装

在 Ubuntu 上,可以通过 apt 命令直接安装

1
apt install -y screen

二、screen的功能

screen的功能大体有三个:

  • 会话恢复:只要Screen本身没有终止,在其内部运行的会话都可以恢复。这一点对于远程登录的用户特别有用。即使网络连接中断,用户也不会失去对已经打开的命令行会话的控制。只要再次登录到主机上执行 screen -r 就可以恢复会话的运行。同样在暂时离开的时候,也可以执行分离命令detach,在保证里面的程序正常运行的情况下让Screen挂起(切换到后台)。
  • 多窗口:在Screen环境下,所有的会话都独立的运行,并拥有各自的编号、输入、输出和窗口缓存。用户可以通过快捷键在不同的窗口下切换,并可以自由的重定向各个窗口的输入和输出。
  • 会话共享:Screen可以让一个或多个用户从不同终端多次登录一个会话,并共享会话的所有特性(比如可以看到完全相同的输出)。它同时提供了窗口访问权限的机制,可以对窗口进行密码保护。

会话恢复

1、启动一个会话

1
screen -S <session_name>

输入命令之后,screen 会创建第一个窗口,并在其中打开一个系统默认的shell,一般都会是bash。所以你敲入命令screen之后,会立刻又返回到命令提示符,仿佛什么也没有发生似的(没有消息就是最好的消息)

2、列出所有的会话

1
screen -ls

通常情况下,screen创建的虚拟终端,有两个工作模式:

  • Attached:表示当前screen,用户正在使用,为活跃状态。
  • Detached:表示当前screen,正在后台运行,为非激发状态。

格式

pid.name (time) (status)

3、后台运行当前会话

通过键盘快捷键:Ctrl + A + D 即可离开当前会话,正在前台执行的程序将转入后台运行,同时运行状态变为 Detached

也可以在当前会话输入命令

1
screen -d 

注意

当你关闭终端主界面,之后重新登录的时候,所有的 screen 都是显示 Detached 的。

但是,有时候,我们创建虚拟终端,并没有使用 Ctrl + A + D 退出并挂起虚拟终端,反而因为长时间没操作,或者本地网络掉包等问题,非正常退出虚拟终端,导致出现SSH连接服务器,并没有在虚拟终端内,却出现 Attached 状态

这时候就需要

1
screen -d <session_name/pid>

使终端重新变为 Detached 状态,再重新连接会话

4、重新连接会话

1
screen -r <session_name/pid>

会话名称就可以通过 screen -ls 命令查询

或者在只开启了一个会话的情况下,也可以直接通过 screen -r 命令进入会话

5、关闭一个会话

如果处在 screen 的某一个会话里面,可以直接通过快捷键 Ctrl+D 推出当前会话(前提:只有一个窗口),或者直接在终端输入 exit

也可以通过命令关闭指定的会话

1
screen -X -S <session_name/pid> quit

如果由于某些情况(比如手动kill)导致一个screen的状态处于Dead,那么我们可以命令删除这些状态处于Dead的进程

1
screen -wipe 

多窗口

在一个screen下,我们还可以可以方便的创建多个子窗口

1、新建窗口

可以通过 Ctrl + A + C 组合快捷键在当前的 screen 下创建一个新的子窗口,并跳转到上面去。

2、查询当前的界面状态

可以通过 Ctrl + A + W 组合快捷键,在屏幕的左下角就会出现类似:0$ bash 1-$ bash 2*$ bash 0$ bash 之类的样式。这个表示当前screen下有3个窗口,当前在的是2号窗口(* 号表示当前位于窗口2)。当然,这个窗口的数目可以有很多。

3、切换窗口

方法很多,可以通过Ctrl + A + A组合快捷键在最近的两个窗口中切换,也可以用Ctrl + A + N 切换到下一个窗口,或是Ctrl + A + P 切换到上一个窗口,或是Ctrl + A + num 切换到第num个窗口。

4、锁定当前窗口

使用快捷键Ctrl + A + S锁定当前窗口。锁定以后,再进行任何输入屏幕都不会再有反应了。但是要注意虽然屏幕上看不到反应,但你的输入都会被Screen中的进程接收到。当使用快捷键Ctrl + A + Q可以解锁当前窗口后,之前输入的内容都会显示出来。

也可以使用Ctrl + A + X锁定,不同的是这样锁定之后,会话会被Screen所属用户的密码保护,需要输入密码才能继续访问这个会话。

5、关闭当前窗口

这个可以直接用Ctrl + D 或者exit 来关闭,当这个窗口是现有screen的最后一个窗口时,就会触发上面讲的关闭当前screen的事件了。

6、暂离当前screen

这个也是screen命令的精髓,用组合键Ctrl + A + D 就能detached当前的screen,回到默认界面。

我们可以通过Ctrl + A + W 命令来测试下当前窗口是不是处于screen状态下,如果不是的话,贸然使用Ctrl + A + D 终端会直接退出登录。

7、屏幕分割

将一个屏幕分割成不同区域显示不同的窗口

① 上下分屏

先按 Ctrl + A ,再按 Shift + S

然后切换分屏:先按 Ctrl + A ,再按 Tab 切换窗口

最后新建窗口: Ctrl + A + C (除了新建窗口,也可以在分屏后通过 Ctrl + A + num 调出已经创建的窗口)

② 左右分屏

先按 Ctrl + A ,再按 Shift + |

然后切换分屏:先按 Ctrl + A ,再按 Tab 切换窗口

最后新建窗口: Ctrl + A + C

③ 关闭分屏

可以用快捷键 Ctrl + A ,然后 Shift + X 关闭当前焦点所在的屏幕区块

也可以用 Ctrl + A ,然后 Shift + Q 关闭除当前区块之外其他的所有区块。

关闭的区块中的窗口并不会关闭,还可以通过窗口切换找到它。

8、Copy/Paste模式

屏幕分割的话,就可以在不同窗口之间进行复制粘贴了

快捷键:Ctrl + A + Esc 进入(会有提示:Copy mode - xxxxxxx)

快捷键说明
<PageUp> 或 Ctrl-u光标上移一页
<PageDown> 或 Ctrl-d光标下移一页
<Left> 或 h光标左移一格(方向键移动)
<Down> 或 j光标下移一行
<Up> 或 k光标上移一行
<Right> 或 l光标右移一格
<Space>选择开始,选择结束
<Esc>退出选择模式
Ctrl + A + ]粘贴选择的内容

会话共享

假设你在和朋友在不同地点以相同用户登录一台机器

你创建一个screen会话,你朋友可以在他的终端上命令:

1
screen -x <session_name/pid>

这个命令会将你朋友的终端 Attach 到你的 Screen 上,并且你的终端不会被Detach。这样你就可以和朋友共享同一个会话了,如果你们当前又处于同一个窗口,那就相当于坐在同一个显示器前面,你的操作会同步演示给你朋友,你朋友的操作也会同步演示给你。当然,如果你们切换到这个会话的不同窗口中去,那还是可以分别进行不同的操作的。

三、问题解决

screen内中文输出乱码

修改字符编码集(有就修改,没有就新建)

1
vim ~/.screenrc

加入以下设置

1
2
3
defutf8 on
defencoding utf8
encoding UTF-8 UTF-8

再次开启screen,就可以看到中文不乱码了