我正在尝试同时生成多个命令,然后在第一个任务完成时将它们全部关闭。
问题在于,有时在生成dotnet服务器并使用sudo浏览我的项目时,在应用程序终止时,生成的进程不会终止。
为什么会发生这种情况以及如何终止进程?
大概这个
func createCommand(command string) {
var cmd *exec.Cmd
cmd = exec.Command("/bin/bash", "-c", command)
return cmd
}
func main() {
commands := []string{
"cd server1 && dotnet run",
"cd server2 && dotnet run",
"sleep 10 && echo complete"
}
var wg sync.WaitGroup
wg.Add(1)
var cmds []*exec.Cmd
defer func() {
fmt.Println("Process clean up")
for _, cmd := range cmds {
cmd.Process.Kill()
}
}()
for _, command := range commands {
cmd := createCommand(command)
cmds = append(cmds, cmd)
go func (c string) {
defer wg.Done()
c.Start()
c.Wait()
}(cmd)
}
wg.Wait()
}
答案 0 :(得分:1)
我不确定sudo的问题。但是您的代码存在以下问题:
您正在生成3个goroutine,但仅向等待组中添加了1个,因此您可能出错了,或者您的代码实际上仅运行了1条命令,而其他2条则不会运行。如果需要3,请将3添加到等待组。
我在go docs中找不到cmd.Process.Kill(),但看到了os.Process.Kill。但是,建议使用上下文取消进程。有了上下文,您的命令肯定会终止。
下面的代码演示了我的想法:
package main
import (
"os/exec"
"fmt"
"sync"
"context"
"time"
)
func createCommand(ctx context.Context, command string) *exec.Cmd{
return exec.CommandContext(ctx, "/bin/bash", "-c", command)
}
func main() {
commands := []string{
"sleep 1000000 && echo complete",
"sleep 1000000 && echo complete",
"sleep 10 && echo complete",
}
var wg sync.WaitGroup
wg.Add(3)
var cmds []*exec.Cmd
ctx, cancel := context.WithTimeout(context.Background(), 20 * time.Second)
defer func() {
fmt.Println("Process clean up")
cancel()
}()
for _, command := range commands {
fmt.Printf("Create command %s\n", command)
cmd := createCommand(ctx, command)
cmds = append(cmds, cmd)
go func (c *exec.Cmd, name string) {
fmt.Printf("Process command %s\n", name)
defer wg.Done()
c.Start()
c.Wait()
fmt.Printf("Finish command %s\n", name)
}(cmd, command)
}
wg.Wait()
}
输出为:
Create command sleep 1000000 && echo complete
Create command sleep 1000000 && echo complete
Create command sleep 10 && echo complete
Process command sleep 10 && echo complete
Finish command sleep 10 && echo complete
Process command sleep 1000000 && echo complete
Finish command sleep 1000000 && echo complete
Process command sleep 1000000 && echo complete
Finish command sleep 1000000 && echo complete
Process clean up