A Semi-Automated Script for tmux
Introduction
Yesterday, I came across a post where someone was running tests, and their SSH session disconnected midway through. Using tmux can prevent this by allowing your processes to continue running even if the SSH connection drops. Of course, you could also use screen, as they are quite similar. This script is intended for beginners, or for those who can’t remember the parameters or simply prefer not to type out the full commands. Experts can feel free to move along.
Script
#!/usr/bin/env bash
set -Eeuo pipefail
has_cmd() { command -v "$1" >/dev/null 2>&1; }
detect_pm() {
if has_cmd apt-get; then echo apt; return; fi
if has_cmd dnf; then echo dnf; return; fi
if has_cmd yum; then echo yum; return; fi
if has_cmd pacman; then echo pacman; return; fi
if has_cmd zypper; then echo zypper; return; fi
if has_cmd apk; then echo apk; return; fi
if has_cmd brew; then echo brew; return; fi
echo none
}
install_tmux() {
local pm="$1" sudo_cmd=""
if [[ ${EUID:-$(id -u)} -ne 0 ]] && [[ "$pm" != "brew" ]]; then sudo_cmd="sudo"; fi
case "$pm" in
apt) $sudo_cmd apt-get update -y && $sudo_cmd apt-get install -y tmux ;;
dnf) $sudo_cmd dnf install -y tmux ;;
yum) $sudo_cmd yum install -y tmux ;;
pacman) $sudo_cmd pacman -Sy --noconfirm tmux ;;
zypper) $sudo_cmd zypper --non-interactive install tmux ;;
apk) $sudo_cmd apk add --no-cache tmux ;;
brew) brew install tmux ;;
*) echo "Could not auto-install tmux: No supported package manager (apt/dnf/yum/pacman/zypper/apk/brew) detected." >&2; exit 1 ;;
esac
}
ensure_tmux() {
if ! has_cmd tmux; then
echo "tmux not detected, attempting to install automatically..."
local pm; pm="$(detect_pm)"
install_tmux "$pm"
fi
}
create_and_run() {
local session="$1" cmd="$2"
if tmux has-session -t "$session" 2>/dev/null; then
echo "Session '$session' already exists. Please choose a different session name." >&2
exit 2
fi
tmux new-session -d -s "$session"
local line
line="$cmd; EXIT_CODE=\$?; tmux kill-session -t \"$session\"; exit \$EXIT_CODE"
tmux send-keys -t "$session" -l "$line"
tmux send-keys -t "$session" C-m
cat <<EOF
Command started in tmux session '$session':
$cmd
To view live output: tmux attach -t $session
To detach from the session (without interrupting the task): Press Ctrl+b then d inside tmux.
The session will be automatically terminated upon task completion.
EOF
}
main() {
ensure_tmux
local session="" cmd=""
if [[ "${1-}" == "-n" ]]; then session="$2"; shift 2; fi
if [[ "${1-}" == "-c" ]]; then cmd="$2"; shift 2; fi
if [[ $# -gt 0 ]]; then
cmd="${cmd:+$cmd }$*"
fi
if [[ -z "$session" ]]; then
read -r -p "Enter a name for the tmux session: " session
session="${session:-job-$(date +%Y%m%d%H%M%S)}"
fi
if [[ -z "$cmd" ]]; then
read -r -p "Enter the command to execute in tmux: " cmd
fi
if [[ -z "$cmd" ]]; then
echo "No command provided to execute." >&2
exit 3
fi
create_and_run "$session" "$cmd"
}
main "$@"
P.S.
How to Use
Log in to your server, save this script as run_in_tmux.sh, and grant it execute permissions with chmod +x run_in_tmux.sh. Then you’re ready to run it.
Examples
run_in_tmux.sh [-n <session_name>] [-c "<command_string>"] [command_and_args...]
# Interactive mode (follow the prompts)
./run_in_tmux.sh
# Specify session name + entire command as a string
./run_in_tmux.sh -n rclone-copy -c 'rclone copy src dst --progress'
# Omit -c and pass the command directly at the end
./run_in_tmux.sh -n rclone-copy rclone copy src dst --progress
Exit Codes
Internal error codes: 1 (failed to auto-install tmux), 2 (session already exists), 3 (no command provided)