Go言語:sshパッケージを使って対話型SSHクライアントを実装する
code.google.com/p/go.crypto/sshで提供されているsshパッケージを使って、標準のsshコマンドと同等の対話型SSHクライアントを実装してみた。
コードは以下。
https://github.com/inatus/ssh-client-go
API・コード例はGoDocに記載されている。
http://godoc.org/code.google.com/p/go.crypto/ssh
しかし、Sessionを作るところまでは例があるからいいとして、その先がよくわからない。
セッションを開始するメソッドと以下のようなものがあるようだ。
- Run: コマンドを引数に指定。コマンドの実行が完了するまでWaitが掛かり、結果はSessionのStdio、Stderrに出力される。
- Start: コマンドを引数に指定。コマンドの実行完了を待たずに先に進む。結果はSessionのStdio、Stderrに出力される。つまり、Startメソッドを実行した直後には結果が出力されない。
- Shell: コマンドを実行せずにシェルを開始する。
- Output: コマンドを引数に指定。コマンドの実行が完了するまでWaitが掛かり、結果が戻り値に返る。
- CombinedOutput: コマンドを引数に指定。コマンドの実行が完了するまでWaitが掛かり、結果が戻り値に返る。標準出力に加え標準エラー出力が返る。
また、Sessionに対してこれらのメソッドは一度しか実行できない。
これらのメソッドの中で、Shell以外は非対話型的な実行を想定していると思われる。したがって、Shellを用いる。
Shellメソッドを実行すると、ログイン直後の出力がStdioに出力される。これをOSの標準出力に出力するようにした。
session.Stdout = os.Stdout
session.Stderr = os.Stderr
次に、ログイン後のコマンド受付処理を実装する。コマンドはStdinに受け付けられる。端末の標準入力から入力されたコマンドをStdinPipeを使ってSessionのStdinに伝える。
in, _ := session.StdinPipe()
for {
reader := bufio.NewReader(os.Stdin)
str, _ := reader.ReadString('n')
fmt.Fprint(in, str)
}
この際、以下に注意する。
- StdinPipeはセッションを開始する前に取得すること。
- コマンドの末尾には改行コード(n)を付けること。
これで通常のsshコマンドと同等な対話型SSHクライアントが構築できる。
ただし、パスワードのマスクやテキストエディタの起動などがうまくできない。