Cross Fox Red

Tmux as a ClusterSSH alternative

Date: 2024-Jun-28

A neat feature of tmux is that is supports multi-pane synchronized input via the set-option synchronize-panes 1 command. This allows you to enter input across all panes simultaneously.

While there are other tmux cluster bash scripts, they focus on trying to replicate ClusterSSH closely instead of being a generic 'open tmux with this many panes and this command.' script. Sometimes you want to sync other things than just ssh. One useful task I used the x11 based ClusterSSH for was opening several ssh to localhost windows and opening a seperate JSON log file in each. This was very handy for debugging having scroll synced across each file. Tmux makes this easier and now with the script below it's as simple as calling it with the commands you want for each pane. Plus it no longer needs an x11 terminal. So using it on a wayland only setup or even over ssh works well too.

Below is a small bash script and some examples showing how you can use synchronized input on tmux, including commands to disable input on certain panes, plus running nested tmux.

Key features of script:

Some useful tmux commands, Prefix: followed by command:

Script saved as: tcs.sh - Tmux Clustered Session. (Can also add script to $PATH)

Usage and examples:

Images:

Code:

#!/bin/bash

# SPDX-License-Identifier: MPL-2.0 OR Unlicense
# Version: 0.1.0

# Halt on errors.
set -o errexit   # Abort on nonzero exitstatus.
set -o nounset   # Abort on unbound variable.
set -o pipefail  # Don't hide errors within pipes.

# Name of tmux session from env var or default: (tcs_<processID>)
session="${TCS_SESSION_NAME:=tcs_$$}"

# Create new tmux session (detached) with custom name.
tmux new-session -d -s "${session}"

# Change default prefix from Ctrl-b to Alt-b (For nested tmux).
tmux set-option -t "${session}" prefix M-b

# Select the first window and pane just to be sure.
tmux select-pane -t "${session}":0.0

# To skip first split as tmux has a pane open by default.
declare -i i=0
# Split window and type cmd.
for cmd in "${@}"; do
    if [[ "${i}" -ne 0 ]]; then
        # Split window to create a pane for -1 each cmdline args.
        # Change the layout to be tiled after each split.
        # If the pane is too small tmux will fail to split.
        tmux split-window -t "${session}"
        tmux select-layout -t "${session}" tiled
    fi

    # Type cmd into each pane.
    tmux send-keys -t "${session}":0."${i}" "${cmd}"
    # Increment & ignore status code.
    (( i++ )) || true
done

# Select first window and pane to start.
tmux select-pane -t "${session}":0.0

# Set panes to start synchronized.
tmux set-option -t "${session}" synchronize-panes 1

# Attach to the newly created session.
tmux attach -t "${session}"