mirror of https://github.com/etcd-io/dbtester.git
175 lines
4.0 KiB
Go
175 lines
4.0 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
|
|
}
|
|
err = f.Close()
|
|
b, berr := ioutil.ReadAll(f)
|
|
if err != nil {
|
|
berr = fmt.Errorf("%v; %v", err, berr)
|
|
}
|
|
return b, berr
|
|
}
|
|
|
|
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
|
|
}
|