1*eda6f593SDavid van Moolenbroek#!/bin/bash 2*eda6f593SDavid van Moolenbroek# 3*eda6f593SDavid van Moolenbroek# By Victor Orlikowski. Public domain. 4*eda6f593SDavid van Moolenbroek# 5*eda6f593SDavid van Moolenbroek# This script maintains snapshots of each pane's 6*eda6f593SDavid van Moolenbroek# history buffer, for each tmux session you are running. 7*eda6f593SDavid van Moolenbroek# 8*eda6f593SDavid van Moolenbroek# It is intended to be run by cron, on whatever interval works 9*eda6f593SDavid van Moolenbroek# for you. 10*eda6f593SDavid van Moolenbroek 11*eda6f593SDavid van Moolenbroek# Maximum number of snapshots to keep. 12*eda6f593SDavid van Moolenbroekmax_backups=12 13*eda6f593SDavid van Moolenbroek# Names of sessions you may wish to exclude from snapshotting, 14*eda6f593SDavid van Moolenbroek# space separated. 15*eda6f593SDavid van Moolenbroekignore_sessions="" 16*eda6f593SDavid van Moolenbroek# The directory into which you want your snapshots placed. 17*eda6f593SDavid van Moolenbroek# The default is probably "good enough." 18*eda6f593SDavid van Moolenbroekbackup_dir=~/.tmux_backup/snapshot 19*eda6f593SDavid van Moolenbroek 20*eda6f593SDavid van Moolenbroek######################################################################## 21*eda6f593SDavid van Moolenbroek 22*eda6f593SDavid van Moolenbroek# Rotate previous backups. 23*eda6f593SDavid van Moolenbroeki=${max_backups} 24*eda6f593SDavid van Moolenbroekwhile [[ ${i} != 0 ]] ; do 25*eda6f593SDavid van Moolenbroekif [ -d ${backup_dir}.${i} ] ; then 26*eda6f593SDavid van Moolenbroek if [[ ${i} = ${max_backups} ]] ; then 27*eda6f593SDavid van Moolenbroek rm -r ${backup_dir}.${i} 28*eda6f593SDavid van Moolenbroek else 29*eda6f593SDavid van Moolenbroek mv ${backup_dir}.${i} ${backup_dir}.$((${i}+1)) 30*eda6f593SDavid van Moolenbroek fi 31*eda6f593SDavid van Moolenbroekfi 32*eda6f593SDavid van Moolenbroeki=$((${i}-1)) 33*eda6f593SDavid van Moolenbroekdone 34*eda6f593SDavid van Moolenbroek 35*eda6f593SDavid van Moolenbroekif [ -d ${backup_dir} ] ; then 36*eda6f593SDavid van Moolenbroek mv ${backup_dir} ${backup_dir}.1 37*eda6f593SDavid van Moolenbroekfi 38*eda6f593SDavid van Moolenbroek 39*eda6f593SDavid van Moolenbroek## Dump hardcopy from all windows in all available tmux sessions. 40*eda6f593SDavid van Moolenbroekunset TMUX 41*eda6f593SDavid van Moolenbroekfor session in $(tmux list-sessions | cut -d' ' -f1 | sed -e 's/:$//') ; do 42*eda6f593SDavid van Moolenbroek for ignore_session in ${ignore_sessions} ; do 43*eda6f593SDavid van Moolenbroek if [ ${session} = ${ignore_session} ] ; then 44*eda6f593SDavid van Moolenbroek continue 2 45*eda6f593SDavid van Moolenbroek fi 46*eda6f593SDavid van Moolenbroek done 47*eda6f593SDavid van Moolenbroek 48*eda6f593SDavid van Moolenbroek # Session name can contain the colon character (":"). 49*eda6f593SDavid van Moolenbroek # This can screw up addressing of windows within tmux, since 50*eda6f593SDavid van Moolenbroek # target windows are specified as target-session:target-window. 51*eda6f593SDavid van Moolenbroek # 52*eda6f593SDavid van Moolenbroek # We use uuidgen to create a "safe" temporary session name, 53*eda6f593SDavid van Moolenbroek # which we then use to create a "detached" session that "links" 54*eda6f593SDavid van Moolenbroek # to the "real" session that we want to back up. 55*eda6f593SDavid van Moolenbroek tmpsession=$(uuidgen) 56*eda6f593SDavid van Moolenbroek tmux new-session -d -s "$tmpsession" -t "$session" 57*eda6f593SDavid van Moolenbroek HISTSIZE=$(tmux show-options -g -t "$tmpsession" | grep "history-limit" | awk '{print $2}') 58*eda6f593SDavid van Moolenbroek for win in $(tmux list-windows -t "$tmpsession" | grep -v "^\s" | cut -d' ' -f1 | sed -e 's/:$//'); do 59*eda6f593SDavid van Moolenbroek session_dir=$(echo "$session" | sed -e 's/ /_/g' | sed -e 's%/%|%g') 60*eda6f593SDavid van Moolenbroek win_spec="$tmpsession":"$win" 61*eda6f593SDavid van Moolenbroek 62*eda6f593SDavid van Moolenbroek if [ ! -d ${backup_dir}/${session_dir}/${win} ] ; then 63*eda6f593SDavid van Moolenbroek mkdir -p ${backup_dir}/${session_dir}/${win} 64*eda6f593SDavid van Moolenbroek fi 65*eda6f593SDavid van Moolenbroek 66*eda6f593SDavid van Moolenbroek for pane in $(tmux list-panes -t "$win_spec" | cut -d' ' -f1 | sed -e 's/:$//'); do 67*eda6f593SDavid van Moolenbroek pane_path=${backup_dir}/${session_dir}/${win}/${pane} 68*eda6f593SDavid van Moolenbroek pane_spec="$win_spec"."$pane" 69*eda6f593SDavid van Moolenbroek 70*eda6f593SDavid van Moolenbroek tmux capture-pane -t "$pane_spec" -S -${HISTSIZE} 71*eda6f593SDavid van Moolenbroek tmux save-buffer ${pane_path} 72*eda6f593SDavid van Moolenbroek 73*eda6f593SDavid van Moolenbroek if [ ! -s ${pane_path} ] ; then 74*eda6f593SDavid van Moolenbroek sleep 1 75*eda6f593SDavid van Moolenbroek rm ${pane_path} 76*eda6f593SDavid van Moolenbroek fi 77*eda6f593SDavid van Moolenbroek done 78*eda6f593SDavid van Moolenbroek done 79*eda6f593SDavid van Moolenbroek tmux kill-session -t "$tmpsession" 80*eda6f593SDavid van Moolenbroek 81*eda6f593SDavid van Moolenbroekdone 82