Linux运维Linux
Linux运维-Tmux使用技巧与最佳实践
王先森2024-07-252024-07-25
Tmux简介
Tmux
是 Terminal Multiplexer 的简称,它是一款优秀的终端复用软件,类似 GNU screen,但比screen
更出色。tmux
来自于OpenBSD,采用BSD授权。使用它最直观的好处就是, 通过一个终端登录远程主机并运行tmux后,在其中可以开启多个控制台而无需再“浪费”多余的终端来连接这台远程主机, 还有一个好处就是当终端关闭后该shell里面运行的任务进程也会随之中断,通过使用tmux就能很容易的解决这个问题。
Tmux和screen的比较
Tmux
和 Screen
都是用于在 Unix-like 系统中进行终端多路复用的工具,它们具有类似的功能,但也有一些区别。下面是它们的优点和区别:
Tmux
的优点和特点:
- 更现代的代码:tmux 是一个相对较新的项目,代码更现代化、维护更活跃,具有更好的可扩展性和可定制性。
- 更丰富的功能:tmux 提供了更丰富的功能集,包括窗格(窗格s)、窗口(windows)、会话(sessions)等,可以更灵活地管理多个终端会话。
- 更好的自定义性:tmux 支持通过配置文件进行各种自定义设置,用户可以根据自己的喜好和需求来配置键绑定、外观等。
- 更强大的脚本支持:tmux 提供了丰富的命令行接口和 API,可以通过脚本来实现更复杂的操作和自动化任务。
Screen
的优点和特点:
- 成熟稳定:screen 是一个非常成熟且稳定的项目,已经存在了很长时间,并被广泛应用于各种 Unix-like 系统中。
- 易于上手:screen 的基本用法相对简单,易于上手,适合新手用户快速上手使用。
- 广泛支持:由于 screen 的历史悠久,它被广泛支持和集成到了许多 Linux 发行版和 Unix-like 系统中,几乎可以在任何系统中找到。
- 兼容性好:由于 screen 的普及程度和长期存在,它的配置文件格式和用法在不同系统之间基本保持一致,具有很好的兼容性。
区别:
- 配置和定制:tmux 提供了更灵活和丰富的配置选项,用户可以更精细地定制各种设置,而 screen 则相对简单直接,定制性不如 tmux。
- 键绑定:tmux 和 screen 的键绑定有所不同,tmux 的键绑定更符合现代习惯,而 screen 的键绑定则相对较老式。
- 性能:一般认为 tmux 在性能方面略优于 screen,尤其是在大规模或者复杂任务下,tmux 的性能更好一些。
总的来说,tmux 和 screen 都是非常强大的工具,选择使用哪个取决于个人偏好、需求和对功能的要求。新用户可能更倾向于使用 screen,而对于需要更丰富功能和定制性的用户,则可能更倾向于选择 tmux。
Tmux安装使用
代码语言:javascript复制# tmux官网下载地址:http://tmux.github.io/
# Ubuntu版本下可以直接使用apt安装
sudo apt-get install tmux
# CentOS版本下使用yum安装
yum install -y tmux
# 在macOS中安装
# 安装 Homebrew
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
# 安装tmux
brew install tmux
# 查看版本
tmux -V
Tmux的快捷键
tmux操作 | 命令解释 | |
---|---|---|
Ctrl Z | 挂起当前会话; | |
Ctrl B | 激活控制台;此时以下按键操作生效; | |
系统操作 | ? | 列出所有快捷健;按q返回 |
d | 脱离兰前会话;这样可以暂时返回Shell界直,输入tmux attach能然重新进入之前的会话 | |
D | 选择要脱离的会话;在同时开启了多个会话时使用 | |
r | 强制重绘未脱离的会话 | |
s | 选择并切换会话;在同时开启了多个会话时使用 | |
: | 进入命令行模式;此时可以输入支持的命令,例如kill-server可以关闭服务器 | |
[ | 进入复制模式;此时的操作与vi/emacs相同,按q/Esc退出 | |
~ | 列出提示信息缓存;其u包含了之前tmux返回的各种提示信息 | |
窗口操作 | c | 创建新窗口; |
& | 关闭当前窗口; | |
数字1-9 | 切换至指定窗口 | |
p | 切换至上一个窗口 | |
n | 切换至下一个窗口 | |
l | 在前后创建间进行互相切换 | |
w | 通过窗口列表切换窗口 | |
f | 在所有窗口中找指定文本 | |
, | 重命名当前窗口; | |
. | 修改当前窗口编号;相当于窗口重新排序; | |
面板操作 | " | 将当前面板平分成上下俩块; |
% | 将当面板平分成左右两块 | |
x | 关闭当前面板 | |
! | 将当前面板置于新窗口;即新建一个窗口;其中包含当前面板 | |
Space(空格) | 在预置面板布局中循环切换;依次包括even-horizontal、even-vertical、main-horizontal、main-vertical、titled | |
q | 显示面板编号 | |
o | 在当前窗口中选择下一个面板 | |
方向键 | 移动光标以选择面板 | |
{ | 向前置换当前面板 | |
} | 先后置换当前面板 | |
Alt o | 逆时针旋转当前窗口的面板 | |
Ctrl o | 顺时针旋转当前窗口的面板 | |
Ctrl 方向键 | 以1个单元格为单位移动边缘以调整当前面板大小 | |
Alt 方向键 | 以5个单元格为单位移动边缘以调整当前面板大小 |
tmux的会话操作
新建会话
启动tmux 窗口第一个编号是0,第二个窗口编号是1,以此类推。这些窗口对应的会话,就是 0
号会话、1
号会话。
使用编号区分会话,不太直观,更好的方法是为会话起名。
代码语言:javascript复制# 新建一个指定名称的会话
tmux new -s wxs1
分离会话
代码语言:javascript复制在 Tmux 窗口中,按下
Ctrl b d
或者输入tmux detach
命令,就会将当前会话与窗口分离。
# 在tmux会话中执行
# 先按Ctrl b之后再按d或者输入tmux detach命令
# 执行以上命令后,就会退出当前 Tmux 窗口,但是会话和里面的进程仍然在后台运行
#查看当前所有的 Tmux 会话
# tmux ls
# tmux list-session
$ tmux ls
wxs1: 1 windows (created Thu Jul 25 14:16:48 2024) [127x24]
$ tmux list-session
wxs1: 1 windows (created Thu Jul 25 14:16:48 2024) [127x24]
# 注意:
wxs1: 表示tmux会话的名字
1 windows: 表示会话中有1个窗口
重新进入会话
代码语言:javascript复制如果在终端环境中运行
tmux ls
查看有tmux会话正在后台运行,如何进入到该正在后台中运行的会话呢,通过运行tmux attach -t wxs1
即可进入到该已存在的会话 wxs1 中。其中attach
也可以简写成a
来表示,-t
指定要进入已存在的会话名,如果不存在则会报告 session not found 错误。
# 重新接入已存在的 tmux 会话
# tmux attach -t <会话编号>
# tmux attach -t <会话名字>
# 注意 -t 后参数输入 tmux list-session 查询结果中 冒号前的字段即可。
若 会话有名字:wxs1 , -t wxs1
若 会话没有名字,已默认编号为名字, -t 默认编号即可
# 会话名是默认编号
$ tmux list-session
0: 1 windows (created Thu Jul 25 14:16:48 2024) [108x19]
1: 1 windows (created Wed Nov 22 17:07:33 2023) [108x19]
$ tmux attach -t 1 # 成功接入 已存在会话,会话名为:1
[detached]
$ tmux ls
wxs1: 1 windows (created Thu Jul 25 14:16:48 2024) [108x19]
$ tmux list-session
wxs1: 1 windows (created Thu Jul 25 14:16:48 2024) [108x19]
$ tmux attach -t wxs1 # new01 : tmux 会话session 名字
杀死会话
代码语言:javascript复制我们可以在终端环境和会话环境中销毁会话,例如在终端环境中运行
tmux kill-session -t wxs1
结束名字为wxs1的tmux会话。 在会话环境中运行 ctrl b : (注意按组合键之后再按一个冒号键),状态栏变成黄色之后提示我们可以在会话环境中输入命令,此时输入 kill-session -t wxs1` 回车即可。其中wxs1是要销毁的会话名。 会话销毁之后,在终端环境中运行tmux ls 或者在会话环境中运行 ctrl b s 则被销毁的会话不会再出现在会话列表中。
1. 使用会话编号
$ tmux kill-session -t <会话编号:即 tmux list-session 查询结果中 冒号前的字段即可>
$ tmux list-session
0: 1 windows (created Thu Jul 25 14:16:48 2024) [108x19]
1: 1 windows (created Thu Jul 22 14:07:33 2023) [108x19]
$ tmux kill-session -t 1
$ tmux list-session
0: 1 windows (created Thu Jul 25 14:16:48 2024) [108x19]
2. 使用会话名称
$ tmux kill-session -t <session-name> # 根据会话名字杀死会话
$ tmux list-session
nws01: 2 windows (created Thu Jul 25 14:16:48 2024) [108x19]
$ tmux kill-session -t nws01
$ tmux list-session # 查询会话
failed to connect to server
切换会话
上述切换会话每次都要退出当前会话,先回到shell终端环境再运行tmux ls 来查看就很不方便,那么在tmux的会话环境中,我们可以通过
ctrl b s
来获取当前linux机器上tmux所有的后台会话列表,此时可以通过方向键选择会话并回车,在会话间进行切换。
重命名会话
代码语言:javascript复制我们可以在终端环境中将会话重命名,如上面的命令,重命名之后通过 tmux ls 命令在终端环境中看到的列表中会显示会话的新名称。
#tmux rename-session -t <old_session_name or default_session_no> <new_session_name>
1. 会话没有名字,只有默认编号
$ tmux list-session # 查询已存在会话
0: 1 windows (created Thu Jul 25 14:16:48 2024) [108x19]
2: 1 windows (created Wed Nov 22 17:16:51 2023) [108x19]
$ tmux rename-session -t 2 nws12 # 将默认编号2的会话重命名 news12
$ tmux list-session
0: 1 windows (created Thu Jul 25 14:16:48 2024) [108x19]
nws12: 1 windows (created Wed Nov 22 17:16:51 2023) [108x19] # 查询编号2的会话名字已更新
2. 回话有名字
$ tmux list-session # 查询已存在会话 1,2
nws01: 1 windows (created Wed Nov 22 16:53:20 2023) [108x19]
nws02: 1 windows (created Wed Nov 22 16:53:27 2023) [108x19]
$ tmux rename-session -t nws01 nws11 # 将会话nws01 重命名为 new11
$ tmux list-session # 查询已存在会话 1,2
nws02: 1 windows (created Wed Nov 22 16:53:27 2023) [108x19]
nws11: 1 windows (created Wed Nov 22 16:53:20 2023) [108x19] # 会话1 名字已更新
tmux的窗格操作
创建分屏
tmux的一个窗口可以被分成多个pane(窗格),可以做出分屏的效果。
代码语言:javascript复制# ctrl b " 水平分屏(组合键之后按一个双引号),用一条水平线把当前窗口分成上下两屏。
代码语言:javascript复制# ctrl b % 垂直分屏(组合键之后按一个百分号),用一条垂线把当前窗口分成左右两屏。
光标不同窗格切换
代码语言:javascript复制ctrl b o 依次切换当前窗口下的各个窗格。
ctrl b Up|Down|Left|Right 根据按箭方向选择切换到某个窗格。
ctrl b Space (空格键) 对当前窗口下的所有窗格重新排列布局,每按一次,换一种样式。
ctrl b z 最大化当前窗格。再按一次后恢复
显示窗格编号
代码语言:javascript复制# 显示窗格编号
Ctrl b q
关闭窗格
ctrl b x 关闭当前使用中的窗格,操作之后会给出是否关闭的提示,按y确认即关闭。
tmux中的历史输出查看
在tmux里面,因为每个窗口(tmux window)的历史内容已经被tmux接管了,当我们在每个tmux的window之间进行来回切换,来回操作,那么我们没有办法看到一个window里面屏幕上的历史输出。没办法使用鼠标滚动(例如在SecureCRT中)查看之前的内容,在SecureCRT中通过鼠标滚动看到的输出一定是各个tmux的window的输出混乱夹杂在一起的,如果要看当前窗口的历史内容,那么应该怎么办呢,通过在当前的tmux window 按 ctrl-b 进入copy mode,然后就可以用PgUp/PgDn来浏览历史输出了,按q退出。
tmux的远程批量操作的shell脚本
代码语言:javascript复制在使用SSH或telnet远程连接服务器时,可能都遇到为一些长时间运行的任务而头疼,比如系统备份、ftp 传输等等。通常情况下我们都是为每一个这样的
任务开一个远程终端窗口,因为他们执行的时间太长了。必须等待它执行完毕,在此期间可不能关掉窗口或者断开连接,否则这个任务就会被杀掉,一切半
途而废了。也许nohup命令可以达到这个目的,如果程序的标准输出/标准错误是终端, nohup默认将其重定向到nohup.out文件。值得注意的是nohup命令
只是使得程序忽略SIGHUP信号,还需要使用标记&把它放在后台运行。
nohup <command> [argument…] &
虽然nohup很容易使用,但还是比较“简陋”的,对于简单的命令能够应付过来,对于复杂交互的程序就麻烦了。
使用tmux打开一个终端窗口,可以在窗口里执行一个长时间运行的交互式命令操作,令其一直在后台跑着,并且在按键ctrl-b-d后,可以无感知的退出窗口,
而退出后窗口不会关闭,即窗口里执行的交互命令也不会结束。这比起传统的"nohup commang & (然后按ctrl c)"的方式要还用很多。
如何在linux终端里创建一个tmux窗口的同时直接在窗口终端里执行命令呢?
这就需要用到tmux send -t session_name "command" ENTER
示例一
[root@boysec ~]# tmux new -d -s kevin_session && tmux send -t kevin_session '/usr/local/bin/main' ENTER && tmux attach -t kevin_session
[detached (from session kevin_session)]
[root@boysec ~]# tmux ls
kevin_session: 1 windows (created Tue Oct 2 19:38:36 2024) [135x34]
上面的命令可以拆分为下面三个:
[root@boysec ~]# tmux new -d -s kevin_session
[root@boysec ~]# tmux send -t kevin_session '/usr/local/bin/main' ENTER
[root@boysec ~]# tmux attach -t kevin_session
解释说明:
上面涉及到三个命令
第一个表示:在后台创建一个窗口,名为kevin_session
第二个表示:创建窗口的同时在终端里执行命令'/usr/local/bin/main',这里用单引号或双引号都可以。
第三个表示:进入到刚才创建的窗口kevin_session里面去
示例二
在创建窗口的同时,可以同时在窗口终端里连续执行两个或多个命令
[root@boysec ~]# su - kevin -c "tmux new -d -s haha && tmux send -t haha 'ifconfig' ENTER && tmux send -t haha 'hostname' ENTER"
kevin_session: 1 windows (created Tue Oct 2 19:38:36 2024) [135x34]
[root@boysec ~]# su - kevin
kevin@bobo:~$ tmux ls
haha: 1 windows (created Tue Oct 2 19:48:12 2024) [135x34]
kevin@bobo:~$ tmux a -t haha
如下一个实例:
在远程进行tmux的批量关闭和批量开启的shell脚本操作
1) 批量关闭/opt/ip.list文件里ip所在机器的main二进制进程(这个main进程是在tmux执行的,一直交互执行的那种)
[root@boysec ~]# vim /opt/script/6_main_stop.sh
#!/bin/bash
for i in $(cat /opt/ip.list)
do
ssh -p22 root@$i 'ps -ef|grep main|grep -v grep|awk -F" " "{print $2}"|xargs kill -9 >/dev/null 2>&1'
done
2)批量开启/opt/ip/list文件里ip所在机器的tmux窗口里的main二进制进程(即先关闭tmux,再创建tmux窗口以及在里面执行main进程)
[root@boysec ~]# vim /opt/script/7_main_start.sh
#!/bin/bash
for i in $(cat /opt/ip.list)
do
ssh -p22 root@$i 'ps -ef|grep tmux|grep -v grep|awk -F" " "{print $2}"|xargs kill -9 >/dev/null 2>&1'
ssh -p22 root@$i 'tmux new -d -s kevin_session && tmux send -t kevin_session '/usr/local/bin/main' ENTER'
done