Skip to content

Instantly share code, notes, and snippets.

@jpalala
Last active October 3, 2025 03:43
Show Gist options
  • Save jpalala/77414a580aadd9891b2cbda3a05dea3d to your computer and use it in GitHub Desktop.
Save jpalala/77414a580aadd9891b2cbda3a05dea3d to your computer and use it in GitHub Desktop.

Revisions

  1. jpalala revised this gist Oct 3, 2025. 1 changed file with 73 additions and 0 deletions.
    73 changes: 73 additions & 0 deletions picker.ssh.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,73 @@
    #!/bin/bash

    # ==============================================================================
    # SSH History Selection Utility (ssh_history.sh)
    #
    # This script reads the user's bash history, filters for SSH connections,
    # and presents a unique list in an interactive numbered menu for selection.
    #
    # Dependencies: grep, awk, tac, uniq (standard Unix utilities)
    # ==============================================================================

    # Define the history file path. Adjust this if you use zsh (~/.zsh_history).
    HISTORY_FILE="$HOME/.bash_history"

    # --- Setup and Filtering ---

    if [ ! -f "$HISTORY_FILE" ]; then
    echo "Error: History file not found at $HISTORY_FILE" >&2
    exit 1
    fi

    # 1. Generate the unique, reversed list of hosts and store it in a temporary variable.
    HOST_LIST=$(grep -h "^ssh " "$HISTORY_FILE" |
    awk '{print $2}' |
    tac |
    uniq)

    # Check if any SSH hosts were found
    if [ -z "$HOST_LIST" ]; then
    echo "No unique SSH commands found in history."
    exit 0
    fi

    # 2. Convert the newline-separated list into a Bash array.
    readarray -t HOST_ARRAY <<< "$HOST_LIST"

    echo "--- Select SSH Host (Enter the number, or 'q' to quit) ---"
    echo ""

    # --- Interactive Selection using 'select' ---

    # PS3 is the prompt string for the select loop
    PS3='Enter number to connect or "q" to quit: '

    # 'select host_choice in "${HOST_ARRAY[@]}"' creates a numbered menu.
    # The selected value is stored in 'host_choice'.
    select host_choice in "${HOST_ARRAY[@]}" "Quit"; do

    # If the user selected an item (host_choice is not empty)
    if [[ -n "$host_choice" ]]; then

    if [[ "$host_choice" == "Quit" ]]; then
    echo "Selection cancelled."
    break # Exit the select loop
    fi

    # 4. Connect to the selected host by replacing the current shell process with SSH
    echo "Connecting to: $host_choice..."

    # Use 'exec' so when SSH exits, the script exits immediately without
    # returning to the 'select' loop or requiring another 'break'.
    exec ssh "$host_choice"

    # Handle invalid input (e.g., entering text or an invalid number)
    else
    echo "Invalid selection. Please enter a number from the list or 'q' to quit."
    fi
    done

    echo ""
    echo "-----------------------------------------------------"

    exit 0
  2. jpalala revised this gist Oct 3, 2025. 1 changed file with 82 additions and 0 deletions.
    82 changes: 82 additions & 0 deletions ssh-picker.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,82 @@
    import os
    import re
    import subprocess
    import sys

    def get_ssh_history():
    """Reads ~/.bash_history and extracts unique SSH host strings."""
    # NOTE: This assumes Bash history. Adjust for Zsh (~/.zsh_history) if needed.
    history_file = os.path.expanduser("~/.bash_history")

    # Regex to capture the host part of an SSH command: 'ssh user@host [options]'
    SSH_REGEX = re.compile(r"^\s*ssh\s+([^-@\s]+(?:@\S+)?)")

    hosts = []

    try:
    # Read history file in reverse (newest first)
    with open(history_file, 'r') as f:
    for line in reversed(f.readlines()):
    match = SSH_REGEX.search(line)
    if match:
    host_string = match.group(1).split()[0] # Take only the first word after 'ssh'

    # Deduplicate the list
    if host_string not in hosts:
    hosts.append(host_string)
    except FileNotFoundError:
    print(f"Error: History file not found at {history_file}", file=sys.stderr)
    sys.exit(1)

    return hosts

    def run_fzf_selection(hosts):
    """Pipes the list of hosts to fzf and returns the selected host."""

    if not hosts:
    print("No SSH commands found in history.", file=sys.stderr)
    return None

    try:
    # 1. Join hosts with newlines for piping
    input_data = "\n".join(hosts)

    # 2. Call fzf via subprocess
    # --no-sort ensures the history order (newest first) is maintained
    # --prompt sets a helpful prompt text
    process = subprocess.run(
    ['fzf', '--no-sort', '--prompt=Select SSH Host: '],
    input=input_data,
    capture_output=True,
    text=True,
    check=True # Raise an exception for non-zero exit codes (e.g., fzf not installed)
    )

    # fzf prints the selected line to stdout
    return process.stdout.strip()

    except FileNotFoundError:
    print("Error: 'fzf' is not installed or not in your PATH.", file=sys.stderr)
    print("Please install fzf (e.g., 'brew install fzf' or 'sudo apt install fzf').", file=sys.stderr)
    sys.exit(1)
    except subprocess.CalledProcessError:
    # User canceled fzf (e.g., pressed Esc)
    sys.exit(0)

    def main():
    history_hosts = get_ssh_history()
    selected_host = run_fzf_selection(history_hosts)

    if selected_host:
    print(f"Connecting to: {selected_host}...")

    # Crucial step: Use os.execvp to replace the current Python process
    # with the SSH process, passing control to the SSH client.
    try:
    os.execvp("ssh", ["ssh", selected_host])
    except FileNotFoundError:
    print("Error: 'ssh' command not found.", file=sys.stderr)
    sys.exit(1)

    if __name__ == "__main__":
    main()
  3. jpalala created this gist Oct 3, 2025.
    25 changes: 25 additions & 0 deletions bastion-connector.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,25 @@
    #!/usr/bin/env bash

    # bastion-connector.sh
    # Simple helper to SSH into private VPC hosts via a bastion jump server.

    # Usage:
    # ./bastion-connector.sh <TARGET_PRIVATE_IP> [USERNAME]
    #
    # Example:
    # ./bastion-connector.sh 10.15.3.42 ubuntu
    # ./bastion-connector.sh 10.15.7.10 root

    # --- Configurable Variables ---
    BASTION_HOST="bastion.vpc.example.com" # Change to your real bastion hostname/IP
    TARGET_IP="$1"
    TARGET_USER="${2:-ubuntu}" # Default username if not provided

    # --- Validation ---
    if [ -z "$TARGET_IP" ]; then
    echo "Usage: $0 <TARGET_PRIVATE_IP> [USERNAME]"
    exit 1
    fi

    echo "🔌 Connecting to $TARGET_IP via bastion $BASTION_HOST ..."
    ssh -J "$TARGET_USER@$BASTION_HOST" "$TARGET_USER@$TARGET_IP"