如何利用 Screen 运行后台任务

在很多文档中,建议我们使用以下方法后台运行代码以便 ssh 退出后服务器仍然能继续执行命令

1
2
3
nohup <cmd> &
or
nohup <cmd> & >> outfile.out

然而,这有两个缺点

  1. nohup 后台运行会在 nohup.out 或是你所指定的重定向文件中,实时打印程序的标准输出和标准错误输出。它的大小是无限量增长的,但一旦直接删除了 nohup.out ,该任务进程就再也无法输出任何内容。更重要的是,项目中已经有了一个独立的较为成熟的日志系统,nohup.out 的内容对我们来说实际上几乎没有作用
  2. 停止 nohup 任务很不直观,需要 ps -def | grep "<target_file_name>" 找到 pid ,然后 kill

因此,可以使用大部分 linux 自带的 screen 指令来实现后台运行任务,无视 ssh 的退出。

咱们服务器这个版本的 CentOS 属于那些小部分的 linux :),因此先需要执行 yum install screen -y

screen 基本用法

详细用法见菜鸟教程

screen 本质上可以理解为在终端上再套一个终端。使用以下代码新建一个叫做 test 的虚拟终端:

1
screen -S test

执行后,终端会变成像执行 clear 后的样子。实际上这已经进入了虚拟终端 test ,这时候你可以直接像普通终端一样操作这个终端,例如,可以直接通过cd 指令打开项目文件,然后用 python keepRunning.py 指令执行一个叫 keepRunning.py 的持续运行的程序。

然后,你可以通过键盘操作 Ctrl + A + D ,这样你就能从“虚拟世界”返回“现实世界”。在现实的终端中,你会看到:

1
2
3
[root@localhost home]# screen -S test
[detached from 143098.test]
[root@localhost home]#

这说明你回到了最初的终端,而刚才你所打开的虚拟终端 test 中执行的命令也同样在执行着。

尽管如此比喻,但 screen 指令完全不涉及任何虚拟化技术,也即几乎没有任何性能损失。可以理解为一个可以后台运行的新终端,文件系统、CPU 等资源还是照样调用。实际上,screen 是一个非常古老的、由 GUN 编写的 linux 程序,它诞生的时候虚拟化的概念还远远没有成熟

为了确认虚拟终端还在后台运行,你可以执行以下命令:

1
2
3
4
5
6
[root@localhost home]# screen -ls
There is a screen on:
143098.test (Detached)
1 Socket in /var/run/screen/S-root.

[root@localhost home]#

这说明你的虚拟终端 test (PID: 143098) 正在后台运行

如何返回这个终端?你可以使用以下命令

1
screen -r test

这样你就能回到这个终端继续你的工作了,此时 keepRunning.py 可能已经运行了好几轮。而退出终端同样使用快捷键 Ctrl + A + D

如何彻底关闭这个终端的进程呢?当然可以使用 kill ,但我建议你直接通过 screen -r 进入虚拟终端,然后出入 exit 和回车,屏幕会这么显示:

1
2
3
4
5
6
[root@localhost home]# screen -r test
[screen is terminating]
[root@localhost home]# screen -ls
No Sockets found in /var/run/screen/S-root.

[root@localhost home]#