Go语言远程执行ssh命令简单封装(支持带交互命令)
使用包:golang.org/x/crypto/ssh
以下封装一个发送命令的Cli结构体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | package utils import ( "fmt" "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/terminal" "io" "net" "os" "time" ) type Cli struct { IP string //IP地址 Username string //用户名 Password string //密码 Port int //端口号 client *ssh.Client //ssh客户端 LastResult string //最近一次Run的结果 } //创建命令行对象 //@param ip IP地址 //@param username 用户名 //@param password 密码 //@param port 端口号,默认22 func New(ip string, username string, password string, port ...int) *Cli { cli := new(Cli) cli.IP = ip cli.Username = username cli.Password = password if len(port) <= 0 { cli.Port = 22 } else { cli.Port = port[0] } return cli } //执行shell //@param shell shell脚本命令 func (c Cli) Run(shell string) (string, error) { if c.client == nil { if err := c.connect(); err != nil { return "" , err } } session, err := c.client.NewSession() if err != nil { return "" , err } defer session.Close() buf, err := session.CombinedOutput(shell) c.LastResult = string(buf) return c.LastResult, err } //连接 func (c *Cli) connect() error { config := ssh.ClientConfig{ User: c.Username, Auth: []ssh.AuthMethod{ssh.Password(c.Password)}, HostKeyCallback: func (hostname string, remote net.Addr, key ssh.PublicKey) error { return nil }, Timeout: 10 * time.Second, } addr := fmt.Sprintf( "%s:%d" , c.IP, c.Port) sshClient, err := ssh.Dial( "tcp" , addr, &config) if err != nil { return err } c.client = sshClient return nil } |
测试执行shell代码
1 2 3 | cli := New( "IP" , "用户名" , "密码" , 端口号) output, err := cli.Run( "free -h" ) fmt.Printf( "%v\n%v" , output, err) |
还有类似top或者vim的命令是需要交互的,可以利用包golang.org/x/crypto/ssh/terminal实现
再封装一个方法RunTerminal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | //执行带交互的命令 func (c *Cli) RunTerminal(shell string, stdout, stderr io.Writer) error { if c.client == nil { if err := c.connect(); err != nil { return err } } session, err := c.client.NewSession() if err != nil { return err } defer session.Close() fd := int(os.Stdin.Fd()) oldState, err := terminal.MakeRaw(fd) if err != nil { panic(err) } defer terminal.Restore(fd, oldState) session.Stdout = stdout session.Stderr = stderr session.Stdin = os.Stdin termWidth, termHeight, err := terminal.GetSize(fd) if err != nil { panic(err) } // Set up terminal modes modes := ssh.TerminalModes{ ssh.ECHO: 1, // enable echoing ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud } // Request pseudo terminal if err := session.RequestPty( "xterm-256color" , termHeight, termWidth, modes); err != nil { return err } session.Run(shell) return nil } |
测试RunTerminal方法
1 | cli := New( "IP" , "用户名" , "密码" , 端口号) cli.RunTerminal( "top" , os.Stdout, os.Stdin) |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)