~/.ssh/config にあるホストからインタラクティブに検索して SSH 接続する

# 背景

`~./ssh/config` に設定を書いておくと `ssh hogehoge` のようにサーバーに SSH 接続できて便利だと思います。

参考 : [~/\.ssh/configについて \- Qiita](https://qiita.com/passol78/items/2ad123e39efeb1a5286b)

しかし、接続先が増えてくるに従って自分が名付けた名前を忘れ、毎回 `~./ssh/config` を `cat` して確認していました。

peco を使ってインタラクティブに検索しつつ SSH 接続できるようにしたので、やり方を書いておきます。

[peco/peco: Simplistic interactive filtering tool](https://github.com/peco/peco)

# 環境

- macOS High Sierra
    - バージョン 10.13.3
- peco
    - v0.5.3 (built with go1.10)

# やり方

```bash:~/.bash_profile
alias sl="cat ~/.ssh/config | grep 'Host [^\*]' | grep -v 'github'  | sed -e 's/Host //'"
alias sp='ssh $(sl | peco)'
```

`sp` で検索モードに入るので、文字を打って絞り込み、エンターで SSH 接続できます。

```bash:$sp
QUERY>
staging-step
staging-web
staging-batch
production-step
production-web
production-batch
```

参考までに、僕の ssh config はこんな感じです。（色々ぼかしてます。）

```:~/.ssh/config
Host *
 AddKeysToAgent yes
 UseKeychain yes

Host staging-step
  HostName xxx.xxx.xxx.xxx
  Port xxx
  User xxx
  IdentityFile ~/.ssh/id_rsa_xxx
Host staging-web
  HostName xxx
  ProxyCommand ssh -W %h:%p staging-step
Host staging-batch
  HostName xxx
  ProxyCommand ssh -W %h:%p staging-step

Host production-step
  HostName xxx.xxx.xxx.xxx
  Port xxx
  User xxx
  IdentityFile ~/.ssh/id_rsa_xxx
Host production-web
  HostName xxx
  ProxyCommand ssh -W %h:%p production-step
Host production-batch
  HostName xxx
  ProxyCommand ssh -W %h:%p production-step

# Github
Host github.com
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_rsa_xxx
Host github.com.private
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_rsa_xxx
```

`sl` でホスト一覧を表示することもできます。

```
$ sl
staging-step
staging-web
staging-batch
production-step
production-web
production-batch
```

後述しますが `Host *` と Github の設定を除くために `sl` は少し複雑になっています。

# 解説

## sl エイリアス

```bash:~/.bash_profile
alias sl="cat ~/.ssh/config | grep 'Host [^\*]' | grep -v 'github'  | sed -e 's/Host //'"
```

1. ~/.ssh/config を `cat` で出力
2. `grep` コマンドで絞り込み
3. `sed` コマンドでいらない部分を削る

という流れになります。

順番に流れを追っていきます。
まずはシンプルに grep してみます。

```bash
$ cat ~/.ssh/config | grep 'Host '
Host *
Host staging-step
Host staging-web
Host staging-batch
Host production-step
Host production-web
Host production-batch
Host github.com
Host github.com.private
```

ここから `Host ` を削ります。

```bash
$ cat ~/.ssh/config | grep 'Host ' | sed -e 's/Host //'
*
staging-step
staging-web
staging-batch
production-step
production-web
production-batch
github.com
github.com.private
```

- `*`
- `github.com`
- `github.com.private`

がない方は、ここまでで良いと思います。
ここからこの3つを削るようにすると、完成です。

```bash:~/.bash_profile
alias sl="cat ~/.ssh/config | grep 'Host [^\*]' | grep -v 'github'  | sed -e 's/Host //'"
```

### `grep 'Host [^\*]'`

正規表現を使っています。正規表現については、以下のシリーズが参考になると思います。
`HostName` と `Host *` に引っ掛けず `Host` の行を取って来ています。

- [初心者歓迎！手と目で覚える正規表現入門・その１「さまざまな形式の電話番号を検索しよう」 \- Qiita](https://qiita.com/jnchito/items/893c887fbf19e17d3ff9)

### `grep -v 'github'`

grep コマンドは -v をつけることでマッチしないものを絞り込めます。

### `sed -e 's/Host //'`

sed コマンドを使うことで、文字列を置換できます。
ここでは、 `Host ` を空文字で置換（削除）しています。

## sp エイリアス

```bash:~/.bash_profile
alias sp='ssh $(sl | peco)'
```

先ほど作成した sl エイリアスを peco でフィルタリングして ssh コマンドに渡してあげれば OK です。
peco に関しては、ここら辺を参考にしました。

- [え、まだpecoを使ってないの？？？ \- Qiita](https://qiita.com/vintersnow/items/08852df841e8d5faa7c2)
- [peco/peco: Simplistic interactive filtering tool](https://github.com/peco/peco)