tmux使用笔记

2017-05-13|Categories: Linux|

安装

启动

  • tmux(通用)
  • tmux -CC (Control Mode)
    • 通过这种方式启动之后,查看man page,例如man tmux,搜索关键字,居然不能高亮
    • 这种方式常用于macOS iTerm2 integration,换到其它平台时操作会不一致。

配置

如何让新的配置生效?

备注:本小节从 http://guoqiao.me/post/2016/tmux 复制,第一次接触tmux的时候,这部分内容帮了我的大忙。

你修改了~/.tmux.conf,但是并没有起作用。你退出tmux,重新进去,发现还是没有生效。这是因为tmux后台有一个server,在你第一次启动tmux的时候启动,并创建会话,当你退出时,它并没有退出。

正确的方法是杀掉server后再重新进入:

tmux kill-server
tmux

或者,重新加载配置文件:

tmux srouce-file ~/.tmux.conf

即使如此,这依然很不方便。你可以使用如下配置:

bind r source-file ~/.tmux.conf \; display-message "Config reloaded!"

现在,你可以按prefix + r来重新加载你的配置文件。并且,在底部的状态栏上,会显示「Config reloaded!」信息。prefix是tmux的专业术语,tmux的快捷键都必须以prefix开始,默认的prefixCTRL+bprefix + r就是先按下CTRL+b,松开后再按下r

网友的优秀配置文件

使用教程

tmux的使用主要就是各种快捷键,数量很多,也不好记忆,只能边用边查,很幸运找到一个非常好的tmux快捷键速查网站

还找到一份tmux的中文wiki,其中包含了脚本化tmux的相关内容。相比The Tao of Tmux的大而全,这份资料可算少而精。

甚至还有让iTerm2中的tmux省去prefix的教程,但这种配置既依赖于特定的操作系统和软件,过程又很复杂,实际价值不大。

同一套快捷键在tmux pane和Vim split window之间移动

备注:本小节从 http://guoqiao.me/post/2016/tmux 复制。

tmux将分割后的小窗口称为「面板(pane)」, 在面板间移动的默认快捷键是prefix + arrow,这虽然好记,可是并不方便。接下来我们逐步改进这个很频繁的操作。

使用prefix + [hjkl]来移动:

bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R

现在,你可以使用Vim的习惯,而不用把手移动到小键盘区的方向键了。但是,这依然需要使用prefix,效率很低。

在Vim中, 我们也可以分割窗口(split window),我用来在窗口间移动的快捷键是Ctrl + [hjkl], 已经习惯了,非常方便。可不可以在tmux也使用同样的快捷键呢? 答案是可以。配置如下:

bind -n C-h select-pane -L
bind -n C-j select-pane -D
bind -n C-k select-pane -U
bind -n C-l select-pane -R

到这里,这个方案似乎已经足够好。但是,它其实引入了新的问题: 当你像我上面的截图那样,在tmux的一个pane中打开Vim并且试图在Vim的分屏中移动时,你会发现快捷键都被tmux截获了, Vim的移动失效了。因为Vim跑在tmux中。

我曾经打算接受现状,当需要在Vim的分屏中移动时,使用Ctrl + ww,把Ctrl + [hjkl]让给tmux。但是要改变一个已经用了很多年的习惯,事实证明是非常困难的。好在有这个困扰的不是我一个人,有一个Vim插件vim-tmux-navigator解决了这个问题。

这个插件首先在Vim中增加了如下映射:

<ctrl-h> => Left
<ctrl-j> => Down
<ctrl-k> => Up
<ctrl-l> => Right
<ctrl-\> => Previous split

这也意味着,你.vimrc中自己做的映射现在不需要了。不过,在~/.tmux.conf中,你要添加如下配置:

is_vim="ps -o state= -o comm= -t '#{pane_tty}' | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"
bind -n C-h if-shell "$is_vim" "send-keys C-h"  "select-pane -L"
bind -n C-j if-shell "$is_vim" "send-keys C-j"  "select-pane -D"
bind -n C-k if-shell "$is_vim" "send-keys C-k"  "select-pane -U"
bind -n C-l if-shell "$is_vim" "send-keys C-l"  "select-pane -R"
bind -n C-\ if-shell "$is_vim" "send-keys C-\\" "select-pane -l"

也就是当你按下Ctrl + [hjkl]时,tmux会判断你是想在Vim里移动,还是在tmux里移动。而且,当你试图从Vim的split移动到tmux的pane时,它能够聪明的判断出来你的意图。到这里,这个问题才算是完美解决。

对于这套配置的使用感受

实际使用之后发现:

  • 在Vim里面可以使用CtrlP快速跳转到指定split window (buffer),效率比Ctrl + [hjkl]要高。
  • Ctrl + [hjkl]是Bash内建的快捷键,都有各自的用途,绑定给tmux之后,命令行操作效率就明显下降,得不偿失。
  • tmux内建的快捷键在pane之间跳转很方便:
    • prefix + o
    • prefix + arrow
    • prefix + q + pane_number

因此,我最终取消了上述的自定义快捷键

同步操作多个tmux panes

copy from https://sanctum.geek.nz/arabesque/sync-tmux-panes/

You can do this by switching to the appropriate window, typing your Tmux prefix (commonly Ctrl-B or Ctrl-A) and then a : (colon) to bring up a Tmux command line, and typing:

:setw synchronize-panes

You can optionally add on or off to specify which state you want; otherwise the option is simply toggled. This option is specific to one window, so it won’t change the way your other sessions or windows operate. When you’re done, toggle it off again by repeating the command.

This is an easy way to run interactive commands on multiple machines, perhaps to compare their speed or output, or if they have a similar setup a quick and dirty way to perform the same administrative tasks in parallel. It’s generally better practice to use Capistrano or Puppet for the latter.

在tmux中回滚,查看操作历史

  1. <prefix> + [:进入copy mode
  2. ctrl-f:向前(下)翻一页
  3. ctrl-b:向后(上)翻一页
  4. /:查找
  5. <space>:开始选择要复制的内容
  6. <enter>:结束选择并复制
  7. <prefix> + ]:粘贴
  8. q:退出copy mode

https://superuser.com/questions/209437/how-do-i-scroll-in-tmux

遇到的问题

tmux session in weird semi-zombie state

https://github.com/tmux/tmux/issues/298

故障描述:

attach到一个session,无法输入任何字符,但可以用快捷键prefix c创建新窗口,在新窗口可以正常输入,回到之前的窗口,输入恢复正常。

issue #298的症状比我的更严重:新窗口一片空白!

解决方案:

  • 方案一:用快捷键prefix x逐个关闭所有异常的pane,然后重新创建session。
  • 方案二:用命令tmux kill-session -a杀死当前session之外的所有session。
  • 方案三:tmux kill-server

备注:

  • detach之后重新attach不能解决问题。
  • tmux的作者在issue #298回复说已经修复了这个问题(2016-04-29),但我在tmux v2.5(2017-05-09发布)仍然碰到这个问题。

Leave A Comment