mirror of
https://github.com/anatolykopyl/sshukh.git
synced 2026-06-14 22:44:11 +00:00
Merge pull request #2 from anatolykopyl/ssh-config-fix
Fixed behaviour when using ssh config alias
This commit is contained in:
12
README.md
12
README.md
@@ -1,4 +1,5 @@
|
||||
# sshukh zsh plugin
|
||||
|
||||
*SSH Update Known Hosts*
|
||||
|
||||
Prompts to update `known_hosts` file for you if needed.
|
||||
@@ -6,25 +7,33 @@ Prompts to update `known_hosts` file for you if needed.
|
||||
## Installation:
|
||||
|
||||
**With Oh-my-zsh:** run the following command:
|
||||
|
||||
```
|
||||
$ git clone https://github.com/anatolykopyl/sshukh.git $HOME/.oh-my-zsh/custom/plugins/sshukh
|
||||
```
|
||||
|
||||
**With Antigen:** add the following to your `.zshrc`:
|
||||
|
||||
```
|
||||
antigen bundle anatolykopyl/sshukh
|
||||
```
|
||||
|
||||
To always use with ssh (recommended) add this alias to your `.zshrc`:
|
||||
|
||||
```
|
||||
alias ssh='sshukh'
|
||||
```
|
||||
|
||||
Zsh may tell you that the plugin is disabled until permissions are fixed. Just run the command it suggests.
|
||||
|
||||
```
|
||||
$ compaudit | xargs chmod g-w,o-w
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Let's connect to an ip that changed hosts:
|
||||
|
||||
```
|
||||
$ sshukh pi@192.168.1.54
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
@@ -45,4 +54,5 @@ Update known_hosts? [y/n] y
|
||||
/Users/akopyl/.ssh/known_hosts updated.
|
||||
Original contents retained as /Users/akopyl/.ssh/known_hosts.old
|
||||
```
|
||||
There is a prompt asking if you want to remove the conflicting host from `known_hosts` and upon answering `y` ssh reruns automatically successfully.
|
||||
|
||||
There is a prompt asking if you want to remove the conflicting host from `known_hosts` and upon answering `y` ssh reruns automatically successfully.
|
||||
@@ -2,7 +2,7 @@
|
||||
# Description
|
||||
# -----------
|
||||
#
|
||||
# User will be prompted if they want to update known_hosts if ssh errors out
|
||||
# User will be prompted if they want to update known_hosts if ssh errors out
|
||||
# with "Host key verification failed."
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
@@ -13,18 +13,130 @@
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
sshukh () {
|
||||
output=$(\ssh "$@" 2>&1 | tee /dev/tty)
|
||||
error=$(echo $output | tail -1)
|
||||
if [[ "$error" == "Host key verification failed."* ]]; then
|
||||
host=$(cut -d'@' -f2 <<< $1)
|
||||
while true; do
|
||||
read yn"?Update known_hosts? [y/n] "
|
||||
case $yn in
|
||||
[Yy]* ) ssh-keygen -R $host && \ssh "$@"; break;;
|
||||
[Nn]* ) break;;
|
||||
* ) echo "Please answer y or n.";;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
# OpenSSH prints "<keytype> host key for <host> has changed." — use that host
|
||||
# for ssh-keygen -R (correct for SSH config Host aliases that resolve to IPs).
|
||||
_sshukh_offending_host_from_output() {
|
||||
print -r -- "$1" | command grep -E -m1 ' host key for .+ has changed' | command sed -E 's/.* host key for ([^ ]+) has changed.*/\1/'
|
||||
}
|
||||
|
||||
# Walk ssh argv like ssh(1): options first, then destination [command ...].
|
||||
# Sets _sshukh_prefix (options only) and _sshukh_dest (user@host or alias).
|
||||
_sshukh_split_ssh_args() {
|
||||
local i a
|
||||
local -a args
|
||||
args=("$@")
|
||||
_sshukh_prefix=()
|
||||
_sshukh_dest=""
|
||||
|
||||
i=1
|
||||
while (( i <= $#args )); do
|
||||
a="${args[i]}"
|
||||
case $a in
|
||||
--)
|
||||
_sshukh_prefix+=("$a")
|
||||
(( i++ ))
|
||||
(( i <= $#args )) || return 1
|
||||
_sshukh_dest="${args[i]}"
|
||||
return 0
|
||||
;;
|
||||
-[46AaCfGgKkMNnqsTtVvXxYy])
|
||||
_sshukh_prefix+=("$a")
|
||||
;;
|
||||
-v*)
|
||||
_sshukh_prefix+=("$a")
|
||||
;;
|
||||
-B|-b|-c|-E|-e|-F|-I|-i|-J|-L|-l|-m|-O|-P|-p|-Q|-R|-S|-W|-w)
|
||||
_sshukh_prefix+=("$a")
|
||||
(( i++ ))
|
||||
(( i <= $#args )) || return 1
|
||||
_sshukh_prefix+=("${args[i]}")
|
||||
;;
|
||||
-D)
|
||||
_sshukh_prefix+=("$a")
|
||||
(( i++ ))
|
||||
(( i <= $#args )) || return 1
|
||||
_sshukh_prefix+=("${args[i]}")
|
||||
;;
|
||||
-D*|-B*|-b*|-c*|-E*|-e*|-F*|-I*|-i*|-J*|-L*|-l*|-m*|-O*|-P*|-p*|-Q*|-R*|-S*|-W*|-w*)
|
||||
_sshukh_prefix+=("$a")
|
||||
;;
|
||||
-o)
|
||||
_sshukh_prefix+=("$a")
|
||||
(( i++ ))
|
||||
(( i <= $#args )) || return 1
|
||||
_sshukh_prefix+=("${args[i]}")
|
||||
;;
|
||||
-o*)
|
||||
_sshukh_prefix+=("$a")
|
||||
;;
|
||||
-*)
|
||||
_sshukh_prefix+=("$a")
|
||||
;;
|
||||
*)
|
||||
_sshukh_dest="$a"
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
(( i++ ))
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# Hostnames to try with ssh-keygen -R: offending line from ssh, then config
|
||||
# alias / canonical names from ssh -G (covers known_hosts under IP vs name).
|
||||
_sshukh_hosts_for_keygen() {
|
||||
local output h stripped dest canon hostpat gout
|
||||
output="$1"
|
||||
shift
|
||||
|
||||
typeset -U hosts
|
||||
hosts=()
|
||||
|
||||
h=$(_sshukh_offending_host_from_output "$output")
|
||||
[[ -n "$h" ]] && hosts+=("$h")
|
||||
|
||||
if _sshukh_split_ssh_args "$@"; then
|
||||
dest="$_sshukh_dest"
|
||||
stripped="${dest#*@}"
|
||||
[[ "$stripped" == "$dest" ]] && stripped="$dest"
|
||||
[[ -n "$stripped" ]] && hosts+=("$stripped")
|
||||
|
||||
gout=$(\ssh -G "${_sshukh_prefix[@]}" "$dest" 2>/dev/null) || gout=""
|
||||
if [[ -n "$gout" ]]; then
|
||||
canon=$(print -r -- "$gout" | command awk '/^hostname / { print $2; exit }')
|
||||
hostpat=$(print -r -- "$gout" | command awk '/^host / { print $2; exit }')
|
||||
[[ -n "$canon" ]] && hosts+=("$canon")
|
||||
[[ -n "$hostpat" ]] && hosts+=("$hostpat")
|
||||
fi
|
||||
fi
|
||||
|
||||
print -rl -- "${hosts[@]}"
|
||||
}
|
||||
|
||||
sshukh () {
|
||||
local output error host
|
||||
|
||||
output=$(\ssh "$@" 2>&1 | tee /dev/tty)
|
||||
error=$(print -r -- "$output" | tail -n1)
|
||||
|
||||
if [[ "$error" != *"Host key verification failed"* ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
while true; do
|
||||
read yn"?Update known_hosts? [y/n] "
|
||||
case $yn in
|
||||
[Yy]* )
|
||||
while IFS= read -r host; do
|
||||
[[ -z "$host" ]] && continue
|
||||
\ssh-keygen -R "$host" 2>/dev/null
|
||||
done < <(_sshukh_hosts_for_keygen "$output" "$@")
|
||||
|
||||
\ssh "$@"
|
||||
break
|
||||
;;
|
||||
[Nn]* ) break;;
|
||||
* ) echo "Please answer y or n.";;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user