#!/bin/bash
set -euo pipefail
readonly FILENAME="${HOME}/.ssh/known_hosts" readonly BACKUP_FILE="${FILENAME}.sshrm.bak"
check_known_hosts() { if [ ! -f "${FILENAME}" ]; then error "known_hosts not found." exit 1 fi }
usage() { echo "Usage: sshrm [-h|--help] [--no-backup] host|line_number" }
confirm() { read -r -p "Proceed? [y/N] " answer case "$answer" in y|Y|yes|YES) return 0 ;; *) error "cancelled." return 1 ;; esac }
error() { echo "Error: $1" }
is_number() { case "$1" in ''|[!0-9]) return 1 ;; *) return 0 ;; esac }
get_host_from_line() { awk -v line="$1" 'NR == line {print $1; exit}' "${FILENAME}" }
create_backup() { cp "${FILENAME}" "${BACKUP_FILE}" }
remove_host() { ssh-keygen -R "$1" }
if [ "${1-}" = "" ]; then error "missing argument." usage exit 1 fi
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then usage exit 0 fi
backup=true if [ "$1" = "--no-backup" ]; then backup=false shift fi
if [ "${1-}" = "" ]; then error "missing argument." usage exit 1 fi
if [ "${2-}" != "" ]; then error "too many arguments." usage exit 1 fi
check_known_hosts
if is_number "$1"; then if [ "$1" -eq 0 ]; then error "invalid line number." exit 1 fi HOST="$(get_host_from_line "$1")" if [ "${HOST}" = "" ]; then error "invalid line number." exit 1 fi else HOST="$1" fi
if ! confirm; then exit 1 fi
if [ "${backup}" = true ]; then create_backup fi
if ! remove_host "$HOST"; then error "removal failed." exit 1 fi