PracticeDev/study_go/real-time-cmd/main.go

79 lines
1.7 KiB
Go
Raw Normal View History

2022-12-20 17:31:11 +08:00
package main
import (
"bufio"
"context"
"fmt"
"io"
"os/exec"
"sync"
"time"
)
func main() {
//ctx, cancel := context.WithCancel(context.Background())
//go func(cancelFunc context.CancelFunc) {
// time.Sleep(10 * time.Second)
// cancelFunc()
//}(cancel)
//err := Command(ctx, "ping www.baidu.com")
//if err != nil {
// return
//}
//err := RunWithTimeout(10*time.Second, "ping www.baidu.com")
//if err != nil {
// return
//}
err := RunCmd("ping www.baidu.com")
if err != nil {
return
}
}
func RunWithTimeout(timeout time.Duration, cmd string) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
return Command(ctx, cmd)
}
func RunCmd(cmd string) error {
return Command(context.Background(), cmd)
}
func Command(ctx context.Context, cmd string) error {
// c := exec.CommandContext(ctx, "cmd", "/C", cmd)
c := exec.CommandContext(ctx, "bash", "-c", cmd) // mac linux
stdout, err := c.StdoutPipe()
if err != nil {
return err
}
var wg sync.WaitGroup
wg.Add(1)
go func(wg *sync.WaitGroup) {
defer wg.Done()
reader := bufio.NewReader(stdout)
for {
// 其实这段去掉程序也会正常运行只是我们就不知道到底什么时候Command被停止了而且如果我们需要实时给web端展示输出的话这里可以作为依据 取消展示
select {
// 检测到ctx.Done()之后停止读取
case <-ctx.Done():
if ctx.Err() != nil {
fmt.Printf("程序出现错误: %q", ctx.Err())
} else {
fmt.Println("程序被终止")
}
return
default:
readString, err := reader.ReadString('\n')
if err != nil || err == io.EOF {
return
}
fmt.Print(readString)
}
}
}(&wg)
err = c.Start()
wg.Wait()
return err
}