1. kawaz
Changes in body
Source | HTML | Preview
@@ -1,21 +1,78 @@
今時のバージョンのOpenSSHではknown_hostsがハッシュ化されてて手動管理がしにくいし、スマートに決めたいのでコマンドでやってみる。
# コマンド
結論から書くと↓こんな感じでOK。(`target-hostname`のホストキーが変わった場合の例)
```bash:
host="target-hostname"
ssh-keygen -R $host
ssh-keyscan -H $host >> ~/.ssh/known_hosts
```
-
-# 説明
- `ssh-keygen -R hostname` は `~/.ssh/known_hosts` から対象ホストのホストキーを削除してくれる。
- 複数あれば全部消してくれるしハッシュ化されてるのもされてないのも全部消してくれるので便利。
- known_hostsファイルをエディタで開いてエラーメッセージで指摘された行数まで移動して手で削除するのなんかより100倍楽。
- `ssh-keyscan` は対象ホストのホストキー一覧を取得するコマンド。
- 無言で実行できるから一旦手動でssh試みてプロンプトでyesとかするより使い勝手が良い。
- `-H`オプションを付けるとホスト名がハッシュ化される、無しなら昔ながらに生のホスト名で出力される。今時はハッシュ化しとけば良いと思う。
- __注意点!__ 追記する為の `>>` を間違えて `>` て書くと既存のキーが全部消えるので気をつけること!
+
+# ちょっと進化系
+`HashKnownHosts yes`な環境だとbash-completionのホスト名補完が効かなくなるので~/.ssh/config内で明示的に`no`にしてる人もいそうな気がする。そういう人はssh-keyscanに勝手にハッシュオプション付けられるのは嫌がるだろうから環境チェックしてからオプションの出し入れするように修正してみた。
+
+https://gist.github.com/kawaz/00dd296ffc86506854ae
+
+```bash:refresh_knownhosts.sh
+#!/bin/bash
+
+# ssh設定値の取得関数
+sshconf() {
+ local key=$1 targethost=$2
+ local value f k v m
+ [[ -z $key ]] && { echo "Usage: $FUNCNAME key [hostname]"; return 1; }
+ for f in ~/.ssh/config /etc/ssh_config; do
+ [[ -r $f ]] || continue
+ while read k v; do
+ if [[ $k == Host ]]; then
+ inhost=
+ for m in $v; do
+ [[ $m =~ ^# ]] && break # skip comment
+ m=${m//./\\.}; m=${m//\*/.*}; m=${m//\?/.}; m="^$m$" # wildcard -> regexp
+ if [[ $targethost =~ $m ]]; then
+ inhost=1
+ break
+ fi
+ done
+ continue
+ fi
+ if [[ $k == $key ]]; then
+ value=$v
+ fi
+ if [[ -n $value && -n $inhost ]]; then
+ break # 最初にマッチしたHostで見つかった設定優先なのでbreak
+ fi
+ done < <(cat $f | grep -v '^$' | egrep -v '^\s*#')
+ if [[ -n $value ]]; then
+ break # 最初のファイル優先なのでbreak
+ fi
+ done
+ [[ -z $value ]] && return 1
+ printf "%s\n" "$value"
+}
+
+# main
+[[ -z $1 ]] && { echo "Usage: $0 hostname [hostname...]"; exit 1; }
+hashopt=
+if [[ $(sshconf HashKnownHosts) == yes ]]; then
+ hashopt=-H
+fi
+for h in "$@"; do
+ ssh-keygen -R "$h"
+ ssh-keyscan $hashopt "$h" >> ~/.ssh/known_hosts
+done
+```
+
+現在の環境上でのsshの設定値を取得するコマンドってありそうでないのね…。お陰で`HashKnownHosts`の値が知りたかっただけなのに長大な関数を書いてしまった(^^;
+
+上記 `sshconf` 関数は結構まじめに書いたつもりなので単に指定のホストに対する設定値を取得するコマンドとして独立していても便利に使えそう。→独立した[sshconf.sh](https://gist.github.com/kawaz/00dd296ffc86506854ae#file-sshconf-sh)ってファイルに分けといた。