Skip to content

Instantly share code, notes, and snippets.

@pda
Last active February 16, 2024 00:00
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pda/f9769fe78d021445f6ffd0672ff94196 to your computer and use it in GitHub Desktop.
Save pda/f9769fe78d021445f6ffd0672ff94196 to your computer and use it in GitHub Desktop.
poorman: a Procfile runner for tmux, in terrible bash
#!/bin/bash
set -e -o pipefail -u
# Launches each Procfile service as a tmux pane in a background window.
# The window is created if it doesn't already exist.
# Panes are created on demand, and existing panes are restarted if stopped.
WINDOW_NAME="poorman"
if [[ ${1:-} == "stop" ]]; then
for p in $(tmux list-panes -t $WINDOW_NAME -F "#D"); do
tmux send-keys -t "$p" "C-c"
done
exit
fi
tmux new-window -adS -n $WINDOW_NAME
tmux set -w -t $WINDOW_NAME monitor-activity off
tmux set -w -t $WINDOW_NAME pane-border-format " #{pane_index}: #{pane_title} "
tmux set -w -t $WINDOW_NAME pane-border-status top
if [[ -e .env ]]; then . .env; fi
port="${PORT:-5000}"
nocmd="$(basename "$SHELL")"
wait=""
while IFS=": " read p cmd; do
[[ $p =~ ^[0-9a-z]+$ && -n $cmd ]] || continue
status=$(tmux list-panes -t $WINDOW_NAME -f "#{==:#{pane_title},$p}" -F "#D #{?#{==:#{pane_current_command},$nocmd},dead,alive}")
if [[ -z $status ]]; then
echo "$p starting (PORT=$port)"
pane=$(tmux split-window -bd -t $WINDOW_NAME -l 4 -PF '#D' "PORT=$port $SHELL")
tmux select-pane -t "$pane" -T "$p"
# give shell/commands a moment, for cleaner output
sleep 0.1; tmux send-keys -t "$pane" "source <(grep '^[A-Z][0-9A-Z_]*' .env | sed -e 's/^/export /')" "C-m"
sleep 0.1; tmux send-keys -t "$pane" "export PORT=$port" "C-m"
sleep 0.1; tmux send-keys -t "$pane" "( $cmd )" "C-m"
wait="1"
elif [[ $status =~ dead ]]; then
echo "$p restarting"
tmux send-keys -t "${status%% *}" "( $cmd )" "C-m"
wait="1"
fi
port=$((port+100))
done < Procfile
tmux select-layout -t $WINDOW_NAME tiled
# Wait a moment for (re)started processes before listing panes.
if [[ $wait == "1" ]]; then sleep 1; fi
tmux list-windows -f "#{==:#{window_name},$WINDOW_NAME}" \
-F 'tmux window #{window_index}: #{window_name} (#{window_panes} panes)'
tmux list-panes -t $WINDOW_NAME \
-F " #{?#{==:#{pane_current_command},$nocmd},#{?#{!=:#{pane_title},#H},✘, },✔} #P: #{?#{==:#{pane_title},#H},#{pane_current_command},#{pane_title}}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment