Go SDK¶
win-sshpass はコマンドラインツールであるだけでなく、再利用可能な Go ライブラリ(package sshpass)でもあります。SSH/SFTP/Shell 機能を自分のアプリケーションに組み込むことができます。
インストール¶
クイックスタート¶
package main
import (
"log"
sshpass "github.com/chuccp/win-sshpass"
)
func main() {
cfg := sshpass.NewConfig()
cfg.Host = "example.com"
cfg.User = "root"
cfg.Password = "secret"
// NewClient は接続を確立し、すぐに使えるクライアントを返します
client, err := sshpass.NewClient(cfg, sshpass.WithSignalHandler())
if err != nil {
log.Fatal(err)
}
defer client.Close()
// コマンド実行(出力ストリームはデフォルトで os.Stdout/os.Stderr)
if err := client.Exec("uname -a"); err != nil {
log.Fatal(err)
}
}
Client のコアメソッド¶
NewClient¶
SSH 接続を確立し、クライアントを返します:
cfg: 接続設定(*sshpass.Config)opts: オプションの関数オプション(...sshpass.Option)cfg.Timeout > 0の場合、操作タイマーが設定され、期限切れになると接続が閉じられます
Exec¶
単一のリモートコマンドを実行:
- 出力ストリームは
WithStdout/WithStderrで設定(デフォルト:os.Stdout/os.Stderr) - 入力ストリームは
WithStdinで設定(デフォルト:os.Stdin)
Shell¶
インタラクティブシェルを開始:
- ターミナルを自動検出し、PTY とローモードをサポート
- 動的ターミナルリサイズをサポート
- rz/sz ファイル転送をサポート(
WithFileSelectorの設定が必要)
SFTP¶
SFTP サブチャンネルを開く:
sftp, err := client.SFTP()
if err != nil {
log.Fatal(err)
}
defer sftp.Close()
// ファイルのアップロード
err = sftp.Upload("./local.txt", "/tmp/remote.txt")
// ファイルのダウンロード
err = sftp.Download("/tmp/remote.txt", "./local.txt")
// 基底の *sftp.Client にアクセス(上級者向け)
rawClient := sftp.SFTP()
Close¶
SSH 接続を閉じる:
- 冪等操作 — 複数回呼び出しても同じエラーを返します
- タイマーとシグナルハンドラーを自動的に停止
TimedOut¶
タイムアウトが原因で失敗したかチェック:
設定(Config)¶
cfg := sshpass.NewConfig()
cfg.Host = "example.com"
cfg.User = "root"
cfg.Password = "secret"
cfg.Port = "22"
cfg.KeyPath = "~/.ssh/id_ed25519"
cfg.StrictHostKey = true
cfg.Timeout = 30 // 操作タイムアウト(秒)、0 = 無制限
cfg.ConnectTimeout = 10 // TCP 接続タイムアウト(秒)
cfg.Retries = 3 // 接続リトライ回数
設定ファイルから読み込み¶
設定ファイルまたはパスワードファイルの読み込み¶
cfg, pass, err := sshpass.LoadConfigOrPasswordFile("file.txt", "", false)
if cfg != nil {
// 設定ファイルです
} else {
// パスワードファイルです。pass にパスワードが含まれています
}
関数オプション¶
関数オプションで Client の動作を設定:
I/O ストリーム¶
// 入出力のリダイレクト
client, err := sshpass.NewClient(cfg,
sshpass.WithStdin(myReader),
sshpass.WithStdout(myWriter),
sshpass.WithStderr(myWriter),
)
プログレスコールバック¶
client, err := sshpass.NewClient(cfg,
sshpass.WithProgress(func(desc string, sent, total int64) {
fmt.Printf("\r%s %d/%d bytes", desc, sent, total)
}),
)
desc: 転送の説明(例:"Uploading file.txt")sent: これまでに転送されたバイト数total: ファイルの合計サイズ- SDK はレンダリングを行いません — 呼び出し元がプログレスを表示します
ファイルセレクター¶
type myFileSelector struct{}
func (s myFileSelector) OpenFile() (string, error) {
// ファイルオープンダイアログを実装
return "/path/to/file", nil
}
func (s myFileSelector) SaveFile(defaultName string) (string, error) {
// ファイル保存ダイアログを実装
return "/path/to/save", nil
}
client, err := sshpass.NewClient(cfg,
sshpass.WithFileSelector(myFileSelector{}),
)
rz/sz シェル転送のファイル選択に使用されます。SDK はデフォルトの実装を提供しません。
シグナルハンドラー¶
接続を閉じる Ctrl+C ハンドラーを登録します。デフォルトではオフで、ホストのシグナル処理を妨げません。
低レベル API¶
Dial¶
SSH クライアント接続を直接作成:
より低レベルの制御が必要なシナリオ用に *ssh.Client を返します。
引数の解析¶
// SSH 引数の解析
config, cmd := sshpass.ParseSSHArgs([]string{"ssh", "user@host", "ls"})
// SCP 引数の解析
config, args := sshpass.ParseSCPArgs([]string{"scp", "file.txt", "user@host:/tmp/"})
// Rsync 引数の解析
config, args := sshpass.ParseRsyncArgs([]string{"rsync", "-avz", "./", "user@host:/backup/"})
// コマンドタイプの検出
cmdType := sshpass.DetectCommandType(args)
ユーティリティ関数¶
// SCP 転送の実行
err := sshpass.RunSCP(client, args)
// Rsync 転送の実行
err := sshpass.RunRsync(client, args)
// リモートパスのクリーンアップ(Git Bash パス変換の処理)
path, err := sshpass.CleanRemotePath("//tmp/file.txt")
// user@host:path フォーマットの解析
user, host, path := sshpass.ParseUserHostPath("user@host:/tmp/file.txt")
// パスの分割(カンマまたはスペース区切り)
paths, err := sshpass.SplitPaths("a.txt,b.txt,c.txt", "local")
// エラーから終了コードを抽出
code, ok := sshpass.ExitCodeFromError(err)
完全な例¶
バッチコマンド実行¶
package main
import (
"fmt"
"log"
sshpass "github.com/chuccp/win-sshpass"
)
func main() {
hosts := []string{"192.168.1.101", "192.168.1.102", "192.168.1.103"}
for _, host := range hosts {
cfg := sshpass.NewConfig()
cfg.Host = host
cfg.User = "root"
cfg.Password = "secret"
client, err := sshpass.NewClient(cfg)
if err != nil {
log.Printf("[%s] 接続失敗: %v", host, err)
continue
}
fmt.Printf("[%s] コマンド実行中...\n", host)
if err := client.Exec("uptime"); err != nil {
log.Printf("[%s] コマンド失敗: %v", host, err)
}
client.Close()
}
}
プログレス付きファイルアップロード¶
package main
import (
"fmt"
"log"
sshpass "github.com/chuccp/win-sshpass"
)
func main() {
cfg := sshpass.NewConfig()
cfg.Host = "example.com"
cfg.User = "root"
cfg.Password = "secret"
client, err := sshpass.NewClient(cfg,
sshpass.WithProgress(func(desc string, sent, total int64) {
pct := sent * 100 / total
fmt.Printf("\r%s %d%%", desc, pct)
}),
)
if err != nil {
log.Fatal(err)
}
defer client.Close()
sftp, err := client.SFTP()
if err != nil {
log.Fatal(err)
}
defer sftp.Close()
if err := sftp.Upload("./large-file.zip", "/tmp/large-file.zip"); err != nil {
log.Fatal(err)
}
fmt.Println("\nアップロード完了!")
}
次のステップ¶
- ベストプラクティス - セキュリティと効率のヒント