LoginSignup
1
0

More than 5 years have passed since last update.

goでssh config設定を忘れてもsshできるようにした

Last updated at Posted at 2018-08-13

こんにちは。かなり久々に書きます。

今は割と大きめの会社でSREをメインにやっていて、
パフォーマンス改善だったり、監視項目の整理・追加etcをしています。
昔はサーバサイドをメインでやっていて、その後android/iosアプリ開発、react+reduxとかやっていました。

今回のエントリーはsshコマンドでログインする際に基本的にconfigに鍵のパスとかを設定して後は、ssh Host名とかでログインするのが一般的かと思います。
ただそのconfigが増えてくると、Hostの名前を何にしたか忘れてしまってわざわざconfigの中身を表示するとかめんどいなーと思い、
今回はgoでいつもssh configの名前を忘れてしまう問題をOSSで解決してみました。
コードのアドバイスでも編集依頼でもなんでもいいので、何かありましたらコメントください!!

github

インストール

brew

brew tap revenue-hack/sshcut
brew install sshcut

go get

go get
go get github.com/revenue-hack/homebrew-sshcut

使い方

.ssh/configの中身が

Host test
HostName 11.111.11.111
User test
Port 21
PreferredAuthentications publickey
IdentityFile ~/.ssh/test.pem
Host test1
HostName 22.222.22.222
User test2
Port 21
PreferredAuthentications publickey
IdentityFile ~/.ssh/test2.pem

な感じで、Hostが正しく記載されていて、
本来のやり方通り

ssh test

みたくssh+Hostでログインできれば使えます。

使い方は
sshcutとコマンドを叩くと

number  Host
0   test
1   test1
select ssh host number?:

のようにHostごとにnumberが振られているので、
後はnumberを選んでenterをするだけで、ログインできます。

コードの簡単な説明

コードは単純でmain.goのみでできています。

main関数のはじめにやっていることは、
configパスから、configファイルを読み込んでいます。

configFilePath, err := getConfigFilePath()
if !err {
    fmt.Println(".ssh config file nothing Error")
    os.Exit(1)
}

実際にファイルを読み込んでいるのはreadFile関数です。

func readFile(configFilePath string) (HostList, bool) {
file, err := os.Open(configFilePath)
    if err != nil {
        fmt.Printf("%s is not exist\n", configFilePath)
        os.Exit(1)
    }
    defer file.Close()
    reader := bufio.NewReaderSize(file, 4096)
    var hosts HostList
    for {
        line, _, err := reader.ReadLine()
        if err == io.EOF {
            break
        } else if err != nil {
            fmt.Println("can't read config file")
            panic(err)
        }
        host, hasHostObject := objectMapping((string(line)))
        if !hasHostObject {
            continue
        }
        hosts.Hosts = append(hosts.Hosts, host)
    }
    if hosts.Hosts == nil {
        return hosts, false
    }
    return hosts, true
}

その際に、objectMapping関数でやっているのはすでにssh configはログインできる前提で、Host情報だけをマッピングしています。

func objectMapping(fileArgs string) (Host, bool) {
    var alias Host
    if strings.Contains(fileArgs, "Host ") {
        args := strings.Fields(fileArgs)
        if len(args) != 2 {
            return alias, false
        }
        alias.Alias = args[1]
        return alias, true
    }
    return alias, false
}

main.goの21行目で、Hostが正しく存在したら、その一覧を表示しています。

fmt.Printf("%s\t%s\n", "number", "Host")
for i, host := range hosts.Hosts {
    fmt.Printf("%d\t%v\n", i, host.Alias)
}
fmt.Printf("%s", "select ssh host number?: ")

27行目からは、ユーザのnumber入力があった場合の処理を記述していて、39行目で、実際にコマンドを実行しています。

stdIn := bufio.NewScanner(os.Stdin)
if stdIn.Scan() {
    text := stdIn.Text()
    key, err := strconv.Atoi(text)
    if err != nil {
        fmt.Println("select ssh host number must be integer")
        os.Exit(1)
    }
    cmd := exec.Command("ssh", hosts.Hosts[key].Alias)
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    if err = cmd.Run(); err != nil {
        fmt.Println("can't ssh connection")
        panic(err)
    }
}

以上です。
何かの参考になればと思います。

1
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
1
0