dbtester/vendor/github.com/gyuho/linux-inspect/proc/status.go

171 lines
3.9 KiB
Go

package proc
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"strings"
"text/template"
"github.com/gyuho/linux-inspect/pkg/fileutil"
"github.com/dustin/go-humanize"
"gopkg.in/yaml.v2"
)
// GetStatusByPID reads '/proc/$PID/status' data.
func GetStatusByPID(pid int64) (s Status, err error) {
d, derr := readStatus(pid)
if derr != nil {
return Status{}, derr
}
s, err = parseStatus(d)
if err != nil {
return s, err
}
s.StateParsedStatus = strings.TrimSpace(s.State)
u, _ := humanize.ParseBytes(s.VmPeak)
s.VmPeakBytesN = u
s.VmPeakParsedBytes = humanize.Bytes(u)
u, _ = humanize.ParseBytes(s.VmSize)
s.VmSizeBytesN = u
s.VmSizeParsedBytes = humanize.Bytes(u)
u, _ = humanize.ParseBytes(s.VmLck)
s.VmLckBytesN = u
s.VmLckParsedBytes = humanize.Bytes(u)
u, _ = humanize.ParseBytes(s.VmPin)
s.VmPinBytesN = u
s.VmPinParsedBytes = humanize.Bytes(u)
u, _ = humanize.ParseBytes(s.VmHWM)
s.VmHWMBytesN = u
s.VmHWMParsedBytes = humanize.Bytes(u)
u, _ = humanize.ParseBytes(s.VmRSS)
s.VmRSSBytesN = u
s.VmRSSParsedBytes = humanize.Bytes(u)
u, _ = humanize.ParseBytes(s.VmData)
s.VmDataBytesN = u
s.VmDataParsedBytes = humanize.Bytes(u)
u, _ = humanize.ParseBytes(s.VmStk)
s.VmStkBytesN = u
s.VmStkParsedBytes = humanize.Bytes(u)
u, _ = humanize.ParseBytes(s.VmExe)
s.VmExeBytesN = u
s.VmExeParsedBytes = humanize.Bytes(u)
u, _ = humanize.ParseBytes(s.VmLib)
s.VmLibBytesN = u
s.VmLibParsedBytes = humanize.Bytes(u)
u, _ = humanize.ParseBytes(s.VmPTE)
s.VmPTEBytesN = u
s.VmPTEParsedBytes = humanize.Bytes(u)
u, _ = humanize.ParseBytes(s.VmPMD)
s.VmPMDBytesN = u
s.VmPMDParsedBytes = humanize.Bytes(u)
u, _ = humanize.ParseBytes(s.VmSwap)
s.VmSwapBytesN = u
s.VmSwapParsedBytes = humanize.Bytes(u)
u, _ = humanize.ParseBytes(s.HugetlbPages)
s.HugetlbPagesBytesN = u
s.HugetlbPagesParsedBytes = humanize.Bytes(u)
return s, nil
}
func readStatus(pid int64) ([]byte, error) {
fpath := fmt.Sprintf("/proc/%d/status", pid)
f, err := fileutil.OpenToRead(fpath)
if err != nil {
return nil, err
}
defer f.Close()
return ioutil.ReadAll(f)
}
func parseStatus(d []byte) (s Status, err error) {
err = yaml.Unmarshal(d, &s)
return s, err
}
const statusTmpl = `
----------------------------------------
[/proc/{{.Pid}}/status]
Name: {{.Name}}
Umask: {{.Umask}}
State: {{.StateParsedStatus}}
Tgid: {{.Tgid}}
Ngid: {{.Ngid}}
Pid: {{.Pid}}
PPid: {{.PPid}}
TracerPid: {{.TracerPid}}
FDSize: {{.FDSize}}
VmPeak: {{.VmPeakParsedBytes}}
VmSize: {{.VmSizeParsedBytes}}
VmLck: {{.VmLckParsedBytes}}
VmPin: {{.VmPinParsedBytes}}
VmHWM: {{.VmHWMParsedBytes}}
VmRSS: {{.VmRSSParsedBytes}}
VmData: {{.VmDataParsedBytes}}
VmStk: {{.VmStkParsedBytes}}
VmExe: {{.VmExeParsedBytes}}
VmLib: {{.VmLibParsedBytes}}
VmPTE: {{.VmPTEParsedBytes}}
VmPMD: {{.VmPMDParsedBytes}}
VmSwap: {{.VmSwapParsedBytes}}
HugetlbPages: {{.HugetlbPagesParsedBytes}}
Threads: {{.Threads}}
Groups: {{.Groups}}
Uid: {{.Uid}}
Gid: {{.Gid}}
SigQ: {{.SigQ}}
SigPnd: {{.SigPnd}}
ShdPnd: {{.ShdPnd}}
SigBlk: {{.SigBlk}}
SigIgn: {{.SigIgn}}
SigCgt: {{.SigCgt}}
CapInh: {{.CapInh}}
CapPrm: {{.CapPrm}}
CapEff: {{.CapEff}}
CapBnd: {{.CapBnd}}
Seccomp: {{.Seccomp}}
Cpus_allowed: {{.CpusAllowed}}
Cpus_allowed_list: {{.CpusAllowedList}}
Mems_allowed: {{.MemsAllowed}}
Mems_allowed_list: {{.MemsAllowedList}}
voluntary_ctxt_switches:
{{.VoluntaryCtxtSwitches}}
nonvoluntary_ctxt_switches:
{{.NonvoluntaryCtxtSwitches}}
----------------------------------------
`
func (s Status) String() string {
tpl := template.Must(template.New("statusTmpl").Parse(statusTmpl))
buf := new(bytes.Buffer)
if err := tpl.Execute(buf, s); err != nil {
log.Fatal(err)
}
return buf.String()
}
// GetProgram returns the program name.
func GetProgram(pid int64) (string, error) {
// Readlink needs root permission
// return os.Readlink(fmt.Sprintf("/proc/%d/exe", pid))
s, err := GetStatusByPID(pid)
return s.Name, err
}