You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
staros/process_unix.go

230 lines
6.4 KiB
Go

// +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
paths, errs := ioutil.ReadDir("/proc")
if errs != nil {
err = errs
return
}
for _, v := range paths {
if v.IsDir() && Exists("/proc/"+v.Name()+"/comm") {
name, _ = readAsString("/proc/" + v.Name() + "/comm")
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 {
if compare(tmp) {
datas = append(datas, tmp)
continue
}
}
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 {
if compare(tmp) {
datas = append(datas, tmp)
continue
}
}
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 {
if compare(tmp) {
datas = append(datas, tmp)
continue
}
}
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 {
if compare(tmp) {
datas = append(datas, tmp)
continue
}
}
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) {
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
}
name, err = readAsString("/proc/" + fmt.Sprint(pid) + "/comm")
main, err = readAsString("/proc/" + fmt.Sprint(pid) + "/status")
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
mainb, err = ioutil.ReadFile("/proc/" + fmt.Sprint(pid) + "/cmdline")
if err != nil {
return
}
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 {
return
}
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")
if err != nil {
return
}
datas.Path = datas.LocalPath
datas.LocalPath = filepath.Dir(datas.LocalPath)
datas.ExecPath, err = os.Readlink("/proc/" + fmt.Sprint(pid) + "/cwd")
if err != nil {
return
}
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 (starcli *StarCmd) SetRunUser(uid, gid uint32) {
starcli.CMD.SysProcAttr = &syscall.SysProcAttr{
Credential: &syscall.Credential{
Uid: uid,
Gid: gid,
},
Setsid: true,
}
}
func (starcli *StarCmd) Release() error {
if err := starcli.CMD.Start(); err != nil {
return err
}
starcli.CMD.SysProcAttr = &syscall.SysProcAttr{
Setsid: true,
}
starcli.CMD.Process.Release()
return nil
}
func (starcli *StarCmd) SetKeepCaps() error {
_, _, err := syscall.RawSyscall(157 /*SYS PRCTL */, 0x8 /*PR SET KEEPCAPS*/, 1, 0)
if 0 != err {
return err
}
return nil
}