0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

~/.ssh/config から IP アドレスに対応する Host 名を簡単に引く方法

0
Last updated at Posted at 2026-03-26

SSH 接続先が増えてくると、~/.ssh/config がだんだん育ってきますよね。

自分の環境でも、例えばこんな感じで管理しています。

Host stg01.example.com
  Hostname 123.456.789.000
  Port 22
  User ec2-user
  IdentityFile ~/ssh/ssh_key/stg01.test.example.com.pem

Host web01.example.com
  Hostname 111.111.111.111
  Port 22
  User ec2-user
  IdentityFile ~/ssh/ssh_key/web01.example.com.pem

普段は web01.example.com のように Host 名で接続できるのでかなり便利です。
ただ、ログや監視通知、踏み台の接続記録なんかで IP アドレスだけを見たときに、

111.111.111.111 ってどの Host だっけ?

となることがちょこちょこありました。

そのたびに ~/.ssh/config を開いて検索するのは、できなくはないけど地味に面倒です。

そこで、IP アドレスを渡すと対応する Host 名を返してくれる sship という小さなスクリプトを作ってみました。

こんなことをしたい

やりたいことはシンプルで、こんな感じです。

sship 123.456.789.000
# => stg01.example.com

同じ IP に複数の Host 名がぶら下がっている場合は、まとめて全部出してほしいです。

sship 222.222.222.222
# => slave.stg01.example.com
# => slave.stg01.example.com_homepage
# => slave.stg01.example.com_planning_ssh

作成したスクリプト

中身は zsh + awk のシンプルなスクリプトです。

#!/bin/zsh

set -eu

config_file="${SSH_CONFIG:-$HOME/.ssh/config}"

if [ $# -ne 1 ]; then
  echo "Usage: $(basename "$0") <ip-or-hostname>" >&2
  exit 1
fi

target="$1"

awk -v target="$target" '
  BEGIN {
    count = 0
  }

  /^[[:space:]]*#/ {
    next
  }

  /^[[:space:]]*Host[[:space:]]+/ {
    line = $0
    sub(/^[[:space:]]*Host[[:space:]]+/, "", line)
    split(line, parts, /[[:space:]]+/)

    delete current_hosts
    current_host_count = 0

    for (i in parts) {
      host = parts[i]
      if (host == "" || host ~ /[*?]/) {
        continue
      }
      current_hosts[++current_host_count] = host
    }

    next
  }

  /^[[:space:]]*Hostname[[:space:]]+/ {
    line = $0
    sub(/^[[:space:]]*Hostname[[:space:]]+/, "", line)
    split(line, parts, /[[:space:]]+/)
    hostname_value = parts[1]

    if (hostname_value != target) {
      next
    }

    for (i = 1; i <= current_host_count; i++) {
      host = current_hosts[i]
      if (!(host in seen)) {
        print host
        seen[host] = 1
        count++
      }
    }
  }

  END {
    if (count == 0) {
      exit 2
    }
  }
' "$config_file" || {
  exit_code=$?
  if [ "$exit_code" -eq 2 ]; then
    echo "No Host found for: $target" >&2
  fi
  exit "$exit_code"
}

仕組みは素朴

やっていることはかなり単純で、~/.ssh/config を上から順番に読みながら、
直前の Host と、その後に出てくる Hostname を対応付けているだけです。

流れとしてはこうなります。

  1. Host ... の行を見つけたら、そのブロックの Host 名を一時的に覚える
  2. Hostname ... の行を見つけたら、入力された IP アドレスと一致するか比較する
  3. 一致したら、さっき覚えていた Host 名を表示する
  4. 同じ Host 名が重複して出ないように制御する

awk だけで完結しているので、依存が少なくて雑に置いても動かしやすいです。

使い方

先ほどのスクリプトをDownloads配下に置いた場合は以下のようにして実行します。

@iMac-PC Downloads % ./ssh-host-by-ip 111.111.111.111
web01.example.com

ただ毎度./ssh-host-by-ipを入力も面倒なので自分は~/.zshrcにaliasを設定してsshipで動作するようにしてます。

#aliasの設定
echo "alias sship='~/Downloads/ssh-host-by-ip'" >> ~/.zshrc
source ~/.zshrc

#動作検証
@iMac-PC Downloads % sship 111.111.111.111
web01.example.com

sship {IPアドレス}
だけで検索できるようになりました!
こっちのが利便性高いですね
※Downloadsにスクリプト本体を置くのはあまり良くないので、実際は別のところに置くことをお勧めいたします。

補足

このスクリプトは HostHostname のシンプルな対応をたどる作りです。
そのため、Include や複雑な Match 条件まで厳密に解釈するものではありません。

とはいえ、よくある「~/.ssh/config に接続先をずらっと並べている」運用なら、かなり実用的だと思います。

まとめ

IP アドレスだけ分かっているときに、~/.ssh/config から対応する Host 名をすぐ引けるようになったので、
ちょっとした調査や接続確認がだいぶ楽になりました。

派手な話ではないですが、こういう小さい道具は日々のストレスをちゃんと減らしてくれるので結構おすすめです。

~/.ssh/config をよく使う人なら、1つ置いておくとわりと便利だと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?