Files
jiacrontab/pkg/kproc/proc_posix.go
jiazhizhong 1279635d7f fix
2022-03-10 17:09:03 +08:00

79 lines
1.3 KiB
Go

// +build !windows
package kproc
import (
"context"
"os"
"os/exec"
"os/user"
"strconv"
"syscall"
"github.com/iwannay/log"
)
func CommandContext(ctx context.Context, name string, arg ...string) *KCmd {
cmd := exec.CommandContext(ctx, name, arg...)
cmd.SysProcAttr = &syscall.SysProcAttr{}
cmd.SysProcAttr.Setsid = true
return &KCmd{
ctx: ctx,
Cmd: cmd,
isKillChildProcess: true,
done: make(chan struct{}),
}
}
// SetUser 设置执行用户要保证root权限
func (k *KCmd) SetUser(username string) {
if username == "" {
return
}
u, err := user.Lookup(username)
if err != nil {
log.Error("setUser error:", err)
return
}
log.Infof("KCmd set uid=%s,gid=%s", u.Uid, u.Gid)
k.SysProcAttr = &syscall.SysProcAttr{}
uid, _ := strconv.Atoi(u.Uid)
gid, _ := strconv.Atoi(u.Gid)
k.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}
}
func (k *KCmd) KillAll() {
select {
case k.done <- struct{}{}:
default:
}
if k.Process == nil {
return
}
if k.isKillChildProcess == false {
return
}
group, err := os.FindProcess(-k.Process.Pid)
if err == nil {
group.Signal(syscall.SIGKILL)
}
}
func (k *KCmd) Wait() error {
defer k.KillAll()
go func() {
select {
case <-k.ctx.Done():
k.KillAll()
case <-k.done:
}
}()
return k.Cmd.Wait()
}