mirror of
https://github.com/shirou/gopsutil.git
synced 2025-04-26 13:48:59 +08:00
commit
35c5899e02
@ -6,6 +6,12 @@ import (
|
||||
|
||||
type Process struct {
|
||||
Pid int32 `json:"pid"`
|
||||
name string
|
||||
status string
|
||||
numCtxSwitches *NumCtxSwitchesStat
|
||||
uids []int32
|
||||
gids []int32
|
||||
numThreads int32
|
||||
}
|
||||
|
||||
type OpenFilesStat struct {
|
||||
|
@ -71,9 +71,6 @@ func (p *Process) Status() (string, error) {
|
||||
|
||||
return string(k.KiStat[:]), nil
|
||||
}
|
||||
func (p *Process) Username() (string, error) {
|
||||
return "", NotImplementedError
|
||||
}
|
||||
func (p *Process) Uids() ([]int32, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
|
@ -69,9 +69,6 @@ func (p *Process) Status() (string, error) {
|
||||
|
||||
return string(k.KiStat[:]), nil
|
||||
}
|
||||
func (p *Process) Username() (string, error) {
|
||||
return "", NotImplementedError
|
||||
}
|
||||
func (p *Process) Uids() ([]int32, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
|
124
process_linux.go
124
process_linux.go
@ -57,7 +57,8 @@ func NewProcess(pid int32) (*Process, error) {
|
||||
p := &Process{
|
||||
Pid: int32(pid),
|
||||
}
|
||||
return p, nil
|
||||
err := p.fillFromStatus()
|
||||
return p, err
|
||||
}
|
||||
|
||||
func (p *Process) Ppid() (int32, error) {
|
||||
@ -68,11 +69,7 @@ func (p *Process) Ppid() (int32, error) {
|
||||
return ppid, nil
|
||||
}
|
||||
func (p *Process) Name() (string, error) {
|
||||
name, _, _, _, _, _, err := p.fillFromStatus()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return name, nil
|
||||
return p.name, nil
|
||||
}
|
||||
func (p *Process) Exe() (string, error) {
|
||||
return p.fillFromExe()
|
||||
@ -95,28 +92,13 @@ func (p *Process) Parent() (*Process, error) {
|
||||
return nil, NotImplementedError
|
||||
}
|
||||
func (p *Process) Status() (string, error) {
|
||||
_, status, _, _, _, _, err := p.fillFromStatus()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return status, nil
|
||||
}
|
||||
func (p *Process) Username() (string, error) {
|
||||
return "", nil
|
||||
return p.status, nil
|
||||
}
|
||||
func (p *Process) Uids() ([]int32, error) {
|
||||
_, _, uids, _, _, _, err := p.fillFromStatus()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return uids, nil
|
||||
return p.uids, nil
|
||||
}
|
||||
func (p *Process) Gids() ([]int32, error) {
|
||||
_, _, _, gids, _, _, err := p.fillFromStatus()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return gids, nil
|
||||
return p.gids, nil
|
||||
}
|
||||
func (p *Process) Terminal() (string, error) {
|
||||
terminal, _, _, _, _, err := p.fillFromStat()
|
||||
@ -142,21 +124,13 @@ func (p *Process) IOCounters() (*IOCountersStat, error) {
|
||||
return p.fillFromIO()
|
||||
}
|
||||
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
|
||||
_, _, _, _, _, numCtxSwitches, err := p.fillFromStatus()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return numCtxSwitches, nil
|
||||
return p.numCtxSwitches, nil
|
||||
}
|
||||
func (p *Process) NumFDs() (int32, error) {
|
||||
return 0, NotImplementedError
|
||||
}
|
||||
func (p *Process) NumThreads() (int32, error) {
|
||||
_, _, _, _, numThreads, _, err := p.fillFromStatus()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return numThreads, nil
|
||||
return p.numThreads, nil
|
||||
}
|
||||
func (p *Process) Threads() (map[string]string, error) {
|
||||
ret := make(map[string]string, 0)
|
||||
@ -338,15 +312,14 @@ func (p *Process) fillFromCmdline() (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// remove \u0000
|
||||
ret := strings.TrimFunc(string(cmdline), func(r rune) bool {
|
||||
ret := strings.FieldsFunc(string(cmdline), func(r rune) bool {
|
||||
if r == '\u0000' {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
return ret, nil
|
||||
return strings.Join(ret, " "), nil
|
||||
}
|
||||
|
||||
// Get IO status from /proc/(pid)/io
|
||||
@ -390,8 +363,8 @@ func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) {
|
||||
}
|
||||
fields := strings.Split(string(contents), " ")
|
||||
|
||||
rss := mustParseUint64(fields[0]) * PageSize
|
||||
vms := mustParseUint64(fields[1]) * PageSize
|
||||
vms := mustParseUint64(fields[0]) * PageSize
|
||||
rss := mustParseUint64(fields[1]) * PageSize
|
||||
memInfo := &MemoryInfoStat{
|
||||
RSS: rss,
|
||||
VMS: vms,
|
||||
@ -409,59 +382,68 @@ func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) {
|
||||
}
|
||||
|
||||
// Get various status from /proc/(pid)/status
|
||||
func (p *Process) fillFromStatus() (string, string, []int32, []int32, int32, *NumCtxSwitchesStat, error) {
|
||||
func (p *Process) fillFromStatus() error {
|
||||
pid := p.Pid
|
||||
statPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "status")
|
||||
contents, err := ioutil.ReadFile(statPath)
|
||||
if err != nil {
|
||||
return "", "", nil, nil, 0, nil, err
|
||||
return err
|
||||
}
|
||||
lines := strings.Split(string(contents), "\n")
|
||||
|
||||
name := ""
|
||||
status := ""
|
||||
var numThreads int32
|
||||
var vol int32
|
||||
var unvol int32
|
||||
var uids []int32
|
||||
var gids []int32
|
||||
p.numCtxSwitches = &NumCtxSwitchesStat{}
|
||||
for _, line := range lines {
|
||||
field := strings.Split(line, ":")
|
||||
if len(field) < 2 {
|
||||
tabParts := strings.SplitN(line, "\t", 2)
|
||||
if len(tabParts) < 2 {
|
||||
continue
|
||||
}
|
||||
// fmt.Printf("%s ->__%s__\n", field[0], strings.Trim(field[1], " \t"))
|
||||
switch field[0] {
|
||||
value := tabParts[1]
|
||||
switch strings.TrimRight(tabParts[0], ":") {
|
||||
case "Name":
|
||||
name = strings.Trim(field[1], " \t")
|
||||
p.name = strings.Trim(value, " \t")
|
||||
case "State":
|
||||
// get between "(" and ")"
|
||||
s := strings.Index(field[1], "(") + 1
|
||||
e := strings.Index(field[1], "(") + 1
|
||||
status = field[1][s:e]
|
||||
// case "PPid": // filled by fillFromStat
|
||||
s := strings.Index(value, "(") + 1
|
||||
e := strings.Index(value, "(") + 1
|
||||
p.status = value[s:e]
|
||||
case "Uid":
|
||||
for _, i := range strings.Split(field[1], "\t") {
|
||||
uids = append(uids, mustParseInt32(i))
|
||||
p.uids = make([]int32, 0, 4)
|
||||
for _, i := range strings.Split(value, "\t") {
|
||||
v, err := strconv.ParseInt(i, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.uids = append(p.uids, int32(v))
|
||||
}
|
||||
case "Gid":
|
||||
for _, i := range strings.Split(field[1], "\t") {
|
||||
gids = append(gids, mustParseInt32(i))
|
||||
p.gids = make([]int32, 0, 4)
|
||||
for _, i := range strings.Split(value, "\t") {
|
||||
v, err := strconv.ParseInt(i, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.gids = append(p.gids, int32(v))
|
||||
}
|
||||
case "Threads":
|
||||
numThreads = mustParseInt32(field[1])
|
||||
v, err := strconv.ParseInt(value, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.numThreads = int32(v)
|
||||
case "voluntary_ctxt_switches":
|
||||
vol = mustParseInt32(field[1])
|
||||
v, err := strconv.ParseInt(value, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.numCtxSwitches.Voluntary = int32(v)
|
||||
case "nonvoluntary_ctxt_switches":
|
||||
unvol = mustParseInt32(field[1])
|
||||
v, err := strconv.ParseInt(value, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.numCtxSwitches.Involuntary = int32(v)
|
||||
}
|
||||
}
|
||||
|
||||
numctx := &NumCtxSwitchesStat{
|
||||
Voluntary: vol,
|
||||
Involuntary: unvol,
|
||||
}
|
||||
return name, status, uids, gids, numThreads, numctx, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Process) fillFromStat() (string, int32, *CPUTimesStat, int64, int32, error) {
|
||||
|
@ -4,6 +4,7 @@ package gopsutil
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/user"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -85,3 +86,17 @@ func (p *Process) Terminate() error {
|
||||
func (p *Process) Kill() error {
|
||||
return p.SendSignal(syscall.SIGKILL)
|
||||
}
|
||||
func (p *Process) Username() (string, error) {
|
||||
uids, err := p.Uids()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(uids) > 0 {
|
||||
u, err := user.LookupId(strconv.Itoa(int(uids[0])))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return u.Username, nil
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user