最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

【速看料】golang执行命令 && 实时获取输出结果

来源:博客园


【资料图】

背景

  • golang可以获取命令执行的输出结果,但要执行完才能够获取。
  • 如果执行的命令是ssh,我们要实时获取,并执行相应的操作呢?

示例

func main() {user := "root"host := "172.16.116.133"//获取执行命令cmd := exec.Command("ssh", fmt.Sprintf("%s@%s", user, host))cmd.Stdin = os.Stdinvar wg sync.WaitGroupwg.Add(2)//捕获标准输出stdout, err := cmd.StdoutPipe()if err != nil {fmt.Println("ERROR:", err)os.Exit(1)}readout := bufio.NewReader(stdout)go func() {defer wg.Done()GetOutput(readout)}()//捕获标准错误stderr, err := cmd.StderrPipe()if err != nil {fmt.Println("ERROR:", err)os.Exit(1)}readerr := bufio.NewReader(stderr)go func() {defer wg.Done()GetOutput(readerr)}()//执行命令cmd.Run()wg.Wait()return}func GetOutput(reader *bufio.Reader) {var sumOutput string//统计屏幕的全部输出内容outputBytes := make([]byte, 200)for {n, err := reader.Read(outputBytes)//获取屏幕的实时输出(并不是按照回车分割,所以要结合sumOutput)if err != nil {if err == io.EOF {break}fmt.Println(err)sumOutput += err.Error()}output := string(outputBytes[:n])fmt.Print(output) //输出屏幕内容sumOutput += output}return}

应用场景

ssh是交互式命令,本示例实现了实时获取输出结果,并判断输出结果中有没有报错,报错则重试(再次登陆)。场景:本Demo只是把"错误"二字视为异常,然后重试,实际上比这复杂的多,比如ssh连接超时重试等,这个逻辑请自行补充。

package mainimport ("bufio""fmt""io""os""os/exec""strings""sync""time")func main(){retryTimes := 3var retryInterval time.Duration = 3user := "root"host := "172.16.116.133"//部分场景下重试登录shouldRetry := truefor i:=1;i<=retryTimes && shouldRetry;i++{//执行命令shouldRetry = RunSSHCommand(user,host)if !shouldRetry{return}time.Sleep(retryInterval * time.Second)}if shouldRetry{fmt.Println("\n失败,请重试或检查")}}func shouldRetryByOutput(output string)bool{if strings.Contains(output,"错误"){//匹配到"错误"就重试.这里只是Demo,请根据实际情况设置。return true}return false}func GetAndFilterOutput(reader *bufio.Reader)(shouldRetry bool){var sumOutput stringoutputBytes:= make([]byte,200)for {n,err := reader.Read(outputBytes)if err!=nil{if err == io.EOF{break}fmt.Println(err)sumOutput += err.Error()}output := string(outputBytes[:n])fmt.Print(output)//输出屏幕内容sumOutput += outputif shouldRetryByOutput(output){shouldRetry = true}}if shouldRetryByOutput(sumOutput){shouldRetry = true}return}func RunSSHCommand(user,host string)(shouldRetry bool){//获取执行命令cmd := exec.Command("ssh",fmt.Sprintf("%s@%s",user,host))cmd.Stdin = os.Stdinvar wg sync.WaitGroupwg.Add(2)//捕获标准输出stdout, err := cmd.StdoutPipe()if err != nil {fmt.Println("ERROR:",err)os.Exit(1)}readout := bufio.NewReader(stdout)go func() {defer wg.Done()shouldRetryTemp := GetAndFilterOutput(readout)if shouldRetryTemp{shouldRetry = true}}()//捕获标准错误stderr, err := cmd.StderrPipe()if err != nil {fmt.Println(err)os.Exit(1)}readerr := bufio.NewReader(stderr)go func() {defer wg.Done()shouldRetryTemp := GetAndFilterOutput(readerr)if shouldRetryTemp{shouldRetry = true}}()//执行命令cmd.Run()wg.Wait()return}

那年,郭少在京城。

关键词: 执行命令 标准输出 实时输出