工具篇
本系列专门用于记录一些软件或者小工具的使用,工欲善其事必先利其器,拥有称心如意的工具,可以大大提高我们的工作效率。
一、TMUX
之所以选择 TMUX 作为第一个工具介绍,是因为从第一次接触它,便真的彻底喜欢上了它,我认识它的时间并不长,是从过年疫情在家期间才初次接触到它。为什么喜欢它呢?它又好在哪里?我相信作为初学者都和我之前一样,肯定遇到了以下几种情况:
- 打开终端,当前终端正在处理某一件事,而我需要再开一个窗口去做另一件事情,然后就
Ctrl+N
打开了很多个终端窗口。一个窗口感觉不用了,就关了,可几秒钟后感觉又需要使用,然而之前的窗口关闭了,之前的状态没了 - 工作中往往需要 ssh 远程登录一些服务器,而如果窗口长时间保持静默则会自动关闭连接,通常拷贝一个大文件,拷贝到一半,连接断了,很烦人
Tmux 就可以完美的解决上面的问题。Tmux是一款优秀的终端复用软件,它有很多特性,比较重要的有:
- 分屏:它通过面板、窗口、会话三级组织结构管理你的终端窗口,相当于你之前通过
Ctrl+N
打开的很多窗口现在可以以一种类似于目录树的结构完美的集成到一个终端窗口下。 - 后台执行:所执行的所有命令均已后台执行的方式进行操作,类似于 nohup 的功能,即使命令执行到一半,只要 tmux 服务不杀死,哪怕此时你把终端窗口关闭掉,当再次打开终端,进入到 tmux 会话中,一切如旧,之前执行的命令仍在持续进行。
- 会话共享:可以将自己的窗口远程分享给别人,适用于教学。
1、安装
# Mac 中
# 先安装 Homebrew,有则跳过
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
# 安装 tmux
brew install tmux
2、概念
Tmux 通过会话、窗口、面板三级结构进行组组的。
- 会话:会话相当于一级目录,类似于一个项目,不同会话下的窗口可以做不同的事情,例如,我可以创建两个会话,一个会话下的窗口专门用于处理本机电脑下的命令;另一个会话下的窗口专门用于远程服务器下的相关操作。
- 窗口:窗口相当于二级目录,一个会话下可以创建很多窗口,窗口可以理解为页面的意思,例如你用 vim 编辑器开发项目,一个窗口可以单独打开一个文件,专门用于编辑该文件。
- 面板:面板相当于三级目录,一个窗口下又可以分屏创建很多面板,例如分屏后,一个面板用于编辑代码,另一个面板用于测试等
上面下方的状态栏部分,黄色部分指示当前的会话名称是 “local”, 后面的 “1 Shell 2 project … 5 tmux” 表明当前会话下共有 5 个窗口,蓝色背底的 “tmux” 表明,你看到的当前整个窗口内容是位于 “tmux” 这个窗口下。上面的窗口一分为二,可以看到中间有一条蓝色的竖线,整个屏幕一分为二,这就是面板的概念,表明 “tmux” 窗口下共有两个面板,如果不分屏的话,则整个窗口就一个面板。
3、具体操作
注:下文中的快捷键,大部分都有前置 lead 键,默认为 ctrl-b,但是在 Mac 下这两个键离得远,不方便,下面的配置中增加了另一个兼容的快捷键为 ctrl-a,还是不得劲,而键盘上的大写锁定键几乎八百年不用一次,且就在 a 旁边,索性系统级键盘映射,将大写锁定键映射为 ctrl 键。下文中用 "qz (前缀)"代表 lead 键即 “ctrl-b”。
3.1 会话
打开终端,这 shell 环境下,直接输入 tmux
就会新建一个会话,新建的会话窗口实际上就和普通的命令行环境差不多,最下面会有一个状态栏,状态栏内的信息可以简单看一下,通常含有会话、窗口信息以及登录信息等,这个具体后面再介绍,输入 exit
便会关闭该会话窗口,同时关闭 tmux 服务。
这面这种方式过于草率,一般用于临时使用解决个小问题,通常更好的方式是给 session 起个名字,正式一些。
新建会话:
-
tmux new-session -s basic
ortmux new -s basic
这样,我们就创建了一个名为 basic 的会话,另外在创建一个会话的同时指定一个窗口名称,tmux new -s windows -n shell
-n
告诉 tmux 窗口名称。 -
在创建会话窗口的时候,还可以指定一个初始命令,如
tmux new -s top "top"
即新建一个名为 top 的会话(没有提供具体的窗口名称,由系统提供默认值),窗口建立后,直接自动运行 top 命令,当命令执行结束,如 q 掉,则该会话或窗口也会 exit。
列出已存在的会话:
-
tmux list-sessions
ortmux ls
,
界面上侧会罗列出所有的会话列表,以及每个会话的窗口数,当前所处的会话列表后面会多一个 (attached) 标记,下侧的内容会随着所选会话发生变化。相当于一个会话窗口预览的功能。会话的选择可以通过上下键选择,也可以通过会话前面的数字序号进行选择。另外选中某个会话,可以通过左右键罗列出该会话下的所有窗口,同样可以再次上下键选择,可以直接进入到所需的窗口下,如上图所示。
detach or attach:
下面的 qz+d 就是先按前导键 “ctrl-b”,而后再按 d,实际上在上图状态栏中间部分(红色框中),当你按下前导键,这里还有一个小白块,说明此时你可以按后缀键进行具体操作。
- 在 tmux 会话窗口中,我们可以通过
qz+d
回到原始 shell 环境中,而将 tmux 会话窗口放在后台运行 - 如果我们只有一个会话,若想再次进入到原 tmux 窗口下,可以执行
tmux attach
- 如果我们有多个会话存在,则必须指定你要进入的那个会话名称
tmux attach -t session_name
- 所以给会话起个名字非常有用,而且当你拥有多个会话时,也可以根据名字区别它们,不会混淆
rename:
即使你用 tmux
直接建立一个会话窗口或者后面工作需要需要给会话改名,都可以的,在 tmux 会话窗口下 qz+:
进入命令行模式,然后输入 rename-session new_name
回车后,并可以修改会话名称
退出会话:
- 在 tmux 会话窗口下可以执行
exit
- 也可以在常规终端下
tmux kill-session -t session_name
杀死 - 退出整个 tmux 服务:
tmux kill-server
所有的会话都会被关闭
【进一步自定义配置后】:
- qz+
C-c
:可用于创建一个新的会话 - qz+
C-f
:可以通过指定名字跳转到其他会话中
3.2 窗口
我们上面已经简单介绍了,在创建会话的时候,自动就会创建一个初始窗口,或者我们可以通过 -n
参数指定这个窗口的名称,我们后面的基本操作也基本都是围绕着窗口或面板进行操作的。
窗口创建:
- 除了在新建会话的时候创建初始窗口,我们还可以在一个会话下创建更多的窗口,
qz+c
窗口重命名:
- 类似会话重命名,我们可以在命令行模式下(
qz+:
)输入rename-window new_name
- 也可以使用快捷键
qz+,
自动进入重命名命令行下,删掉原来的名字重新起个新名字即可
窗口移动:如何从当前窗口跳转到其他窗口中,如上图,我们在会话 “local” 下建了 4 个窗口,除了上面介绍的在 ls 命令下选择,还可以更直接的进行跳转:
qz+p
:切换到上个窗口,qz+n
: 切换到下个窗口,- 你会发现每个窗口名前都有一个数字,如果你未配置,默认数字从 0 开始,所以你可以
qz+数字
切换到指定窗口 - 上面数字方式对于 0-9 有效,窗口为 10 就不能用了,可以采用
qz+w
罗列出所有窗口,通过上下键选择 - 如果窗口过多,可以用
qz+f
find 通过关键词过滤出符合条件的窗口列表 qz+TAB
相当于返回键,返回到上次你使用过的窗口
qz+p
和qz+n
个人用的较少,第一是不如数字简单明了,第二是可能记不住(pred & next),第三是可能后期该快捷键可能会被映射到其他功能上。qz+ C-h
andqz+ C-l
let you navigate windows (defaultn
andp
are unbound)
关闭窗口:
- 当一个会话有多个窗口,exit 只会退出当前窗口,如果只有一个窗口,则会连会话一同退出
qz+&
非暴力退出,退出前会提示你是否关闭,需要输入 y/n 确认qz+x
实际是窗格退出,但是如果没有其他窗格,一个窗口也可以看做是一个大窗格,该命令也可以关闭该窗口
3.3 窗格
窗格可以看做是分屏,可以将一个窗口一分为二,分成两个窗格,也可以继续切分
分屏
qz+%
后面我们会配置成qz+|
很直观,一条竖线将窗口分为左右两部分qz+"
后面我们会配置成qz+-
很直观,一条横线将窗口分为上下两部分
窗格切换:
qz+o
轮流激活不同的窗格qz+方向键
:激活不同方位的窗格,经过后面的配置,hjkl 方向键也可以qz+空格
:以不同的展示形式排列窗格
关闭窗格:
- exit 关闭当前窗格
qz+x
非暴力式关闭
【配置后】qz+
:
H
,J
,K
,L
可以让你分别将窗格向左、下、上、右不同的方向放大或缩小<
和>
可以交换两个窗格的位置+
可以将当前窗格独立处理作为一个单独的窗口,相当于一个窗格最大化的操作
4、TMUX 配置
为了更加便利的使用 tmux,我们可以自定义配置一些操作起来更加方便的内容,我采用的是 gpakosz/.tmux。
例如上面一段内容的具体配置内容是:
# pane navigation
bind -r h select-pane -L # move left
bind -r j select-pane -D # move down
bind -r k select-pane -U # move up
bind -r l select-pane -R # move right
bind > swap-pane -D # swap current pane with the next one
bind < swap-pane -U # swap current pane with the previous one
# maximize current pane
bind + run 'cut -c3- ~/.tmux.conf | sh -s _maximize_pane "#{session_name}" #D'
# pane resizing
bind -r H resize-pane -L 2
bind -r J resize-pane -D 2
bind -r K resize-pane -U 2
bind -r L resize-pane -R 2
更多的配置可以详见该配置文件,也可以根据自己的喜好,进行自定义配置。
下面介绍几个其他个人比较喜欢的配置项:
- 新增窗格时,工作目录默认切换到当前目录,新增窗格的需求通常出现在对同一级文件进行操作,否则每次都需要从 home 目录 cd 就很烦,另外如果是 ssh ,则新增窗格也会自动登陆同一服务器中
- 鼠标支持:
qz+m
,主要用于调整窗格大小,可以鼠标在分界线上滑动,比上述 HJKL 方式方便的多,再次qz+m
关闭鼠标支持功能 - 保存与恢复,这要依赖于插件 Tmux Resurrect 和 Tmux Continuum,前者支持 tmxu 会话保存功能,
qz+ctrl-s
保存当前所有的会话状态,即使退出 tmux 服务(例如下班关机了),当再次打开终端,输入 “tmux” 启动 tmux 后,qz+ctrl-r
就可以帮你恢复到之前的状态。后面的插件是可以自动帮我们定时保存,默认每 15 分钟保存一次,这样即使忘记保存就直接关机了,也可以帮你恢复到比较接近最后的工作状态。
5、结对编程
会话共享主要用于演示或教学,以及多人结对编程等场景,通常的教学或者演示场景是通过屏幕共享的方式进行的,这会对带宽有较高的要求,tmux 结对编程,即使是最慢的酒店 wifi 也可以让你与另一个开发人员轻松进行远程协作。
共享账户:
最简单的方式是两个人公用同一个账户,例如可以新建一个 tmux 账户,现在我们在 tmux 账户下安装一个 tmux ,并创建一个会话,例如 tmux new-session -s Pairing
,其他人也可以用 tmux 账户登录,进入到 Pairing 会话中,tmux attach -t Pairing
。这样当两个人处于同一窗口下就会同步对方的操作。
会话组:
虽然上面的共享账户的方式是很简单的,但是这种情况下,双方看到的窗口将会始终保持一致,双方均可对当前界面造成影响,但是更多的时候,我们希望你忙你的,我忙我的。使用会话组可以解决这个问题。同样我们先新建一个会话:tmux new-sessiong -s groupedsession
,不同的是其他人不再直接 attach 到该会话中,而是以该会话为目标新进一个新的会话:tmux new-sessiong -t groupedsession -s mysession
.
当第二个会话启动时,两个用户可以同时与会话交互,就像第二个用户 attach 到会话一样。但是,用户可以创建相互独立的窗口。因此,如果我们的新用户创建了一个窗口,都会看到新窗口显示在状态行中,但你将继续停留在自己当前正在使用的窗口中!
第二个用户可以使用 kill session 终止他们的会话,而原始会话仍然存在。但是,如果关闭所有窗口,两个会话都将被终止,所以要小心,如果你只是想有人加入进来,帮你完成一些代码,上述方案就有些啰嗦,下面我们介绍 tmate。
tmate:
tmate 是 tmux 的一个分支,旨在让结对编程变得更加畅爽。使用 tmate,你可以快速邀请其他开发人员进行协作。当你启动tmate 时,它会生成一个地址用来建立连接。你不必设置任何密钥或使用任何中间服务。相反,tmate 的服务器会为你处理隧道连接。
# 安装 tmate
brew install tmate
# 启动 tmate
tmate
在界面下方会有一个 “[tmate] ssh session: ssh …” 的信息,在上方红色框中也有更详细的信息,其中下方的信息几秒钟后就会消失,如果没有看到上方的信息,且复制的时候消息已消失,可以输入 tamte show-messages
就会看到了。当前界面下按 “q” 就可回到 shell 界面。如果是希望演示给别人看,那么复制上面的 “ssh session read only” 即可。
我们下面在左侧窗口,先登录到服务器中,然后再服务器下执行 ssh 登录,我们看一下效果:
登录后,我们就会发现界面与右侧本机完全一致,且不可操作,只有可读权限,当在本机下进行操作,左侧远程服务器下完全同步显示。
演示结束后,本地下 exit 退出 tmate 服务即可,同时远程服务器连接关闭,回到自己的 shell 环境下。
在上述过程中,我们实际借助的是 “https://tmate.io”,如果处于安全性考虑,你可以在自己的服务下搭建中转服务。
使用共享帐户或 tmate 很容易,但与团队成员共享用户帐户或让某人远程访问你的开发机器并不总是可取的。让我们看看另一种方法。
Sockets 下的独立账户结对
使用 tmux 下支持的套接字来完成多个不同账户下的结对编程,为了进行演示,我们先创建两个测试账户:
sudo adduser user_1
sudo adduser user_2
创建 tmux 用户组,并创建 “/var/tmux” 目录用于维护共享的会话
sudo addgroup tmux
sudo mkdir /var/tmux
# 接下来,更改 /var/tmux 文件夹的组所有权,以便 tmux 组具有访问权限:
sudo chgrp tmux /var/tmux
# 然后更改文件夹的权限,以便 tmux 组的所有成员都可以访问新文件:
sudo chmod g+ws /var/tmux
# 把两个新建用户加入到 tmux 用户组
sudo usermod -aG tmux user_1
sudo usermod -aG tmux user_2
现在用 user_1 账户登录,创建一个新的会话,并将会话 socket 文件保存到 /var/tmux 目录下:tmux -S /var/tmux/pairing
,然后新建一个窗口用 user_2 账户登录,只用指定 socket 文件 attach,tmux -S /var/tmux/pairing attach
,完美实现不同账号下的结对编程。