go的多进程
虽然说可以直接用go的协程直接起子进程,但是为了保证当起子进程时父类的结构尽可能简单,变采用主进程起子进程的形式
异步起进程
主进程起进程,起协程监听子进程的执行情况,可以使后台的子进程跑满制定数量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| package main
import ( "log" "os" "strconv" )
var processChan = make(chan int, 10)
func processListen(process *os.Process) { p, _ := process.Wait() exitCode := p.ExitCode() log.Println("process finish ExitCode: ", exitCode) <-processChan }
func main() { poolsize := 8 for { for len(processChan) < poolsize {
procAttr := &os.ProcAttr{ Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}, Sys: &syscall.SysProcAttr{ Setpgid: true, Pdeathsig: syscall.SIGKILL, }, } process, err := os.StartProcess("/bin/bash", []string{"bash", "-c", "echo processChan size: " + strconv.Itoa(len(processChan))}, procAttr) if err != nil { log.Println("StartProcess err: ", err) continue } processChan <- -1 go processListen(process) } }
}
|
分批同步起线程
每次都起poolsize数量的进程,当后台的子进程全执行完之后,再起新的一批
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| package main
import ( "os" ) func main() { poolsize := 8 for { for i:= 0; i < poolsize ;i++{ var processId []*os.Process var size int procAttr := &os.ProcAttr{ Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}, Sys: &syscall.SysProcAttr{ Setpgid: true, Pdeathsig: syscall.SIGKILL, }, }
process, err := os.StartProcess("/bin/bash", []string{"bash", "-c", "echo process start"}, procAttr)
if err != nil { log.Println("StartProcess err: ", err) ifsuccess = 0 continue } size++ processId = append(processId, process) } for size > 0 { p, _ := processId[size-1].Wait() exitCode := p.ExitCode() size-- log.Println("exitCode: ", exitCode) } } }
|
坑
exec.Commond
也可以使用exec.Commond 但是cmd结构体中的process不能外部访问,我不知道怎么用这个获取进程的exitcode,所以没用。
os.ProcessState.kill()
当执行这个自带的kill函数后向子进程发送的并不是 kill 信号 而是kill -9 这将导致子进程占用的资源不会被正常释放,从而变成僵尸进程