113 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
			
		
		
	
	
			113 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
#!/bin/bash
 | 
						|
# tmux-oneshot.sh
 | 
						|
# Run a single command in a tmux session
 | 
						|
 | 
						|
# Built-in prompt patterns (command_pattern:prompt_pattern:timeout_seconds)
 | 
						|
PROMPT_PATTERNS=(
 | 
						|
    "ssh*:Password|password:5"
 | 
						|
    "sudo*:Password|password|\\[sudo\\] password for:5"
 | 
						|
    "su*:Password|password:5"
 | 
						|
    "mysql*:Enter password:3"
 | 
						|
    "docker*:Password:2"
 | 
						|
)
 | 
						|
 | 
						|
# Generic function to wait for prompts based on command patterns
 | 
						|
wait_for_prompt() {
 | 
						|
    local cmd="$1"
 | 
						|
    
 | 
						|
    # Find matching pattern for this command
 | 
						|
    for pattern in "${PROMPT_PATTERNS[@]}"; do
 | 
						|
        IFS=':' read -r cmd_pattern prompt_pattern timeout <<< "$pattern"
 | 
						|
        if [[ "$cmd" == $cmd_pattern ]]; then
 | 
						|
            echo "Waiting for prompt: $prompt_pattern (timeout: ${timeout}s)"
 | 
						|
            timeout=$((timeout * 10))  # Convert to 0.1s intervals
 | 
						|
            while [ $timeout -gt 0 ] && ! tmux capture-pane -t $SESSION -p | tail -3 | grep -E "($prompt_pattern)" >/dev/null 2>&1; do
 | 
						|
                sleep 0.1
 | 
						|
                timeout=$((timeout - 1))
 | 
						|
            done
 | 
						|
            if [ $timeout -eq 0 ]; then
 | 
						|
                echo "Timeout waiting for prompt: $prompt_pattern"
 | 
						|
            fi
 | 
						|
            return
 | 
						|
        fi
 | 
						|
    done
 | 
						|
    
 | 
						|
    # No pattern matched, brief pause
 | 
						|
    sleep 0.5
 | 
						|
}
 | 
						|
 | 
						|
# Load config file if it exists
 | 
						|
SCRIPT_DIR=$(dirname "$0")
 | 
						|
SCRIPT_NAME=$(basename "$0" .sh)
 | 
						|
CONFIG_FILE="${SCRIPT_DIR}/${SCRIPT_NAME}.conf"
 | 
						|
if [ -f "$CONFIG_FILE" ]; then
 | 
						|
    echo "Loading config from $CONFIG_FILE"
 | 
						|
    source "$CONFIG_FILE"
 | 
						|
else
 | 
						|
    echo "Config file $CONFIG_FILE not found, generating template..."
 | 
						|
    cat > "$CONFIG_FILE" << 'EOF'
 | 
						|
# tmux-oneshot.conf
 | 
						|
# Configuration file for tmux-oneshot.sh
 | 
						|
 | 
						|
# Session name (leave empty to use first word of command)
 | 
						|
SESSION=""
 | 
						|
 | 
						|
# For multiple commands, use an array:
 | 
						|
# COMMANDS=("ssh root@server" "sudo su" "password123")
 | 
						|
COMMANDS=()
 | 
						|
 | 
						|
# Whether to attach to session after running command (0 or 1)
 | 
						|
ATTACH_SESSION=0
 | 
						|
EOF
 | 
						|
    echo "Generated $CONFIG_FILE with default values. Please edit and run again."
 | 
						|
    exit 0
 | 
						|
fi
 | 
						|
 | 
						|
# Validate required variables
 | 
						|
if [ -z "$SESSION" ] && [ ${#COMMANDS[@]} -eq 0 ]; then
 | 
						|
    echo "Error: Either SESSION or COMMANDS must be set in $CONFIG_FILE" >&2
 | 
						|
    exit 1
 | 
						|
fi
 | 
						|
 | 
						|
# Use command line arguments if provided, otherwise use config
 | 
						|
if [ $# -gt 0 ]; then
 | 
						|
    COMMANDS=("$*")
 | 
						|
    echo "Using command line arguments: $*"
 | 
						|
else
 | 
						|
    if [ ${#COMMANDS[@]} -eq 0 ]; then
 | 
						|
        echo "Error: No commands provided and no commands set in config" >&2
 | 
						|
        exit 1
 | 
						|
    fi
 | 
						|
    echo "Using config commands: ${COMMANDS[*]}"
 | 
						|
fi
 | 
						|
 | 
						|
# Use session name from config, or first word of first command if not set
 | 
						|
if [ -z "$SESSION" ]; then
 | 
						|
    SESSION=$(echo "${COMMANDS[0]}" | awk '{print $1}')
 | 
						|
fi
 | 
						|
 | 
						|
# Create session if missing
 | 
						|
if ! tmux has-session -t $SESSION 2>/dev/null; then
 | 
						|
    echo "Creating tmux session: $SESSION"
 | 
						|
    tmux new-session -d -s $SESSION
 | 
						|
else
 | 
						|
    echo "Session $SESSION exists, reusing..."
 | 
						|
fi
 | 
						|
 | 
						|
# Send commands individually with proper timing
 | 
						|
echo "Running commands: ${COMMANDS[*]}"
 | 
						|
for i in "${!COMMANDS[@]}"; do
 | 
						|
    cmd="${COMMANDS[$i]}"
 | 
						|
    echo "Running: $cmd"
 | 
						|
    tmux send-keys -t $SESSION "$cmd" C-m
 | 
						|
    # Only wait if there is a subsequent command
 | 
						|
    if [ $i -lt $((${#COMMANDS[@]} - 1)) ]; then
 | 
						|
        # Wait for command to complete or prompt for input with timeout
 | 
						|
        wait_for_prompt "$cmd"
 | 
						|
    fi
 | 
						|
done
 | 
						|
 | 
						|
if [ $ATTACH_SESSION -eq 1 ]; then
 | 
						|
    echo "Attaching to tmux session: $SESSION"
 | 
						|
    tmux attach -t $SESSION
 | 
						|
fi |