bug fix & netconn add

master
Starainrt 4 years ago
parent fd5cf2c1f6
commit d981a03b14

@ -0,0 +1,21 @@
//+build darwin
package staros
import (
"os"
"syscall"
"time"
)
func timespecToTime(ts syscall.Timespec) time.Time {
return time.Unix(int64(ts.Sec), int64(ts.Nsec))
}
func GetFileCreationTime(fileinfo os.FileInfo) time.Time {
return timespecToTime(fileinfo.Sys().(*syscall.Stat_t).Ctimespec)
}
func GetFileAccessTime(fileinfo os.FileInfo) time.Time {
return timespecToTime(fileinfo.Sys().(*syscall.Stat_t).Atimespec)
}

@ -1,4 +1,4 @@
//+build linux darwin //+build linux
package staros package staros
@ -18,4 +18,4 @@ func GetFileCreationTime(fileinfo os.FileInfo) time.Time {
func GetFileAccessTime(fileinfo os.FileInfo) time.Time { func GetFileAccessTime(fileinfo os.FileInfo) time.Time {
return timespecToTime(fileinfo.Sys().(*syscall.Stat_t).Atim) return timespecToTime(fileinfo.Sys().(*syscall.Stat_t).Atim)
} }

@ -23,5 +23,5 @@ func SetFileTimes(file *os.File,info os.FileInfo) {
} }
func SetFileTimesbyTime(file *os.File) { func SetFileTimesbyTime(file *os.File) {
syscall.SetFileTime()
} }

@ -2,7 +2,100 @@
package staros package staros
import (
"encoding/binary"
"fmt"
"golang.org/x/sys/unix"
"os/exec"
"strconv"
"strings"
"unsafe"
)
// Memory 系统内存信息 // Memory 系统内存信息
func Memory() MemStatus { func Memory() (MemStatus,error) {
return MemStatus{} return darwinMemory()
}
type swapUsage struct {
Total uint64
Avail uint64
Used uint64
Pagesize int32
Encrypted bool
}
func darwinMemory() (MemStatus, error) {
var err error
var res MemStatus
vm_stat, err := exec.LookPath("vm_stat")
if err != nil {
return res, err
}
out, err := exec.Command(vm_stat).CombinedOutput()
if err != nil {
return res, err
}
totalString, err := unix.Sysctl("hw.memsize")
if err != nil {
return res, err
}
// unix.sysctl() helpfully assumes the result is a null-terminated string and
// removes the last byte of the result if it's 0 :/
totalString += "\x00"
res.All = uint64(binary.LittleEndian.Uint64([]byte(totalString)))
lines := strings.Split(string(out), "\n")
pagesize := uint64(unix.Getpagesize())
for _, line := range lines {
fields := strings.Split(line, ":")
if len(fields) < 2 {
continue
}
key := strings.TrimSpace(fields[0])
value := strings.Trim(fields[1], " .")
switch key {
case "Pages free":
free, e := strconv.ParseUint(value, 10, 64)
if e != nil {
err = e
}
res.Free = free * pagesize
case "Pages inactive":
inactive, e := strconv.ParseUint(value, 10, 64)
if e != nil {
err = e
}
res.Available = inactive * pagesize
case "Pages active":
active, e := strconv.ParseUint(value, 10, 64)
if e != nil {
err = e
}
_ = active * pagesize
case "Pages wired down":
wired, e := strconv.ParseUint(value, 10, 64)
if e != nil {
err = e
}
_ = wired * pagesize
}
}
res.Available += res.Free
res.Used = res.All - res.Available
//swap
value, err := unix.SysctlRaw("vm.swapusage")
if err != nil {
return res, err
}
if len(value) != 32 {
return res, fmt.Errorf("unexpected output of sysctl vm.swapusage: %v (len: %d)", value, len(value))
}
swap := (*swapUsage)(unsafe.Pointer(&value[0]))
res.SwapAll = swap.Total
res.SwapUsed = swap.Used
res.SwapFree = swap.Avail
return res, err
} }

@ -5,11 +5,11 @@ package staros
import "syscall" import "syscall"
// Memory 系统内存信息 // Memory 系统内存信息
func Memory() MemStatus { func Memory() (MemStatus, error) {
var mem MemStatus var mem MemStatus
ram := new(syscall.Sysinfo_t) ram := new(syscall.Sysinfo_t)
if err := syscall.Sysinfo(ram); err != nil { if err := syscall.Sysinfo(ram); err != nil {
return mem return mem, err
} }
mem.All = uint64(ram.Totalram) mem.All = uint64(ram.Totalram)
mem.BuffCache = uint64(ram.Bufferram) mem.BuffCache = uint64(ram.Bufferram)
@ -20,5 +20,5 @@ func Memory() MemStatus {
mem.SwapFree = uint64(ram.Freeswap) mem.SwapFree = uint64(ram.Freeswap)
mem.SwapUsed = uint64(mem.SwapAll - mem.SwapFree) mem.SwapUsed = uint64(mem.SwapAll - mem.SwapFree)
mem.Used = uint64(mem.All - mem.Free) mem.Used = uint64(mem.All - mem.Free)
return mem return mem, nil
} }

@ -0,0 +1,26 @@
// +build windows
package staros
import "b612.me/win32api"
// Memory 系统内存信息
func Memory() (MemStatus, error) {
var mem MemStatus
ram := new(win32api.MEMORYSTATUSEX)
_, err := win32api.GlobalMemoryStatusEx(ram)
if err != nil {
return mem, err
}
mem.All = uint64(ram.UllTotalPhys)
mem.Free = uint64(ram.UllAvailPhys)
mem.Available = uint64(ram.UllAvailPhys)
mem.Used = uint64(mem.All - mem.Free)
mem.SwapAll = uint64(ram.UllTotalPageFile)
mem.SwapFree = uint64(ram.UllAvailPageFile)
mem.SwapUsed = mem.SwapAll - mem.SwapFree
mem.VirtualAll = uint64(mem.VirtualAll)
mem.VirtualAvail = uint64(mem.VirtualAvail)
mem.VirtualUsed = mem.VirtualAll - mem.VirtualUsed
return mem, nil
}

@ -1,85 +0,0 @@
// +build !windows
package staros
import (
"errors"
"io/ioutil"
"strconv"
"strings"
"time"
)
func NetUsage() ([]NetAdapter, error) {
data, err := ioutil.ReadFile("/proc/net/dev")
if err != nil {
return []NetAdapter{}, err
}
sps := strings.Split(strings.TrimSpace(string(data)), "\n")
if len(sps) < 3 {
return []NetAdapter{}, errors.New("No Adaptor")
}
var res []NetAdapter
netLists := sps[2:]
for _, v := range netLists {
v = strings.ReplaceAll(v, " ", " ")
for strings.Contains(v, " ") {
v = strings.ReplaceAll(v, " ", " ")
}
v = strings.TrimSpace(v)
card := strings.Split(v, " ")
name := strings.ReplaceAll(card[0], ":", "")
recvBytes, _ := strconv.Atoi(card[1])
sendBytes, _ := strconv.Atoi(card[9])
res = append(res, NetAdapter{name, uint64(recvBytes), uint64(sendBytes)})
}
return res, nil
}
func NetUsageByname(name string) (NetAdapter, error) {
ada, err := NetUsage()
if err != nil {
return NetAdapter{}, err
}
for _, v := range ada {
if v.Name == name {
return v, nil
}
}
return NetAdapter{}, errors.New("Not Found")
}
func NetSpeeds(duration time.Duration) ([]NetSpeed, error) {
list1, err := NetUsage()
if err != nil {
return []NetSpeed{}, err
}
time.Sleep(duration)
list2, err := NetUsage()
if err != nil {
return []NetSpeed{}, err
}
if len(list1) > len(list2) {
return []NetSpeed{}, errors.New("NetWork Adaptor Num Not ok")
}
var res []NetSpeed
for k, v := range list1 {
recv := float64(list2[k].RecvBytes-v.RecvBytes) / duration.Seconds()
send := float64(list2[k].SendBytes-v.SendBytes) / duration.Seconds()
res = append(res, NetSpeed{v.Name, recv, send})
}
return res, nil
}
func NetSpeedsByName(duration time.Duration, name string) (NetSpeed, error) {
ada, err := NetSpeeds(duration)
if err != nil {
return NetSpeed{}, err
}
for _, v := range ada {
if v.Name == name {
return v, nil
}
}
return NetSpeed{}, errors.New("Not Found")
}

@ -0,0 +1,9 @@
package staros
import (
"testing"
)
func Test_TrimSpace(t *testing.T) {
}

@ -0,0 +1,248 @@
// +build !windows
package staros
import (
"errors"
"io/ioutil"
"os"
"strconv"
"strings"
"time"
)
func NetUsage() ([]NetAdapter, error) {
data, err := ioutil.ReadFile("/proc/net/dev")
if err != nil {
return []NetAdapter{}, err
}
sps := strings.Split(strings.TrimSpace(string(data)), "\n")
if len(sps) < 3 {
return []NetAdapter{}, errors.New("No Adaptor")
}
var res []NetAdapter
netLists := sps[2:]
for _, v := range netLists {
v = strings.ReplaceAll(v, " ", " ")
for strings.Contains(v, " ") {
v = strings.ReplaceAll(v, " ", " ")
}
v = strings.TrimSpace(v)
card := strings.Split(v, " ")
name := strings.ReplaceAll(card[0], ":", "")
recvBytes, _ := strconv.Atoi(card[1])
sendBytes, _ := strconv.Atoi(card[9])
res = append(res, NetAdapter{name, uint64(recvBytes), uint64(sendBytes)})
}
return res, nil
}
func NetUsageByname(name string) (NetAdapter, error) {
ada, err := NetUsage()
if err != nil {
return NetAdapter{}, err
}
for _, v := range ada {
if v.Name == name {
return v, nil
}
}
return NetAdapter{}, errors.New("Not Found")
}
func NetSpeeds(duration time.Duration) ([]NetSpeed, error) {
list1, err := NetUsage()
if err != nil {
return []NetSpeed{}, err
}
time.Sleep(duration)
list2, err := NetUsage()
if err != nil {
return []NetSpeed{}, err
}
if len(list1) > len(list2) {
return []NetSpeed{}, errors.New("NetWork Adaptor Num Not ok")
}
var res []NetSpeed
for k, v := range list1 {
recv := float64(list2[k].RecvBytes-v.RecvBytes) / duration.Seconds()
send := float64(list2[k].SendBytes-v.SendBytes) / duration.Seconds()
res = append(res, NetSpeed{v.Name, recv, send})
}
return res, nil
}
func NetSpeedsByName(duration time.Duration, name string) (NetSpeed, error) {
ada, err := NetSpeeds(duration)
if err != nil {
return NetSpeed{}, err
}
for _, v := range ada {
if v.Name == name {
return v, nil
}
}
return NetSpeed{}, errors.New("Not Found")
}
// NetConnections return all TCP/UDP/UNIX DOMAIN SOCKET Connections
// if your uid != 0 ,and analysePid==true ,you should have CAP_SYS_PRTACE and CAP_DAC_OVERRIDE/CAP_DAC_READ_SEARCH Caps
func NetConnections(analysePid bool) ([]NetConn, error) {
var result []NetConn
var inodeMap map[string]int64
var err error
fileList := []string{
"/proc/net/tcp",
"/proc/net/tcp6",
"/proc/net/udp",
"/proc/net/udp6",
"/proc/net/unix",
}
if analysePid {
inodeMap, err = GetInodeMap()
if err != nil {
return result, err
}
}
for _, file := range fileList {
data, err := ioutil.ReadFile(file)
if err != nil {
return result, err
}
tmpRes, err := analyseNetFiles(data, inodeMap, file[strings.LastIndex(file, "/")+1:])
if err != nil {
return result, err
}
result = append(result, tmpRes...)
}
return result, nil
}
func GetInodeMap() (map[string]int64, error) {
res := make(map[string]int64)
paths, err := ioutil.ReadDir("/proc")
if err != nil {
return nil, err
}
for _, v := range paths {
if v.IsDir() && Exists("/proc/"+v.Name()+"/fd") {
fds, err := ioutil.ReadDir("/proc/" + v.Name() + "/fd")
if err != nil && Exists("/proc/"+v.Name()+"/fd") {
return nil, err
}
for _, fd := range fds {
socket, err := os.Readlink("/proc/" + v.Name() + "/fd/" + fd.Name())
if err != nil {
continue
}
start := strings.Index(socket, "[")
if start < 0 {
continue
}
pid, err := strconv.ParseInt(v.Name(), 10, 64)
if err != nil {
break
}
res[socket[start+1:len(socket)-1]] = pid
}
}
}
return nil, err
}
func analyseNetFiles(data []byte, inodeMap map[string]int64, typed string) ([]NetConn, error) {
if typed == "unix" {
return analyseUnixFiles(data, inodeMap, typed)
}
var result []NetConn
strdata := strings.TrimSpace(string(data))
strdata = remainOne(strdata, " ", " ")
csvData := strings.Split(strdata, "\n")
pidMap := make(map[int64]*Process)
for line, lineData := range csvData {
if line == 0 {
continue
}
v := strings.Split(strings.TrimSpace(lineData), " ")
var res NetConn
ip, port, err := parseHexIpPort(v[1])
if err != nil {
return result, err
}
res.LocalAddr = ip
res.LocalPort = port
ip, port, err = parseHexIpPort(v[2])
if err != nil {
return result, err
}
res.RemoteAddr = ip
res.RemotePort = port
res.Uid, err = strconv.ParseInt(v[7], 10, 64)
if err != nil {
return result, err
}
res.Inode = v[9]
if inodeMap != nil && len(inodeMap) > 0 {
var ok bool
res.Pid, ok = inodeMap[res.Inode]
if !ok {
res.Pid = -1
} else {
_, ok := pidMap[res.Pid]
if !ok {
tmp, err := FindProcessByPid(res.Pid)
if err != nil {
pidMap[res.Pid] = nil
} else {
pidMap[res.Pid] = &tmp
}
}
res.Process = pidMap[res.Pid]
}
}
res.Typed = typed
result = append(result, res)
}
return result, nil
}
func analyseUnixFiles(data []byte, inodeMap map[string]int64, typed string) ([]NetConn, error) {
var result []NetConn
strdata := strings.TrimSpace(string(data))
strdata = remainOne(strdata, " ", " ")
csvData := strings.Split(strdata, "\n")
pidMap := make(map[int64]*Process)
for line, lineData := range csvData {
if line == 0 {
continue
}
v := strings.Split(strings.TrimSpace(lineData), " ")
var res NetConn
res.Inode = v[6]
if len(v) == 8 {
res.Socket = v[7]
}
if inodeMap != nil && len(inodeMap) > 0 {
var ok bool
res.Pid, ok = inodeMap[res.Inode]
if !ok {
res.Pid = -1
} else {
_, ok := pidMap[res.Pid]
if !ok {
tmp, err := FindProcessByPid(res.Pid)
if err != nil {
pidMap[res.Pid] = nil
} else {
pidMap[res.Pid] = &tmp
}
}
res.Uid = int64(pidMap[res.Pid].RUID)
res.Process = pidMap[res.Pid]
}
}
res.Typed = typed
result = append(result, res)
}
return result, nil
}

@ -24,3 +24,10 @@ func NetSpeedsByName(duration time.Duration, name string) (NetSpeed, error) {
return NetSpeed{}, nil return NetSpeed{}, nil
} }
// NetConnections return all TCP/UDP/UNIX DOMAIN SOCKET Connections
// if your uid != 0 ,and analysePid==true ,you should have CAP_SYS_PRTACE and CAP_DAC_OVERRIDE/CAP_DAC_READ_SEARCH Caps
func NetConnections(analysePid bool) ([]NetConn, error) {
var result []NetConn
return result, nil
}

@ -1,4 +1,4 @@
// +build !windows // +build linux darwin unix
package staros package staros

@ -27,23 +27,6 @@ func IsRoot() bool {
return wincmd.Isas() return wincmd.Isas()
} }
// Memory 系统内存信息
func Memory() MemStatus {
var mem MemStatus
ram := new(win32api.MEMORYSTATUSEX)
win32api.GlobalMemoryStatusEx(ram)
mem.All = uint64(ram.UllTotalPhys)
mem.Free = uint64(ram.UllAvailPhys)
mem.Available = uint64(ram.UllAvailPhys)
mem.Used = uint64(mem.All - mem.Free)
mem.SwapAll = uint64(ram.UllTotalPageFile)
mem.SwapFree = uint64(ram.UllAvailPageFile)
mem.SwapUsed = mem.SwapAll - mem.SwapFree
mem.VirtualAll = uint64(mem.VirtualAll)
mem.VirtualAvail = uint64(mem.VirtualAvail)
mem.VirtualUsed = mem.VirtualAll - mem.VirtualUsed
return mem
}
func DiskUsage(path string) (disk DiskStatus) { func DiskUsage(path string) (disk DiskStatus) {
kernel32, err := syscall.LoadLibrary("Kernel32.dll") kernel32, err := syscall.LoadLibrary("Kernel32.dll")

@ -7,6 +7,8 @@ import (
"io" "io"
"os" "os"
"os/exec" "os/exec"
"strings"
"sync"
"syscall" "syscall"
"time" "time"
) )
@ -31,6 +33,7 @@ type StarCmd struct {
stderrBuf *bytes.Buffer stderrBuf *bytes.Buffer
stdoutpoint int stdoutpoint int
stderrpoint int stderrpoint int
lock sync.Mutex
prewrite []string prewrite []string
prewritetime time.Duration prewritetime time.Duration
stopctxfunc context.CancelFunc stopctxfunc context.CancelFunc
@ -98,12 +101,13 @@ func (starcli *StarCmd) queryStdout(ctx context.Context) {
case <-ctx.Done(): case <-ctx.Done():
return return
default: default:
break
} }
out := make([]byte, 65535) out := make([]byte, 65535)
n, err := starcli.outfile.Read(out) n, err := starcli.outfile.Read(out)
if n != 0 { if n != 0 {
starcli.lock.Lock()
starcli.stdoutBuf.Write(out[:n]) starcli.stdoutBuf.Write(out[:n])
starcli.lock.Unlock()
for _, v := range out[:n] { for _, v := range out[:n] {
starcli.stdout = append(starcli.stdout, v) starcli.stdout = append(starcli.stdout, v)
} }
@ -112,7 +116,9 @@ func (starcli *StarCmd) queryStdout(ctx context.Context) {
if err == io.EOF { if err == io.EOF {
break break
} else { } else {
starcli.runerr = err if !strings.Contains(err.Error(),"file already closed") {
starcli.runerr = err
}
return return
} }
} }
@ -125,12 +131,13 @@ func (starcli *StarCmd) queryStderr(ctx context.Context) {
case <-ctx.Done(): case <-ctx.Done():
return return
default: default:
break
} }
out := make([]byte, 65535) out := make([]byte, 65535)
n, err := starcli.errfile.Read(out) n, err := starcli.errfile.Read(out)
if n != 0 { if n != 0 {
starcli.lock.Lock()
starcli.stderrBuf.Write(out[:n]) starcli.stderrBuf.Write(out[:n])
starcli.lock.Unlock()
for _, v := range out[:n] { for _, v := range out[:n] {
starcli.errout = append(starcli.errout, v) starcli.errout = append(starcli.errout, v)
} }
@ -139,7 +146,9 @@ func (starcli *StarCmd) queryStderr(ctx context.Context) {
if err == io.EOF { if err == io.EOF {
break break
} else { } else {
starcli.runerr = err if !strings.Contains(err.Error(),"file already closed") {
starcli.runerr = err
}
return return
} }
} }
@ -147,8 +156,10 @@ func (starcli *StarCmd) queryStderr(ctx context.Context) {
return return
} }
func (starcli *StarCmd) NowLineOutput() (string, error) { func (starcli *StarCmd) NowLineOutput() (string, error) {
starcli.lock.Lock()
buf, _ := starcli.stdoutBuf.ReadBytes('\n') buf, _ := starcli.stdoutBuf.ReadBytes('\n')
buferr, _ := starcli.stderrBuf.ReadBytes(byte('\n')) buferr, _ := starcli.stderrBuf.ReadBytes(byte('\n'))
starcli.lock.Unlock()
if len(buferr) != 0 { if len(buferr) != 0 {
return string(buf), errors.New(string(buferr)) return string(buf), errors.New(string(buferr))
} }
@ -156,11 +167,15 @@ func (starcli *StarCmd) NowLineOutput() (string, error) {
} }
func (starcli *StarCmd) NowLineStdOut() string { func (starcli *StarCmd) NowLineStdOut() string {
starcli.lock.Lock()
defer starcli.lock.Unlock()
buf, _ := starcli.stdoutBuf.ReadBytes('\n') buf, _ := starcli.stdoutBuf.ReadBytes('\n')
return string(buf) return string(buf)
} }
func (starcli *StarCmd) NowLineStdErr() error { func (starcli *StarCmd) NowLineStdErr() error {
starcli.lock.Lock()
defer starcli.lock.Unlock()
buferr, _ := starcli.stderrBuf.ReadBytes(byte('\n')) buferr, _ := starcli.stderrBuf.ReadBytes(byte('\n'))
if len(buferr) != 0 { if len(buferr) != 0 {
return errors.New(string(buferr)) return errors.New(string(buferr))
@ -170,16 +185,20 @@ func (starcli *StarCmd) NowLineStdErr() error {
func (starcli *StarCmd) NowAllOutput() (string, error) { func (starcli *StarCmd) NowAllOutput() (string, error) {
var outstr string var outstr string
starcli.lock.Lock()
buf := make([]byte, starcli.stdoutBuf.Len()) buf := make([]byte, starcli.stdoutBuf.Len())
n, _ := starcli.stdoutBuf.Read(buf) n, _ := starcli.stdoutBuf.Read(buf)
starcli.lock.Unlock()
if n != 0 { if n != 0 {
outstr = string(buf[:n]) outstr = string(buf[:n])
} }
if starcli.runerr != nil { if starcli.runerr != nil {
return outstr, starcli.runerr return outstr, starcli.runerr
} }
starcli.lock.Lock()
buf = make([]byte, starcli.stderrBuf.Len()) buf = make([]byte, starcli.stderrBuf.Len())
n, _ = starcli.stderrBuf.Read(buf) n, _ = starcli.stderrBuf.Read(buf)
starcli.lock.Unlock()
if n != 0 { if n != 0 {
return outstr, errors.New(string(buf[:n])) return outstr, errors.New(string(buf[:n]))
} }
@ -188,8 +207,10 @@ func (starcli *StarCmd) NowAllOutput() (string, error) {
func (starcli *StarCmd) NowStdOut() string { func (starcli *StarCmd) NowStdOut() string {
var outstr string var outstr string
starcli.lock.Lock()
buf := make([]byte, starcli.stdoutBuf.Len()) buf := make([]byte, starcli.stdoutBuf.Len())
n, _ := starcli.stdoutBuf.Read(buf) n, _ := starcli.stdoutBuf.Read(buf)
starcli.lock.Unlock()
if n != 0 { if n != 0 {
outstr = string(buf[:n]) outstr = string(buf[:n])
} }
@ -197,9 +218,10 @@ func (starcli *StarCmd) NowStdOut() string {
} }
func (starcli *StarCmd) NowStdErr() error { func (starcli *StarCmd) NowStdErr() error {
starcli.lock.Lock()
buf := make([]byte, starcli.stderrBuf.Len()) buf := make([]byte, starcli.stderrBuf.Len())
n, _ := starcli.stderrBuf.Read(buf) n, _ := starcli.stderrBuf.Read(buf)
starcli.lock.Unlock()
if n != 0 { if n != 0 {
return errors.New(string(buf[:n])) return errors.New(string(buf[:n]))
} }

@ -30,11 +30,43 @@ func FindProcessByName(name string) (datas []Process, err error) {
func FindProcess(compare func(Process) bool) (datas []Process, err error) { func FindProcess(compare func(Process) bool) (datas []Process, err error) {
var name, main string var name, main string
var mainb []byte var mainb []byte
paths, errs := ioutil.ReadDir("/proc") var netErr error
if errs != nil { var netInfo []NetConn
err = errs paths, err := ioutil.ReadDir("/proc")
if err != nil {
return return
} }
netInfo, netErr = NetConnections(false)
appendNetInfo := func(p *Process) {
if netErr != nil {
p.netErr = netErr
return
}
fds, err := ioutil.ReadDir("/proc/" + strconv.Itoa(int(p.Pid)) + "/fd")
if err != nil && Exists("/proc/"+strconv.Itoa(int(p.Pid))+"/fd") {
p.netErr = err
return
}
for _, fd := range fds {
socket, err := os.Readlink("/proc/" + strconv.Itoa(int(p.Pid)) + "/fd/" + fd.Name())
if err != nil {
p.netErr = err
return
}
start := strings.Index(socket, "[")
if start < 0 {
continue
}
sid := socket[start+1 : len(socket)-1]
for _, v := range netInfo {
if v.Inode == sid {
v.Pid = p.Pid
v.Process = p
p.netConn = append(p.netConn, v)
}
}
}
}
for _, v := range paths { for _, v := range paths {
if v.IsDir() && Exists("/proc/"+v.Name()+"/comm") { if v.IsDir() && Exists("/proc/"+v.Name()+"/comm") {
name, err = readAsString("/proc/" + v.Name() + "/comm") name, err = readAsString("/proc/" + v.Name() + "/comm")
@ -49,68 +81,80 @@ func FindProcess(compare func(Process) bool) (datas []Process, err error) {
tmp.Name = strings.TrimSpace(name) tmp.Name = strings.TrimSpace(name)
main, err = readAsString("/proc/" + v.Name() + "/status") main, err = readAsString("/proc/" + v.Name() + "/status")
if err != nil { if err != nil {
tmp.Err = err
if compare(tmp) { if compare(tmp) {
appendNetInfo(&tmp)
datas = append(datas, tmp) datas = append(datas, tmp)
continue continue
} }
} else {
data := splitBy(main, ":")
tmp.Pid, _ = strconv.ParseInt(data["Pid"], 10, 64)
tmp.PPid, _ = strconv.ParseInt(data["PPid"], 10, 64)
tmp.TPid, _ = strconv.ParseInt(data["TracerPid"], 10, 64)
uids := splitBySpace(data["Uid"])
gids := splitBySpace(data["Gid"])
tmp.RUID, _ = strconv.Atoi(uids[0])
tmp.EUID, _ = strconv.Atoi(uids[1])
tmp.RGID, _ = strconv.Atoi(gids[0])
tmp.EGID, _ = strconv.Atoi(gids[1])
tmp.VmPeak, _ = strconv.ParseInt(splitBySpace(data["VmPeak"])[0], 10, 64)
tmp.VmSize, _ = strconv.ParseInt(splitBySpace(data["VmSize"])[0], 10, 64)
tmp.VmHWM, _ = strconv.ParseInt(splitBySpace(data["VmHWM"])[0], 10, 64)
tmp.VmRSS, _ = strconv.ParseInt(splitBySpace(data["VmRSS"])[0], 10, 64)
tmp.VmLck, _ = strconv.ParseInt(splitBySpace(data["VmLck"])[0], 10, 64)
tmp.VmData, _ = strconv.ParseInt(splitBySpace(data["VmData"])[0], 10, 64)
tmp.VmLck *= 1024
tmp.VmData *= 1024
tmp.VmPeak *= 1024
tmp.VmSize *= 1024
tmp.VmHWM *= 1024
tmp.VmRSS *= 1024
} }
data := splitBy(main, ":")
tmp.Pid, _ = strconv.ParseInt(data["Pid"], 10, 64)
tmp.PPid, _ = strconv.ParseInt(data["PPid"], 10, 64)
tmp.TPid, _ = strconv.ParseInt(data["TracerPid"], 10, 64)
uids := splitBySpace(data["Uid"])
gids := splitBySpace(data["Gid"])
tmp.RUID, _ = strconv.Atoi(uids[0])
tmp.EUID, _ = strconv.Atoi(uids[1])
tmp.RGID, _ = strconv.Atoi(gids[0])
tmp.EGID, _ = strconv.Atoi(gids[1])
tmp.VmPeak, _ = strconv.ParseInt(splitBySpace(data["VmPeak"])[0], 10, 64)
tmp.VmSize, _ = strconv.ParseInt(splitBySpace(data["VmSize"])[0], 10, 64)
tmp.VmHWM, _ = strconv.ParseInt(splitBySpace(data["VmHWM"])[0], 10, 64)
tmp.VmRSS, _ = strconv.ParseInt(splitBySpace(data["VmRSS"])[0], 10, 64)
tmp.VmLck, _ = strconv.ParseInt(splitBySpace(data["VmLck"])[0], 10, 64)
tmp.VmData, _ = strconv.ParseInt(splitBySpace(data["VmData"])[0], 10, 64)
tmp.VmLck *= 1024
tmp.VmData *= 1024
tmp.VmPeak *= 1024
tmp.VmSize *= 1024
tmp.VmHWM *= 1024
tmp.VmRSS *= 1024
mainb, err = ioutil.ReadFile("/proc/" + v.Name() + "/cmdline") mainb, err = ioutil.ReadFile("/proc/" + v.Name() + "/cmdline")
if err != nil { if err != nil {
tmp.Err = err
if compare(tmp) { if compare(tmp) {
appendNetInfo(&tmp)
datas = append(datas, tmp) datas = append(datas, tmp)
continue continue
} }
} else {
args := bytes.Split(mainb, []byte{0})
for _, v := range args {
tmp.Args = append(tmp.Args, string(v))
}
} }
args := bytes.Split(mainb, []byte{0})
for _, v := range args {
tmp.Args = append(tmp.Args, string(v))
}
mainb, err = ioutil.ReadFile("/proc/" + v.Name() + "/environ") mainb, err = ioutil.ReadFile("/proc/" + v.Name() + "/environ")
if err != nil { if err != nil {
tmp.Err = err
if compare(tmp) { if compare(tmp) {
appendNetInfo(&tmp)
datas = append(datas, tmp) datas = append(datas, tmp)
continue continue
} }
} } else {
args = bytes.Split(mainb, []byte{0}) args := bytes.Split(mainb, []byte{0})
for _, v := range args { for _, v := range args {
tmp.Env = append(tmp.Env, string(v)) tmp.Env = append(tmp.Env, string(v))
}
} }
main, err = readAsString("/proc/" + v.Name() + "/stat") main, err = readAsString("/proc/" + v.Name() + "/stat")
if err != nil { if err != nil {
tmp.Err = err
if compare(tmp) { if compare(tmp) {
appendNetInfo(&tmp)
datas = append(datas, tmp) datas = append(datas, tmp)
continue continue
} }
} else {
times := splitBySpace(main)
uptime, _ := strconv.ParseInt(strings.TrimSpace(times[21]), 10, 64)
tmp.Uptime = time.Unix(StartTime().Unix()+uptime/100, int64((float64(uptime)/100-float64(uptime/100))*1000000000))
} }
times := splitBySpace(main)
uptime, _ := strconv.ParseInt(strings.TrimSpace(times[21]), 10, 64)
tmp.Uptime = time.Unix(StartTime().Unix()+uptime/100, int64((float64(uptime)/100-float64(uptime/100))*1000000000))
if compare(tmp) { if compare(tmp) {
appendNetInfo(&tmp)
datas = append(datas, tmp) datas = append(datas, tmp)
} }
} }
@ -126,6 +170,38 @@ func FindProcessByPid(pid int64) (datas Process, err error) {
err = errors.New("Not Found") err = errors.New("Not Found")
return return
} }
netInfo, netErr := NetConnections(false)
appendNetInfo := func(p *Process) {
if netErr != nil {
p.netErr = netErr
return
}
fds, err := ioutil.ReadDir("/proc/" + strconv.Itoa(int(p.Pid)) + "/fd")
if err != nil && Exists("/proc/"+strconv.Itoa(int(p.Pid))+"/fd") {
p.netErr = err
return
}
for _, fd := range fds {
socket, err := os.Readlink("/proc/" + strconv.Itoa(int(p.Pid)) + "/fd/" + fd.Name())
if err != nil {
p.netErr = err
return
}
start := strings.Index(socket, "[")
if start < 0 {
continue
}
sid := socket[start+1 : len(socket)-1]
for _, v := range netInfo {
if v.Inode == sid {
v.Pid = p.Pid
v.Process = p
p.netConn = append(p.netConn, v)
}
}
}
}
name, err = readAsString("/proc/" + fmt.Sprint(pid) + "/comm") name, err = readAsString("/proc/" + fmt.Sprint(pid) + "/comm")
if err != nil { if err != nil {
return return
@ -157,22 +233,27 @@ func FindProcessByPid(pid int64) (datas Process, err error) {
datas.VmSize *= 1024 datas.VmSize *= 1024
datas.VmHWM *= 1024 datas.VmHWM *= 1024
datas.VmRSS *= 1024 datas.VmRSS *= 1024
appendNetInfo(&datas)
mainb, err = ioutil.ReadFile("/proc/" + fmt.Sprint(pid) + "/cmdline") mainb, err = ioutil.ReadFile("/proc/" + fmt.Sprint(pid) + "/cmdline")
if err != nil { if err != nil {
return datas.Err = err
} err = nil
args := bytes.Split(mainb, []byte{0}) } else {
for _, v := range args { args := bytes.Split(mainb, []byte{0})
datas.Args = append(datas.Args, string(v)) for _, v := range args {
datas.Args = append(datas.Args, string(v))
}
} }
mainb, err = ioutil.ReadFile("/proc/" + fmt.Sprint(pid) + "/environ") mainb, err = ioutil.ReadFile("/proc/" + fmt.Sprint(pid) + "/environ")
if err != nil { if err != nil {
return datas.Err = err
} err = nil
args = bytes.Split(mainb, []byte{0}) } else {
for _, v := range args { args := bytes.Split(mainb, []byte{0})
datas.Env = append(datas.Env, string(v)) for _, v := range args {
datas.Env = append(datas.Env, string(v))
}
} }
datas.LocalPath, err = os.Readlink("/proc/" + fmt.Sprint(pid) + "/exe") datas.LocalPath, err = os.Readlink("/proc/" + fmt.Sprint(pid) + "/exe")

@ -62,3 +62,11 @@ func Daemon(path string, args ...string) (int, error) {
func (starcli *StarCmd) SetRunUser(uid, gid uint32) { func (starcli *StarCmd) SetRunUser(uid, gid uint32) {
} }
func (starcli *StarCmd) Release() error {
if err := starcli.CMD.Start(); err != nil {
return err
}
starcli.CMD.Process.Release()
return nil
}

@ -9,8 +9,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"b612.me/staros"
) )
type SysConf struct { type SysConf struct {
@ -76,9 +74,6 @@ func NewLinuxConf(EqualFlag string) *SysConf {
} }
func (syscfg *SysConf) ParseFromFile(filepath string) error { func (syscfg *SysConf) ParseFromFile(filepath string) error {
if !staros.Exists(filepath) {
return errors.New(filepath + " 不存在")
}
data, err := ioutil.ReadFile(filepath) data, err := ioutil.ReadFile(filepath)
if err != nil { if err != nil {
return err return err

@ -2,7 +2,9 @@ package staros
import ( import (
"bytes" "bytes"
"errors"
"io/ioutil" "io/ioutil"
"strconv"
"strings" "strings"
) )
@ -42,3 +44,116 @@ func readAsString(path string) (string, error) {
} }
return string(data), nil return string(data), nil
} }
func remainOne(data, old, new string) string {
data = strings.TrimSpace(data)
if !strings.Contains(data, old) {
return data
}
data = strings.ReplaceAll(data, old, new)
return remainOne(data, old, new)
}
func parseHexIpPort(str string) (string, int, error) {
str = strings.TrimSpace(str)
if len(str) != 13 && len(str) != 37 {
return "", 0, errors.New("Not a valid ip:port addr:" + str)
}
ipPort := strings.Split(str, ":")
if len(ipPort) != 2 {
return "", 0, errors.New("Not a valid ip:port addr:" + str)
}
if len(ipPort[0]) == 8 {
ip, err := parseHexIPv4(ipPort[0])
if err != nil {
return "", 0, err
}
port, err := parseHexPort(ipPort[1])
return ip, port, err
}
if len(ipPort[0]) == 32 {
ip, err := parseHexIPv6(ipPort[0])
if err != nil {
return "", 0, err
}
port, err := parseHexPort(ipPort[1])
return ip, port, err
}
return "", 0, errors.New("Invalid ip address:" + str)
}
func parseHexPort(str string) (int, error) {
tmpUint32, err := strconv.ParseUint(str, 16, 32)
return int(tmpUint32), err
}
func parseHexIPv4(str string) (string, error) {
var result string
if len(str) != 8 {
return "", errors.New("Not a vaild ipv4:" + str)
}
tmpUint64, err := strconv.ParseUint(str, 16, 32)
if err != nil {
return "", err
}
numicIp := uint32(tmpUint64)
for i := 0; i < 4; i++ {
result += strconv.FormatUint(uint64(uint8(numicIp>>(8*uint8(i)))), 10) + "."
}
return result[0 : len(result)-1], nil
}
func parseHexIPv6(str string) (string, error) {
var result string
if len(str) != 32 {
return "", errors.New("Not a vaild ipv6:" + str)
}
for i := 0; i < 4; i++ {
part := str[i*8 : (i+1)*8]
tmpUint64, err := strconv.ParseUint(part, 16, 32)
if err != nil {
return "", err
}
tmpUint32 := uint32(tmpUint64)
//07C2022A
for i := 0; i < 4; i++ {
tmp := strconv.FormatUint(uint64(uint8(tmpUint32>>uint8(8*i))), 16)
if len(tmp) == 1 {
tmp = "0" + tmp
}
result += tmp
if (i+1)%2 == 0 {
result += ":"
}
}
}
ipv6 := result[0 : len(result)-1]
ipv6List := strings.Split(ipv6, ":")
prepareZero := false
alreadyZero := false
for k, v := range ipv6List {
if v == "0000" && !alreadyZero {
ipv6List[k] = ""
prepareZero = true
continue
}
if v != "0000" && prepareZero {
alreadyZero = true
}
var nonZero = 0
for i := 0; i < 4; i++ {
sig := v[i : i+1]
if sig != "0" {
nonZero = i
break
}
}
ipv6List[k] = v[nonZero:4]
}
ipv6 = strings.TrimSuffix(remainOne(strings.Join(ipv6List, ":"), ":::", "::"), "::")
if ipv6 == "" {
ipv6 = "::0"
}
return ipv6, nil
}

@ -46,6 +46,13 @@ type Process struct {
VmHWM int64 VmHWM int64
VmRSS int64 VmRSS int64
VmData int64 VmData int64
netConn []NetConn
netErr error
Err error
}
func (p Process) GetNetConns() ([]NetConn, error) {
return p.netConn, p.netErr
} }
type MemStatus struct { type MemStatus struct {
@ -70,3 +77,16 @@ type DiskStatus struct {
Free uint64 Free uint64
Available uint64 Available uint64
} }
type NetConn struct {
LocalAddr string
LocalPort int
Typed string
RemoteAddr string
RemotePort int
Socket string
Inode string
Pid int64
Uid int64
Process *Process
}

Loading…
Cancel
Save