原文请猛戳:http://galoisplusplus.gitcafe.com/blog/2014/02/23/take-tmux-snapshots-automatically/
前段时间学校的EECS楼发生火灾,最近隔三差五停电检修,打断我在server上跑的实验。 而且我习惯上用tmux开多个session和window,一遇到停电我的tmux现场就悲剧了。 复电重开机之后要把tmux现场手动重新建好也很麻烦,于是我就挤出一点时间琢磨着写个简单的script去自动保存和重载tmux的副本。
首先我对tmux现场的定义其实还蛮简单的——我希望能记录tmux的session和window的名称、每个pane当前在什么路径以及在跑什么程序。 这些在tmux的man page中都有相应的内建变量(Variable)可以提供,这里谨列举如下:
session_name | Name of session |
window_name | Name of windown |
pane_current_path | Current path if available |
pane_current_command | Current command if available |
有了这么给力的内建变量,我们很快就可以写出保存tmux现场的命令了:
1
|
|
简单解释一下,tmux的list-windows
命令顾名思义就是列举窗口,其后可以接以下参数:
1
|
|
[-a]自然是指所有窗口;[-F]指定输出格式,我上面那条命令是依次列出session名、window名、pane当前执行程序和pane当前路径,并以空格隔开;[-t]指定输出在哪个session,默认是当前的session,这里我没有用,反正输出结果最后是要被重定向到文件的。
那么有了tmux现场的snapshot之后,我们应该如何恢复现场呢?
首先当然是解析snapshot中的信息,得到\${session_name}、\${window_name}、\${pane_current_command}、\${pane_current_path}的信息。
接下来是把各个session和window恢复好。
tmux稍显繁琐的地方是:用new-window
创建新的window时必须指定现有的session,假如session不存在,该命令不会创建session,而会报错结束。 所以,当我们恢复每次恢复一个window时,需要先知道它所在的session是否存在:如果存在,则用new-window
直接在该session上创建window;如果不存在,则需要用new-session
来创建session,session创建后会有一个默认的窗口,我们就把所要恢复的窗口的环境设定到默认窗口上。
判断session是否存在可以用tmux的has-session
命令:
1 2 3 4 |
|
如果session存在,上述命令的退出码为0,否则则为1。这在bash中只需执行:
1
|
|
之后判断$?
即可。
假如session不存在,则我用以下命令创建新session,并设默认窗口名为当前所要恢复的窗口的名称:
1
|
|
假如session已存在,则我用以下命令在该session上恢复原来的窗口:
1
|
|
下面我们要让每个pane都回到原来的路径,我的想法是直接把一个cd
的shell命令送到当前的pane,并执行这条命令。 在tmux中的解决方案稍微有点小技巧,关键是用send-keys
命令把该shell命令和一个ENTER送到该窗口,这种方式就像直接在窗口输入上述shell命令再按回车键执行。 以下是跳转回原来路径的tmux完整命令:
1
|
|
恢复每个pane原来在执行的命令也可以用上述同样的方法。 可惜的是,tmux尽管提供了\${pane_current_command}的内建变量,但这个变量却无法提供精确的信息。例如执行的命令是类似exe arg1 arg2
带参数的形式,\${pane_current_command}只会给出exe
而无法检测到任何参数。因此,当我们重载tmux现场时直接执行\${pane_current_command}可能会带来问题。我采取的方案很简单,在每个终端窗口用\${pane_current_command}给一个提示,让使用者自行判断恢复后应该执行什么命令。 给出提示的tmux命令可以和之前恢复原路径的命令合并在一起:
1
|
|
最后,我想把这个script加到crontab中,所以我需要让它自动判断当前应该做snapshots还是从snapshots恢复tmux现场。 我采用的方式也比较简单,通过ps
看看当前有没有tmux
进程:没有的话说明需要恢复,此时先执行tmux start-server
;有的话则进行snapshots的保存。
完整的脚本如下(或者参考我的gist):
(tmuxEnvSaver.sh) download 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 |
|
我设了如下的crontab:
1 2 3 |
|
这样就可以自动保存和重载简单的tmux现场了。
当然,tmux还有很多内建变量,因此这个简单的脚本还可以继续改进,让snapshots的信息更丰富,偶还是等下次有空再折腾吧XD
后续
我搜到一些相关的文章,有用perl来写类似脚本的,可供大家参考: