mirror of
https://github.com/nezhahq/nezha.git
synced 2025-02-08 12:38:13 -05:00
[agent v0.3.6] 🐛 fix: kill process group
This commit is contained in:
parent
e439747c09
commit
0f24c0d7ef
@ -234,18 +234,32 @@ func doTask(task *pb.Task) {
|
|||||||
startedAt := time.Now()
|
startedAt := time.Now()
|
||||||
var cmd *exec.Cmd
|
var cmd *exec.Cmd
|
||||||
var endCh = make(chan struct{})
|
var endCh = make(chan struct{})
|
||||||
|
var pg utils.ProcessExitGroup
|
||||||
timeout := time.NewTimer(time.Hour * 2)
|
timeout := time.NewTimer(time.Hour * 2)
|
||||||
if utils.IsWindows() {
|
if utils.IsWindows() {
|
||||||
|
var err error
|
||||||
|
pg, err = utils.NewProcessExitGroup()
|
||||||
|
if err != nil {
|
||||||
|
// Windows 进程组创建失败,直接退出
|
||||||
|
result.Data = err.Error()
|
||||||
|
client.ReportTask(ctx, &result)
|
||||||
|
return
|
||||||
|
}
|
||||||
cmd = exec.Command("cmd", "/c", task.GetData())
|
cmd = exec.Command("cmd", "/c", task.GetData())
|
||||||
|
pg.AddProcess(cmd.Process)
|
||||||
} else {
|
} else {
|
||||||
cmd = exec.Command("sh", "-c", task.GetData())
|
cmd = exec.Command("sh", "-c", task.GetData())
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
||||||
}
|
}
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
|
||||||
go func() {
|
go func() {
|
||||||
select {
|
select {
|
||||||
case <-timeout.C:
|
case <-timeout.C:
|
||||||
result.Data = "任务执行超时\n"
|
result.Data = "任务执行超时\n"
|
||||||
cmd.Process.Kill()
|
if utils.IsWindows() {
|
||||||
|
pg.Dispose()
|
||||||
|
} else {
|
||||||
|
cmd.Process.Kill()
|
||||||
|
}
|
||||||
close(endCh)
|
close(endCh)
|
||||||
case <-endCh:
|
case <-endCh:
|
||||||
}
|
}
|
||||||
|
@ -80,13 +80,19 @@ func cmdExec() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
var cmd *exec.Cmd
|
var cmd *exec.Cmd
|
||||||
|
var pg utils.ProcessExitGroup
|
||||||
if utils.IsWindows() {
|
if utils.IsWindows() {
|
||||||
|
pg, err = utils.NewProcessExitGroup()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
cmd = exec.Command("cmd", "/c", execFrom+"/cmd/playground/example.sh hello asd")
|
cmd = exec.Command("cmd", "/c", execFrom+"/cmd/playground/example.sh hello asd")
|
||||||
|
pg.AddProcess(cmd.Process)
|
||||||
} else {
|
} else {
|
||||||
cmd = exec.Command("sh", "-c", execFrom+`/cmd/playground/example.sh hello && \
|
cmd = exec.Command("sh", "-c", execFrom+`/cmd/playground/example.sh hello && \
|
||||||
echo world!`)
|
echo world!`)
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
||||||
}
|
}
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
|
||||||
var endCh = make(chan struct{})
|
var endCh = make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
output, err := cmd.Output()
|
output, err := cmd.Output()
|
||||||
@ -97,8 +103,14 @@ echo world!`)
|
|||||||
go func() {
|
go func() {
|
||||||
time.Sleep(time.Second * 2)
|
time.Sleep(time.Second * 2)
|
||||||
fmt.Println("killed")
|
fmt.Println("killed")
|
||||||
if err := syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL); err != nil {
|
if utils.IsWindows() {
|
||||||
panic(err)
|
if err := pg.Dispose(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
select {
|
select {
|
||||||
|
1
go.mod
1
go.mod
@ -22,6 +22,7 @@ require (
|
|||||||
github.com/spf13/viper v1.7.1
|
github.com/spf13/viper v1.7.1
|
||||||
github.com/stretchr/testify v1.6.1
|
github.com/stretchr/testify v1.6.1
|
||||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
|
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
|
||||||
|
golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5
|
||||||
google.golang.org/grpc v1.33.1
|
google.golang.org/grpc v1.33.1
|
||||||
google.golang.org/protobuf v1.25.0
|
google.golang.org/protobuf v1.25.0
|
||||||
gopkg.in/yaml.v2 v2.2.8
|
gopkg.in/yaml.v2 v2.2.8
|
||||||
|
20
pkg/utils/proccess_group_darwin.go
Normal file
20
pkg/utils/proccess_group_darwin.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProcessExitGroup struct{}
|
||||||
|
|
||||||
|
func NewProcessExitGroup() (ProcessExitGroup, error) {
|
||||||
|
return ProcessExitGroup{}, errors.New("not implement")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g ProcessExitGroup) Dispose() error {
|
||||||
|
return errors.New("not implement")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g ProcessExitGroup) AddProcess(p *os.Process) error {
|
||||||
|
return errors.New("not implement")
|
||||||
|
}
|
20
pkg/utils/proccess_group_linux.go
Normal file
20
pkg/utils/proccess_group_linux.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProcessExitGroup struct{}
|
||||||
|
|
||||||
|
func NewProcessExitGroup() (ProcessExitGroup, error) {
|
||||||
|
return ProcessExitGroup{}, errors.New("not implement")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g ProcessExitGroup) Dispose() error {
|
||||||
|
return errors.New("not implement")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g ProcessExitGroup) AddProcess(p *os.Process) error {
|
||||||
|
return errors.New("not implement")
|
||||||
|
}
|
49
pkg/utils/proccess_group_windows.go
Normal file
49
pkg/utils/proccess_group_windows.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
// We use this struct to retreive process handle(which is unexported)
|
||||||
|
// from os.Process using unsafe operation.
|
||||||
|
type process struct {
|
||||||
|
Pid int
|
||||||
|
Handle uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProcessExitGroup windows.Handle
|
||||||
|
|
||||||
|
func NewProcessExitGroup() (ProcessExitGroup, error) {
|
||||||
|
handle, err := windows.CreateJobObject(nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := windows.JOBOBJECT_EXTENDED_LIMIT_INFORMATION{
|
||||||
|
BasicLimitInformation: windows.JOBOBJECT_BASIC_LIMIT_INFORMATION{
|
||||||
|
LimitFlags: windows.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if _, err := windows.SetInformationJobObject(
|
||||||
|
handle,
|
||||||
|
windows.JobObjectExtendedLimitInformation,
|
||||||
|
uintptr(unsafe.Pointer(&info)),
|
||||||
|
uint32(unsafe.Sizeof(info))); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProcessExitGroup(handle), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g ProcessExitGroup) Dispose() error {
|
||||||
|
return windows.CloseHandle(windows.Handle(g))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g ProcessExitGroup) AddProcess(p *os.Process) error {
|
||||||
|
return windows.AssignProcessToJobObject(
|
||||||
|
windows.Handle(g),
|
||||||
|
windows.Handle((*process)(unsafe.Pointer(p)).Handle))
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user