golang执行命令 && 实时获取输出结果

[复制链接]
发表于 2023-2-19 16:53:38 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
背景


  • golang可以获取命令执行的输出结果,但要执行完才能够获取。
  • 如果执行的命令是ssh,我们要实时获取,并执行相应的操作呢?
示例
  1. func main() {
  2.         user := "root"
  3.         host := "172.16.116.133"
  4.         //获取执行命令
  5.         cmd := exec.Command("ssh", fmt.Sprintf("%s@%s", user, host))
  6.         cmd.Stdin = os.Stdin
  7.         var wg sync.WaitGroup
  8.         wg.Add(2)
  9.         //捕获标准输出
  10.         stdout, err := cmd.StdoutPipe()
  11.         if err != nil {
  12.                 fmt.Println("ERROR:", err)
  13.                 os.Exit(1)
  14.         }
  15.         readout := bufio.NewReader(stdout)
  16.         go func() {
  17.                 defer wg.Done()
  18.                 GetOutput(readout)
  19.         }()
  20.         //捕获标准错误
  21.         stderr, err := cmd.StderrPipe()
  22.         if err != nil {
  23.                 fmt.Println("ERROR:", err)
  24.                 os.Exit(1)
  25.         }
  26.         readerr := bufio.NewReader(stderr)
  27.         go func() {
  28.                 defer wg.Done()
  29.                 GetOutput(readerr)
  30.         }()
  31.         //执行命令
  32.         cmd.Run()
  33.         wg.Wait()
  34.         return
  35. }
  36. func GetOutput(reader *bufio.Reader) {
  37.         var sumOutput string                                //统计屏幕的全部输出内容
  38.         outputBytes := make([]byte, 200)
  39.         for {
  40.                 n, err := reader.Read(outputBytes)                //获取屏幕的实时输出(并不是按照回车分割,所以要结合sumOutput)
  41.                 if err != nil {
  42.                         if err == io.EOF {
  43.                                 break
  44.                         }
  45.                         fmt.Println(err)
  46.                         sumOutput += err.Error()
  47.                 }
  48.                 output := string(outputBytes[:n])
  49.                 fmt.Print(output) //输出屏幕内容
  50.                 sumOutput += output
  51.         }
  52.         return
  53. }
复制代码
应用场景

ssh是交互式命令,本示例实现了实时获取输出结果,并判断输出结果中有没有报错,报错则重试(再次登陆)。
场景:本Demo只是把"错误"二字视为异常,然后重试,实际上比这复杂的多,比如ssh连接超时重试等,这个逻辑请自行补充。
[code]package mainimport (        "bufio"        "fmt"        "io"        "os"        "os/exec"        "strings"        "sync"        "time")func main(){        retryTimes := 3        var retryInterval time.Duration = 3        user := "root"        host := "172.16.116.133"        //部分场景下重试登录        shouldRetry := true        for i:=1;i
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表