Linux 环境下程序不间断运行
一、背景
在linux命令行中执行程序,程序通常会占用当前终端,如果不启动新的终端就没法执行其他操作。简单可以通过'&'将程序放到后台执行,但是这种方法有个问题就是,一旦连接远程服务器的网络异常或者本机ssh客户端、系统等关闭亦或出现问题导致连接断开,那么放到后台执行的程序就会被终止。
对于需要长时间运行的守护进程或者服务端程序这种异常断开造成的进程终止不可接受。下面就介绍三种解决这种问题的通用方案(不涉及程序改造)
二、nohup命令
在启动程序命令后面添加&将程序放到后台作业队列中,管理任务队列中任务可以通过jobs等命令。
但是任务队列中的任务通常情况下,其父进程都是当前终端的shell进程。而一旦父进程退出,则会发送hangup信号给所有子进程,子进程收到hangup以后也会退出。我们可以通过让后台进程忽略来自父进程的hangup信号或者修改后台进程的父进程id来避免后台进程退出。使用nohup命令执行的命令nohup ./tesh.sh & 可以忽略hangup信号(需要启动程序时将程序放到后台执行,否则关闭终端依然会导致进程结束),使用setsid命令 setsid ./test.sh & 可以将当前程序的父进程设置为init进程,这样就不会收到当前shell进程发出的hangup信号了。具体用法如下:
新启动程序
|
nohup ./test.sh >log 2>&1 &
|
setsid ./test.sh >log 2>&1 &
|
已运行程序
|
nohup -p PID
|
disown -h %n
|
注:nohup命令会将所执行的命令的标准输出重定向到当前目录的nohup.out文件中(如果命令中没有重定向标准输出),但是不会重定向标准错误输出。其余的setsid、disown只是修改进程的sid,使其与当前shell脱离,但是并没有改变原命令的标准输出、标准错误输出,所以这些后台运行的进程,当需要标准输出或标准错误输出的时候,发现默认的输出位置终端不可用,就会报异常退出。因此,在运行后台进程时,尽量将利用 >log 2>&1 对命令的输出进行重定向(如表格中第一行)。
三、screen命令
GNU Screen可以看作是窗口管理器的命令行界面版本。它提供了统一的管理多个会话的界面和相应的功能,大部分Linux发行版都默认带有screen。通过将screen会话与当前终端shell进程detach来避免当前终端shell的异常导致的screen中运行的程序的终止。
screen -S NAME
|
screen -S sxhlinux
|
新建一个名为sxhlinux的screen会话
|
screen -ls
|
screen -ls
|
查看当前系统中所有的screen会话
|
screen -d NAME
|
screen -d sxhlinux
|
将sxhlinux会话与当前shell终端分离
|
screen -r NAME
|
screen -r sxhlinux
|
在当前shell进程中与名为sxhlinux的进程重新连接
|
screen -R NAME
|
screen -R sxhlinux
|
同-r选项,另外如果sxhlinux不存在,
就会重新新建一个名为sxhlinux的screen会话
|
screen -x NAME
|
screen -x sxhlinux
|
多个终端同时操作名为sxhlinux的screen会话,操作同步可见
|
在每个screen 会话中都有如下快捷键可以使用
ctrl-a c
|
在当前会话中创建一个新的的shell窗口
|
ctrl-a n/p
|
切换到下/上一个窗口
|
ctrl-a d
|
使当前会话与原shell detach
|
ctrl-a w
|
列出当前会话中的所有窗口
|
ctrl-a k
|
关闭当前窗口
|
ctrl-a x/q
|
锁定、解锁当前窗口
|
ctrl-a [/]
|
[启动复制模式(vi操作习惯),第一次空格键表示开始复制,第二次空格表示结束复制;
]将[复制的内容粘贴到当前位置
|
ctrl-a S/|
|
将当前屏幕水平/垂直分成两部分,可以通过ctrl-a TAB来切换
|
可以修改/etc/screenrc或者~/.screenrc配置文件来配置screen,选项vbell off/on 控制错误闪屏提醒。本文关注点在保证用户程序不因终端、网络异常等问题造成程序运行中断,因此这里有关screen只进行简单的介绍,有兴趣的可以搜索相关文章或者看官方document。
四、tmux命令
虽然screen很好用,但是已经很多年没有添加新特性了,还存在一些bug。作为screen的替代者,tmux在各方面完全可以替代甚至超过screen,唯一的缺点是Linux发行版没有默认安装tmux,需要用户联网安装。下面就简单介绍tmux的使用方法:
tmux new -s NAME
|
tmux new -s sxhlinux
|
创建一个
|
tmux detach -s NAME
|
tmux detach -s sxhlinux
|
将sxhlinux会话分离
|
tmux attach -t NAME
|
tmux a -t sxhlinux
|
重新连接sxhlinux会话
|
tmux ls
|
tmux ls
|
列出当前所有的tmux会话
|
tmux lsc [-t NAME]
|
tmux lsc [-t sxhlinux]
|
列出所有[连接到sxhlinux]的客户端
|
tmux rename -t OLD NEW
|
tmux rename -t sxh sxhlinux
|
将会话sxh重命名为sxhlinux
|
tmux kill-session -t NAME
|
tmux kill-session -t sxhlinux
|
关闭sxhlinux会话
|
tmux默认的快捷键组合前缀为ctrl b,不过为了和screen习惯保持一致,我们可以修改tmux的配置文件~/.tmux.conf来讲组合前缀改成ctrl a
ctrl-a c
|
同screen
|
ctrl-a d
|
同screen
|
ctrl-a f
|
在当前会话所有打开的窗口中搜索文本
|
ctrl-a n/p
|
同screen
|
ctrl-a &
|
关闭当前窗口
|
ctrl-a x
|
关闭当前会话
|
修改的tmux配置文件如下(注:#以及后面的内容仅做说明,实际使用的时候请删除)
set -g prefix C-a #配置快捷键前缀为ctrl a unbind C-b #取消快捷键前缀ctrl b unbind '%' #取消左右分pane的快捷键 % bind | splitw -h #指定左右分pane的快捷键 | bind k selectp -U #指定选择上方pane的快捷键 k bind j selectp -D #指定选择上方pane的快捷键 j bind h selectp -L #指定选择上方pane的快捷键 h bind l selectp -R #指定选择上方pane的快捷键 l
通常情况下,如果系统重启原来的tmux会话就会丢失(因为tmux由一个server进程来保存相关会话信息,系统重启原来的server进程消失,所以之前的tmux会话也就不存在了)安装tmux-continuum插件解决tmux会话不能保存的问题。
-
tmux-continuum插件要求tmux版本为1.9以上,目前CentOS 7 上的版本为1.8。 所以,需要我们去github的tmux项目中下载新版本的tmux替换系统中已有的老版本。
-
下载并安装tmux插件 git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
- 编辑 ~/.tmux.conf文件,并在最后追加如下内容
# Edit ~/.tmux.conf and added lines below at the bottom set -g @plugin 'tmux-plugins/tpm' set -g @plugin 'tmux-plugins/tmux-sensible' set -g @plugin 'tmux-plugins/tmux-resurrect' set -g @plugin 'tmux-plugins/tmux-continuum' set -g @continuum-restore 'on' # Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf) run '~/.tmux/plugins/tpm/tpm'
- 执行 tmux new -s test 创建一个临时的session,然后在session中执行 ctrl-a I 组合键安装tmux-continuum。安装完成后ctrl-d结束当前session。至此continuum插件安装完成。
参考资料:https://github.com/tmux/tmux https://github.com/tmux-plugins/tpm https://github.com/tmux-plugins/tmux-continuum
五、总结
nohup一般作为启动服务或者守护进程来执行一个单独的命令的情形下使用(记得输出重定向);screen和tmux可以作为日常连接远程开发服务器做开发使用,可以方便的切换各种工作台,而不用打开多个终端。
欢迎技术探讨:sxhlinux@163.com