Linux运维-Tmux使用技巧与最佳实践 {#CrawlerTitle}
王先森 2024-07-25 2024-07-25
Tmux简介 {#Tmux简介}
Tmux
是 Terminal Multiplexer 的简称,它是一款优秀的终端复用软件,类似 GNU screen ,但比 screen
更出色。 tmux
来自于 OpenBSD ,采用BSD授权。使用它最直观的好处就是, 通过一个终端登录远程主机并运行tmux后,在其中可以开启多个控制台而无需再"浪费"多余的终端来连接这台远程主机, 还有一个好处就是当终端关闭后该shell里面运行的任务进程也会随之中断,通过使用tmux就能很容易的解决这个问题。
Tmux和screen的比较 {#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安装使用 {#Tmux安装使用}
|---------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| # 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的快捷键}
|------|-----------|-------------------------------------------------------------------------------------| | 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个单元格为单位移动边缘以调整当前面板大小 |
{#sheet0}
tmux的会话操作 {#tmux的会话操作}
新建会话 {#新建会话}
启动tmux 窗口第一个编号是0,第二个窗口编号是1,以此类推。这些窗口对应的会话,就是 0
号会话、 1
号会话。
使用编号区分会话,不太直观,更好的方法是为会话起名。
|-------------|----------------------------------------|
| 1 2
| # 新建一个指定名称的会话 tmux new -s wxs1
|
分离会话 {#分离会话}
在 Tmux 窗口中,按下
Ctrl+b d
或者输入tmux detach
命令,就会将当前会话与窗口分离。
|---------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| # 在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 ls
查看有tmux会话正在后台运行,如何进入到该正在后台中运行的会话呢,通过运行tmux attach -t wxs1
即可进入到该已存在的会话 wxs1 中。其中attach
也可以简写成a
来表示,-t
指定要进入已存在的会话名,如果不存在则会报告 session not found 错误。
|------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| # 重新接入已存在的 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 则被销毁的会话不会再出现在会话列表中。
|------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| 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 命令在终端环境中看到的列表中会显示会话的新名称。
|---------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| # 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的窗格操作}
创建分屏 {#创建分屏}
tmux的一个窗口可以被分成多个pane(窗格),可以做出分屏的效果。
|-----------|---------------------------------------------------------|
| 1
| # ctrl+b " 水平分屏(组合键之后按一个双引号),用一条水平线把当前窗口分成上下两屏。
|
|-----------|--------------------------------------------------------|
| 1
| # ctrl+b % 垂直分屏(组合键之后按一个百分号),用一条垂线把当前窗口分成左右两屏。
|
光标不同窗格切换 {#光标不同窗格切换}
|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4
| ctrl+b o 依次切换当前窗口下的各个窗格。 ctrl+b Up|Down|Left|Right 根据按箭方向选择切换到某个窗格。 ctrl+b Space (空格键) 对当前窗口下的所有窗格重新排列布局,每按一次,换一种样式。 ctrl+b z 最大化当前窗格。再按一次后恢复
|
显示窗格编号 {#显示窗格编号}
|-------------|-----------------------------|
| 1 2
| # 显示窗格编号 Ctrl + b q
|
关闭窗格 {#关闭窗格}
ctrl+b x 关闭当前使用中的窗格,操作之后会给出是否关闭的提示,按y确认即关闭。
tmux中的历史输出查看 {#tmux中的历史输出查看}
在tmux里面,因为每个窗口(tmux window)的历史内容已经被tmux接管了,当我们在每个tmux的window之间进行来回切换,来回操作,那么我们没有办法看到一个window里面屏幕上的历史输出。没办法使用鼠标滚动(例如在SecureCRT中)查看之前的内容,在SecureCRT中通过鼠标滚动看到的输出一定是各个tmux的window的输出混乱夹杂在一起的,如果要看当前窗口的历史内容,那么应该怎么办呢,通过在当前的tmux window 按 ctrl-b 进入copy mode,然后就可以用PgUp/PgDn来浏览历史输出了,按q退出。
tmux的远程批量操作的shell脚本 {#tmux的远程批量操作的shell脚本}
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| 在使用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
|