Linux运维-Tmux使用技巧与最佳实践

2024-07-27 10:20:16 浏览数 (1)

Linux运维Linux

Linux运维-Tmux使用技巧与最佳实践

王先森2024-07-252024-07-25

Tmux简介

TmuxTerminal Multiplexer 的简称,它是一款优秀的终端复用软件,类似 GNU screen,但比screen更出色。tmux来自于OpenBSD,采用BSD授权。使用它最直观的好处就是, 通过一个终端登录远程主机并运行tmux后,在其中可以开启多个控制台而无需再“浪费”多余的终端来连接这台远程主机, 还有一个好处就是当终端关闭后该shell里面运行的任务进程也会随之中断,通过使用tmux就能很容易的解决这个问题。

Tmux和screen的比较

TmuxScreen 都是用于在 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
new_sessionnew_session

分离会话

在 Tmux 窗口中,按下Ctrl b d或者输入tmux detach命令,就会将当前会话与窗口分离。

代码语言:javascript复制
# 在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个窗口
tmux-lstmux-ls

重新进入会话

如果在终端环境中运行 tmux ls 查看有tmux会话正在后台运行,如何进入到该正在后台中运行的会话呢,通过运行 tmux attach -t wxs1 即可进入到该已存在的会话 wxs1 中。其中attach也可以简写成a来表示, -t 指定要进入已存在的会话名,如果不存在则会报告 session not found 错误。

代码语言:javascript复制
# 重新接入已存在的 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 名字

杀死会话

我们可以在终端环境和会话环境中销毁会话,例如在终端环境中运行 tmux kill-session -t wxs1 结束名字为wxs1的tmux会话。 在会话环境中运行 ctrl b : (注意按组合键之后再按一个冒号键),状态栏变成黄色之后提示我们可以在会话环境中输入命令,此时输入 kill-session -t wxs1` 回车即可。其中wxs1是要销毁的会话名。 会话销毁之后,在终端环境中运行tmux ls 或者在会话环境中运行 ctrl b s 则被销毁的会话不会再出现在会话列表中。

代码语言:javascript复制
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所有的后台会话列表,此时可以通过方向键选择会话并回车,在会话间进行切换。

切换会话切换会话

重命名会话

我们可以在终端环境中将会话重命名,如上面的命令,重命名之后通过 tmux ls 命令在终端环境中看到的列表中会显示会话的新名称。

代码语言:javascript复制
#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 " 水平分屏(组合键之后按一个双引号),用一条水平线把当前窗口分成上下两屏。
horizontalhorizontal
代码语言:javascript复制
# ctrl b % 垂直分屏(组合键之后按一个百分号),用一条垂线把当前窗口分成左右两屏。
verticalvertical

光标不同窗格切换

代码语言: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

0 人点赞