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,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· [翻译] 为什么 Tracebit 用 C# 开发
· 腾讯ima接入deepseek-r1,借用别人脑子用用成真了~
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· DeepSeek崛起:程序员“饭碗”被抢,还是职业进化新起点?
· 深度对比:PostgreSQL 和 SQL Server 在统计信息维护中的关键差异