Merge pull request #12 from def/master

Process changes merged
pull/13/head
shirou 11 years ago
commit 35c5899e02

@ -6,6 +6,12 @@ import (
type Process struct { type Process struct {
Pid int32 `json:"pid"` Pid int32 `json:"pid"`
name string
status string
numCtxSwitches *NumCtxSwitchesStat
uids []int32
gids []int32
numThreads int32
} }
type OpenFilesStat struct { type OpenFilesStat struct {

@ -71,9 +71,6 @@ func (p *Process) Status() (string, error) {
return string(k.KiStat[:]), nil return string(k.KiStat[:]), nil
} }
func (p *Process) Username() (string, error) {
return "", NotImplementedError
}
func (p *Process) Uids() ([]int32, error) { func (p *Process) Uids() ([]int32, error) {
k, err := p.getKProc() k, err := p.getKProc()
if err != nil { if err != nil {

@ -69,9 +69,6 @@ func (p *Process) Status() (string, error) {
return string(k.KiStat[:]), nil return string(k.KiStat[:]), nil
} }
func (p *Process) Username() (string, error) {
return "", NotImplementedError
}
func (p *Process) Uids() ([]int32, error) { func (p *Process) Uids() ([]int32, error) {
k, err := p.getKProc() k, err := p.getKProc()
if err != nil { if err != nil {

@ -57,7 +57,8 @@ func NewProcess(pid int32) (*Process, error) {
p := &Process{ p := &Process{
Pid: int32(pid), Pid: int32(pid),
} }
return p, nil err := p.fillFromStatus()
return p, err
} }
func (p *Process) Ppid() (int32, error) { func (p *Process) Ppid() (int32, error) {
@ -68,11 +69,7 @@ func (p *Process) Ppid() (int32, error) {
return ppid, nil return ppid, nil
} }
func (p *Process) Name() (string, error) { func (p *Process) Name() (string, error) {
name, _, _, _, _, _, err := p.fillFromStatus() return p.name, nil
if err != nil {
return "", err
}
return name, nil
} }
func (p *Process) Exe() (string, error) { func (p *Process) Exe() (string, error) {
return p.fillFromExe() return p.fillFromExe()
@ -95,28 +92,13 @@ func (p *Process) Parent() (*Process, error) {
return nil, NotImplementedError return nil, NotImplementedError
} }
func (p *Process) Status() (string, error) { func (p *Process) Status() (string, error) {
_, status, _, _, _, _, err := p.fillFromStatus() return p.status, nil
if err != nil {
return "", err
}
return status, nil
}
func (p *Process) Username() (string, error) {
return "", nil
} }
func (p *Process) Uids() ([]int32, error) { func (p *Process) Uids() ([]int32, error) {
_, _, uids, _, _, _, err := p.fillFromStatus() return p.uids, nil
if err != nil {
return nil, err
}
return uids, nil
} }
func (p *Process) Gids() ([]int32, error) { func (p *Process) Gids() ([]int32, error) {
_, _, _, gids, _, _, err := p.fillFromStatus() return p.gids, nil
if err != nil {
return nil, err
}
return gids, nil
} }
func (p *Process) Terminal() (string, error) { func (p *Process) Terminal() (string, error) {
terminal, _, _, _, _, err := p.fillFromStat() terminal, _, _, _, _, err := p.fillFromStat()
@ -142,21 +124,13 @@ func (p *Process) IOCounters() (*IOCountersStat, error) {
return p.fillFromIO() return p.fillFromIO()
} }
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) { func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
_, _, _, _, _, numCtxSwitches, err := p.fillFromStatus() return p.numCtxSwitches, nil
if err != nil {
return nil, err
}
return numCtxSwitches, nil
} }
func (p *Process) NumFDs() (int32, error) { func (p *Process) NumFDs() (int32, error) {
return 0, NotImplementedError return 0, NotImplementedError
} }
func (p *Process) NumThreads() (int32, error) { func (p *Process) NumThreads() (int32, error) {
_, _, _, _, numThreads, _, err := p.fillFromStatus() return p.numThreads, nil
if err != nil {
return 0, err
}
return numThreads, nil
} }
func (p *Process) Threads() (map[string]string, error) { func (p *Process) Threads() (map[string]string, error) {
ret := make(map[string]string, 0) ret := make(map[string]string, 0)
@ -338,15 +312,14 @@ func (p *Process) fillFromCmdline() (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
// remove \u0000 ret := strings.FieldsFunc(string(cmdline), func(r rune) bool {
ret := strings.TrimFunc(string(cmdline), func(r rune) bool {
if r == '\u0000' { if r == '\u0000' {
return true return true
} }
return false return false
}) })
return ret, nil return strings.Join(ret, " "), nil
} }
// Get IO status from /proc/(pid)/io // Get IO status from /proc/(pid)/io
@ -390,8 +363,8 @@ func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) {
} }
fields := strings.Split(string(contents), " ") fields := strings.Split(string(contents), " ")
rss := mustParseUint64(fields[0]) * PageSize vms := mustParseUint64(fields[0]) * PageSize
vms := mustParseUint64(fields[1]) * PageSize rss := mustParseUint64(fields[1]) * PageSize
memInfo := &MemoryInfoStat{ memInfo := &MemoryInfoStat{
RSS: rss, RSS: rss,
VMS: vms, VMS: vms,
@ -409,59 +382,68 @@ func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) {
} }
// Get various status from /proc/(pid)/status // 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 pid := p.Pid
statPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "status") statPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "status")
contents, err := ioutil.ReadFile(statPath) contents, err := ioutil.ReadFile(statPath)
if err != nil { if err != nil {
return "", "", nil, nil, 0, nil, err return err
} }
lines := strings.Split(string(contents), "\n") lines := strings.Split(string(contents), "\n")
p.numCtxSwitches = &NumCtxSwitchesStat{}
name := ""
status := ""
var numThreads int32
var vol int32
var unvol int32
var uids []int32
var gids []int32
for _, line := range lines { for _, line := range lines {
field := strings.Split(line, ":") tabParts := strings.SplitN(line, "\t", 2)
if len(field) < 2 { if len(tabParts) < 2 {
continue continue
} }
// fmt.Printf("%s ->__%s__\n", field[0], strings.Trim(field[1], " \t")) value := tabParts[1]
switch field[0] { switch strings.TrimRight(tabParts[0], ":") {
case "Name": case "Name":
name = strings.Trim(field[1], " \t") p.name = strings.Trim(value, " \t")
case "State": case "State":
// get between "(" and ")" // get between "(" and ")"
s := strings.Index(field[1], "(") + 1 s := strings.Index(value, "(") + 1
e := strings.Index(field[1], "(") + 1 e := strings.Index(value, "(") + 1
status = field[1][s:e] p.status = value[s:e]
// case "PPid": // filled by fillFromStat
case "Uid": case "Uid":
for _, i := range strings.Split(field[1], "\t") { p.uids = make([]int32, 0, 4)
uids = append(uids, mustParseInt32(i)) 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": case "Gid":
for _, i := range strings.Split(field[1], "\t") { p.gids = make([]int32, 0, 4)
gids = append(gids, mustParseInt32(i)) 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": 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": 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": 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) { func (p *Process) fillFromStat() (string, int32, *CPUTimesStat, int64, int32, error) {

@ -4,6 +4,7 @@ package gopsutil
import ( import (
"os" "os"
"os/user"
"os/exec" "os/exec"
"strconv" "strconv"
"strings" "strings"
@ -85,3 +86,17 @@ func (p *Process) Terminate() error {
func (p *Process) Kill() error { func (p *Process) Kill() error {
return p.SendSignal(syscall.SIGKILL) 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…
Cancel
Save