Run External Process
We can use os/exec
module's Command
function to call external program.
Use Output
proc := exec.Command("ls", "-l")
output, err := proc.Output()
if err != nil {
log.Fatalln("Process running error", err)
}
fmt.Println(string(output))
Use Run
proc2 := exec.Command("cd", "/")
if err := proc2.Run(); err != nil {
log.Fatalln("Process running error", err)
}
fmt.Println(proc2.ProcessState.Success()) // true or false to indicate program successfully terminated
Use Start
and Wait
Start
starts the specified command but does not wait for it to complete. (Run asynchronously)
proc3 := exec.Command("ls", "-l")
out := bytes.NewBuffer([]byte{})
proc3.Stdout = out
proc3.Start()
proc3.Wait()
if proc3.ProcessState.Success() {
fmt.Print(out.String())
}
Result:
total 8
-rw-r--r-- 1 johndoe staff 1237 Apr 22 23:12 main.go
Use StdoutPipe
The code below will monitor external program's stdout, and set a running max time. When the time is up, master will keep the child program.
proc4 := exec.Command("ping", "google.com")
stdout, err := proc4.StdoutPipe()
proc4.Start()
quit := make(chan bool)
ch := make(chan string)
go func() {
buf := make([]byte, 512)
for {
n, err := stdout.Read(buf)
if err != nil {
fmt.Println("Process stdout error", err)
break
}
if n != 0 {
ch <- string(buf[:n])
}
}
fmt.Println("Process ended")
close(ch)
}()
quit := make(chan bool)
time.AfterFunc(5*time.Second, func() {
quit <- true
})
running:
for {
select {
case s, ok := <-ch:
if !ok {
break running
}
fmt.Print(s)
case <-quit:
fmt.Println("Process running timeout")
proc4.Process.Kill()
}
}
Result:
PING google.com (172.217.9.238): 56 data bytes
64 bytes from 172.217.9.238: icmp_seq=0 ttl=116 time=13.415 ms
64 bytes from 172.217.9.238: icmp_seq=1 ttl=116 time=20.761 ms
64 bytes from 172.217.9.238: icmp_seq=2 ttl=116 time=20.706 ms
64 bytes from 172.217.9.238: icmp_seq=3 ttl=116 time=21.156 ms
64 bytes from 172.217.9.238: icmp_seq=4 ttl=116 time=19.031 ms
Process running timeout
Process stdout error EOF
Process ended