go的多进程
虽然说可以直接用go的协程直接起子进程,但是为了保证当起子进程时父类的结构尽可能简单,变采用主进程起子进程的形式
异步起进程
主进程起进程,起协程监听子进程的执行情况,可以使后台的子进程跑满制定数量
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数量的进程,当后台的子进程全执行完之后,再起新的一批
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 这将导致子进程占用的资源不会被正常释放,从而变成僵尸进程