tmux (简体中文)
tmux 是一个终端复用器: 可以激活多个终端或窗口, 在每个终端都可以单独访问,每一个终端都可以访问,运行和控制各自的程序.tmux类似于screen,可以关闭窗口将程序放在后台运行,需要的时候再重新连接。
Tmux 与基于 ISC 协议发布的 GNU Screen 类似,这个tmux FAQ 页面包含两者的区别。
安装
从官方源安装软件包tmux。可选安装tmux-bash-completion-gitAUR为tmux提供了bash补全功能。
配置
用户私人配置文件在~/.tmux.conf
, 全局配置文件在 /etc/tmux.conf
。
快捷键前缀
按键 | 动作 |
---|---|
c | 创建一个新窗口 |
n | 切换至下一窗口 |
p | 切换到上一个窗口 |
" | 水平分割窗口 |
% | 垂直分割窗口 |
, | 重新命名当前窗口 |
o | 移动至下一个面板 |
默认绑定的前缀按键为Ctrl-b. 比如说垂直分割窗口的快捷键就是 Ctrl-b %
。
使用多个面板分割窗口后, 先按前缀快捷键(比如说:Ctrl-b
)然后按住Ctrl键就可以使用方向键调整面板大小。 如果要交换面板也是采用同样的方式,只是按键由方向键换成“O“键。
快捷键前缀可以用tmux.conf
中的bind和unbind命令修改。比如你可以在配置文件中增加下面命令,把前缀Ctrl-b
改成Ctrl-a
:
unbind C-b set -g prefix C-a bind C-a send-prefix
Alt
键(Meta键)代替Ctrl
键。例如:set -g prefix m-'\'
。
其他几种在窗口间移动的快捷键:
Ctrl-b l (回到上一个选定的窗口) Ctrl-b w (显示所有的窗口和窗口序号) Ctrl-b <window number> (移动到指定序号的窗口, 默认序号是 0 – 9) Ctrl-b q (显示当前面板号时, 输入指定的面板号可跳转.)
如果你打开10个以上的面板怎么办? tmux有寻找窗口的选项和快捷键.
Ctrl-b f <window name> (寻找指定名字的窗口) Ctrl-b w (从交互式列表中选择窗口)
复制模式
一个tmux窗口可能处于几个模式中的一个。默认模式允许直接访问连接到窗口的终端;另一种是复制模式。一旦在复制模式下,你可以在缓冲区包括滚动历史。vi或emacs风格的按键方式绑定在复制模式中,默认是emacs,除非编辑器包含"vi"。
使用下列快捷键可以进入滚动模式:
Ctrl-b [
可以在默认编辑器的缓冲区中进行浏览。 离开复制模式,使用下面的按键: vi模式
q
emacs模式
Esc
打开URL
你需要安装 urlviewAUR来打开URL 另外需要配置如下:
打开一个新的终端:
bind-key u capture-pane \; save-buffer /tmp/tmux-buffer \; run-shell "$TERMINAL -e urlview /tmp/tmux-buffer"
或者直接在tmux的一个新窗口 (不需要新终端):
bind-key u capture-pane \; save-buffer /tmp/tmux-buffer \; new-window -n "urlview" '$SHELL -c "urlview < /tmp/tmux-buffer"'
正确设置 term
如果使用的是 256 色的终端,必须在 tmux 的配置文件 tmux.conf
中将终端设置为 tmux
或 tmux-256color
:
set -g default-terminal "tmux-256color"
或在 .bashrc
中添加:
# for tmux: export 256color [ -n "$TMUX" ] && export TERM=screen-256color
如果你在 tmux.conf
启用xterm-keys, 那你需要构建一个新的终端信息来声明新的退出命令,否则程序无法获取退出方式。用 tic
编译下列信息,你可以使用 "xterm-screen-256color" 来作为你的TERM:
# A screen- based TERMINFO that declares the escape sequences # enabled by the tmux config "set-window-option -g xterm-keys". # # Prefix the name with xterm- since some applications inspect # the TERM *name* in addition to the terminal capabilities advertised. xterm-screen-256color|GNU Screen with 256 colors bce and tmux xterm-keys, # As of Nov'11, the below keys are picked up by # .../tmux/blob/master/trunk/xterm-keys.c: kDC=\E[3;2~, kEND=\E[1;2F, kHOM=\E[1;2H, kIC=\E[2;2~, kLFT=\E[1;2D, kNXT=\E[6;2~, kPRV=\E[5;2~, kRIT=\E[1;2C, # Change this to screen-256color if the terminal you run tmux in # does not support bce: use=screen-256color-bce,
其他设置
设置最多回滚的行数
set -g history-limit 10000
用systemd后台自启tmux
开机自启tmux有诸多好处,当tmux服务在后台运行时,启动一个tmux会话能减少许多延时。
此外,即使你没有登录,对tmux会话的任何定制都将保留,tmux会话也将会被持久化。这对于那些有重度tmux配置(启动慢)或者共享tmux会话的人来说特别有用。
下面这个systemd service配置可作为参考 (启动 tmux@username.service
):
/etc/systemd/system/tmux@.service
[Unit] Description=Start tmux in detached session [Service] Type=forking User=%I ExecStart=/usr/bin/tmux new-session -s %u -d ExecStop=/usr/bin/tmux kill-session -t %u [Install] WantedBy=multi-user.target
WorkingDirectory=custom_path
设置工作路径.把这个文件放在 systemd/User 目录下,如 ~/.config/systemd/user/tmux.service
. 这样tmux service 就会在你登录时自动启动.
会话初始化
可以通过修改配置文件~/.tmux.conf
来使得tmux在初始化一个session的时候自动新建窗口, 比如:
new -n WindowName Command neww -n WindowName Command neww -n WindowName Command
如果想在tmux启动session的时候自动分割窗口, 只需要把相应分割命令加在你想分割的窗口的neww命令之下, 如下:
new -s SessionName -n WindowName Command neww -n foo/bar foo # 在这之下添加分割窗口命令 splitw -v -p 50 -t 0 bar selectw -t 1 selectp -t 0
这将启动两个窗口, 第二个窗口会被命名为foo/bar并且会被垂直对半分割, 其中窗格foo会在窗格bar的上面,光标会在第二个窗口(foo/bar)上面的窗格(foo)
{{注意|除非你在你得配置文件.conf
中特别指定, 否则会话(session), window(窗口),panes(窗格)的序号都是从0开始算起.}
想要管理多个会话, 需要在你的配置文件中用source命令分别执行相应会话的配置文件
# initialize sessions bind F source-file ~/.tmux/foo bind B source-file ~/.tmux/bar
提示和小技巧
启动时使用默认布局
Session managers like tmuxinator and tmuxp make it easy to manage common session configurations.
For tmuxinator, install tmuxinatorAUR from AUR. Test your installation with
tmuxinator doctor
获取默认布局参数
Start tmux as usual and configure your windows and panes layout as you like. When finished, get the current layout values by executing (while you are still within the current tmux session)
tmux list-windows
The output may look like this (two windows with 3 panes and 2 panes layout)
0: default* (3 panes) [274x83] [layout 20a0,274x83,0,0{137x83,0,0,3,136x83,138,0[136x41,138,0,5,136x41,138,42,6]}] @2 (active) 1: remote- (2 panes) [274x83] [layout e3d3,274x83,0,0[274x41,0,0,4,274x41,0,42,7]] @3
The Interesting part you need to copy for later use begins after [layout... and excludes ... ] @2 (active). For the first window layout you need to copy e.g. 20a0,274x83,0,0{137x83,0,0,3,136x83,138,0[136x41,138,0,5,136x41,138,42,6]}
定义默认布局
Knowing this, you can exit the current tmux session. Following this, you create your default tmux session layout by editing tmuxinator's config file (Do not copy the example, get your layout values as described above)
~/.tmuxinator/default.yml
name: default root: ~/ windows: - default: layout: 20a0,274x83,0,0{137x83,0,0,3,136x83,138,0[136x41,138,0,5,136x41,138,42,6]} panes: - clear - vim - clear && emacs -nw - remote: layout: 24ab,274x83,0,0{137x83,0,0,3,136x83,138,0,4} panes: - -
The example defines two windows named "default" and "remote". With your determined layout values. For each pane you have to use at least one -
line. Within the first window panes you start the commandline "clear" in pane one, "vim" in pane two and "clear && emacs -nw" executes two commands in pane three on each tmux start. The second window layout has two panes without defining any start commmands.
Test the new default layout with (yes, it is "mux"):
mux default
自动使用默认布局启动tmux
如果想在启动终端的时候直接进入tmux, 并且使用默认布局, 可以设置
~/.bashrc
if [ -z "$TMUX" ]; then mux default fi
默认会话的替代实现方式
Instead of using the above method, one can just write a bash script that when run, will create the default session and attach to it. Then you can execute it from a terminal to get the pre-designed configuration in that terminal
#!/bin/bash tmux new-session -d -n WindowName Command tmux new-window -n NewWindowName tmux split-window -v tmux selectp -t 1 tmux split-window -h tmux selectw -t 1 tmux -2 attach-session -d
Start tmux in urxvt
Use this command to start urxvt with a started tmux session. I use this with the exec command from my .ratpoisonrc file.
urxvt -e bash -c "tmux -q has-session && exec tmux attach-session -d || exec tmux new-session -n$USER -s$USER@$HOSTNAME"
启动shell时自动启动tmux
Bash
对bash用户, 只需要将下面命令添加到自己家目录下的.bashrc, 要注意这句命令需要在alias配置之前.对其它shell的配置也是类似的
~/.bashrc
# If not running interactively, do not do anything [[ $- != *i* ]] && return [[ -z "$TMUX" ]] && exec tmux
下面的配置会尝试只启动一个会话, 当你登录时, 如果之前启动过会话, 那么它会直接attach, 而不是新开一个. 想要新开一个session要么是因为之前没有会话, 要么是你手动启动一个新的会话.
# TMUX if which tmux >/dev/null 2>&1; then #if not inside a tmux session, and if no session is started, start a new session test -z "$TMUX" && (tmux attach || tmux new-session) fi
下面的配置实现的功能相似, 但是他会在启动tmux之前先检查一下tmux是否已经安装. 它也会在你登出之前帮你重新连接上未关闭的session, 这样可以让你手动关闭会话并保存相应的工作,避免数据丢失,进程异常中断.
# TMUX if which tmux >/dev/null 2>&1; then # if no session is started, start a new session test -z ${TMUX} && tmux # when quitting tmux, try to attach while test -z ${TMUX}; do tmux attach || break done fi
另外一种配置, 一样可以实现自动连接已存在的会话,否则会新开一个:
if [[ -z "$TMUX" ]] ;then ID="`tmux ls | grep -vm1 attached | cut -d: -f1`" # get the id of a deattached session if [[ -z "$ID" ]] ;then # if not available create a new one tmux new-session else tmux attach-session -t "$ID" # if available attach to it fi fi
启动non-login shell
Tmux starts a login shell by default, which may result in multiple negative side effects:
- Users of fortune may notice that quotes are printed when creating a new panel.
- The configuration files for login shells such as
~/.profile
are interpreted each time a new panel is created, so commands intended to be run on session initialization (e.g. setting audio level) are executed.
To disable this behaviour, add to ~/.tmux.conf
:
set -g default-command "${SHELL}"
像标签一样使用窗口
The following settings added to ~/.tmux.conf
allow to use tmux windows like tabs, such as those provided by the reference of these hotkeys — urxvt's tabbing extensions. An advantage thereof is that these virtual “tabs” are independent of the terminal emulator.
#urxvt tab like window switching (-n: no prior escape seq) bind -n S-down new-window bind -n S-left prev bind -n S-right next bind -n C-left swap-window -t -1 bind -n C-right swap-window -t +1
Of course, those should not overlap with other applications' hotkeys, such as the terminal's. Given that they substitute terminal tabbing that might as well be deactivated, though.
It can also come handy to supplement the EOT hotkey Ctrl+d
with one for tmux's detach:
bind-key -n C-j detach
Clients simultaneously interacting with various windows of a session
In Practical Tmux[失效链接 2021-05-17 ⓘ], Brandur Leach writes:
- Screen and tmux's behaviour for when multiple clients are attached to one session differs slightly. In Screen, each client can be connected to the session but view different windows within it, but in tmux, all clients connected to one session must view the same window.
- This problem can be solved in tmux by spawning two separate sessions and synchronizing the second one to the windows of the first, then pointing a second new session to the first.
The script “tmx
” below implements this — the version here is slightly modified to execute “tmux new-window
” if “1” is its second parameter. Invoked as tmx <base session name> [1]
it launches the base session if necessary. Otherwise a new “client” session linked to the base, optionally add a new window and attach, setting it to kill itself once it turns “zombie”.
tmx
#!/bin/bash # # Modified TMUX start script from: # http://forums.gentoo.org/viewtopic-t-836006-start-0.html # # Store it to `~/bin/tmx` and issue `chmod +x`. # # Works because bash automatically trims by assigning to variables and by # passing arguments trim() { echo $1; } if [[ -z "$1" ]]; then echo "Specify session name as the first argument" exit fi # Only because I often issue `ls` to this script by accident if [[ "$1" == "ls" ]]; then tmux ls exit fi base_session="$1" # This actually works without the trim() on all systems except OSX tmux_nb=$(trim `tmux ls | grep "^$base_session" | wc -l`) if [[ "$tmux_nb" == "0" ]]; then echo "Launching tmux base session $base_session ..." tmux new-session -s $base_session else # Make sure we are not already in a tmux session if [[ -z "$TMUX" ]]; then echo "Launching copy of base session $base_session ..." # Session id is date and time to prevent conflict session_id=`date +%Y%m%d%H%M%S` # Create a new session (without attaching it) and link to base session # to share windows tmux new-session -d -t $base_session -s $session_id if [[ "$2" == "1" ]]; then # Create a new window in that session tmux new-window fi # Attach to the new session & kill it once orphaned tmux attach-session -t $session_id \; set-option destroy-unattached fi fi
A useful setting for this is
setw -g aggressive-resize on
added to ~/.tmux.conf
. It causes tmux to resize a window based on the smallest client actually viewing it, not on the smallest one attached to the entire session.
An alternative taken from [1][失效链接 2021-11-08 ⓘ] is to put the following ~/.bashrc:
.bashrc
function rsc() { CLIENTID=$1.`date +%S` tmux new-session -d -t $1 -s $CLIENTID \; set-option destroy-unattached \; attach-session -t $CLIENTID } function mksc() { tmux new-session -d -s $1 rsc $1 }
Citing the author:
- "mksc foo" creates a always detached permanent client named "foo". It also calls "rsc foo" to create a client to newly created session. "rsc foo" creates a new client grouped by "foo" name. It has destroy-unattached turned on so when I leave it, it kills client.
- Therefore, when my computer looses network connectivity, all "foo.something" clients are killed while "foo" remains. I can then call "rsc foo" to continue work from where I stopped.
根据终端类型自动更正TERM环境变量
Instead of setting a fixed TERM variable in tmux, it is possible to set the proper TERM (either screen
or screen-256color
) according to the type of your terminal emulator:
~/.tmux.conf
## set the default TERM set -g default-terminal screen ## update the TERM variable of terminal emulator when creating a new session or attaching a existing session set -g update-environment 'DISPLAY SSH_ASKPASS SSH_AGENT_PID SSH_CONNECTION WINDOWID XAUTHORITY TERM' ## determine if we should enable 256-colour support if "[[ ${TERM} =~ 256color || ${TERM} == fbterm ]]" 'set -g default-terminal screen-256color'
~/.zshrc
## workaround for handling TERM variable in multiple tmux sessions properly from http://sourceforge.net/p/tmux/mailman/message/32751663/[失效链接 2020-08-06 ⓘ] by Nicholas Marriott if [[ -n ${TMUX} && -n ${commands[tmux]} ]];then case $(tmux showenv TERM 2>/dev/null) in *256color) ;& TERM=fbterm) TERM=screen-256color ;; *) TERM=screen esac fi
不用重启tmux就能加载新的配置
如果对tmux的配置文件~/.tmux.conf
做了修改, 默认情况下tmux是不会自动重新加载的, 除非关闭所有正在运行的tmux会话. 如果不想关闭会话而手动加载tmux的配置文件, 可以在命令行下输入:
tmux source-file <path>
也可以在配置文件 ~/.tmux.conf
中加入下面配置(这样下次输入 ctrl+b r就可以加载新的配置文件了):
bind r source-file <path>
还有一种做法是输入前缀+冒号(ctrl+b :),然后输入如下命令:
source .tmux.conf
样例代码:attach已启动的会话而不是新开一个
This script checks for a program presumed to have been started by a previous run of itself. Unless found it creates a new tmux session and attaches to a window named after and running the program. If however the program was found it merely attaches to the session and selects the window.
#!/bin/bash PID=$(pidof $1) if [ -z "$PID" ]; then tmux new-session -d -s main ; tmux new-window -t main -n $1 "$*" ; fi tmux attach-session -d -t main ; tmux select-window -t $1 ; exit 0
A derived version to run irssi with the nicklist plugin can be found on its ArchWiki page.
标题栏自动更改
If you SSH into a host in a tmux window, you will notice the window title of your terminal emulator remains to be user@localhost
rather than user@server
. To allow the title bar to adapt to whatever host you connect to, set the following in ~/.tmux.conf
set -g set-titles on set -g set-titles-string "#T"
For set-titles-string
, #T
will display user@host:~
and change accordingly as you connect to different hosts.
自动布局
When creating new splits or destroying older ones the currently selected layout is not applied. To fix that, add following binds which will apply the currently selected layout to new or remaining panes:
bind-key -n M-c kill-pane \; select-layout bind-key -n M-n split-window \; select-layout
使用类似Vim的快捷键设置
See [2] for a configuration friendly to vim users.
With tmux 2.4 change:
bind -t vi-copy 'v' begin-selection bind -t vi-copy 'y' copy-selection bind -t vi-copy 'Space' halfpage-down bind -t vi-copy 'Bspace' halfpage-up
to:
bind-key -T copy-mode-vi 'v' send -X begin-selection bind-key -T copy-mode-vi 'y' send -X copy-selection bind-key -T copy-mode-vi 'Space' send -X halfpage-down bind-key -T copy-mode-vi 'Bspace' send -X halfpage-up
常见问题与解答
滚动问题
如果你在终端中使用Shift-PageUp/Shift-PageDown 翻页有问题,把下面加到配置文件中试试:
set -g terminal-overrides 'xterm*:smcup@:rmcup@'
Shift+F6 not working in Midnight Commander
If the Shift+F6
key combination is not working with either TERM=screen
or TERM=screen-256color
, then from inside tmux, run this command:
infocmp > screen (or screen-256color)
Open the file in a text editor, and add the following to the bottom of that file:
kf16=\E[29~,
Then compile the file with tic
. The keys should be working now.
ICCCM Selection Integration
It is possible to copy a tmux paste buffer to an ICCCM selection, and vice-versa, by defining a shell command which interfaces tmux with an X11 selection interface. The following tmux config file snippet effectively integrates CLIPBOARD
with the current tmux paste buffer using xclip:
~/.tmux.conf
... ##CLIPBOARD selection integration ##Requires prefix key before the command key #Copy tmux paste buffer to CLIPBOARD bind C-c run "tmux save-buffer - | xclip -i -selection clipboard" #Copy CLIPBOARD to tmux paste buffer and paste tmux paste buffer bind C-v run "tmux set-buffer -- \"$(xclip -o -selection clipboard)\"; tmux paste-buffer"
As alternative you can use xsel
:
~/.tmux.conf
... ##CLIPBOARD selection integration ##Requires prefix key before the command key #Copy tmux paste buffer to CLIPBOARD bind C-c run "tmux show-buffer | xsel -i -b" #Copy CLIPBOARD to tmux paste buffer and paste tmux paste buffer bind C-v run "tmux set-buffer -- \"$(xsel -o -b)\"; tmux paste-buffer"
It seems xclip
does not close STDOUT
after it has read from tmux
's buffer. As such, tmux
does not know that the copy task has completed, and continues to /await xclip
's termination, thereby rendering the window manager unresponsive. To work around this, you can execute the command via run-shell -b
instead of run
, you can redirect STDOUT
of xclip
to /dev/null
, or you can use an alternative command like xsel
.
Urxvt MiddleClick Solution
There is an unofficial perl extension (mentioned in the official FAQ[失效链接 2020-08-06 ⓘ]) to enable copying/pasting in and out of urxvt with tmux via Middle Mouse Clicking.
First, you will need to download the perl script and place it into urxvts perl lib:
wget http://anti.teamidiot.de/static/nei/*/Code/urxvt/osc-xterm-clipboard mv osc-xterm-clipboard /usr/lib/urxvt/perl/
You will also need to enable that perl script in your .Xdefaults:
~/.Xdefaults
... *URxvt.perl-ext-common: osc-xterm-clipboard ...
Next, you want to tell tmux about the new function and enable mouse support (if you have not already). The third option is optional, to enable scrolling and selecting inside panes with your mouse:
~/.tmux.conf
... set-option -ga terminal-override ',rxvt-uni*:XT:Ms=\E]52;%p1%s;%p2%s\007' set-window-option -g mode-mouse on set-option -g mouse-select-pane on ...
That's it. Be sure to end all instances of tmux before trying the new MiddleClick functionality.
While in tmux, Shift+MiddleMouseClick will paste the clipboard selection while just MiddleMouseClick will paste your tmux buffer. Outside of tmux, just use MiddleMouseClick to paste your tmux buffer and your standard Ctrl-c to copy.
外部链接
- Practical Tmux[失效链接 2021-05-17 ⓘ] by Brandur Leach, providing a number of configuration tips
- Tmux tutorial section from the OpenBSD FAQ
- OpenBSD Reference Manual for tmux
- Screen and tmux feature comparison page by Dayid Alan
- Tmux tutorial Part 1 & Part 2 blog posts on Hawk Host
- tmux.conf[失效链接 2020-08-06 ⓘ] example with CPU bar and shortcut to search man pages and display them vertically
- powerline provides a powerful, dynamic statusbar configuration for tmux
Forum threads
- 2009-11-06 - Arch Linux - Anyone loving Tmux in place of Screen? Info/Tips etc. URLs I have found