mirror of
https://github.com/taigrr/wtf
synced 2025-01-18 04:03:14 -08:00
332 lines
7.9 KiB
Go
332 lines
7.9 KiB
Go
package linux
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Provides much of the information from ProcessStatm and ProcessStat
|
|
type ProcessStatus struct {
|
|
Name string
|
|
State string
|
|
Tgid uint64
|
|
Pid uint64
|
|
PPid int64
|
|
TracerPid uint64
|
|
RealUid uint64
|
|
EffectiveUid uint64
|
|
SavedSetUid uint64
|
|
FilesystemUid uint64
|
|
RealGid uint64
|
|
EffectiveGid uint64
|
|
SavedSetGid uint64
|
|
FilesystemGid uint64
|
|
FDSize uint64
|
|
Groups []int64
|
|
VmPeak uint64
|
|
VmSize uint64
|
|
VmLck uint64
|
|
VmHWM uint64
|
|
VmRSS uint64
|
|
VmData uint64
|
|
VmStk uint64
|
|
VmExe uint64
|
|
VmLib uint64
|
|
VmPTE uint64
|
|
VmSwap uint64
|
|
Threads uint64
|
|
SigQLength uint64
|
|
SigQLimit uint64
|
|
SigPnd uint64
|
|
ShdPnd uint64
|
|
SigBlk uint64
|
|
SigIgn uint64
|
|
SigCgt uint64
|
|
CapInh uint64
|
|
CapPrm uint64
|
|
CapEff uint64
|
|
CapBnd uint64
|
|
Seccomp uint8
|
|
CpusAllowed []uint32
|
|
MemsAllowed []uint32
|
|
VoluntaryCtxtSwitches uint64
|
|
NonvoluntaryCtxtSwitches uint64
|
|
}
|
|
|
|
func ReadProcessStatus(path string) (*ProcessStatus, error) {
|
|
|
|
b, err := ioutil.ReadFile(path)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
status := ProcessStatus{}
|
|
|
|
lines := strings.Split(string(b), "\n")
|
|
|
|
for _, line := range lines {
|
|
|
|
if strings.Index(line, ":") == -1 {
|
|
continue
|
|
}
|
|
|
|
l := strings.Split(line, ":")
|
|
|
|
k := strings.TrimSpace(l[0])
|
|
v := strings.TrimSpace(l[1])
|
|
|
|
switch k {
|
|
case "Name":
|
|
status.Name = v
|
|
case "State":
|
|
status.State = v
|
|
case "Tgid":
|
|
if status.Tgid, err = strconv.ParseUint(v, 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
case "Pid":
|
|
if status.Pid, err = strconv.ParseUint(v, 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
case "PPid":
|
|
if status.PPid, err = strconv.ParseInt(v, 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
case "TracerPid":
|
|
if status.TracerPid, err = strconv.ParseUint(v, 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
case "Uid":
|
|
if f := strings.Fields(v); len(f) == 4 {
|
|
if status.RealUid, err = strconv.ParseUint(f[0], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
if status.EffectiveUid, err = strconv.ParseUint(f[1], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
if status.SavedSetUid, err = strconv.ParseUint(f[2], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
if status.FilesystemUid, err = strconv.ParseUint(f[3], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
case "Gid":
|
|
if f := strings.Fields(v); len(f) == 4 {
|
|
if status.RealGid, err = strconv.ParseUint(f[0], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
if status.EffectiveGid, err = strconv.ParseUint(f[1], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
if status.SavedSetGid, err = strconv.ParseUint(f[2], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
if status.FilesystemGid, err = strconv.ParseUint(f[3], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
case "FDSize":
|
|
if status.FDSize, err = strconv.ParseUint(v, 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
case "Groups":
|
|
{
|
|
|
|
f := strings.Fields(v)
|
|
status.Groups = make([]int64, len(f))
|
|
|
|
for i := range status.Groups {
|
|
if status.Groups[i], err = strconv.ParseInt(f[i], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
}
|
|
case "VmPeak":
|
|
{
|
|
f := strings.Fields(v)
|
|
if status.VmPeak, err = strconv.ParseUint(f[0], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
case "VmSize":
|
|
{
|
|
f := strings.Fields(v)
|
|
if status.VmSize, err = strconv.ParseUint(f[0], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
case "VmLck":
|
|
{
|
|
f := strings.Fields(v)
|
|
if status.VmLck, err = strconv.ParseUint(f[0], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
case "VmHWM":
|
|
{
|
|
f := strings.Fields(v)
|
|
if status.VmHWM, err = strconv.ParseUint(f[0], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
case "VmRSS":
|
|
{
|
|
f := strings.Fields(v)
|
|
if status.VmRSS, err = strconv.ParseUint(f[0], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
case "VmData":
|
|
{
|
|
f := strings.Fields(v)
|
|
if status.VmData, err = strconv.ParseUint(f[0], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
case "VmStk":
|
|
{
|
|
f := strings.Fields(v)
|
|
if status.VmStk, err = strconv.ParseUint(f[0], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
case "VmExe":
|
|
{
|
|
f := strings.Fields(v)
|
|
if status.VmExe, err = strconv.ParseUint(f[0], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
case "VmLib":
|
|
{
|
|
f := strings.Fields(v)
|
|
if status.VmLib, err = strconv.ParseUint(f[0], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
case "VmPTE":
|
|
{
|
|
f := strings.Fields(v)
|
|
if status.VmPTE, err = strconv.ParseUint(f[0], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
case "VmSwap":
|
|
{
|
|
f := strings.Fields(v)
|
|
if status.VmSwap, err = strconv.ParseUint(f[0], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
case "Threads":
|
|
if status.Threads, err = strconv.ParseUint(v, 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
case "SigQ":
|
|
{
|
|
if f := strings.Split(v, "/"); len(f) == 2 {
|
|
if status.SigQLength, err = strconv.ParseUint(f[0], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
if status.SigQLimit, err = strconv.ParseUint(f[1], 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
case "SigPnd":
|
|
if status.SigPnd, err = strconv.ParseUint(v, 16, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
case "ShdPnd":
|
|
if status.ShdPnd, err = strconv.ParseUint(v, 16, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
case "SigBlk":
|
|
if status.SigBlk, err = strconv.ParseUint(v, 16, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
case "SigIgn":
|
|
if status.SigIgn, err = strconv.ParseUint(v, 16, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
case "SigCgt":
|
|
if status.SigCgt, err = strconv.ParseUint(v, 16, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
case "CapInh":
|
|
if status.CapInh, err = strconv.ParseUint(v, 16, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
case "CapPrm":
|
|
if status.CapPrm, err = strconv.ParseUint(v, 16, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
case "CapEff":
|
|
if status.CapEff, err = strconv.ParseUint(v, 16, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
case "CapBnd":
|
|
if status.CapBnd, err = strconv.ParseUint(v, 16, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
case "Seccomp":
|
|
{
|
|
|
|
var n uint64
|
|
|
|
if n, err = strconv.ParseUint(v, 10, 8); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
status.Seccomp = uint8(n)
|
|
}
|
|
case "Cpus_allowed":
|
|
{
|
|
|
|
var n uint64
|
|
|
|
f := strings.Split(v, ",")
|
|
status.CpusAllowed = make([]uint32, len(f))
|
|
|
|
for i := range status.CpusAllowed {
|
|
if n, err = strconv.ParseUint(f[i], 16, 32); err != nil {
|
|
return nil, err
|
|
}
|
|
status.CpusAllowed[i] = uint32(n)
|
|
}
|
|
|
|
}
|
|
case "Mems_allowed":
|
|
{
|
|
|
|
var n uint64
|
|
|
|
f := strings.Split(v, ",")
|
|
status.MemsAllowed = make([]uint32, len(f))
|
|
|
|
for i := range status.MemsAllowed {
|
|
if n, err = strconv.ParseUint(f[i], 16, 32); err != nil {
|
|
return nil, err
|
|
}
|
|
status.MemsAllowed[i] = uint32(n)
|
|
}
|
|
|
|
}
|
|
case "voluntary_ctxt_switches":
|
|
if status.VoluntaryCtxtSwitches, err = strconv.ParseUint(v, 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
case "nonvoluntary_ctxt_switches":
|
|
if status.NonvoluntaryCtxtSwitches, err = strconv.ParseUint(v, 10, 64); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
|
|
return &status, nil
|
|
}
|