|
|
@@ -0,0 +1,89 @@
|
|
|
+//go:build !windows
|
|
|
+// +build !windows
|
|
|
+
|
|
|
+package utils
|
|
|
+
|
|
|
+import (
|
|
|
+ "bytes"
|
|
|
+ "context"
|
|
|
+ log "github.com/sirupsen/logrus"
|
|
|
+ "os/exec"
|
|
|
+ "syscall"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+func ScriptCMD(path string, param ...string) (string, error) {
|
|
|
+ // TODO: 执行command, 没有超时的限制吗?需要升级go版本, 升级到1.6也不行哈, 换一种方式context @jay
|
|
|
+ // cmd := exec.Command(path, param...)
|
|
|
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
|
|
+ defer cancel()
|
|
|
+ cmd := exec.CommandContext(ctx, path, param...)
|
|
|
+ var out bytes.Buffer
|
|
|
+ cmd.Stdout = &out
|
|
|
+ // cmd.Timeout = time.Second * 10
|
|
|
+ err := cmd.Run()
|
|
|
+ result := out.String()
|
|
|
+
|
|
|
+ log.Infof("cmd content : [%s] cmd error :[%v]", result, err)
|
|
|
+ if err != nil {
|
|
|
+ log.Errorf("path %s param %v error %s", path, param, err)
|
|
|
+ return result, err
|
|
|
+ }
|
|
|
+ //result = out.String()
|
|
|
+ return result, err
|
|
|
+}
|
|
|
+
|
|
|
+func ScriptCMDNO(path string, param ...string) (string, error) {
|
|
|
+ return ScriptCMD(path, param...)
|
|
|
+ //cmd := exec.Command(path, param...)
|
|
|
+ //var out bytes.Buffer
|
|
|
+ //cmd.Stdout = &out
|
|
|
+ //err := cmd.Run()
|
|
|
+ //if err != nil {
|
|
|
+ // log.Error(err)
|
|
|
+ // return "", err
|
|
|
+ //}
|
|
|
+ //result := out.String()
|
|
|
+ //return result, err
|
|
|
+}
|
|
|
+
|
|
|
+// 提权cmd
|
|
|
+func AuthoritativeCMD(uid32 uint32, waitTime time.Duration, osEnv []string, command string, args ...string) (string, error) {
|
|
|
+ log.Infof("AuthoritativeCMD [command = %s][args = %v][waitTime=%v][uid=%d]", command, args, waitTime, uid32)
|
|
|
+ ctx, cancel := context.WithTimeout(context.Background(), waitTime)
|
|
|
+ defer cancel()
|
|
|
+ cmd := exec.CommandContext(ctx, command, args...)
|
|
|
+ cmd.Env = osEnv
|
|
|
+ cmd.SysProcAttr = &syscall.SysProcAttr{
|
|
|
+ // 设置子进程为相同pgid,防止子进程再次fork的子进程脱管
|
|
|
+ //Setpgid: true,
|
|
|
+ // 提权执行
|
|
|
+ Credential: &syscall.Credential{
|
|
|
+ Uid: uid32,
|
|
|
+ },
|
|
|
+ }
|
|
|
+ go func() {
|
|
|
+ defer func() {
|
|
|
+ if err := recover(); err != nil {
|
|
|
+ log.Errorf("AuthoritativeCMD panic:%v", err)
|
|
|
+ }
|
|
|
+ }()
|
|
|
+ select {
|
|
|
+ case <-ctx.Done():
|
|
|
+ err := syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
|
|
|
+ if err == nil {
|
|
|
+ log.Warnf("Timeout kill success : [%d], err:[%v]", cmd.Process.Pid, err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }()
|
|
|
+ content, err := cmd.CombinedOutput()
|
|
|
+ log.Infof("cmd content : [%s] cmd error :[%v]", content, err)
|
|
|
+ if err != nil {
|
|
|
+ return string(content), err
|
|
|
+ }
|
|
|
+ return string(content), err
|
|
|
+}
|
|
|
+
|
|
|
+func BackgroundCMD(uid32 uint32, waitTime time.Duration, osEnv []string, command string, args ...string) (string, error) {
|
|
|
+ return "ok", nil
|
|
|
+}
|