// +build linux darwin package staros import ( "bytes" "errors" "fmt" "io/ioutil" "os" "os/exec" "path/filepath" "strconv" "strings" "syscall" "time" ) //FindProcessByName 通过进程名来查询应用信息 func FindProcessByName(name string) (datas []Process, err error) { return FindProcess(func(in Process) bool { if name == in.Name { return true } return false }) } // FindProcess 通过进程信息来查询应用信息 func FindProcess(compare func(Process) bool) (datas []Process, err error) { var name, main string var mainb []byte var netErr error var netInfo []NetConn paths, err := ioutil.ReadDir("/proc") if err != nil { return } netInfo, netErr = NetConnections(false, "") appendNetInfo := func(p *Process) { if netErr != nil { p.netErr = netErr return } fds, err := ioutil.ReadDir("/proc/" + strconv.Itoa(int(p.Pid)) + "/fd") if err != nil && Exists("/proc/"+strconv.Itoa(int(p.Pid))+"/fd") { p.netErr = err return } for _, fd := range fds { socket, err := os.Readlink("/proc/" + strconv.Itoa(int(p.Pid)) + "/fd/" + fd.Name()) if err != nil { p.netErr = err return } start := strings.Index(socket, "[") if start < 0 { continue } sid := socket[start+1 : len(socket)-1] for _, v := range netInfo { if v.Inode == sid { v.Pid = p.Pid v.Process = p p.netConn = append(p.netConn, v) } } } } for _, v := range paths { if v.IsDir() && Exists("/proc/"+v.Name()+"/comm") { name, err = readAsString("/proc/" + v.Name() + "/comm") if err != nil { continue } var tmp Process tmp.LocalPath, err = os.Readlink("/proc/" + v.Name() + "/exe") tmp.Path = tmp.LocalPath tmp.LocalPath = filepath.Dir(tmp.LocalPath) tmp.ExecPath, err = os.Readlink("/proc/" + v.Name() + "/cwd") tmp.Name = strings.TrimSpace(name) main, err = readAsString("/proc/" + v.Name() + "/status") if err != nil { tmp.Err = err if compare(tmp) { appendNetInfo(&tmp) datas = append(datas, tmp) continue } } else { data := splitBy(main, ":") tmp.Pid, _ = strconv.ParseInt(data["Pid"], 10, 64) tmp.PPid, _ = strconv.ParseInt(data["PPid"], 10, 64) tmp.TPid, _ = strconv.ParseInt(data["TracerPid"], 10, 64) uids := splitBySpace(data["Uid"]) gids := splitBySpace(data["Gid"]) tmp.RUID, _ = strconv.Atoi(uids[0]) tmp.EUID, _ = strconv.Atoi(uids[1]) tmp.RGID, _ = strconv.Atoi(gids[0]) tmp.EGID, _ = strconv.Atoi(gids[1]) tmp.VmPeak, _ = strconv.ParseInt(splitBySpace(data["VmPeak"])[0], 10, 64) tmp.VmSize, _ = strconv.ParseInt(splitBySpace(data["VmSize"])[0], 10, 64) tmp.VmHWM, _ = strconv.ParseInt(splitBySpace(data["VmHWM"])[0], 10, 64) tmp.VmRSS, _ = strconv.ParseInt(splitBySpace(data["VmRSS"])[0], 10, 64) tmp.VmLck, _ = strconv.ParseInt(splitBySpace(data["VmLck"])[0], 10, 64) tmp.VmData, _ = strconv.ParseInt(splitBySpace(data["VmData"])[0], 10, 64) tmp.VmLck *= 1024 tmp.VmData *= 1024 tmp.VmPeak *= 1024 tmp.VmSize *= 1024 tmp.VmHWM *= 1024 tmp.VmRSS *= 1024 } mainb, err = ioutil.ReadFile("/proc/" + v.Name() + "/cmdline") if err != nil { tmp.Err = err if compare(tmp) { appendNetInfo(&tmp) datas = append(datas, tmp) continue } } else { args := bytes.Split(mainb, []byte{0}) for _, v := range args { tmp.Args = append(tmp.Args, string(v)) } } mainb, err = ioutil.ReadFile("/proc/" + v.Name() + "/environ") if err != nil { tmp.Err = err if compare(tmp) { appendNetInfo(&tmp) datas = append(datas, tmp) continue } } else { args := bytes.Split(mainb, []byte{0}) for _, v := range args { tmp.Env = append(tmp.Env, string(v)) } } main, err = readAsString("/proc/" + v.Name() + "/stat") if err != nil { tmp.Err = err if compare(tmp) { appendNetInfo(&tmp) datas = append(datas, tmp) continue } } else { times := splitBySpace(main) uptime, _ := strconv.ParseInt(strings.TrimSpace(times[21]), 10, 64) tmp.Uptime = time.Unix(StartTime().Unix()+uptime/100, int64((float64(uptime)/100-float64(uptime/100))*1000000000)) } if compare(tmp) { appendNetInfo(&tmp) datas = append(datas, tmp) } } } return } // FindProcessByPid 通过Pid来查询应用信息 func FindProcessByPid(pid int64) (datas Process, err error) { var name, main string var mainb []byte if !Exists("/proc/" + fmt.Sprint(pid) + "/comm") { err = errors.New("Not Found") return } netInfo, netErr := NetConnections(false, "") appendNetInfo := func(p *Process) { if netErr != nil { p.netErr = netErr return } fds, err := ioutil.ReadDir("/proc/" + strconv.Itoa(int(p.Pid)) + "/fd") if err != nil && Exists("/proc/"+strconv.Itoa(int(p.Pid))+"/fd") { p.netErr = err return } for _, fd := range fds { socket, err := os.Readlink("/proc/" + strconv.Itoa(int(p.Pid)) + "/fd/" + fd.Name()) if err != nil { p.netErr = err return } start := strings.Index(socket, "[") if start < 0 { continue } sid := socket[start+1 : len(socket)-1] for _, v := range netInfo { if v.Inode == sid { v.Pid = p.Pid v.Process = p p.netConn = append(p.netConn, v) } } } } name, err = readAsString("/proc/" + fmt.Sprint(pid) + "/comm") if err != nil { return } main, err = readAsString("/proc/" + fmt.Sprint(pid) + "/status") if err != nil { return } data := splitBy(main, ":") datas.Name = strings.TrimSpace(name) datas.Pid, _ = strconv.ParseInt(data["Pid"], 10, 64) datas.PPid, _ = strconv.ParseInt(data["PPid"], 10, 64) datas.TPid, _ = strconv.ParseInt(data["TracerPid"], 10, 64) uids := splitBySpace(data["Uid"]) gids := splitBySpace(data["Gid"]) datas.RUID, _ = strconv.Atoi(uids[0]) datas.EUID, _ = strconv.Atoi(uids[1]) datas.RGID, _ = strconv.Atoi(gids[0]) datas.EGID, _ = strconv.Atoi(gids[1]) datas.VmPeak, _ = strconv.ParseInt(splitBySpace(data["VmPeak"])[0], 10, 64) datas.VmSize, _ = strconv.ParseInt(splitBySpace(data["VmSize"])[0], 10, 64) datas.VmHWM, _ = strconv.ParseInt(splitBySpace(data["VmHWM"])[0], 10, 64) datas.VmRSS, _ = strconv.ParseInt(splitBySpace(data["VmRSS"])[0], 10, 64) datas.VmLck, _ = strconv.ParseInt(splitBySpace(data["VmLck"])[0], 10, 64) datas.VmData, _ = strconv.ParseInt(splitBySpace(data["VmData"])[0], 10, 64) datas.VmLck *= 1024 datas.VmData *= 1024 datas.VmPeak *= 1024 datas.VmSize *= 1024 datas.VmHWM *= 1024 datas.VmRSS *= 1024 appendNetInfo(&datas) mainb, err = ioutil.ReadFile("/proc/" + fmt.Sprint(pid) + "/cmdline") if err != nil { datas.Err = err err = nil } else { args := bytes.Split(mainb, []byte{0}) for _, v := range args { datas.Args = append(datas.Args, string(v)) } } mainb, err = ioutil.ReadFile("/proc/" + fmt.Sprint(pid) + "/environ") if err != nil { datas.Err = err err = nil } else { args := bytes.Split(mainb, []byte{0}) for _, v := range args { datas.Env = append(datas.Env, string(v)) } } datas.LocalPath, err = os.Readlink("/proc/" + fmt.Sprint(pid) + "/exe") datas.Path = datas.LocalPath datas.LocalPath = filepath.Dir(datas.LocalPath) datas.ExecPath, err = os.Readlink("/proc/" + fmt.Sprint(pid) + "/cwd") main, err = readAsString("/proc/" + fmt.Sprint(pid) + "/stat") if err != nil { return } times := splitBySpace(main) uptime, _ := strconv.ParseInt(strings.TrimSpace(times[21]), 10, 64) datas.Uptime = time.Unix(StartTime().Unix()+uptime/100, int64((float64(uptime)/100-float64(uptime/100))*1000000000)) return } func Daemon(path string, args ...string) (int, error) { cmd := exec.Command(path, args...) cmd.SysProcAttr = &syscall.SysProcAttr{ Setsid: true, } if err := cmd.Start(); err != nil { return -1, err } pid := cmd.Process.Pid err := cmd.Process.Release() return pid, err } func DaemonWithUser(uid, gid uint32, groups []uint32, path string, args ...string) (int, error) { cmd := exec.Command(path, args...) cmd.SysProcAttr = &syscall.SysProcAttr{ Credential: &syscall.Credential{ Uid: uid, Gid: gid, Groups: groups, }, Setsid: true, } if err := cmd.Start(); err != nil { return -1, err } pid := cmd.Process.Pid err := cmd.Process.Release() return pid, err } func (starcli *StarCmd) SetRunUser(uid, gid uint32, groups []uint32) { starcli.CMD.SysProcAttr = &syscall.SysProcAttr{ Credential: &syscall.Credential{ Uid: uid, Gid: gid, Groups: groups, }, Setsid: true, } } func (starcli *StarCmd) Release() error { if starcli.CMD.SysProcAttr == nil { starcli.CMD.SysProcAttr = &syscall.SysProcAttr{ Setsid: true, } } else { if !starcli.CMD.SysProcAttr.Setsid { starcli.CMD.SysProcAttr.Setsid = true } } if !starcli.IsRunning() { if err := starcli.CMD.Start(); err != nil { return err } } time.Sleep(time.Millisecond * 10) return starcli.CMD.Process.Release() } func (starcli *StarCmd) SetKeepCaps() error { _, _, err := syscall.RawSyscall(157 /*SYS PRCTL */, 0x8 /*PR SET KEEPCAPS*/, 1, 0) if 0 != err { return err } return nil } func SetKeepCaps() error { _, _, err := syscall.RawSyscall(157 /*SYS PRCTL */, 0x8 /*PR SET KEEPCAPS*/, 1, 0) if 0 != err { return err } return nil }