mirror of
https://github.com/shirou/gopsutil.git
synced 2025-05-04 22:17:34 +08:00
Merge branch 'master' of github.com:shirou/gopsutil
This commit is contained in:
commit
23b2034406
@ -66,8 +66,8 @@ Current Status
|
|||||||
- disk_usage (linux, freebsd, windows)
|
- disk_usage (linux, freebsd, windows)
|
||||||
- boot_time (linux, freebsd, windows(but little broken))
|
- boot_time (linux, freebsd, windows(but little broken))
|
||||||
- users (linux, freebsd)
|
- users (linux, freebsd)
|
||||||
- pids (freebsd)
|
- pids (linux, freebsd)
|
||||||
- pid_exists (freebsd)
|
- pid_exists (linux, freebsd)
|
||||||
|
|
||||||
- not yet
|
- not yet
|
||||||
|
|
||||||
|
@ -22,15 +22,10 @@ func HostInfo() (HostInfoStat, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret.Hostname = hostname
|
ret.Hostname = hostname
|
||||||
|
uptimemsec, _, err := procGetTickCount.Call()
|
||||||
kernel32, err := syscall.LoadLibrary("kernel32.dll")
|
if uptimemsec == 0 {
|
||||||
if err != nil {
|
return ret, syscall.GetLastError()
|
||||||
return ret, err
|
|
||||||
}
|
}
|
||||||
defer syscall.FreeLibrary(kernel32)
|
|
||||||
GetTickCount, _ := syscall.GetProcAddress(kernel32, "GetTickCount")
|
|
||||||
|
|
||||||
uptimemsec, _, err := syscall.Syscall(uintptr(GetTickCount), 0, 0, 0, 0)
|
|
||||||
|
|
||||||
ret.Uptime = int64(uptimemsec) / 1000
|
ret.Uptime = int64(uptimemsec) / 1000
|
||||||
|
|
||||||
|
84
process.go
84
process.go
@ -6,64 +6,64 @@ type Process struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Exe string `json:"exe"`
|
Exe string `json:"exe"`
|
||||||
Cmdline string `json:"cmdline"`
|
Cmdline string `json:"cmdline"`
|
||||||
Create_time int64
|
Create_time int64 `json:"create_time"`
|
||||||
// Parent Process // FIXME: recursive
|
// Parent Process // FIXME: recursive
|
||||||
Status string
|
Status string `json:"status"`
|
||||||
Cwd string
|
Cwd string `json:"cwd"`
|
||||||
Username string
|
Username string `json:"username"`
|
||||||
Uids []int32
|
Uids []int32 `json:"uids"`
|
||||||
Gids []int32
|
Gids []int32 `json:"gids"`
|
||||||
Terminal string
|
Terminal string `json:"terminal"`
|
||||||
Nice int32
|
Nice int32 `json:"nice"`
|
||||||
Ionice int32
|
Ionice int32 `json:"ionice"`
|
||||||
Rlimit []RlimitStat
|
Rlimit []RlimitStat `json:"rlimit"`
|
||||||
Io_counters Io_countersStat
|
Io_counters Io_countersStat `json:"io_counter"`
|
||||||
Num_ctx_switches int32
|
Num_ctx_switches int32 `json:"num_ctx_switches"`
|
||||||
Num_fds int32
|
Num_fds int32 `json:"num_fds"`
|
||||||
Num_handles int32
|
Num_handles int32 `json:"num_handles"`
|
||||||
Num_Threads int32
|
Num_Threads int32 `json:"nunm_threads"`
|
||||||
// Threads map[string]string
|
// Threads map[string]string `json:"threads"`
|
||||||
Cpu_times CPU_TimesStat
|
Cpu_times CPU_TimesStat `json:"cpu_times"`
|
||||||
// Cpu_percent
|
// Cpu_percent `json:"cpu_percent"`
|
||||||
Cpu_affinity []int32
|
Cpu_affinity []int32 `json:"cpu_affinity"`
|
||||||
Memory_info Memory_infoStat
|
Memory_info Memory_infoStat `json:"memory_info"`
|
||||||
Memory_info_ex map[string]string
|
Memory_info_ex map[string]string `json:"memori_info_ex"`
|
||||||
Memory_percent float32
|
Memory_percent float32 `json:"memory_percent"`
|
||||||
Memory_maps []Memory_mapsStat
|
Memory_maps []Memory_mapsStat `json:"memory_maps"`
|
||||||
// Children []Process // FIXME: recursive
|
// Children []Process // FIXME: recursive `json:"children"`
|
||||||
Open_files []Open_filesStat
|
Open_files []Open_filesStat `json:"open_files"`
|
||||||
Connections []Net_connectionStat
|
Connections []Net_connectionStat `json:"connections"`
|
||||||
Is_running bool
|
Is_running bool `json:"is_running"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Open_filesStat struct {
|
type Open_filesStat struct {
|
||||||
Path string
|
Path string `json:"path"`
|
||||||
Fd uint32
|
Fd uint32 `json:"fd"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Memory_infoStat struct {
|
type Memory_infoStat struct {
|
||||||
RSS int32 // bytes
|
RSS int32 `json:"rss"` // bytes
|
||||||
VMS int32 // bytes
|
VMS int32 `json:"vms"` // bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
type Memory_mapsStat struct {
|
type Memory_mapsStat struct {
|
||||||
Path string
|
Path string `json:"path"`
|
||||||
RSS int32
|
RSS int32 `json:"rss"`
|
||||||
Anonymous int32
|
Anonymous int32 `json:"anonymous"`
|
||||||
Swap int32
|
Swap int32 `json:"swap"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RlimitStat struct {
|
type RlimitStat struct {
|
||||||
Rresource int32
|
Resource int32 `json:"resource"`
|
||||||
Soft int32
|
Soft int32 `json:"soft"`
|
||||||
Hard int32
|
Hard int32 `json:"hard"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Io_countersStat struct {
|
type Io_countersStat struct {
|
||||||
Read_count int32
|
Read_count int32 `json:"read_count"`
|
||||||
Write_count int32
|
Write_count int32 `json:"write_count"`
|
||||||
Read_bytes int32
|
Read_bytes int32 `json:"read_bytes"`
|
||||||
Write_bytes int32
|
Write_bytes int32 `json:"write_bytes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func Pid_exists(pid int32) (bool, error) {
|
func Pid_exists(pid int32) (bool, error) {
|
||||||
|
@ -23,29 +23,6 @@ func Pids() ([]int32, error) {
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh reloads all the data associated with this process.
|
|
||||||
func (p *Process) Refresh() error {
|
|
||||||
|
|
||||||
mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PID, p.Pid}
|
|
||||||
|
|
||||||
buf, length, err := call_syscall(mib)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
proc_k := Kinfo_proc{}
|
|
||||||
if length != uint64(unsafe.Sizeof(proc_k)) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
k, err := parse_kinfo_proc(buf)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
copy_params(&k, p)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func copy_params(k *Kinfo_proc, p *Process) error {
|
func copy_params(k *Kinfo_proc, p *Process) error {
|
||||||
p.Exe = byteToString(k.Ki_comm[:])
|
p.Exe = byteToString(k.Ki_comm[:])
|
||||||
p.Ppid = k.Ki_ppid
|
p.Ppid = k.Ki_ppid
|
||||||
@ -53,17 +30,6 @@ func copy_params(k *Kinfo_proc, p *Process) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findProcess(pid int32) (*Process, error) {
|
|
||||||
mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, pid}
|
|
||||||
|
|
||||||
_, _, err := call_syscall(mib)
|
|
||||||
if err != nil {
|
|
||||||
return &Process{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return newProcess(pid)
|
|
||||||
}
|
|
||||||
|
|
||||||
func processes() ([]Process, error) {
|
func processes() ([]Process, error) {
|
||||||
results := make([]Process, 0, 50)
|
results := make([]Process, 0, 50)
|
||||||
|
|
||||||
@ -85,7 +51,7 @@ func processes() ([]Process, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
p, err := newProcess(int32(k.Ki_pid))
|
p, err := NewProcess(int32(k.Ki_pid))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -146,7 +112,24 @@ func call_syscall(mib []int32) ([]byte, uint64, error) {
|
|||||||
return buf, length, nil
|
return buf, length, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newProcess(pid int32) (*Process, error) {
|
func NewProcess(pid int32) (*Process, error) {
|
||||||
p := &Process{Pid: pid}
|
p := &Process{Pid: pid}
|
||||||
return p, p.Refresh()
|
mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PID, p.Pid}
|
||||||
|
|
||||||
|
buf, length, err := call_syscall(mib)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
proc_k := Kinfo_proc{}
|
||||||
|
if length != uint64(unsafe.Sizeof(proc_k)) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
k, err := parse_kinfo_proc(buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_params(&k, p)
|
||||||
|
return p, nil
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewProcess(pid int32) (Process, error) {
|
func NewProcess(pid int32) (*Process, error) {
|
||||||
p := Process{
|
p := &Process{
|
||||||
Pid: int32(pid),
|
Pid: int32(pid),
|
||||||
}
|
}
|
||||||
go fillFromStat(pid, &p)
|
go fillFromStat(pid, p)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// user := parseInt32(fields[13])
|
// user := parseInt32(fields[13])
|
||||||
@ -101,8 +101,8 @@ func getState(status uint8) (string, error) {
|
|||||||
return "running", nil
|
return "running", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func processes() ([]Process, error) {
|
func processes() ([]*Process, error) {
|
||||||
ret := make([]Process, 0)
|
ret := make([]*Process, 0)
|
||||||
|
|
||||||
pids, err := Pids()
|
pids, err := Pids()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -3,6 +3,7 @@ package gopsutil
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,7 +18,12 @@ func Test_Pids(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_Pid_exists(t *testing.T) {
|
func Test_Pid_exists(t *testing.T) {
|
||||||
ret, err := Pid_exists(1)
|
check_pid := 1
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
check_pid = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, err := Pid_exists(int32(check_pid))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("error %v", err)
|
t.Errorf("error %v", err)
|
||||||
}
|
}
|
||||||
@ -28,7 +34,12 @@ func Test_Pid_exists(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_NewProcess(t *testing.T) {
|
func Test_NewProcess(t *testing.T) {
|
||||||
ret, err := NewProcess(1)
|
check_pid := 1
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
check_pid = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, err := NewProcess(int32(check_pid))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("error %v", err)
|
t.Errorf("error %v", err)
|
||||||
}
|
}
|
||||||
|
117
process_windows.go
Normal file
117
process_windows.go
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
package gopsutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
procCloseHandle = modKernel32.NewProc("CloseHandle")
|
||||||
|
procCreateToolhelp32Snapshot = modKernel32.NewProc("CreateToolhelp32Snapshot")
|
||||||
|
procProcess32First = modKernel32.NewProc("Process32FirstW")
|
||||||
|
procProcess32Next = modKernel32.NewProc("Process32NextW")
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ERROR_NO_MORE_FILES = 0x12
|
||||||
|
MAX_PATH = 260
|
||||||
|
)
|
||||||
|
|
||||||
|
type PROCESSENTRY32 struct {
|
||||||
|
DwSize uint32
|
||||||
|
CntUsage uint32
|
||||||
|
Th32ProcessID uint32
|
||||||
|
Th32DefaultHeapID uintptr
|
||||||
|
Th32ModuleID uint32
|
||||||
|
CntThreads uint32
|
||||||
|
Th32ParentProcessID uint32
|
||||||
|
PcPriClassBase int32
|
||||||
|
DwFlags uint32
|
||||||
|
SzExeFile [MAX_PATH]uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
type SYSTEM_PROCESS_INFORMATION struct {
|
||||||
|
ULONG NextEntryOffset;
|
||||||
|
ULONG NumberOfThreads;
|
||||||
|
BYTE Reserved1[48];
|
||||||
|
PVOID Reserved2[3];
|
||||||
|
HANDLE UniqueProcessId;
|
||||||
|
PVOID Reserved3;
|
||||||
|
ULONG HandleCount;
|
||||||
|
BYTE Reserved4[4];
|
||||||
|
PVOID Reserved5[11];
|
||||||
|
SIZE_T PeakPagefileUsage;
|
||||||
|
SIZE_T PrivatePageCount;
|
||||||
|
LARGE_INTEGER Reserved6[6];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
func Pids() ([]int32, error) {
|
||||||
|
ret := make([]int32, 0)
|
||||||
|
|
||||||
|
procs, err := processes()
|
||||||
|
if err != nil {
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
for _, proc := range procs {
|
||||||
|
ret = append(ret, proc.Pid)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewProcess(pid int32) (*Process, error) {
|
||||||
|
p := &Process{Pid: pid}
|
||||||
|
|
||||||
|
if (pid == 0) || (pid == 4) {
|
||||||
|
p.Cmdline = ""
|
||||||
|
}
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func copy_params(pe32 *PROCESSENTRY32, p *Process) error {
|
||||||
|
p.Ppid = int32(pe32.Th32ParentProcessID)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get processes
|
||||||
|
// This is borrowed from go-ps
|
||||||
|
func processes() ([]*Process, error) {
|
||||||
|
handle, _, _ := procCreateToolhelp32Snapshot.Call(
|
||||||
|
0x00000002,
|
||||||
|
0)
|
||||||
|
if handle < 0 {
|
||||||
|
return nil, syscall.GetLastError()
|
||||||
|
}
|
||||||
|
defer procCloseHandle.Call(handle)
|
||||||
|
|
||||||
|
var entry PROCESSENTRY32
|
||||||
|
entry.DwSize = uint32(unsafe.Sizeof(entry))
|
||||||
|
ret, _, _ := procProcess32First.Call(handle, uintptr(unsafe.Pointer(&entry)))
|
||||||
|
if ret == 0 {
|
||||||
|
return nil, fmt.Errorf("Error retrieving process info.")
|
||||||
|
}
|
||||||
|
|
||||||
|
results := make([]*Process, 0)
|
||||||
|
for {
|
||||||
|
pid := int32(entry.Th32ProcessID)
|
||||||
|
p, err := NewProcess(pid)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
copy_params(&entry, p)
|
||||||
|
results = append(results, p)
|
||||||
|
|
||||||
|
ret, _, _ := procProcess32Next.Call(handle, uintptr(unsafe.Pointer(&entry)))
|
||||||
|
if ret == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results, nil
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user