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