Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 42ad19e798 | |||
| 232bc3835e | |||
| 1333eb85bb | |||
| dae84c0a85 | |||
|
ed85eb7616
|
|||
|
d8c0d86ca0
|
|||
|
bbd85885df
|
|||
|
c615c4bb00
|
|||
| 5353429b8c | |||
| cf453821ef |
@@ -0,0 +1,28 @@
|
|||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package staros
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// DefaultFreq - frequency, in Hz, middle A
|
||||||
|
DefaultFreq = 0.0
|
||||||
|
// DefaultDuration - duration in milliseconds
|
||||||
|
DefaultDuration = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
// Beep beeps the PC speaker (https://en.wikipedia.org/wiki/PC_speaker).
|
||||||
|
func Beep(freq float64, duration int) error {
|
||||||
|
osa, err := exec.LookPath("osascript")
|
||||||
|
if err != nil {
|
||||||
|
// Output the only beep we can
|
||||||
|
_, err = os.Stdout.Write([]byte{7})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command(osa, "-e", `beep`)
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
+138
@@ -0,0 +1,138 @@
|
|||||||
|
// +build linux
|
||||||
|
|
||||||
|
package staros
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
const (
|
||||||
|
// This number represents the fixed frequency of the original PC XT's timer chip, which is approximately 1.193 MHz. This number
|
||||||
|
// is divided with the desired frequency to obtain a counter value, that is subsequently fed into the timer chip, tied to the PC speaker.
|
||||||
|
clockTickRate = 1193180
|
||||||
|
|
||||||
|
// linux/kd.h, start sound generation (0 for off)
|
||||||
|
kiocsound = 0x4B2F
|
||||||
|
|
||||||
|
// linux/input-event-codes.h
|
||||||
|
evSnd = 0x12 // Event type
|
||||||
|
sndTone = 0x02 // Sound
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// DefaultFreq - frequency, in Hz, middle A
|
||||||
|
DefaultFreq = 440.0
|
||||||
|
// DefaultDuration - duration in milliseconds
|
||||||
|
DefaultDuration = 200
|
||||||
|
)
|
||||||
|
|
||||||
|
// inputEvent represents linux/input.h event structure.
|
||||||
|
type inputEvent struct {
|
||||||
|
Time syscall.Timeval // time in seconds since epoch at which event occurred
|
||||||
|
Type uint16 // event type
|
||||||
|
Code uint16 // event code related to the event type
|
||||||
|
Value int32 // event value related to the event type
|
||||||
|
}
|
||||||
|
|
||||||
|
// ioctl system call manipulates the underlying device parameters of special files.
|
||||||
|
func ioctl(fd, name, data uintptr) error {
|
||||||
|
_, _, e := syscall.Syscall(syscall.SYS_IOCTL, fd, name, data)
|
||||||
|
if e != 0 {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Beep beeps the PC speaker (https://en.wikipedia.org/wiki/PC_speaker).
|
||||||
|
//
|
||||||
|
// On Linux it needs permission to access `/dev/tty0` or `/dev/input/by-path/platform-pcspkr-event-spkr` files for writing,
|
||||||
|
// and `pcspkr` module must be loaded. User must be in correct groups, usually `input` and/or `tty`.
|
||||||
|
//
|
||||||
|
// If it can not open device files, it will fallback to sending Bell character (https://en.wikipedia.org/wiki/Bell_character).
|
||||||
|
// For bell character in X11 terminals you can enable bell with `xset b on`. For console check `setterm` and `--blength` or `--bfreq` options.
|
||||||
|
//
|
||||||
|
// On macOS this just sends bell character. Enable `Audible bell` in Terminal --> Preferences --> Settings --> Advanced.
|
||||||
|
//
|
||||||
|
// On Windows it uses Beep function via syscall.
|
||||||
|
//
|
||||||
|
// On Web it plays hard coded beep sound.
|
||||||
|
func Beep(freq float64, duration int) error {
|
||||||
|
if freq == 0 {
|
||||||
|
freq = DefaultFreq
|
||||||
|
} else if freq > 20000 {
|
||||||
|
freq = 20000
|
||||||
|
} else if freq < 0 {
|
||||||
|
freq = DefaultFreq
|
||||||
|
}
|
||||||
|
|
||||||
|
if duration == 0 {
|
||||||
|
duration = DefaultDuration
|
||||||
|
}
|
||||||
|
|
||||||
|
period := int(float64(clockTickRate) / freq)
|
||||||
|
|
||||||
|
var evdev bool
|
||||||
|
|
||||||
|
f, err := os.OpenFile("/dev/tty0", os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
e := err
|
||||||
|
f, err = os.OpenFile("/dev/input/by-path/platform-pcspkr-event-spkr", os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
e = errors.New("beeep: " + e.Error() + "; " + err.Error())
|
||||||
|
|
||||||
|
// Output the only beep we can
|
||||||
|
_, err = os.Stdout.Write([]byte{7})
|
||||||
|
if err != nil {
|
||||||
|
return errors.New(e.Error() + "; " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
evdev = true
|
||||||
|
}
|
||||||
|
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
if evdev { // Use Linux evdev API
|
||||||
|
ev := inputEvent{}
|
||||||
|
ev.Type = evSnd
|
||||||
|
ev.Code = sndTone
|
||||||
|
ev.Value = int32(freq)
|
||||||
|
|
||||||
|
d := *(*[unsafe.Sizeof(ev)]byte)(unsafe.Pointer(&ev))
|
||||||
|
|
||||||
|
// Start beep
|
||||||
|
f.Write(d[:])
|
||||||
|
|
||||||
|
time.Sleep(time.Duration(duration) * time.Millisecond)
|
||||||
|
|
||||||
|
ev.Value = 0
|
||||||
|
d = *(*[unsafe.Sizeof(ev)]byte)(unsafe.Pointer(&ev))
|
||||||
|
|
||||||
|
// Stop beep
|
||||||
|
f.Write(d[:])
|
||||||
|
} else { // Use ioctl
|
||||||
|
// Start beep
|
||||||
|
err = ioctl(f.Fd(), kiocsound, uintptr(period))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Duration(duration) * time.Millisecond)
|
||||||
|
|
||||||
|
// Stop beep
|
||||||
|
err = ioctl(f.Fd(), kiocsound, uintptr(0))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package staros
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
rat float64 = 1.059463094 //2^(1/12)
|
||||||
|
C float64 = 493.8833013 * rat
|
||||||
|
CU = C * rat * rat
|
||||||
|
D = CU * rat
|
||||||
|
DU = D * rat
|
||||||
|
E = DU * rat
|
||||||
|
F = E * rat
|
||||||
|
FU = F * rat
|
||||||
|
G = FU * rat
|
||||||
|
GU = G * rat
|
||||||
|
A = GU * rat
|
||||||
|
AU = A * rat
|
||||||
|
B = AU * rat
|
||||||
|
)
|
||||||
|
|
||||||
|
func beepMusic(qual ...float64) {
|
||||||
|
for _, v := range qual {
|
||||||
|
fmt.Println(v)
|
||||||
|
Beep(v, 700)
|
||||||
|
time.Sleep(time.Millisecond * 1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Music(t *testing.T) {
|
||||||
|
beepMusic(G, D, A, AU, A, G, F, D, DU, D, C, D, AU/2, C, G/2, C, D)
|
||||||
|
time.Sleep(time.Second * 3)
|
||||||
|
beepMusic(D,AU,A,G,A,D*2,F*2,G*2,F*2,D*2,D*2,C*2,D*2,DU*2,D*2,AU,A,E,G,FU)
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
package staros
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// DefaultFreq - frequency, in Hz, middle A
|
||||||
|
DefaultFreq = 587.0
|
||||||
|
// DefaultDuration - duration in milliseconds
|
||||||
|
DefaultDuration = 500
|
||||||
|
)
|
||||||
|
|
||||||
|
// Beep beeps the PC speaker (https://en.wikipedia.org/wiki/PC_speaker).
|
||||||
|
func Beep(freq float64, duration int) error {
|
||||||
|
if freq == 0 {
|
||||||
|
freq = DefaultFreq
|
||||||
|
} else if freq > 32767 {
|
||||||
|
freq = 32767
|
||||||
|
} else if freq < 37 {
|
||||||
|
freq = DefaultFreq
|
||||||
|
}
|
||||||
|
|
||||||
|
if duration == 0 {
|
||||||
|
duration = DefaultDuration
|
||||||
|
}
|
||||||
|
|
||||||
|
kernel32, _ := syscall.LoadLibrary("kernel32.dll")
|
||||||
|
beep32, _ := syscall.GetProcAddress(kernel32, "Beep")
|
||||||
|
|
||||||
|
defer syscall.FreeLibrary(kernel32)
|
||||||
|
|
||||||
|
_, _, e := syscall.Syscall(uintptr(beep32), uintptr(2), uintptr(int(freq)), uintptr(duration), 0)
|
||||||
|
if e != 0 {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -1,6 +1,18 @@
|
|||||||
package staros
|
package staros
|
||||||
|
|
||||||
import "os"
|
import (
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ERR_ALREADY_LOCKED = errors.New("ALREADY LOCKED")
|
||||||
|
var ERR_TIMEOUT = errors.New("TIME OUT")
|
||||||
|
|
||||||
|
func NewFileLock(filepath string) FileLock {
|
||||||
|
return FileLock{
|
||||||
|
filepath: filepath,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 检测文件/文件夹是否存在
|
// 检测文件/文件夹是否存在
|
||||||
func Exists(path string) bool {
|
func Exists(path string) bool {
|
||||||
|
|||||||
@@ -3,11 +3,81 @@
|
|||||||
package staros
|
package staros
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"b612.me/stario"
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type FileLock struct {
|
||||||
|
fd int
|
||||||
|
filepath string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileLock) openFileForLock() error {
|
||||||
|
fd, err := syscall.Open(f.filepath, syscall.O_CREAT|syscall.O_RDONLY, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f.filepath = f.filepath
|
||||||
|
f.fd = fd
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileLock) Lock(Exclusive bool) error {
|
||||||
|
var lockType int
|
||||||
|
if Exclusive {
|
||||||
|
lockType = syscall.LOCK_EX
|
||||||
|
} else {
|
||||||
|
lockType = syscall.LOCK_SH
|
||||||
|
}
|
||||||
|
if err := f.openFileForLock(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return syscall.Flock(f.fd, lockType)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileLock) LockNoBlocking(Exclusive bool) error {
|
||||||
|
var lockType int
|
||||||
|
if Exclusive {
|
||||||
|
lockType = syscall.LOCK_EX
|
||||||
|
} else {
|
||||||
|
lockType = syscall.LOCK_SH
|
||||||
|
}
|
||||||
|
if err := f.openFileForLock(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err := syscall.Flock(f.fd, lockType|syscall.LOCK_NB)
|
||||||
|
if err != nil {
|
||||||
|
syscall.Close(f.fd)
|
||||||
|
if err == syscall.EWOULDBLOCK {
|
||||||
|
return ERR_ALREADY_LOCKED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileLock) Unlock() error {
|
||||||
|
err := syscall.Flock(f.fd, syscall.LOCK_UN)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return syscall.Close(f.fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileLock) LockWithTimeout(tm time.Duration, Exclusive bool) error {
|
||||||
|
return stario.WaitUntilTimeout(tm, func(tmout chan struct{}) error {
|
||||||
|
err := f.Lock(Exclusive)
|
||||||
|
select {
|
||||||
|
case <-tmout:
|
||||||
|
f.Unlock()
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func timespecToTime(ts syscall.Timespec) time.Time {
|
func timespecToTime(ts syscall.Timespec) time.Time {
|
||||||
return time.Unix(int64(ts.Sec), int64(ts.Nsec))
|
return time.Unix(int64(ts.Sec), int64(ts.Nsec))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package staros
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_FileLock(t *testing.T) {
|
||||||
|
filename := "./test.file"
|
||||||
|
lock := NewFileLock(filename)
|
||||||
|
lock2 := NewFileLock(filename)
|
||||||
|
fmt.Println("lock1", lock.LockNoBlocking(false))
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
fmt.Println("lock2", lock2.LockWithTimeout(time.Second*5, false))
|
||||||
|
fmt.Println("unlock1", lock.Unlock())
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
fmt.Println("unlock2", lock2.Unlock())
|
||||||
|
fmt.Println("lock2", lock2.LockNoBlocking(true))
|
||||||
|
fmt.Println("unlock2", lock2.Unlock())
|
||||||
|
os.Remove(filename)
|
||||||
|
}
|
||||||
@@ -3,11 +3,17 @@
|
|||||||
package staros
|
package staros
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"b612.me/stario"
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type FileLock struct {
|
||||||
|
fd int
|
||||||
|
filepath string
|
||||||
|
}
|
||||||
|
|
||||||
func timespecToTime(ts syscall.Timespec) time.Time {
|
func timespecToTime(ts syscall.Timespec) time.Time {
|
||||||
return time.Unix(int64(ts.Sec), int64(ts.Nsec))
|
return time.Unix(int64(ts.Sec), int64(ts.Nsec))
|
||||||
}
|
}
|
||||||
@@ -19,3 +25,67 @@ 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *FileLock) openFileForLock() error {
|
||||||
|
fd, err := syscall.Open(f.filepath, syscall.O_CREAT|syscall.O_RDONLY, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f.filepath = f.filepath
|
||||||
|
f.fd = fd
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileLock) Lock(Exclusive bool) error {
|
||||||
|
var lockType int
|
||||||
|
if Exclusive {
|
||||||
|
lockType = syscall.LOCK_EX
|
||||||
|
} else {
|
||||||
|
lockType = syscall.LOCK_SH
|
||||||
|
}
|
||||||
|
if err := f.openFileForLock(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return syscall.Flock(f.fd, lockType)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileLock) LockNoBlocking(Exclusive bool) error {
|
||||||
|
var lockType int
|
||||||
|
if Exclusive {
|
||||||
|
lockType = syscall.LOCK_EX
|
||||||
|
} else {
|
||||||
|
lockType = syscall.LOCK_SH
|
||||||
|
}
|
||||||
|
if err := f.openFileForLock(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err := syscall.Flock(f.fd, lockType|syscall.LOCK_NB)
|
||||||
|
if err != nil {
|
||||||
|
syscall.Close(f.fd)
|
||||||
|
if err == syscall.EWOULDBLOCK {
|
||||||
|
return ERR_ALREADY_LOCKED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileLock) Unlock() error {
|
||||||
|
err := syscall.Flock(f.fd, syscall.LOCK_UN)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return syscall.Close(f.fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileLock) LockWithTimeout(tm time.Duration, Exclusive bool) error {
|
||||||
|
return stario.WaitUntilTimeout(tm, func(tmout chan struct{}) error {
|
||||||
|
err := f.Lock(Exclusive)
|
||||||
|
select {
|
||||||
|
case <-tmout:
|
||||||
|
f.Unlock()
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
+98
-2
@@ -3,11 +3,17 @@
|
|||||||
package staros
|
package staros
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"b612.me/win32api"
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type FileLock struct {
|
||||||
|
filepath string
|
||||||
|
handle win32api.HANDLE
|
||||||
|
}
|
||||||
|
|
||||||
func GetFileCreationTime(fileinfo os.FileInfo) time.Time {
|
func GetFileCreationTime(fileinfo os.FileInfo) time.Time {
|
||||||
d := fileinfo.Sys().(*syscall.Win32FileAttributeData)
|
d := fileinfo.Sys().(*syscall.Win32FileAttributeData)
|
||||||
return time.Unix(0, d.CreationTime.Nanoseconds())
|
return time.Unix(0, d.CreationTime.Nanoseconds())
|
||||||
@@ -18,10 +24,100 @@ func GetFileAccessTime(fileinfo os.FileInfo) time.Time {
|
|||||||
return time.Unix(0, d.LastAccessTime.Nanoseconds())
|
return time.Unix(0, d.LastAccessTime.Nanoseconds())
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetFileTimes(file *os.File,info os.FileInfo) {
|
func SetFileTimes(file *os.File, info os.FileInfo) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetFileTimesbyTime(file *os.File) {
|
func SetFileTimesbyTime(file *os.File) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *FileLock) openFileForLock() error {
|
||||||
|
name, err := syscall.UTF16PtrFromString(f.filepath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
handle, err := syscall.CreateFile(
|
||||||
|
name,
|
||||||
|
syscall.GENERIC_READ,
|
||||||
|
syscall.FILE_SHARE_READ,
|
||||||
|
nil,
|
||||||
|
syscall.OPEN_ALWAYS,
|
||||||
|
syscall.FILE_FLAG_OVERLAPPED|0x00000080,
|
||||||
|
0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f.handle = win32api.HANDLE(handle)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileLock) lockForTimeout(timeout time.Duration, lockType win32api.DWORD) error {
|
||||||
|
var err error
|
||||||
|
if err = f.openFileForLock(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
event, err := win32api.CreateEventW(nil, true, false, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
myEvent := &syscall.Overlapped{HEvent: syscall.Handle(event)}
|
||||||
|
defer syscall.CloseHandle(myEvent.HEvent)
|
||||||
|
_, err = win32api.LockFileEx(f.handle, lockType, 0, 1, 0, myEvent)
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err != syscall.ERROR_IO_PENDING {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
millis := uint32(syscall.INFINITE)
|
||||||
|
if timeout >= 0 {
|
||||||
|
millis = uint32(timeout.Nanoseconds() / 1000000)
|
||||||
|
}
|
||||||
|
s, err := syscall.WaitForSingleObject(myEvent.HEvent, millis)
|
||||||
|
switch s {
|
||||||
|
case syscall.WAIT_OBJECT_0:
|
||||||
|
// success!
|
||||||
|
return nil
|
||||||
|
case syscall.WAIT_TIMEOUT:
|
||||||
|
f.Unlock()
|
||||||
|
return ERR_TIMEOUT
|
||||||
|
default:
|
||||||
|
f.Unlock()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileLock) Lock(Exclusive bool) error {
|
||||||
|
var lockType win32api.DWORD
|
||||||
|
if Exclusive {
|
||||||
|
lockType = win32api.LOCKFILE_EXCLUSIVE_LOCK
|
||||||
|
} else {
|
||||||
|
lockType = 0
|
||||||
|
}
|
||||||
|
return f.lockForTimeout(0, lockType)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileLock) LockWithTimeout(tm time.Duration, Exclusive bool) error {
|
||||||
|
var lockType win32api.DWORD
|
||||||
|
if Exclusive {
|
||||||
|
lockType = win32api.LOCKFILE_EXCLUSIVE_LOCK
|
||||||
|
} else {
|
||||||
|
lockType = 0
|
||||||
|
}
|
||||||
|
return f.lockForTimeout(tm, lockType)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileLock) LockNoBlocking(Exclusive bool) error {
|
||||||
|
var lockType win32api.DWORD
|
||||||
|
if Exclusive {
|
||||||
|
lockType = win32api.LOCKFILE_EXCLUSIVE_LOCK
|
||||||
|
} else {
|
||||||
|
lockType = 0
|
||||||
|
}
|
||||||
|
return f.lockForTimeout(0, lockType|win32api.LOCKFILE_FAIL_IMMEDIATELY)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileLock) Unlock() error {
|
||||||
|
return syscall.Close(syscall.Handle(f.handle))
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
module b612.me/staros
|
||||||
|
|
||||||
|
go 1.16
|
||||||
|
|
||||||
|
require (
|
||||||
|
b612.me/stario v0.0.9
|
||||||
|
b612.me/win32api v0.0.2
|
||||||
|
b612.me/wincmd v0.0.3
|
||||||
|
golang.org/x/sys v0.18.0
|
||||||
|
)
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
b612.me/stario v0.0.9 h1:bFDlejUJMwZ12a09snZJspQsOlkqpDAl9qKPEYOGWCk=
|
||||||
|
b612.me/stario v0.0.9/go.mod h1:x4D/x8zA5SC0pj/uJAi4FyG5p4j5UZoMEZfvuRR6VNw=
|
||||||
|
b612.me/win32api v0.0.2 h1:5PwvPR5fYs3a/v+LjYdtRif+5Q04zRGLTVxmCYNjCpA=
|
||||||
|
b612.me/win32api v0.0.2/go.mod h1:sj66sFJDKElEjOR+0YhdSW6b4kq4jsXu4T5/Hnpyot0=
|
||||||
|
b612.me/wincmd v0.0.3 h1:GYrkYnNun39yfNcA2+u0h4VW/BYbTrJK39QW4W1LCYA=
|
||||||
|
b612.me/wincmd v0.0.3/go.mod h1:nWdNREHO6F+2PngEUcyYN3Eo7DzYEVa/fO6czd9d/fo=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||||
|
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||||
|
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
|
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||||
|
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
|
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||||
|
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
|
||||||
|
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
+90
-12
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build !windows
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package staros
|
package staros
|
||||||
@@ -67,7 +68,13 @@ func NetSpeeds(duration time.Duration) ([]NetSpeed, error) {
|
|||||||
for k, v := range list1 {
|
for k, v := range list1 {
|
||||||
recv := float64(list2[k].RecvBytes-v.RecvBytes) / duration.Seconds()
|
recv := float64(list2[k].RecvBytes-v.RecvBytes) / duration.Seconds()
|
||||||
send := float64(list2[k].SendBytes-v.SendBytes) / duration.Seconds()
|
send := float64(list2[k].SendBytes-v.SendBytes) / duration.Seconds()
|
||||||
res = append(res, NetSpeed{v.Name, recv, send})
|
res = append(res, NetSpeed{
|
||||||
|
Name: v.Name,
|
||||||
|
RecvSpeeds: recv,
|
||||||
|
SendSpeeds: send,
|
||||||
|
RecvBytes: list2[k].RecvBytes,
|
||||||
|
SendBytes: list2[k].SendBytes,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
@@ -87,16 +94,28 @@ func NetSpeedsByName(duration time.Duration, name string) (NetSpeed, error) {
|
|||||||
|
|
||||||
// NetConnections return all TCP/UDP/UNIX DOMAIN SOCKET Connections
|
// 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
|
// 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) {
|
func NetConnections(analysePid bool, types string) ([]NetConn, error) {
|
||||||
var result []NetConn
|
var result []NetConn
|
||||||
var inodeMap map[string]int64
|
var inodeMap map[string]int64
|
||||||
var err error
|
var err error
|
||||||
fileList := []string{
|
var fileList []string
|
||||||
"/proc/net/tcp",
|
if types == "" || strings.Contains(strings.ToLower(types), "all") {
|
||||||
"/proc/net/tcp6",
|
fileList = []string{
|
||||||
"/proc/net/udp",
|
"/proc/net/tcp",
|
||||||
"/proc/net/udp6",
|
"/proc/net/tcp6",
|
||||||
"/proc/net/unix",
|
"/proc/net/udp",
|
||||||
|
"/proc/net/udp6",
|
||||||
|
"/proc/net/unix",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if strings.Contains(strings.ToLower(types), "tcp") {
|
||||||
|
fileList = append(fileList, "/proc/net/tcp", "/proc/net/tcp6")
|
||||||
|
}
|
||||||
|
if strings.Contains(strings.ToLower(types), "udp") {
|
||||||
|
fileList = append(fileList, "/proc/net/udp", "/proc/net/udp6")
|
||||||
|
}
|
||||||
|
if strings.Contains(strings.ToLower(types), "unix") {
|
||||||
|
fileList = append(fileList, "/proc/net/unix")
|
||||||
}
|
}
|
||||||
if analysePid {
|
if analysePid {
|
||||||
inodeMap, err = GetInodeMap()
|
inodeMap, err = GetInodeMap()
|
||||||
@@ -135,6 +154,9 @@ func GetInodeMap() (map[string]int64, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if !strings.Contains(socket, "socket") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
start := strings.Index(socket, "[")
|
start := strings.Index(socket, "[")
|
||||||
if start < 0 {
|
if start < 0 {
|
||||||
continue
|
continue
|
||||||
@@ -147,7 +169,7 @@ func GetInodeMap() (map[string]int64, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func analyseNetFiles(data []byte, inodeMap map[string]int64, typed string) ([]NetConn, error) {
|
func analyseNetFiles(data []byte, inodeMap map[string]int64, typed string) ([]NetConn, error) {
|
||||||
@@ -177,6 +199,60 @@ func analyseNetFiles(data []byte, inodeMap map[string]int64, typed string) ([]Ne
|
|||||||
}
|
}
|
||||||
res.RemoteAddr = ip
|
res.RemoteAddr = ip
|
||||||
res.RemotePort = port
|
res.RemotePort = port
|
||||||
|
//connection state
|
||||||
|
if strings.Contains(typed, "tcp") {
|
||||||
|
state, err := strconv.ParseInt(strings.TrimSpace(v[3]), 16, 64)
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
res.Status = TCP_STATE[state]
|
||||||
|
}
|
||||||
|
txrx_queue := strings.Split(strings.TrimSpace(v[4]), ":")
|
||||||
|
if len(txrx_queue) != 2 {
|
||||||
|
return result, errors.New("not a valid net file")
|
||||||
|
}
|
||||||
|
tx_queue, err := strconv.ParseInt(txrx_queue[0], 16, 64)
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
res.TX_Queue = tx_queue
|
||||||
|
rx_queue, err := strconv.ParseInt(txrx_queue[1], 16, 64)
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
res.RX_Queue = rx_queue
|
||||||
|
timer := strings.Split(strings.TrimSpace(v[5]), ":")
|
||||||
|
if len(timer) != 2 {
|
||||||
|
return result, errors.New("not a valid net file")
|
||||||
|
}
|
||||||
|
switch timer[0] {
|
||||||
|
case "00":
|
||||||
|
res.TimerActive = "NO_TIMER"
|
||||||
|
case "01":
|
||||||
|
//重传定时器
|
||||||
|
res.TimerActive = "RETRANSMIT"
|
||||||
|
case "02":
|
||||||
|
//连接定时器、FIN_WAIT_2定时器或TCP保活定时器
|
||||||
|
res.TimerActive = "KEEPALIVE"
|
||||||
|
case "03":
|
||||||
|
//TIME_WAIT定时器
|
||||||
|
res.TimerActive = "TIME_WAIT"
|
||||||
|
case "04":
|
||||||
|
//持续定时器
|
||||||
|
res.TimerActive = "ZERO_WINDOW_PROBE"
|
||||||
|
default:
|
||||||
|
res.TimerActive = "UNKNOWN"
|
||||||
|
}
|
||||||
|
timerJif, err := strconv.ParseInt(timer[1], 16, 64)
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
res.TimerJiffies = timerJif
|
||||||
|
timerCnt, err := strconv.ParseInt(strings.TrimSpace(v[6]), 16, 64)
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
res.RtoTimer = timerCnt
|
||||||
res.Uid, err = strconv.ParseInt(v[7], 10, 64)
|
res.Uid, err = strconv.ParseInt(v[7], 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
@@ -229,7 +305,7 @@ func analyseUnixFiles(data []byte, inodeMap map[string]int64, typed string) ([]N
|
|||||||
res.Pid = -1
|
res.Pid = -1
|
||||||
} else {
|
} else {
|
||||||
_, ok := pidMap[res.Pid]
|
_, ok := pidMap[res.Pid]
|
||||||
if !ok {
|
if !ok || pidMap[res.Pid] == nil {
|
||||||
tmp, err := FindProcessByPid(res.Pid)
|
tmp, err := FindProcessByPid(res.Pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pidMap[res.Pid] = nil
|
pidMap[res.Pid] = nil
|
||||||
@@ -237,8 +313,10 @@ func analyseUnixFiles(data []byte, inodeMap map[string]int64, typed string) ([]N
|
|||||||
pidMap[res.Pid] = &tmp
|
pidMap[res.Pid] = &tmp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res.Uid = int64(pidMap[res.Pid].RUID)
|
if pidMap[res.Pid] != nil {
|
||||||
res.Process = pidMap[res.Pid]
|
res.Uid = int64(pidMap[res.Pid].RUID)
|
||||||
|
res.Process = pidMap[res.Pid]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res.Typed = typed
|
res.Typed = typed
|
||||||
|
|||||||
+55
-3
@@ -3,6 +3,7 @@
|
|||||||
package staros
|
package staros
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os/user"
|
"os/user"
|
||||||
@@ -12,6 +13,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var clockTicks = 100 // default value
|
||||||
|
|
||||||
// StartTime 开机时间
|
// StartTime 开机时间
|
||||||
func StartTime() time.Time {
|
func StartTime() time.Time {
|
||||||
tmp, _ := readAsString("/proc/stat")
|
tmp, _ := readAsString("/proc/stat")
|
||||||
@@ -63,9 +66,9 @@ func getCPUSample() (idle, total uint64) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error: ", i, fields[i], err)
|
fmt.Println("Error: ", i, fields[i], err)
|
||||||
}
|
}
|
||||||
total += val // tally up all the numbers to get total ticks
|
total += val // tally up all the numbers to get total ticks
|
||||||
if i == 4 { // idle is the 5th field in the cpu line
|
if i == 4 || i == 5 { // idle is the 5th field in the cpu line
|
||||||
idle = val
|
idle += val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -73,6 +76,55 @@ func getCPUSample() (idle, total uint64) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func splitProcStat(content []byte) []string {
|
||||||
|
nameStart := bytes.IndexByte(content, '(')
|
||||||
|
nameEnd := bytes.LastIndexByte(content, ')')
|
||||||
|
restFields := strings.Fields(string(content[nameEnd+2:])) // +2 skip ') '
|
||||||
|
name := content[nameStart+1 : nameEnd]
|
||||||
|
pid := strings.TrimSpace(string(content[:nameStart]))
|
||||||
|
fields := make([]string, 3, len(restFields)+3)
|
||||||
|
fields[1] = string(pid)
|
||||||
|
fields[2] = string(name)
|
||||||
|
fields = append(fields, restFields...)
|
||||||
|
return fields
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCPUSampleByPid(pid int) float64 {
|
||||||
|
contents, err := ioutil.ReadFile("/proc/" + strconv.Itoa(pid) + "/stat")
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
fields := splitProcStat(contents)
|
||||||
|
utime, err := strconv.ParseFloat(fields[14], 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
stime, err := strconv.ParseFloat(fields[15], 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is no such thing as iotime in stat file. As an approximation, we
|
||||||
|
// will use delayacct_blkio_ticks (aggregated block I/O delays, as per Linux
|
||||||
|
// docs). Note: I am assuming at least Linux 2.6.18
|
||||||
|
var iotime float64
|
||||||
|
if len(fields) > 42 {
|
||||||
|
iotime, err = strconv.ParseFloat(fields[42], 64)
|
||||||
|
if err != nil {
|
||||||
|
iotime = 0 // Ancient linux version, most likely
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iotime = 0 // e.g. SmartOS containers
|
||||||
|
}
|
||||||
|
return utime/float64(clockTicks) + stime/float64(clockTicks) + iotime/float64(clockTicks)
|
||||||
|
}
|
||||||
|
func CpuUsageByPid(pid int, sleep time.Duration) float64 {
|
||||||
|
total1 := getCPUSampleByPid(pid)
|
||||||
|
time.Sleep(sleep)
|
||||||
|
total2 := getCPUSampleByPid(pid)
|
||||||
|
return (total2 - total1) / sleep.Seconds() * 100
|
||||||
|
}
|
||||||
|
|
||||||
// CpuUsage 获取CPU使用量
|
// CpuUsage 获取CPU使用量
|
||||||
func CpuUsage(sleep time.Duration) float64 {
|
func CpuUsage(sleep time.Duration) float64 {
|
||||||
|
|||||||
+41
-25
@@ -9,6 +9,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -16,12 +17,11 @@ import (
|
|||||||
//StarCmd Is Here
|
//StarCmd Is Here
|
||||||
|
|
||||||
type StarCmd struct {
|
type StarCmd struct {
|
||||||
CMD *exec.Cmd
|
CMD *exec.Cmd
|
||||||
outfile io.ReadCloser
|
outfile io.ReadCloser
|
||||||
infile io.WriteCloser
|
infile io.WriteCloser
|
||||||
errfile io.ReadCloser
|
errfile io.ReadCloser
|
||||||
running bool
|
running int32
|
||||||
runningChan chan int
|
|
||||||
//Store AlL of the Standed Outputs
|
//Store AlL of the Standed Outputs
|
||||||
stdout []byte
|
stdout []byte
|
||||||
//Store All of the Standed Errors
|
//Store All of the Standed Errors
|
||||||
@@ -42,11 +42,10 @@ type StarCmd struct {
|
|||||||
func Command(command string, args ...string) (*StarCmd, error) {
|
func Command(command string, args ...string) (*StarCmd, error) {
|
||||||
var err error
|
var err error
|
||||||
shell := new(StarCmd)
|
shell := new(StarCmd)
|
||||||
shell.running = false
|
shell.running = 0
|
||||||
shell.prewritetime = time.Millisecond * 200
|
shell.prewritetime = time.Millisecond * 200
|
||||||
shell.stdoutBuf = bytes.NewBuffer(make([]byte, 0))
|
shell.stdoutBuf = bytes.NewBuffer(make([]byte, 0))
|
||||||
shell.stderrBuf = bytes.NewBuffer(make([]byte, 0))
|
shell.stderrBuf = bytes.NewBuffer(make([]byte, 0))
|
||||||
shell.runningChan = make(chan int, 3)
|
|
||||||
shell.stopctx, shell.stopctxfunc = context.WithCancel(context.Background())
|
shell.stopctx, shell.stopctxfunc = context.WithCancel(context.Background())
|
||||||
cmd := exec.Command(command, args...)
|
cmd := exec.Command(command, args...)
|
||||||
shell.CMD = cmd
|
shell.CMD = cmd
|
||||||
@@ -69,10 +68,9 @@ func Command(command string, args ...string) (*StarCmd, error) {
|
|||||||
func CommandContext(ctx context.Context, command string, args ...string) (*StarCmd, error) {
|
func CommandContext(ctx context.Context, command string, args ...string) (*StarCmd, error) {
|
||||||
var err error
|
var err error
|
||||||
shell := new(StarCmd)
|
shell := new(StarCmd)
|
||||||
shell.running = false
|
shell.running = 0
|
||||||
shell.stdoutBuf = bytes.NewBuffer(make([]byte, 0))
|
shell.stdoutBuf = bytes.NewBuffer(make([]byte, 0))
|
||||||
shell.stderrBuf = bytes.NewBuffer(make([]byte, 0))
|
shell.stderrBuf = bytes.NewBuffer(make([]byte, 0))
|
||||||
shell.runningChan = make(chan int, 3)
|
|
||||||
shell.prewritetime = time.Millisecond * 200
|
shell.prewritetime = time.Millisecond * 200
|
||||||
shell.stopctx, shell.stopctxfunc = context.WithCancel(context.Background())
|
shell.stopctx, shell.stopctxfunc = context.WithCancel(context.Background())
|
||||||
cmd := exec.CommandContext(ctx, command, args...)
|
cmd := exec.CommandContext(ctx, command, args...)
|
||||||
@@ -95,7 +93,7 @@ func CommandContext(ctx context.Context, command string, args ...string) (*StarC
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (starcli *StarCmd) queryStdout(ctx context.Context) {
|
func (starcli *StarCmd) queryStdout(ctx context.Context) {
|
||||||
for starcli.running && starcli.CMD != nil {
|
for starcli.IsRunning() && starcli.CMD != nil {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
@@ -115,7 +113,7 @@ func (starcli *StarCmd) queryStdout(ctx context.Context) {
|
|||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
if !strings.Contains(err.Error(),"file already closed") {
|
if !strings.Contains(err.Error(), "file already closed") {
|
||||||
starcli.runerr = err
|
starcli.runerr = err
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -125,7 +123,7 @@ func (starcli *StarCmd) queryStdout(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (starcli *StarCmd) queryStderr(ctx context.Context) {
|
func (starcli *StarCmd) queryStderr(ctx context.Context) {
|
||||||
for starcli.running && starcli.CMD != nil {
|
for starcli.IsRunning() && starcli.CMD != nil {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
@@ -145,7 +143,7 @@ func (starcli *StarCmd) queryStderr(ctx context.Context) {
|
|||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
if !strings.Contains(err.Error(),"file already closed") {
|
if !strings.Contains(err.Error(), "file already closed") {
|
||||||
starcli.runerr = err
|
starcli.runerr = err
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -247,20 +245,38 @@ func (starcli *StarCmd) AllStdErr() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (starcli *StarCmd) setRunning(alive bool) {
|
||||||
|
if alive {
|
||||||
|
val := atomic.LoadInt32(&starcli.running)
|
||||||
|
if val == 0 {
|
||||||
|
atomic.AddInt32(&starcli.running, 1)
|
||||||
|
} else {
|
||||||
|
atomic.AddInt32(&starcli.running, 1-val)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val := atomic.LoadInt32(&starcli.running)
|
||||||
|
if val == 1 {
|
||||||
|
atomic.AddInt32(&starcli.running, -1)
|
||||||
|
} else {
|
||||||
|
atomic.AddInt32(&starcli.running, -val)
|
||||||
|
}
|
||||||
|
}
|
||||||
func (starcli *StarCmd) Start() error {
|
func (starcli *StarCmd) Start() error {
|
||||||
if err := starcli.CMD.Start(); err != nil {
|
if err := starcli.CMD.Start(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
starcli.running = true
|
starcli.setRunning(true)
|
||||||
go func() {
|
go func() {
|
||||||
err := starcli.CMD.Wait()
|
err := starcli.CMD.Wait()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
starcli.runerr = err
|
starcli.runerr = err
|
||||||
}
|
}
|
||||||
starcli.stopctxfunc()
|
starcli.stopctxfunc()
|
||||||
starcli.running = false
|
starcli.setRunning(false)
|
||||||
starcli.exitcode = starcli.CMD.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
|
if starcli.CMD.ProcessState != nil {
|
||||||
starcli.runningChan <- 1
|
starcli.exitcode = starcli.CMD.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
go starcli.queryStdout(starcli.stopctx)
|
go starcli.queryStdout(starcli.stopctx)
|
||||||
go starcli.queryStderr(starcli.stopctx)
|
go starcli.queryStderr(starcli.stopctx)
|
||||||
@@ -282,11 +298,11 @@ func (starcli *StarCmd) Start() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (starcli *StarCmd) IsRunning() bool {
|
func (starcli *StarCmd) IsRunning() bool {
|
||||||
return starcli.running
|
return 0 != atomic.LoadInt32(&starcli.running)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (starcli *StarCmd) Stoped() <-chan int {
|
func (starcli *StarCmd) Stoped() <-chan struct{} {
|
||||||
return starcli.runningChan
|
return starcli.stopctx.Done()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (starcli *StarCmd) Exec(cmd string, wait int) (string, error) {
|
func (starcli *StarCmd) Exec(cmd string, wait int) (string, error) {
|
||||||
@@ -313,12 +329,12 @@ func (starcli *StarCmd) ExitCode() int {
|
|||||||
return starcli.exitcode
|
return starcli.exitcode
|
||||||
}
|
}
|
||||||
|
|
||||||
func (starcli *StarCmd) Kill() error{
|
func (starcli *StarCmd) Kill() error {
|
||||||
err:=starcli.CMD.Process.Kill()
|
err := starcli.CMD.Process.Kill()
|
||||||
if err!=nil{
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
starcli.running = false
|
starcli.setRunning(false)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-9
@@ -36,7 +36,7 @@ func FindProcess(compare func(Process) bool) (datas []Process, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
netInfo, netErr = NetConnections(false)
|
netInfo, netErr = NetConnections(false, "")
|
||||||
appendNetInfo := func(p *Process) {
|
appendNetInfo := func(p *Process) {
|
||||||
if netErr != nil {
|
if netErr != nil {
|
||||||
p.netErr = netErr
|
p.netErr = netErr
|
||||||
@@ -170,7 +170,7 @@ func FindProcessByPid(pid int64) (datas Process, err error) {
|
|||||||
err = errors.New("Not Found")
|
err = errors.New("Not Found")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
netInfo, netErr := NetConnections(false)
|
netInfo, netErr := NetConnections(false, "")
|
||||||
appendNetInfo := func(p *Process) {
|
appendNetInfo := func(p *Process) {
|
||||||
if netErr != nil {
|
if netErr != nil {
|
||||||
p.netErr = netErr
|
p.netErr = netErr
|
||||||
@@ -283,12 +283,12 @@ func Daemon(path string, args ...string) (int, error) {
|
|||||||
return pid, err
|
return pid, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func DaemonWithUser(uid, gid uint32,groups []uint32,path string, args ...string) (int, error) {
|
func DaemonWithUser(uid, gid uint32, groups []uint32, path string, args ...string) (int, error) {
|
||||||
cmd := exec.Command(path, args...)
|
cmd := exec.Command(path, args...)
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||||
Credential: &syscall.Credential{
|
Credential: &syscall.Credential{
|
||||||
Uid: uid,
|
Uid: uid,
|
||||||
Gid: gid,
|
Gid: gid,
|
||||||
Groups: groups,
|
Groups: groups,
|
||||||
},
|
},
|
||||||
Setsid: true,
|
Setsid: true,
|
||||||
@@ -301,11 +301,11 @@ func DaemonWithUser(uid, gid uint32,groups []uint32,path string, args ...string)
|
|||||||
return pid, err
|
return pid, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (starcli *StarCmd) SetRunUser(uid, gid uint32,groups []uint32) {
|
func (starcli *StarCmd) SetRunUser(uid, gid uint32, groups []uint32) {
|
||||||
starcli.CMD.SysProcAttr = &syscall.SysProcAttr{
|
starcli.CMD.SysProcAttr = &syscall.SysProcAttr{
|
||||||
Credential: &syscall.Credential{
|
Credential: &syscall.Credential{
|
||||||
Uid: uid,
|
Uid: uid,
|
||||||
Gid: gid,
|
Gid: gid,
|
||||||
Groups: groups,
|
Groups: groups,
|
||||||
},
|
},
|
||||||
Setsid: true,
|
Setsid: true,
|
||||||
@@ -318,13 +318,16 @@ func (starcli *StarCmd) Release() error {
|
|||||||
Setsid: true,
|
Setsid: true,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
starcli.CMD.SysProcAttr.Setsid = true
|
if !starcli.CMD.SysProcAttr.Setsid {
|
||||||
|
starcli.CMD.SysProcAttr.Setsid = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if !starcli.IsRunning() {
|
if !starcli.IsRunning() {
|
||||||
if err := starcli.CMD.Start(); err != nil {
|
if err := starcli.CMD.Start(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
time.Sleep(time.Millisecond * 10)
|
||||||
return starcli.CMD.Process.Release()
|
return starcli.CMD.Process.Release()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -59,7 +59,7 @@ func Daemon(path string, args ...string) (int, error) {
|
|||||||
return pid, nil
|
return pid, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (starcli *StarCmd) SetRunUser(uid, gid uint32) {
|
func (starcli *StarCmd) SetRunUser(uid, gid uint32, groups []uint32) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,4 +69,4 @@ func (starcli *StarCmd) Release() error {
|
|||||||
}
|
}
|
||||||
starcli.CMD.Process.Release()
|
starcli.CMD.Process.Release()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-13
@@ -78,8 +78,7 @@ func (syscfg *SysConf) ParseFromFile(filepath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
syscfg.Parse(data)
|
return syscfg.Parse(data)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse 生成INI文件结构
|
// Parse 生成INI文件结构
|
||||||
@@ -477,7 +476,7 @@ func SliceIn(slice interface{}, data interface{}) bool {
|
|||||||
|
|
||||||
// Unmarshal 输出结果到结构体中
|
// Unmarshal 输出结果到结构体中
|
||||||
func (cfg *SysConf) Unmarshal(ins interface{}) error {
|
func (cfg *SysConf) Unmarshal(ins interface{}) error {
|
||||||
var structSet func(t reflect.Type, v reflect.Value,oriSeg string) error
|
var structSet func(t reflect.Type, v reflect.Value, oriSeg string) error
|
||||||
t := reflect.TypeOf(ins)
|
t := reflect.TypeOf(ins)
|
||||||
v := reflect.ValueOf(ins).Elem()
|
v := reflect.ValueOf(ins).Elem()
|
||||||
if v.Kind() != reflect.Struct {
|
if v.Kind() != reflect.Struct {
|
||||||
@@ -487,7 +486,7 @@ func (cfg *SysConf) Unmarshal(ins interface{}) error {
|
|||||||
return errors.New("Cannot Write!")
|
return errors.New("Cannot Write!")
|
||||||
}
|
}
|
||||||
t = t.Elem()
|
t = t.Elem()
|
||||||
structSet = func(t reflect.Type, v reflect.Value,oriSeg string) error {
|
structSet = func(t reflect.Type, v reflect.Value, oriSeg string) error {
|
||||||
for i := 0; i < t.NumField(); i++ {
|
for i := 0; i < t.NumField(); i++ {
|
||||||
tp := t.Field(i)
|
tp := t.Field(i)
|
||||||
vl := v.Field(i)
|
vl := v.Field(i)
|
||||||
@@ -495,13 +494,16 @@ func (cfg *SysConf) Unmarshal(ins interface{}) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if vl.Type().Kind() == reflect.Struct {
|
if vl.Type().Kind() == reflect.Struct {
|
||||||
structSet(vl.Type(), vl,tp.Tag.Get("seg"))
|
structSet(vl.Type(), vl, tp.Tag.Get("seg"))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
seg := tp.Tag.Get("seg")
|
seg := tp.Tag.Get("seg")
|
||||||
key := tp.Tag.Get("key")
|
key := tp.Tag.Get("key")
|
||||||
if oriSeg!="" {
|
if key != "" && seg == "" && cfg.HaveSegMent {
|
||||||
seg=oriSeg
|
seg = "unnamed"
|
||||||
|
}
|
||||||
|
if oriSeg != "" {
|
||||||
|
seg = oriSeg
|
||||||
}
|
}
|
||||||
if seg == "" || key == "" {
|
if seg == "" || key == "" {
|
||||||
continue
|
continue
|
||||||
@@ -530,12 +532,12 @@ func (cfg *SysConf) Unmarshal(ins interface{}) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return structSet(t, v,"")
|
return structSet(t, v, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marshal 输出结果到结构体中
|
// Marshal 输出结果到结构体中
|
||||||
func (cfg *SysConf) Marshal(ins interface{}) ([]byte, error) {
|
func (cfg *SysConf) Marshal(ins interface{}) ([]byte, error) {
|
||||||
var structSet func(t reflect.Type, v reflect.Value,oriSeg string)
|
var structSet func(t reflect.Type, v reflect.Value, oriSeg string)
|
||||||
t := reflect.TypeOf(ins)
|
t := reflect.TypeOf(ins)
|
||||||
v := reflect.ValueOf(ins)
|
v := reflect.ValueOf(ins)
|
||||||
if v.Kind() != reflect.Struct {
|
if v.Kind() != reflect.Struct {
|
||||||
@@ -545,20 +547,20 @@ func (cfg *SysConf) Marshal(ins interface{}) ([]byte, error) {
|
|||||||
t = t.Elem()
|
t = t.Elem()
|
||||||
v = v.Elem()
|
v = v.Elem()
|
||||||
}
|
}
|
||||||
structSet = func(t reflect.Type, v reflect.Value,oriSeg string) {
|
structSet = func(t reflect.Type, v reflect.Value, oriSeg string) {
|
||||||
for i := 0; i < t.NumField(); i++ {
|
for i := 0; i < t.NumField(); i++ {
|
||||||
var seg, key, comment string = "", "", ""
|
var seg, key, comment string = "", "", ""
|
||||||
tp := t.Field(i)
|
tp := t.Field(i)
|
||||||
vl := v.Field(i)
|
vl := v.Field(i)
|
||||||
if vl.Type().Kind() == reflect.Struct {
|
if vl.Type().Kind() == reflect.Struct {
|
||||||
structSet(vl.Type(), vl,tp.Tag.Get("seg"))
|
structSet(vl.Type(), vl, tp.Tag.Get("seg"))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
seg = tp.Tag.Get("seg")
|
seg = tp.Tag.Get("seg")
|
||||||
key = tp.Tag.Get("key")
|
key = tp.Tag.Get("key")
|
||||||
comment = tp.Tag.Get("comment")
|
comment = tp.Tag.Get("comment")
|
||||||
if oriSeg != "" {
|
if oriSeg != "" {
|
||||||
seg=oriSeg
|
seg = oriSeg
|
||||||
}
|
}
|
||||||
if seg == "" || key == "" {
|
if seg == "" || key == "" {
|
||||||
continue
|
continue
|
||||||
@@ -570,7 +572,7 @@ func (cfg *SysConf) Marshal(ins interface{}) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
structSet(t, v,"")
|
structSet(t, v, "")
|
||||||
return cfg.Build(), nil
|
return cfg.Build(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,22 @@ const (
|
|||||||
TB = GB << 10
|
TB = GB << 10
|
||||||
PB = TB << 10
|
PB = TB << 10
|
||||||
)
|
)
|
||||||
|
const (
|
||||||
|
TCP_UNKNOWN = iota
|
||||||
|
TCP_ESTABLISHED
|
||||||
|
TCP_SYN_SENT
|
||||||
|
TCP_SYN_RECV
|
||||||
|
TCP_FIN_WAIT1
|
||||||
|
TCP_FIN_WAIT2
|
||||||
|
TCP_TIME_WAIT
|
||||||
|
TCP_CLOSE
|
||||||
|
TCP_CLOSE_WAIT
|
||||||
|
TCP_LAST_ACL
|
||||||
|
TCP_LISTEN
|
||||||
|
TCP_CLOSING
|
||||||
|
)
|
||||||
|
|
||||||
|
var TCP_STATE = []string{"TCP_UNKNOWN", "TCP_ESTABLISHED", "TCP_SYN_SENT", "TCP_SYN_RECV", "TCP_FIN_WAIT1", "TCP_FIN_WAIT2", "TCP_TIME_WAIT", "TCP_CLOSE", "TCP_CLOSE_WAIT", "TCP_LAST_ACL", "TCP_LISTEN", "TCP_CLOSING"}
|
||||||
|
|
||||||
type NetAdapter struct {
|
type NetAdapter struct {
|
||||||
Name string
|
Name string
|
||||||
@@ -19,9 +35,11 @@ type NetAdapter struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type NetSpeed struct {
|
type NetSpeed struct {
|
||||||
Name string
|
Name string
|
||||||
RecvBytes float64
|
RecvSpeeds float64
|
||||||
SendBytes float64
|
SendSpeeds float64
|
||||||
|
RecvBytes uint64
|
||||||
|
SendBytes uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process 定义一个进程的信息
|
// Process 定义一个进程的信息
|
||||||
@@ -79,14 +97,20 @@ type DiskStatus struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type NetConn struct {
|
type NetConn struct {
|
||||||
LocalAddr string
|
LocalAddr string
|
||||||
LocalPort int
|
LocalPort int
|
||||||
Typed string
|
Typed string
|
||||||
RemoteAddr string
|
RemoteAddr string
|
||||||
RemotePort int
|
RemotePort int
|
||||||
Socket string
|
Socket string
|
||||||
Inode string
|
Inode string
|
||||||
Pid int64
|
Status string
|
||||||
Uid int64
|
TX_Queue int64
|
||||||
Process *Process
|
RX_Queue int64
|
||||||
|
TimerActive string
|
||||||
|
TimerJiffies int64
|
||||||
|
RtoTimer int64
|
||||||
|
Pid int64
|
||||||
|
Uid int64
|
||||||
|
Process *Process
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user