如何使用Golang exec调用scutil监控macOS网络变化并输出到Channel
在Golang中执行scutil监控命令并将结果输出到Channel
直接用exec.Command执行原命令会失败,因为该命令依赖shell的管道、子shell等特性,Go默认不会启动shell解析这些语法。以下是实现方案:
核心思路
- 调用系统shell(如
bash)执行完整命令串,解析shell语法 - 捕获命令的标准输出,将输出内容实时发送到指定Channel
- 处理命令执行中的错误和退出逻辑,确保Channel能正确关闭
实现代码
package main import ( "bufio" "os/exec" "sync" ) // MonitorIPv4State 启动scutil监控并将输出发送到channel func MonitorIPv4State(outputChan chan<- string) error { // 用bash执行完整的监控命令 cmd := exec.Command("bash", "-c", `(echo -e "n.add State:/Network/Global/IPv4\nn.watch" & cat) | scutil`) // 获取命令的标准输出管道 stdout, err := cmd.StdoutPipe() if err != nil { return err } // 启动命令 if err := cmd.Start(); err != nil { return err } var wg sync.WaitGroup wg.Add(1) // 启动goroutine读取输出并发送到channel go func() { defer wg.Done() defer close(outputChan) scanner := bufio.NewScanner(stdout) for scanner.Scan() { line := scanner.Text() outputChan <- line } }() // 等待命令执行完成和输出读取结束 go func() { cmd.Wait() wg.Wait() }() return nil } // 示例使用 func main() { // 创建带缓冲的channel,根据需求调整缓冲大小 outputChan := make(chan string, 10) err := MonitorIPv4State(outputChan) if err != nil { panic(err) } // 读取channel中的监控结果 for line := range outputChan { println("监控输出:", line) } }
关键说明
- 使用
bash -c包裹原命令,让shell处理子shell、管道和echo的转义字符 - 通过
StdoutPipe获取命令的实时输出,用bufio.Scanner逐行读取 - 用
sync.WaitGroup确保输出读取完成后再关闭channel,避免数据丢失 - channel的缓冲大小可根据实际监控输出频率调整,防止阻塞
内容的提问来源于stack exchange,提问作者Peilin Wu
相关产品推荐
相关产品推荐

