10 Commits

Author SHA1 Message Date
b612 42ad19e798 update go.mod 2024-03-10 14:21:37 +08:00
b612 232bc3835e re-support go 1.16 2023-02-11 17:53:24 +08:00
b612 1333eb85bb adjust linux network speed monitor 2023-02-03 13:54:13 +08:00
b612 dae84c0a85 update go mod 2023-02-03 13:36:41 +08:00
b612 ed85eb7616 update go mod and fix filelock error on darwin 2022-03-18 17:22:38 +08:00
b612 d8c0d86ca0 go mod support 2022-03-14 11:40:14 +08:00
b612 bbd85885df add beep function 2022-01-04 14:18:38 +08:00
b612 c615c4bb00 vendor update 2021-11-12 15:58:01 +08:00
b612 5353429b8c shared lock support 2021-09-01 13:52:43 +08:00
b612 cf453821ef new feature add 2021-09-01 11:01:51 +08:00
18 changed files with 831 additions and 80 deletions
+28
View File
@@ -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
View File
@@ -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
}
+37
View File
@@ -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)
}
+41
View File
@@ -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
}
+13 -1
View File
@@ -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 {
+70
View File
@@ -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))
} }
+23
View File
@@ -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)
}
+70
View File
@@ -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
View File
@@ -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))
}
+10
View File
@@ -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
)
+51
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
} }
+37 -13
View File
@@ -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
} }