在使用Linux系统的过程中,有时候我们希望将程序挂在后台运行,常见的情况有:
- 有些程序类似于服务,需要长期后台运行,作为守护进程
- 有些脚本执行时间很长,希望其在后台慢慢运行
- 对于使用SSH远程连接的情况,一旦SSH连接中断,则所有运行的程序也将全部终止
- 有些程序执行时间很长,但不希望一直维持SSH连接,需要程序后台运行
- 有时候网络状况不稳定,SSH连接很容易中断;一旦连接中断则程序执行也直接中断
其实仔细分析以上需求,有两种情况:
- (1)对于前两者,其实只需要程序后台静默执行即可,这样可以空出前台终端执行其它操作而不必打开新终端
- (2)对于第三种情况,其需要程序不依赖虚拟终端执行,这样可以使得断开SSH连接而程序不终止
方法一:使用&符号
在执行shell命令的时候我们可以在命令的后面加上一个“&
”,这样就可以使得该程序在后台运行。但是当程序运行起来之后依旧会再次在shell中输出打印信息,shell依旧被占用,并且关闭shell则程序退出;这个时候我们可以使用ctrl+z
命令,使得这个信息消失,可以做别的事情,但是关闭shell的时候程序依旧会退出,因此此方法无法解决第三种需求
# 执行当前目录下的test.py脚本,并使用&使其在后台运行
python ./test.py &
# 可以使用ps命令查看程序是否正在运行
ps
ps -ef | grep test # 如果程序很多,可以进行过滤
# 如果需要手动终止进程,可以使用killall命令;[进程名]就是ps输出的名称
killall [进程名]
方法一:使用nohup命令
nohup
命令可以让程序在后台不挂断的运行,即使是SSH连接断开。
nohup
用途:不挂断地运行命令
语法:nohup Command [Arg ...] [&]
- 无论是否将nohup命令的输出重定向到终端,输出都将附加到当前目录的nohup.out文件中。如果当前目录的nohup.out文件不可写,输出重定向到$HOME/nohup.out文件中
- 如果没有文件能创建或打开以用于追加,那么Command参数指定的命令不可调用
- 退出状态出口值:
- 126:可以查找但不能调用Command参数指定的命令
- 127:nohup命令发生错误或不能查找由Command参数指定的命令
- 否则,nohup命令的退出状态是Command参数指定命令的退出状态
仅仅使用nohup
命令能保证程序忽略挂起信号一直运行,但是输出还是会在终端和默认的当前目录的nohup.out
文件中输出,关闭终端的时候不会结束程序,这样不是很优雅,最好的方式是在nohup
后面加上&
,这样就是最佳的执行方式了。
nohup command > myout.file 2>&1 &
- command - 要执行的命令
- > - 将输出追加到文件中
- myout.file - 要将输出保存到的文件
- 0 – stdin (standard input)
- 1 – stdout (standard output)
- 2 – stderr (standard error)
- &是一个描述符,如果1或2前不加&,会被当成一个普通文件
- 2>&1是将标准错误输出重定向到标准输出
- 1>&2的意思则是将标准输出重定向到标准错误
- &>filename的意思是将标准输出和标准错误输出都重定向到文件filename中
- 上面写法是将标准错误(2)重定向到标准输出(&1);标准输出(&1)再被重定向输入到myout.file文件中
- 最后的&就是方法一中的&,让程序后台执行
对于前面执行python脚本的例子可以写成(将日志保存到当前目录下的out.log文件中):
nohup python ./test.py > out.log 2>&1 &
# 可以使用ps命令查看程序是否正在运行 ps ps -ef | grep test # 如果程序很多,可以进行过滤 # 如果需要手动终止进程,可以使用killall命令;[进程名]就是ps输出的名称 killall [进程名]
nohup和&的区别
nohup
运行命令可以使命令永久的执行下去,和用户终端没有关系,例如我们断开SSH连接都不会影响运行,注意了nohup
没有后台运行的意思;&
是指在后台运行,但当用户推出(挂起)的时候,命令自动也跟着退出。
结合起来用就是:nohup COMMAND &
,这样就能使命令永久的在后台执行
方法三:使用screen命令
GNU Screen简称Screen或screen,源自GNU计划,初始版本早在1987年就发布;Screen是一个全屏窗口管理器,它可以在多个进程(通常是交互式shell)之间多路传输物理终端
上面的nohup加&组合方法通常适用于临时执行某一个脚本,因为脚本运行时间很长,需要让其在后台慢慢执行
而screen
命令则更适合执行大量的命令,通常是在网络状况不佳的情况下进行远程操作;毕竟谁都不希望命令执行了一半,结果因为网络质量不好或服务器配置过低导致SSH连接中断,结果所有努力全部白费,还会面临因为中途强行中断而出现的死锁、缓存等乱七八糟的问题
Screen主要有三大功能/特性:
会话恢复:只要Screen本身没有终止,在其内部运行的会话都可以恢复。这一点对于远程登录的用户特别有用——即使网络连接中断,用户也不会失去对已经打开的命令行会话的控制。只要再次登录到主机上执行screen -r就可以恢复会话的运行。同样在暂时离开的时候,也可以执行分离命令dettach,在保证里面的程序正常运行的情况下让Screen挂起(切换到后台)。
多窗口:在Screen环境下,所有的会话都独立的运行,并拥有各自的编号、输入、输出和窗口缓存。用户可以通过快捷键在不同的窗口下切换,并可以自由的重定向各个窗口的输入和输出。Screen实现了基本的文本操作,如复制粘贴等;还提供了类似滚动条的功能,可以查看窗口状况的历史记录。窗口还可以被分区和命名,还可以监视后台窗口的活动。
会话共享:Screen可以让一个或多个用户从不同终端多次登录一个会话,并共享会话的所有特性(比如可以看到完全相同的输出)。它同时提供了窗口访问权限的机制,可以对窗口进行密码保护。
Screen通常没有预装在Linux系统发行版本中,需要手动安装:
sudo apt install screen # Ubuntu/Debian
sudo yum install screen # CentOS/RHEL/CentOS Stream
sudo dnf install screen # Fedora
sudo pacman -S screen # Arch Linux
以上为通过使用软件仓库的发行包进行安装,也可以下载源码自行编译安装
基本概念
Screen的进程管理由会话(session)和窗口(window)组成;我们可以使用screen命令创建很多的screen会话,同时每一个screen会话又可以包含很多的screen窗口
会话(session):screen会话就是当我们进入screen空间下的一个界面,一个会话占用一个进程pid;这个界面有其自己的名字,有其自己内部交互的快捷键,能够拥有很多不同的子终端的界面
Screen可以让一个或多个用户从不同终端多次登录一个会话,并共享会话的所有特性(比如可以看到完全相同的输出)。它同时提供了窗口访问权限的机制,可以对窗口进行密码保护窗口(window):每一个子窗口都是附属与一个screen会话下的,他们互不影响,能够分别执行不同的命令(这是整个screen命令的精华所在),相当于一个虚拟终端
对screen窗口进行管理的命令以ctrl+a开头。 工作时,我们需要做的就是先选定(创建)某一个screen会话,然后选定(创建)其中的一个子窗口。这样如果我们需要换一个界面的话,我们就只需要更换另一个子窗口就行了状态:
- Screen会话主要存在两种状态:
- Attached:表示当前screen正在作为主终端使用,为活跃状态
- Detached:表示当前screen正在后台使用,为非激发状态
- Dead: 表示当前screen已经终止,可以用
screen -wipe
进行清理
Screen命令的一般格式如下:
screen [-opts] [cmd [args]]
Screen中的常用命令:
以下命令中
screen
开头的是shell命令,需要在原始的命令行中执行;Ctrl+*
是快捷键,需要在进入到screen会话中使用
以下快捷键中,以创建窗口(Ctrl+a c)为例,大部分C-a c和C-a C-c等价;但也有少数例外,具体以官方文档和实际使用为准;快捷键大小写敏感(Ctrl+a c和Ctrl+a C是不同的操作)
# 创建会话
screen -S session_name # session_name虽然可以省略,但是非常有用
screen -R session_name # -R会检查session_name,如果存在则进入已有会话,如果不存在则创建并进入
注意:使用-S创建会话不检查name,如果已经有该name的会话存在,则会创建一个新的同名会话,只是id不同
screen -ls # 列出所有会话,也可以写成-list
# 创建子窗口
Ctrl+a c # 在当前的会话下面生成一个新的窗口并切换过去
# 管理子窗口
Ctrl+a w # 窗口列表
Ctrl+a a # 在最近的两个窗口之间切换
Ctrl+a n # 切换到下一个窗口
Ctrl+a p # 切换到上一个窗口
Ctrl+a 0-9 #切换到第0-9个窗口
Ctrl+a " # 会弹出所有子窗口让你选择
Ctrl+a A # 重命名窗口
# 退出窗口
Ctrl+a d # 退出当前窗口(保留窗口),返回到进入screen前的shell状态;此时会话进入detached状态
Ctrl+a k # 关闭当前窗口,并切换到下一个窗口;当关闭最后一个窗口后返回原始shell状态;k/K均可
exit # 关闭当前窗口,并切换到下一个窗口;当关闭最后一个窗口后返回原始shell状态(同Ctrl+a k)
screen -d session_name/session_id # 在会话外退出窗口(保留窗口),会话进入detached状态
提示:session_id就是该会话的进程pid,可以通过screen ls或者top等方式查看
exit相当于是在窗口内执行了“exit”命令推出了终端,其对应的窗口会自动终止,作用相当于快捷键Ctrl+a k/K
# 重新进入会话
screen -r session_name/session_id # 重新进入处于detached状态的会话
screen -R session_name/session_id # 如前所述,-R在name或id不存在的情况下会创建新会话并进入
注意:如果一个会话处于attached状态,但你不在其中,也需要先screen -d name/id将其退出,再screen -r name/id进入
这种情况通常发生在因网络状态、系统负载等原因造成非正常退出的情况下,你不在会话中但会话却处于attached状态
# 删除会话
screen -X -S session_name/session_id quit # 使用-S/-R/-r均可;name/id要跟在-S/-R/-r后面
screen -wipe # 清理处于dead状态的会话
# 锁定/解锁窗口
Ctrl+a x # 锁定窗口,相当于锁屏操作
Ctrl+a s # 锁定窗口,相当于发送XOFF字符
Ctrl+a q # 解锁窗口,相当于发生XON字符
# 日志
Ctrl+a h # 开始/停止记录输出日志到文件
其会将窗口的输出保存到文件,默认的日志文件会保存到当前用户的根目录下(~/screenlog.0)
# 帮助
screen -help # 显示screen的帮助文档
Ctrl+a ? # 在会话内显示快捷键文档
还是以前面的python脚本为例,使用screen方法的操作如下:
screen -S test # 创建一个会话,命名为test
python ./test.py # 在默认的窗口中使用python执行脚本test.py
ctrl+a d # 使用快捷键退出窗口,返回原始shell
screen -ls # 检查已有会话
此时则可以继续其它工作,如果是远程连接也可以放心断开ssh连接;如果需要返回查看:
screen -r test # 重新连接会话“test”,也可以使用id
任务执行完成后可以销毁screen会话:
exit # 这里相当于在虚拟终端(窗口内)执行exit命令退出终端,也可以使用快捷键Ctrl+a k/K结束窗口
# 如果会话中只有这一个0号窗口,则结束窗口后其依附的会话test也将终止,此时可以使用wipe清理缓存
screen -wipe
高级用法(会话共享、屏幕分割、复制粘贴)(点击展开)
会话共享
会话共享实现的效果是:在两个地点登录同一台机器,进入同一个会话,此时两个屏幕的内容可以实现同步输入/输出内容,其效果有些类似于“屏幕共享”
具体步骤如下:
- (1)在第一个终端中创建/进入一个screen会话
- (2)在另一个终端中使用命令
screen -x
,该(-x)选项可以attach到一个没有detach的会话中
前面基本常用命令中提到过,使用screen -r
选项进入会话要求该会话必须处于detached状态,而screen -x
的作用是进入到一个处于没有detached状态的会话中,实现“多屏显示”的效果
屏幕分割
屏幕分割功能可以实现在一块屏幕(终端)中显示多个窗口
Ctrl+a S # 水平分屏
Ctrl+a | # 垂直分屏
Ctrl+a Tab # 在不同区域间切换输入焦点
Ctrl+a K # 关闭当前区域(不会终止窗口);如果只有一个区域则什么都不会发生
Ctrl+a Q # 关闭其它所有区域(不会终止窗口)
复制/粘贴
使用Ctrl+a [或者Ctrl+a Esc可以进入复制模式,其操作类似于vi编辑器
在复制模式下按任意非命令按键可以退出
使用Ctrl+a ]
可以将复制到内容粘贴出来,并且支持跨窗口操作
Ctrl+a [/Esc # 复制
Ctrl+a ] # 粘贴
自定义快捷键
可以使用bind
命令自定义快捷键
方法四:使用systemctl
systemctl是Linux系统上用于管理系统服务(systemd单元)的命令行工具。它可以用来启动、停止、重启、禁用、启用、查询和管理系统服务的状态
使用systemctl可以让程序以守护进程的方式在后台一直运行,这种方法更适合对一些作为服务的程序使用
注意:使用该方法需要root权限
systemctl的完整内容过于复杂,这里仅给出简要的使用说明,以快速实现让程序后台运行的目的,还是以执行前面的python脚本为例:
先转到/etc/systemd/system/目录:
cd /etc/systemd/system
创建一个.service文件,例如这里创建一个名为test的服务:
vim test.service
文件内容参考如下:
[Unit]
Description=test service
After=network.target
[Service]
Type=simple
ExecStart=python /home/tianzi/test.py
[Install]
WantedBy=multi-user.target
Description
是服务描述,可以随意填写ExecStart
是启动服务要执行的命令,例如这里是运行python脚本“/home/tianzi/test.sh”
然后启用并启动服务:
sudo systemctl enable test.service # 这是设置开机启动,如果是一次性任务请跳过
sudo systemctl start test.service # 执行“test”服务;.service通常可省略,上同
查看服务状态和日志输出:
sudo systemctl status test
参考:
https://blog.csdn.net/Pan_peter/article/details/128875714
https://www.cnblogs.com/zyrblog/p/11044285.html
https://blog.csdn.net/weixin_39925939/article/details/121033427
Comments | NOTHING