单用户安装 Tmux 终端复用神器,类似 screen 命令

tmux 是一个优秀的终端复用器类自由软件,功能类似 GNU Screen,但使用 BSD 许可发布。用户可以通过 tmux 在一个终端内管理多个分离的会话,窗口及面板,对于同时使用多个命令行,或多个任务时非常方便。

tmux的主要元素分为三层:

  • Session 一组窗口的集合,通常用来概括同一个任务。session可以有自己的名字便于任务之间的切换。
  • Window 单个可见窗口。Windows有自己的编号,也可以认为和ITerm2中的Tab类似。
  • Pane 窗格,被划分成小块的窗口,类似于Vim中 C-w +v 后的效果。

元素结构图

安装

基本流程如下,转自 https://gist.github.com/ryin/3106801,中文部分是我的备注,请注意修改,适当修改后可以写到 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
#!/bin/bash

# Script for installing tmux on systems where you don't have root access.
# tmux will be installed in $HOME/local/bin.
# It's assumed that wget and a C/C++ compiler are installed.

# exit on error
set -e

# 最新版本是 2.7 亲测可以成功安装。
TMUX_VERSION=2.7

# create our directories
mkdir -p $HOME/local $HOME/tmux_tmp
cd $HOME/tmux_tmp

# download source files for tmux
wget -O tmux-${TMUX_VERSION}.tar.gz https://github.com/tmux/tmux/releases/download/${TMUX_VERSION}/tmux-${TMUX_VERSION}.tar.gz


# download source files for libevent and ncurses (这个 libevent 的下载链接是 https 的,如果不能下载的话就用本地机器下载后上传,或者自己想办法)
wget https://github.com/downloads/libevent/libevent/libevent-2.0.19-stable.tar.gz
wget ftp://ftp.gnu.org/gnu/ncurses/ncurses-5.9.tar.gz

# extract files, configure, and compile

############
# libevent #
############
tar xvzf libevent-2.0.19-stable.tar.gz
cd libevent-2.0.19-stable
./configure --prefix=$HOME/local --disable-shared
make
make install
cd ..

############
# ncurses #
############
tar xvzf ncurses-5.9.tar.gz
cd ncurses-5.9
./configure --prefix=$HOME/local
make
make install
cd ..

############
# tmux #
############
tar xvzf tmux-${TMUX_VERSION}.tar.gz
cd tmux-${TMUX_VERSION}
./configure CFLAGS="-I$HOME/local/include -I$HOME/local/include/ncurses" LDFLAGS="-L$HOME/local/lib -L$HOME/local/include/ncurses -L$HOME/local/include"
CPPFLAGS="-I$HOME/local/include -I$HOME/local/include/ncurses" LDFLAGS="-static -L$HOME/local/include -L$HOME/local/include/ncurses -L$HOME/local/lib" make
cp tmux $HOME/local/bin
cd ..

# cleanup
rm -rf $HOME/tmux_tmp

echo "$HOME/local/bin/tmux is now available. You can optionally add $HOME/local/bin to your PATH."

配置

然后在 ~/.bashrc 添加 export PATH="$HOME/local/bin/:$PATH"
重新登陆 或者 source ~/.bashrc 即可使用 Tmux

我的 tmux 配置文件 ~/.tmux.conf

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
# 为了能让Tmux动态载入配置而不是重启,设一个快捷键<prefix>r来重新载入配置
bind r source-file ~/.tmux.conf \; display-message "Config reloaded"

# 默认的<prefix>是Ctrl+b,调整为Ctrl+a
#unbind ^b
set -g prefix 'C-a'
set -g prefix2 'C-b'

# 可以把hjkl设置为切换窗格的快捷键
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R

# 调整窗格大小
bind L resize-pane -L 10 # 向左扩展
bind R resize-pane -R 10 # 向右扩展
bind K resize-pane -U 5 # 向上扩展
bind J resize-pane -D 5 # 向下扩展

# 当打开新窗格时Shell仍然在Home目录,可以设置为当前目录
bind '"' split-window -c '#{pane_current_path}'
bind '%' split-window -h -c '#{pane_current_path}'

# 按下<Escape>进入拷贝模式,v进行选择,y拷贝所选内容,p进行粘贴
bind Escape copy-mode
bind -t vi-copy v begin-selection
bind -t vi-copy y copy-selection
unbind p
bind p pasteb
setw -g mode-keys vi # Vi风格选择文本

# 通过点击选择窗格,通过拖动更改窗格大小,通过鼠标选择窗口,还可以通过鼠标选择复制区域
set -g mouse off

# new window shift + 下 新建 window
bind -n S-down new-window
# prev shift + <- 前一个 window
bind -n S-left prev
# next shift + -> 后一个 window
bind -n S-right next
# history limit
set -g history-limit 90000
# bottom color 底部背景(青)
set -g status-bg colour6
# active window title background 底部active window 背景(红)
set-window-option -g window-status-current-bg color53

# 定制右面状态栏
# set -g status-right "#[fg=green]#(uptime |cut -d ',' -f 1)#[default] • #[fg=green]#(cut -d ' ' -f 1-3 /proc/loadavg)#[default]"

# 设置状态栏刷新时间
set -g status-interval 1

常用命令、快捷键

以下命令适用于 bash 环境

输入 功能
tmux show -g 来查看使用的配置(该命令需要tmux正在运行)
tmux start new
tmux new -s myname start new with session name
tmux a # (or at, or attach) attach
tmux a -t myname attach to named
tmux ls list sessions
tmux set status-interval 1 每秒更新状态栏
tmux kill-session -t myname kill session
tmux kill-server 相当于重启?
tmux ls &verbar; grep : &verbar; cut -d. -f1 &verbar; awk ‘{print substr($1, 0, length($1)-1)}’ &verbar; xargs kill Kill all the tmux sessions

备注: MarkDown 表格 中的 | 要用 Html 中的 &verbar; &verbar; &vert; &VerticalLine; &#x0007C; &#124; 任选一个进行替换。有些解释器也可以用 \| 转义.

以下命令适用于在 Tmux 中,按下前缀键之后

前缀键 <prefix> 默认是 Ctrl+B, 习惯 screen 命令的可以改为 Ctrl+A

Sessions

按键 功能
:new new session
s list sessions
$ name session

Windows (tabs)

按键 功能
c create window
w list windows
n next window
p previous window
f find window
, name window
& kill window

Panes (splits)

按键 功能
% vertical split
horizontal split
o swap panes
q show pane numbers
x kill pane
+ break pane into window (e.g. to select text by mouse to copy)
- restore pane from window
space - toggle between layouts
q (Show pane numbers, when the numbers show up type the key to goto that pane)
{ (Move the current pane left)
} (Move the current pane right)
z toggle pane zoom

插件

Tmux Plugin Manager

Github 地址: tpm. 安装很简单,按照README操作即可。

常用插件

  • tmux-sensible:推荐安装,有一些增强功能
  • tmux-resurrect:保存会话,下次开机恢复
  • tmux-prefix-highlight:在右下角显示你是否已经按下
  • tmux-copycat:增强搜索功能

附录

我的 ~/.bashrc 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
export PATH="$HOME/local/bin/:$PATH"

alias rm='rm -i'
alias l='ls -lh'
alias cd..='cd ..'
alias du='du -sh'

alias s='screen'
alias sl='screen -ls'
alias sr='screen -r'

alias t='tmux'
alias ta='tmux at'
alias tl='tmux ls'
alias tnew='tmux new -s'

alias rz='echo "please exit tmux to use rzz"'
alias sz='echo "please exit tmux to use szz"'

~/.vimrc 配置

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
set ts=4
set expandtab
autocmd BufWritePost $MYVIMRC source $MYVIMRC
set nocompatible "去掉讨厌的有关vi一致性模式,避免以前版本的一些bug和局限
""""""""""""""""""""""""""""""""""""""""""""""""""""
" set theme
syntax enable
set background=dark

"colorscheme solarized
"colorscheme molokai
set t_Co=256
colorscheme desert

""""""""""""""""""""""""""""""""""""""""""""""""""""
set cul "高亮光标所在行
autocmd InsertLeave * se cul " 用浅色高亮当前行
autocmd InsertEnter * se nocul " 用浅色高亮当前行
set cuc
autocmd InsertLeave * se cuc " 用浅色高亮当前列
autocmd InsertEnter * se nocuc " 用浅色高亮当前列
" 设置标记一列的背景颜色和数字一行颜色一致
hi! link SignColumn LineNr
hi! link ShowMarksHLl DiffAdd
hi! link ShowMarksHLu DiffChange

""""""""""""""""""""""""""""""""""""""""""""""""""""
" 相对行号: 行号变成相对,可以用 nj/nk 进行跳转
set relativenumber number
au FocusLost * :set norelativenumber number
au FocusGained * :set relativenumber
" 插入模式下用绝对行号, 普通模式下用相对
autocmd InsertEnter * :set norelativenumber number
autocmd InsertLeave * :set relativenumber
function! NumberToggle()
if(&relativenumber == 1)
set norelativenumber number
else
set relativenumber
endif
endfunc
nnoremap <C-n> :call NumberToggle()<cr>

"""""""""""""""""""""""""""""""""""""""""""""""""""""
"显示行数,设置软回车和缩进还有语法
set shiftwidth=4
set softtabstop=4
nnoremap ; :
" 检测文件类型
filetype on
" 针对不同的文件类型采用不同的缩进格式
filetype indent on
" 允许插件
filetype plugin on
" 启动自动补全
filetype plugin indent on
set smartindent
set autoindent
set smarttab
"syntax on

""""""""""""""""""""""""""""""""""""""""""""""""""""
"一旦一行的字符超出80个的话就把那些字符的背景设为红色
highlight OverLength ctermbg=red ctermfg=white guibg=#592929
match OverLength /\%81v.\+/

""""""""""""""""""""""""""""""""""""""""""""""""""""
"<F5>自动运行python
nnoremap <buffer> <F5> :exec '!python' shellescape(@%, 1)<cr>

""""""""""""""""""""""""""""""""""""""""""""""""""""
" 设置 退出vim后,内容显示在终端屏幕, 可以用于查看和复制, 不需要可以去掉
" 好处:误删什么的,如果以前屏幕打开,可以找回
set t_ti= t_te=

""""""""""""""""""""""""""""""""""""""""""""""""""""
" change the terminal's title
set title

""""""""""""""""""""""""""""""""""""""""""""""""""""
" 设置文内智能搜索提示
" 高亮search命中的文本
set hlsearch
" 打开增量搜索模式,随着键入即时搜索
set incsearch
" 搜索时忽略大小写
set ignorecase
" 有一个或以上大写字母时仍大小写敏感
set smartcase

""""""""""""""""""""""""""""""""""""""""""""""""""""
" 显示当前的行号列号
set ruler
" 在状态栏显示正在输入的命令
set showcmd
" 左下角显示当前vim模式
set showmode

" 在上下移动光标时,光标的上方或下方至少会保留显示的行数
set scrolloff=7

" set winwidth=79

" 命令行(在状态行下)的高度,默认为1,这里是2
" set statusline=%<%f%h%m%r%=%k[%{(&fenc==\"\")?&enc:&fenc}%{(&bomb?\",BOM\":\"\")}]%-14.(%l,%c%V%)\ %P
set statusline=%F%m%r%h%w\ [FORMAT=%{&ff}]\ [TYPE=%Y]\ [POS=%l,%v][%p%%]\ %{strftime(\"%y/%m/%d\ -\ %H:%M\")} "状态行显示的内容
" Always show the status line - use 2 lines for the status bar
set laststatus=2

""""""""""""""""""""""""""""""""""""""""""""""""""""
set pastetoggle=<F7> " when in insert mode, press <F7> to go to
" paste mode, where you can paste mass data
" that won't be autoindented

" disbale paste mode when leaving insert mode
au InsertLeave * set nopaste

" F7 set paste问题已解决, 粘贴代码前不需要按F7了
" F7 粘贴模式paste_mode开关,用于有格式的代码粘贴
" Automatically set paste mode in Vim when pasting in insert mode
function! XTermPasteBegin()
set pastetoggle=<Esc>[201~
set paste
return ""
endfunction
inoremap <special> <expr> <Esc>[200~ XTermPasteBegin()

""""""""""""""""""""""""""""""""""""""""""""""""""""
" F1 废弃这个键,防止调出系统帮助
" I can type :help on my own, thanks. Protect your fat fingers from the evils of <F1>
noremap <F1> <Esc>"

" F2 行号开关,用于鼠标复制代码用
" 为方便复制,用<F2>开启/关闭行号显示:
function! HideNumber()
if(&relativenumber == &number)
set relativenumber! number!
elseif(&number)
set number!
else
set relativenumber!
endif
set number?
endfunc
nnoremap <F2> :call HideNumber()<CR>
" F3 显示可打印字符开关
nnoremap <F3> :set list! list?<CR>
" F4 换行开关
nnoremap <F4> :set wrap! wrap?<CR>

" F6 语法开关,关闭语法可以加快大文件的展示
nnoremap <F6> :exec exists('syntax_on') ? 'syn off' : 'syn on'<CR>

""""""""""""""""""""""""""""""""""""""""""""""""""""
" 定义函数AutoSetFileHead,自动插入文件头
autocmd BufNewFile *.sh,*.py exec ":call AutoSetFileHead()"
function! AutoSetFileHead()
"如果文件类型为.sh文件
if &filetype == 'sh'
call setline(1, "\#!/bin/bash")
endif

"如果文件类型为python
if &filetype == 'python'
call setline(1, "\#!/usr/bin/env python")
call append(1, "\# encoding: utf-8")
endif

normal G
normal o
normal o
endfunc

仿制品

下面这俩货是一个人做的,很厉害,试用了,不推荐使用:新东西 bug 很多

pymux

去 github 一搜就有了

pyvim

同上, 是 vim 的 python 版

参考资料