ssh
前言
日常运维、批量服务器管理、自动化运维脚本开发中,SSH 远程操作是必备能力。Go 生态中最标准、使用最广泛的 SSH 客户端库就是 golang.org/x/crypto/ssh,支持密码登录、SSH 私钥登录、远程命令执行、交互式终端等常用能力。
本文从零带你快速入门,梳理核心用法、完整可运行代码、常用场景封装,拿来就能直接用到项目中。
一、安装依赖
Go 标准库未内置 SSH 相关能力,需要安装官方扩展加密包:
go get golang.org/x/crypto/ssh
二、SSH 核心使用流程
使用 Go ssh 包,固定遵循三步流程,记住即可上手:
- 组装客户端配置:用户名、认证方式(密码/私钥)、连接超时、主机密钥校验策略
- 建立 TCP+SSH 连接
- 创建 Session 会话,执行远程命令、获取标准输出与错误输出
三、方式一:密码登录 + 执行远程命令
最简单常用的方式,适合测试环境、内网服务器运维。
完整示例代码
package main
import (
"bytes"
"fmt"
"log"
"time"
"golang.org/x/crypto/ssh"
)
func main() {
// 1. 构造SSH客户端配置
sshConfig := &ssh.ClientConfig{
User: "root",
Timeout: 5 * time.Second,
HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 测试环境忽略主机密钥校验
Auth: []ssh.AuthMethod{
ssh.Password("你的服务器密码"),
},
}
// 2. 建立SSH连接
client, err := ssh.Dial("tcp", "192.168.1.100:22", sshConfig)
if err != nil {
log.Fatalf("SSH连接失败: %v", err)
}
defer client.Close()
fmt.Println("SSH 连接成功")
// 3. 创建会话
session, err := client.NewSession()
if err != nil {
log.Fatalf("创建会话失败: %v", err)
}
defer session.Close()
// 绑定标准输出、标准错误
var stdout, stderr bytes.Buffer
session.Stdout = &stdout
session.Stderr = &stderr
// 执行远程命令
cmd := "ls -l /home && uptime"
if err := session.Run(cmd); err != nil {
log.Fatalf("命令执行失败: %v\n错误信息: %s", err, stderr.String())
}
// 打印结果
fmt.Println("===== 命令执行结果 =====")
fmt.Println(stdout.String())
}
关键说明
HostKeyCallback: ssh.InsecureIgnoreHostKey():跳过服务器公钥校验,仅测试环境使用session.Run():阻塞执行命令,命令结束后自动返回- 通过
bytes.Buffer接收标准输出和错误输出,方便业务解析
四、方式二:SSH 私钥登录(生产推荐)
生产环境禁止密码明文登录,优先使用 SSH 私钥免密登录,兼容服务器默认 id_rsa 密钥。
完整示例代码
package main
import (
"bytes"
"fmt"
"log"
"os"
"time"
"golang.org/x/crypto/ssh"
)
func main() {
// 1. 读取本地私钥文件
keyPath := "/home/用户/.ssh/id_rsa"
privateKeyBytes, err := os.ReadFile(keyPath)
if err != nil {
log.Fatalf("读取私钥失败: %v", err)
}
// 2. 解析私钥
signer, err := ssh.ParsePrivateKey(privateKeyBytes)
if err != nil {
log.Fatalf("解析私钥失败: %v", err)
}
// 3. 组装SSH配置
sshConfig := &ssh.ClientConfig{
User: "root",
Timeout: 5 * time.Second,
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
Auth: []ssh.AuthMethod{
ssh.PublicKeys(signer),
},
}
// 4. 连接服务器
client, err := ssh.Dial("tcp", "192.168.1.100:22", sshConfig)
if err != nil {
log.Fatalf("SSH连接失败: %v", err)
}
defer client.Close()
// 5. 执行命令
session, _ := client.NewSession()
defer session.Close()
var stdout bytes.Buffer
session.Stdout = &stdout
_ = session.Run("df -h")
fmt.Println("磁盘信息:")
fmt.Println(stdout.String())
}
扩展:加密私钥
如果私钥设置了密码,使用带密码解析方法:
ssh.ParsePrivateKeyWithPassphrase(privateKeyBytes, []byte("私钥密码"))
五、常用高阶用法
1. 异步执行长耗时命令
适合 sleep、后台任务等长时间运行的命令,不阻塞等待:
session.Start("sleep 10 && echo 任务完成")
// 后续可做其他业务逻辑
session.Wait()
2. 开启伪终端(支持交互式命令)
执行 sudo、mysql 等交互式命令时,必须开启 PTY:
// 申请伪终端
session.RequestPty("xterm", 80, 40, ssh.TerminalModes{})
3. 拆解连接与命令执行
可封装成工具函数,复用 SSH 连接,批量执行多台服务器命令。
六、生产环境安全注意事项
- 禁止使用
ssh.InsecureIgnoreHostKey(),会跳过服务器身份校验,存在中间人攻击风险; - 密码登录不要硬编码在代码中,建议配置文件、环境变量读取;
- 优先使用 SSH 私钥登录,关闭服务器密码登录功能;
- 连接务必使用
defer client.Close()、defer session.Close()释放资源,避免连接泄露。
七、总结
- 依赖安装:
go get golang.org/x/crypto/ssh; - 固定流程:配置 → 连接 → Session 会话 → 执行命令;
- 两种认证:密码登录适合测试,私钥登录适合生产;
- 核心 API:
ssh.Dial建连、client.NewSession创建会话、session.Run执行命令。

浙公网安备 33010602011771号