28 Commits

Author SHA1 Message Date
b612 0b6373e9e3 Merge branch 'master' of git.b612.me:b612/staros 2024-08-30 15:03:24 +08:00
b612 0e7072d72a update go.mod 2024-08-30 15:02:53 +08:00
b612 c1b5b0c2c5 update host file 2024-04-10 15:52:57 +08:00
b612 a1fdeb62fc update host file 2024-04-10 15:19:25 +08:00
b612 bae1b83843 update 2024-04-10 13:10:41 +08:00
b612 4190d59159 update host file 2024-04-10 11:19:04 +08:00
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
b612 3501166592 bug fix 2021-07-07 10:39:07 +08:00
Starainrt d981a03b14 bug fix & netconn add 2021-06-04 10:44:53 +08:00
Starainrt fd5cf2c1f6 csv support 2021-05-17 15:09:04 +08:00
Starainrt c3ca057b96 add ini config parse and fix bug:math problem 2021-03-17 11:16:28 +08:00
b612 c3a165e64a bug fix:struct error while get file creation date 2020-12-22 09:27:55 +08:00
b612 ad5c18667a add mathmatic calc 2020-12-21 17:19:41 +08:00
b612 cdf3a18981 bug fix 2020-11-27 11:20:23 +08:00
b612 6de9af62cc fix bug while use common user 2020-11-26 16:14:12 +08:00
b612 bca0d42559 fix bug while use common user 2020-11-26 15:54:46 +08:00
b612 26da8c8b88 fix bug that darwin cannot compile due to syscall_t error 2020-08-21 11:17:48 +08:00
b612 5c2cce2da2 cli bug fix 2020-07-27 14:19:05 +08:00
b612 a94fc8d19d new feature add 2020-07-17 09:56:23 +08:00
36 changed files with 4181 additions and 363 deletions
+2
View File
@@ -0,0 +1,2 @@
.idea
.vscode
+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 {
+91
View File
@@ -0,0 +1,91 @@
//+build darwin
package staros
import (
"b612.me/stario"
"os"
"syscall"
"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 {
return time.Unix(int64(ts.Sec), int64(ts.Nsec))
}
func GetFileCreationTime(fileinfo os.FileInfo) time.Time {
return timespecToTime(fileinfo.Sys().(*syscall.Stat_t).Ctimespec)
}
func GetFileAccessTime(fileinfo os.FileInfo) time.Time {
return timespecToTime(fileinfo.Sys().(*syscall.Stat_t).Atimespec)
}
+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)
}
+91
View File
@@ -0,0 +1,91 @@
//+build linux
package staros
import (
"b612.me/stario"
"os"
"syscall"
"time"
)
type FileLock struct {
fd int
filepath string
}
func timespecToTime(ts syscall.Timespec) time.Time {
return time.Unix(int64(ts.Sec), int64(ts.Nsec))
}
func GetFileCreationTime(fileinfo os.FileInfo) time.Time {
return timespecToTime(fileinfo.Sys().(*syscall.Stat_t).Ctim)
}
func GetFileAccessTime(fileinfo os.FileInfo) time.Time {
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
})
}
+123
View File
@@ -0,0 +1,123 @@
// +build windows
package staros
import (
"b612.me/win32api"
"os"
"syscall"
"time"
)
type FileLock struct {
filepath string
handle win32api.HANDLE
}
func GetFileCreationTime(fileinfo os.FileInfo) time.Time {
d := fileinfo.Sys().(*syscall.Win32FileAttributeData)
return time.Unix(0, d.CreationTime.Nanoseconds())
}
func GetFileAccessTime(fileinfo os.FileInfo) time.Time {
d := fileinfo.Sys().(*syscall.Win32FileAttributeData)
return time.Unix(0, d.LastAccessTime.Nanoseconds())
}
func SetFileTimes(file *os.File, info os.FileInfo) {
}
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.10
b612.me/win32api v0.0.2
b612.me/wincmd v0.0.4
golang.org/x/sys v0.24.0
)
+75
View File
@@ -0,0 +1,75 @@
b612.me/stario v0.0.10 h1:+cIyiDCBCjUfodMJDp4FLs+2E1jo7YENkN+sMEe6550=
b612.me/stario v0.0.10/go.mod h1:1Owmu9jzKWgs4VsmeI8YWlGwLrCwPNM/bYpxkyn+MMk=
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.4 h1:fv9p1V8mw2HdUjaoZBWZy0T41JftueyLxAuch1MgtdI=
b612.me/wincmd v0.0.4/go.mod h1:o3yPoE+DpVPHGKl/q1WT1C8OaIVwHEnpeNgMFqzlwD8=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
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.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
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/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
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.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
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/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
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.12.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/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
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.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
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.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
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/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+1059 -146
View File
File diff suppressed because it is too large Load Diff
+145 -3
View File
@@ -6,7 +6,149 @@ import (
) )
func Test_Hosts(t *testing.T) { func Test_Hosts(t *testing.T) {
//RemoveHostbyIp("192.168.222.33") var h = NewHosts()
Parse() err := h.Parse("./test_hosts.txt")
fmt.Println(GetAllListbyIp()) if err != nil {
t.Error(err)
}
next := h.firstUid
for next != 0 {
node, _ := h.GetNode(next)
fmt.Printf("Last %d, Next: %d, IP: %s, Hosts: %s, Comment: %s\n", node.LastUID(), node.NextUID(), node.IP(), node.Hosts(), node.Comment())
next = node.NextUID()
}
data := h.ListHostsByIP("11.22.33.44")
if len(data) != 2 {
t.Error("Expected 2, got ", len(data))
} else {
t.Log(data)
}
data = h.ListIPsByHost("dns.b612.me")
if len(data) < 1 || data[0] != "4.5.6.7" {
t.Error("Expected 4.5.6.7, got ", data)
} else {
t.Log(data)
}
err = h.RemoveHosts("dns.b612.me")
if err != nil {
t.Error(err)
}
data = h.ListIPsByHost("dns.b612.me")
if len(data) > 0 {
t.Error("Expected 0, got ", len(data))
} else {
t.Log(data)
}
err = h.RemoveHosts("test.dns.set.b612.me")
if err != nil {
t.Error(err)
}
data = h.ListIPsByHost("remove.b612.me")
if len(data) < 1 || data[0] != "11.22.33.44" {
t.Error("Expected 11.22.33.44, got ", data)
} else {
t.Log(data)
}
nodes := h.ListByIP("11.22.33.44")
if nodes == nil {
t.Error("Expected not nil, got ", nodes)
} else {
t.Log(nodes)
}
nodes[0].AddHosts("hello.b612.me")
err = h.UpdateNode(nodes[0])
if err != nil {
t.Error(err)
}
data = h.ListIPsByHost("hello.b612.me")
if len(data) < 1 || data[0] != "11.22.33.44" {
t.Error("Not Expected Data", data)
} else {
t.Log(data)
}
insertNode := new(HostNode)
insertNode.SetIP("11.11.11.11")
insertNode.SetHosts("insert.b612.me")
insertNode.SetComment("Insert Node")
insertNode.SetNextUID(nodes[0].UID())
insertNode.SetLastUID(nodes[0].LastUID())
err = h.InsertNode(insertNode)
if err != nil {
t.Error(err)
}
data = h.ListIPsByHost("insert.b612.me")
if len(data) < 1 || data[0] != "11.11.11.11" {
t.Error("Expected 11.11.11.11 got ", data)
} else {
t.Log(data)
}
err = h.SaveAs("./test_hosts_01.txt")
if err != nil {
t.Error(err)
}
err = h.DeleteNode(insertNode)
if err != nil {
t.Error(err)
}
data = h.ListIPsByHost("insert.b612.me")
if len(data) > 0 {
t.Error("Expected 0 got ", data)
} else {
t.Log(data)
}
for i := 0; i < 100; i++ {
err = h.RemoveHosts("release-ftpd")
if err != nil {
t.Error(err)
}
err = h.AddHosts("2.3.4.9", "release-ftpd")
if err != nil {
t.Error(err)
}
}
err = h.SetHostIPs("ssh.b612.me", "9.9.9.9")
if err != nil {
t.Error(err)
}
data = h.ListIPsByHost("ssh.b612.me")
if len(data) == 0 {
t.Error("Expected 1 got ", data)
} else {
t.Log(data)
}
err = h.SetIPHosts("10.10.10.10", "ssh.b612.me", "ssr.b612.me")
if len(data) == 0 {
t.Error("Expected 1 got ", data)
}
err = h.SaveAs("./test_hosts_02.txt")
if err != nil {
t.Error(err)
}
}
func BenchmarkAddHosts(b *testing.B) {
var h = NewHosts()
err := h.Parse("./test_hosts.txt")
if err != nil {
b.Error(err)
}
for i := 0; i < b.N; i++ {
err = h.AddHosts("1.3.4.5", "test.b612.me")
if err != nil {
b.Error(err)
}
}
} }
+23
View File
@@ -0,0 +1,23 @@
#hosts This file describes a number of hostname-to-address
#mappings for the TCP/IP subsystem. It is mostly
#used at boot time, when no name servers are running.
#On small systems, this file can be used instead of a
#"named" name server.
#Syntax:
#IP-Address Full-Qualifie
#special IPv6 addre
127.0.0.1 localhost
127.0.0.1 b612
8.8.8.8 ssh.b612.me
#special IPv6 addresses
::1 localhost ipv6-localhost ipv6-loopback
fe00::0 ipv6-localnet
ff00::0 ipv6-mcastprefix
ff02::1 ipv6-allnodes
ff02::2 ipv6-allrouters
ff02::3 ipv6-allhosts
1.2.3.4 ssh.b612.me
4.5.6.7 dns.b612.me
8.9.10.11 release-ftpd
11.22.33.44 test.dns.set.b612.me remove.b612.me
4.5.6.7 game.b612.me
+305
View File
@@ -0,0 +1,305 @@
package staros
import (
"errors"
"fmt"
"math"
"strconv"
"strings"
)
func Calc(math string) (float64, error) {
math = strings.Replace(math, " ", "", -1)
math = strings.ToLower(math)
if err := check(math); err != nil {
return 0, err
}
result,err:=calc(math)
if err!=nil {
return 0,err
}
return floatRound(result,15),nil
}
func floatRound(f float64, n int) float64 {
format := "%." + strconv.Itoa(n) + "f"
res, _ := strconv.ParseFloat(fmt.Sprintf(format, f), 64)
return res
}
func check(math string) error {
math = strings.Replace(math, " ", "", -1)
math = strings.ToLower(math)
var bracketSum int
var signReady bool
for k, v := range math {
if string([]rune{v}) == "(" {
bracketSum++
}
if string([]rune{v}) == ")" {
bracketSum--
}
if bracketSum < 0 {
return fmt.Errorf("err at position %d.Reason is right bracket position not correct,except (", k)
}
if containSign(string([]rune{v})) {
if signReady {
if string([]rune{v}) != "+" && string([]rune{v}) != "-" {
return fmt.Errorf("err at position %d.Reason is sign %s not correct", k, string([]rune{v}))
}
} else {
signReady = true
continue
}
}
signReady = false
}
if bracketSum != 0 {
return fmt.Errorf("Error:right bracket is not equal as left bracket")
}
return nil
}
func calc(math string) (float64, error) {
var bracketLeft int
var bracketRight int
var DupStart int = -1
for pos, str := range math {
if string(str) == "(" {
bracketLeft = pos
}
if string(str) == ")" {
bracketRight = pos
break
}
}
if bracketRight == 0 && bracketLeft != 0 || (bracketLeft > bracketRight) {
return 0, fmt.Errorf("Error:bracket not correct at %d ,except )", bracketLeft)
}
if bracketRight == 0 && bracketLeft == 0 {
return calcLong(math)
}
line := math[bracketLeft+1 : bracketRight]
num, err := calcLong(line)
if err != nil {
return 0, err
}
for i := bracketLeft - 1; i >= 0; i-- {
if !containSign(math[i : i+1]) {
DupStart = i
continue
}
break
}
if DupStart != -1 {
sign := math[DupStart:bracketLeft]
num, err := calcDuaFloat(sign, num)
if err != nil {
return 0, err
}
math = math[:DupStart] + fmt.Sprintf("%.15f", num) + math[bracketRight+1:]
DupStart = -1
} else {
math = math[:bracketLeft] + fmt.Sprintf("%.15f", num) + math[bracketRight+1:]
}
return calc(math)
}
func calcLong(str string) (float64, error) {
var sigReady bool = false
var sigApply bool = false
var numPool []float64
var operPool []string
var numStr string
var oper string
if str[0:1] == "+" || str[0:1] == "-" {
sigReady = true
}
for _, stp := range str {
if sigReady && containSign(string(stp)) {
sigReady = false
sigApply = true
oper = string(stp)
continue
}
if !containSign(string(stp)) {
sigReady = false
numStr = string(append([]rune(numStr), stp))
continue
}
if !sigReady {
sigReady = true
}
if sigApply {
num, err := calcDua(oper, numStr)
if err != nil {
return 0, err
}
sigApply = false
numPool = append(numPool, num)
} else {
num, err := parseNumbic(numStr)
if err != nil {
return 0, err
}
numPool = append(numPool, num)
}
numStr = ""
operPool = append(operPool, string(stp))
}
if sigApply {
num, err := calcDua(oper, numStr)
if err != nil {
return 0, err
}
numPool = append(numPool, num)
} else {
num, err := parseNumbic(numStr)
if err != nil {
return 0, err
}
numPool = append(numPool, num)
}
return calcPool(numPool, operPool)
}
func calcPool(numPool []float64, operPool []string) (float64, error) {
if len(numPool) == 1 && len(operPool) == 0 {
return numPool[0], nil
}
if len(numPool) < len(operPool) {
return 0, errors.New(("Operate Signal Is too much"))
}
calcFunc := func(k int, v string) (float64, error) {
num, err := calcSigFloat(numPool[k], v, numPool[k+1])
if err != nil {
return 0, err
}
tmp := append(numPool[:k], num)
numPool = append(tmp, numPool[k+2:]...)
operPool = append(operPool[:k], operPool[k+1:]...)
return calcPool(numPool, operPool)
}
for k, v := range operPool {
if v == "^" {
return calcFunc(k, v)
}
}
for k, v := range operPool {
if v == "*" || v == "/" {
return calcFunc(k, v)
}
}
for k, v := range operPool {
return calcFunc(k, v)
}
return 0, nil
}
func calcSigFloat(floatA float64, b string, floatC float64) (float64, error) {
switch b {
case "+":
return floatRound(floatA + floatC,15), nil
case "-":
return floatRound(floatA - floatC,15), nil
case "*":
return floatRound(floatA * floatC,15), nil
case "/":
if floatC == 0 {
return 0, errors.New("Divisor cannot be 0")
}
return floatRound(floatA / floatC,15), nil
case "^":
return math.Pow(floatA, floatC), nil
}
return 0, fmt.Errorf("unexpect method:%s", b)
}
func calcSig(a, b, c string) (float64, error) {
floatA, err := parseNumbic(a)
if err != nil {
return 0, err
}
floatC, err := parseNumbic(c)
if err != nil {
return 0, err
}
return calcSigFloat(floatA, b, floatC)
}
func calcDuaFloat(a string, floatB float64) (float64, error) {
switch a {
case "sin":
return math.Sin(floatB), nil
case "cos":
return math.Cos(floatB), nil
case "tan":
return math.Tan(floatB), nil
case "abs":
return math.Abs(floatB), nil
case "arcsin":
return math.Asin(floatB), nil
case "arccos":
return math.Acos(floatB), nil
case "arctan":
return math.Atan(floatB), nil
case "sqrt":
return math.Sqrt(floatB), nil
case "loge":
return math.Log(floatB), nil
case "log10":
return math.Log10(floatB), nil
case "log2":
return math.Log2(floatB), nil
case "floor":
return math.Floor(floatB), nil
case "ceil":
return math.Ceil(floatB), nil
case "round":
return math.Round(floatB), nil
case "trunc":
return math.Trunc(floatB), nil
case "+":
return 0 + floatB, nil
case "-":
return 0 - floatB, nil
}
return 0, fmt.Errorf("unexpect method:%s", a)
}
func calcDua(a, b string) (float64, error) {
floatB, err := parseNumbic(b)
if err != nil {
return 0, err
}
return calcDuaFloat(a, floatB)
}
func parseNumbic(str string) (float64, error) {
switch str {
case "pi":
return float64(math.Pi), nil
case "e":
return float64(math.E), nil
default:
return strconv.ParseFloat(str, 64)
}
}
func containSign(str string) bool {
var sign []string = []string{"+", "-", "*", "/", "^"}
for _, v := range sign {
if str == v {
return true
}
}
return false
}
func contain(pool []string, str string) bool {
for _, v := range pool {
if v == str {
return true
}
}
return false
}
+101
View File
@@ -0,0 +1,101 @@
//+build darwin
package staros
import (
"encoding/binary"
"fmt"
"golang.org/x/sys/unix"
"os/exec"
"strconv"
"strings"
"unsafe"
)
// Memory 系统内存信息
func Memory() (MemStatus,error) {
return darwinMemory()
}
type swapUsage struct {
Total uint64
Avail uint64
Used uint64
Pagesize int32
Encrypted bool
}
func darwinMemory() (MemStatus, error) {
var err error
var res MemStatus
vm_stat, err := exec.LookPath("vm_stat")
if err != nil {
return res, err
}
out, err := exec.Command(vm_stat).CombinedOutput()
if err != nil {
return res, err
}
totalString, err := unix.Sysctl("hw.memsize")
if err != nil {
return res, err
}
// unix.sysctl() helpfully assumes the result is a null-terminated string and
// removes the last byte of the result if it's 0 :/
totalString += "\x00"
res.All = uint64(binary.LittleEndian.Uint64([]byte(totalString)))
lines := strings.Split(string(out), "\n")
pagesize := uint64(unix.Getpagesize())
for _, line := range lines {
fields := strings.Split(line, ":")
if len(fields) < 2 {
continue
}
key := strings.TrimSpace(fields[0])
value := strings.Trim(fields[1], " .")
switch key {
case "Pages free":
free, e := strconv.ParseUint(value, 10, 64)
if e != nil {
err = e
}
res.Free = free * pagesize
case "Pages inactive":
inactive, e := strconv.ParseUint(value, 10, 64)
if e != nil {
err = e
}
res.Available = inactive * pagesize
case "Pages active":
active, e := strconv.ParseUint(value, 10, 64)
if e != nil {
err = e
}
_ = active * pagesize
case "Pages wired down":
wired, e := strconv.ParseUint(value, 10, 64)
if e != nil {
err = e
}
_ = wired * pagesize
}
}
res.Available += res.Free
res.Used = res.All - res.Available
//swap
value, err := unix.SysctlRaw("vm.swapusage")
if err != nil {
return res, err
}
if len(value) != 32 {
return res, fmt.Errorf("unexpected output of sysctl vm.swapusage: %v (len: %d)", value, len(value))
}
swap := (*swapUsage)(unsafe.Pointer(&value[0]))
res.SwapAll = swap.Total
res.SwapUsed = swap.Used
res.SwapFree = swap.Avail
return res, err
}
+24
View File
@@ -0,0 +1,24 @@
//+build linux
package staros
import "syscall"
// Memory 系统内存信息
func Memory() (MemStatus, error) {
var mem MemStatus
ram := new(syscall.Sysinfo_t)
if err := syscall.Sysinfo(ram); err != nil {
return mem, err
}
mem.All = uint64(ram.Totalram)
mem.BuffCache = uint64(ram.Bufferram)
mem.Free = uint64(ram.Freeram)
mem.Shared = uint64(ram.Sharedram)
mem.Available = uint64(ram.Freeram + ram.Sharedram + ram.Bufferram)
mem.SwapAll = uint64(ram.Totalswap)
mem.SwapFree = uint64(ram.Freeswap)
mem.SwapUsed = uint64(mem.SwapAll - mem.SwapFree)
mem.Used = uint64(mem.All - mem.Free)
return mem, nil
}
+26
View File
@@ -0,0 +1,26 @@
// +build windows
package staros
import "b612.me/win32api"
// Memory 系统内存信息
func Memory() (MemStatus, error) {
var mem MemStatus
ram := new(win32api.MEMORYSTATUSEX)
_, err := win32api.GlobalMemoryStatusEx(ram)
if err != nil {
return mem, err
}
mem.All = uint64(ram.UllTotalPhys)
mem.Free = uint64(ram.UllAvailPhys)
mem.Available = uint64(ram.UllAvailPhys)
mem.Used = uint64(mem.All - mem.Free)
mem.SwapAll = uint64(ram.UllTotalPageFile)
mem.SwapFree = uint64(ram.UllAvailPageFile)
mem.SwapUsed = mem.SwapAll - mem.SwapFree
mem.VirtualAll = uint64(mem.VirtualAll)
mem.VirtualAvail = uint64(mem.VirtualAvail)
mem.VirtualUsed = mem.VirtualAll - mem.VirtualUsed
return mem, nil
}
+9
View File
@@ -0,0 +1,9 @@
package staros
import (
"testing"
)
func Test_TrimSpace(t *testing.T) {
}
+326
View File
@@ -0,0 +1,326 @@
//go:build !windows
// +build !windows
package staros
import (
"errors"
"io/ioutil"
"os"
"strconv"
"strings"
"time"
)
func NetUsage() ([]NetAdapter, error) {
data, err := ioutil.ReadFile("/proc/net/dev")
if err != nil {
return []NetAdapter{}, err
}
sps := strings.Split(strings.TrimSpace(string(data)), "\n")
if len(sps) < 3 {
return []NetAdapter{}, errors.New("No Adaptor")
}
var res []NetAdapter
netLists := sps[2:]
for _, v := range netLists {
v = strings.ReplaceAll(v, " ", " ")
for strings.Contains(v, " ") {
v = strings.ReplaceAll(v, " ", " ")
}
v = strings.TrimSpace(v)
card := strings.Split(v, " ")
name := strings.ReplaceAll(card[0], ":", "")
recvBytes, _ := strconv.Atoi(card[1])
sendBytes, _ := strconv.Atoi(card[9])
res = append(res, NetAdapter{name, uint64(recvBytes), uint64(sendBytes)})
}
return res, nil
}
func NetUsageByname(name string) (NetAdapter, error) {
ada, err := NetUsage()
if err != nil {
return NetAdapter{}, err
}
for _, v := range ada {
if v.Name == name {
return v, nil
}
}
return NetAdapter{}, errors.New("Not Found")
}
func NetSpeeds(duration time.Duration) ([]NetSpeed, error) {
list1, err := NetUsage()
if err != nil {
return []NetSpeed{}, err
}
time.Sleep(duration)
list2, err := NetUsage()
if err != nil {
return []NetSpeed{}, err
}
if len(list1) > len(list2) {
return []NetSpeed{}, errors.New("NetWork Adaptor Num Not ok")
}
var res []NetSpeed
for k, v := range list1 {
recv := float64(list2[k].RecvBytes-v.RecvBytes) / duration.Seconds()
send := float64(list2[k].SendBytes-v.SendBytes) / duration.Seconds()
res = append(res, NetSpeed{
Name: v.Name,
RecvSpeeds: recv,
SendSpeeds: send,
RecvBytes: list2[k].RecvBytes,
SendBytes: list2[k].SendBytes,
})
}
return res, nil
}
func NetSpeedsByName(duration time.Duration, name string) (NetSpeed, error) {
ada, err := NetSpeeds(duration)
if err != nil {
return NetSpeed{}, err
}
for _, v := range ada {
if v.Name == name {
return v, nil
}
}
return NetSpeed{}, errors.New("Not Found")
}
// NetConnections return all TCP/UDP/UNIX DOMAIN SOCKET Connections
// if your uid != 0 ,and analysePid==true ,you should have CAP_SYS_PRTACE and CAP_DAC_OVERRIDE/CAP_DAC_READ_SEARCH Caps
func NetConnections(analysePid bool, types string) ([]NetConn, error) {
var result []NetConn
var inodeMap map[string]int64
var err error
var fileList []string
if types == "" || strings.Contains(strings.ToLower(types), "all") {
fileList = []string{
"/proc/net/tcp",
"/proc/net/tcp6",
"/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 {
inodeMap, err = GetInodeMap()
if err != nil {
return result, err
}
}
for _, file := range fileList {
data, err := ioutil.ReadFile(file)
if err != nil {
return result, err
}
tmpRes, err := analyseNetFiles(data, inodeMap, file[strings.LastIndex(file, "/")+1:])
if err != nil {
return result, err
}
result = append(result, tmpRes...)
}
return result, nil
}
func GetInodeMap() (map[string]int64, error) {
res := make(map[string]int64)
paths, err := ioutil.ReadDir("/proc")
if err != nil {
return nil, err
}
for _, v := range paths {
if v.IsDir() && Exists("/proc/"+v.Name()+"/fd") {
fds, err := ioutil.ReadDir("/proc/" + v.Name() + "/fd")
if err != nil && Exists("/proc/"+v.Name()+"/fd") {
return nil, err
}
for _, fd := range fds {
socket, err := os.Readlink("/proc/" + v.Name() + "/fd/" + fd.Name())
if err != nil {
continue
}
if !strings.Contains(socket, "socket") {
continue
}
start := strings.Index(socket, "[")
if start < 0 {
continue
}
pid, err := strconv.ParseInt(v.Name(), 10, 64)
if err != nil {
break
}
res[socket[start+1:len(socket)-1]] = pid
}
}
}
return res, err
}
func analyseNetFiles(data []byte, inodeMap map[string]int64, typed string) ([]NetConn, error) {
if typed == "unix" {
return analyseUnixFiles(data, inodeMap, typed)
}
var result []NetConn
strdata := strings.TrimSpace(string(data))
strdata = remainOne(strdata, " ", " ")
csvData := strings.Split(strdata, "\n")
pidMap := make(map[int64]*Process)
for line, lineData := range csvData {
if line == 0 {
continue
}
v := strings.Split(strings.TrimSpace(lineData), " ")
var res NetConn
ip, port, err := parseHexIpPort(v[1])
if err != nil {
return result, err
}
res.LocalAddr = ip
res.LocalPort = port
ip, port, err = parseHexIpPort(v[2])
if err != nil {
return result, err
}
res.RemoteAddr = ip
res.RemotePort = port
//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)
if err != nil {
return result, err
}
res.Inode = v[9]
if inodeMap != nil && len(inodeMap) > 0 {
var ok bool
res.Pid, ok = inodeMap[res.Inode]
if !ok {
res.Pid = -1
} else {
_, ok := pidMap[res.Pid]
if !ok {
tmp, err := FindProcessByPid(res.Pid)
if err != nil {
pidMap[res.Pid] = nil
} else {
pidMap[res.Pid] = &tmp
}
}
res.Process = pidMap[res.Pid]
}
}
res.Typed = typed
result = append(result, res)
}
return result, nil
}
func analyseUnixFiles(data []byte, inodeMap map[string]int64, typed string) ([]NetConn, error) {
var result []NetConn
strdata := strings.TrimSpace(string(data))
strdata = remainOne(strdata, " ", " ")
csvData := strings.Split(strdata, "\n")
pidMap := make(map[int64]*Process)
for line, lineData := range csvData {
if line == 0 {
continue
}
v := strings.Split(strings.TrimSpace(lineData), " ")
var res NetConn
res.Inode = v[6]
if len(v) == 8 {
res.Socket = v[7]
}
if inodeMap != nil && len(inodeMap) > 0 {
var ok bool
res.Pid, ok = inodeMap[res.Inode]
if !ok {
res.Pid = -1
} else {
_, ok := pidMap[res.Pid]
if !ok || pidMap[res.Pid] == nil {
tmp, err := FindProcessByPid(res.Pid)
if err != nil {
pidMap[res.Pid] = nil
} else {
pidMap[res.Pid] = &tmp
}
}
if pidMap[res.Pid] != nil {
res.Uid = int64(pidMap[res.Pid].RUID)
res.Process = pidMap[res.Pid]
}
}
}
res.Typed = typed
result = append(result, res)
}
return result, nil
}
+33
View File
@@ -0,0 +1,33 @@
// +build windows
package staros
import (
"time"
)
func NetUsage() ([]NetAdapter, error) {
var res []NetAdapter
return res, nil
}
func NetUsageByname(name string) (NetAdapter, error) {
return NetAdapter{}, nil
}
func NetSpeeds(duration time.Duration) ([]NetSpeed, error) {
var res []NetSpeed
return res, nil
}
func NetSpeedsByName(duration time.Duration, name string) (NetSpeed, error) {
return NetSpeed{}, nil
}
// NetConnections return all TCP/UDP/UNIX DOMAIN SOCKET Connections
// if your uid != 0 ,and analysePid==true ,you should have CAP_SYS_PRTACE and CAP_DAC_OVERRIDE/CAP_DAC_READ_SEARCH Caps
func NetConnections(analysePid bool) ([]NetConn, error) {
var result []NetConn
return result, nil
}
+55 -24
View File
@@ -1,8 +1,9 @@
// +build linux darwin // +build linux darwin unix
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")
@@ -29,25 +32,6 @@ func IsRoot() bool {
return false return false
} }
// Memory 系统内存信息
func Memory() MemStatus {
var mem MemStatus
ram := new(syscall.Sysinfo_t)
if err := syscall.Sysinfo(ram); err != nil {
return mem
}
mem.All = ram.Totalram
mem.BuffCache = ram.Bufferram
mem.Free = ram.Freeram
mem.Shared = ram.Sharedram
mem.Available = ram.Freeram + ram.Sharedram + ram.Bufferram
mem.SwapAll = ram.Totalswap
mem.SwapFree = ram.Freeswap
mem.SwapUsed = mem.SwapAll - mem.SwapFree
mem.Used = mem.All - mem.Free
return mem
}
func Whoami() (uid, gid int, uname, gname, home string, err error) { func Whoami() (uid, gid int, uname, gname, home string, err error) {
var me *user.User var me *user.User
var gup *user.Group var gup *user.Group
@@ -83,8 +67,8 @@ func getCPUSample() (idle, total uint64) {
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
@@ -92,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 {
@@ -105,8 +138,6 @@ func CpuUsage(sleep time.Duration) float64 {
//fmt.Printf("CPU usage is %f%% [busy: %f, total: %f]\n", cpuUsage, totalTicks-idleTicks, totalTicks) //fmt.Printf("CPU usage is %f%% [busy: %f, total: %f]\n", cpuUsage, totalTicks-idleTicks, totalTicks)
} }
func DiskUsage(path string) (disk DiskStatus) { func DiskUsage(path string) (disk DiskStatus) {
fs := syscall.Statfs_t{} fs := syscall.Statfs_t{}
err := syscall.Statfs(path, &fs) err := syscall.Statfs(path, &fs)
+4 -17
View File
@@ -27,23 +27,6 @@ func IsRoot() bool {
return wincmd.Isas() return wincmd.Isas()
} }
// Memory 系统内存信息
func Memory() MemStatus {
var mem MemStatus
ram := new(win32api.MEMORYSTATUSEX)
win32api.GlobalMemoryStatusEx(ram)
mem.All = uint64(ram.UllTotalPhys)
mem.Free = uint64(ram.UllAvailPhys)
mem.Available = uint64(ram.UllAvailPhys)
mem.Used = uint64(mem.All - mem.Free)
mem.SwapAll = uint64(ram.UllTotalPageFile)
mem.SwapFree = uint64(ram.UllAvailPageFile)
mem.SwapUsed = mem.SwapAll - mem.SwapFree
mem.VirtualAll = uint64(mem.VirtualAll)
mem.VirtualAvail = uint64(mem.VirtualAvail)
mem.VirtualUsed = mem.VirtualAll - mem.VirtualUsed
return mem
}
func DiskUsage(path string) (disk DiskStatus) { func DiskUsage(path string) (disk DiskStatus) {
kernel32, err := syscall.LoadLibrary("Kernel32.dll") kernel32, err := syscall.LoadLibrary("Kernel32.dll")
@@ -71,3 +54,7 @@ func DiskUsage(path string) (disk DiskStatus) {
disk.Available = uint64(lpFreeBytesAvailable) disk.Available = uint64(lpFreeBytesAvailable)
return return
} }
func CpuUsage(sleep time.Duration) float64 {
return 0
}
+347
View File
@@ -0,0 +1,347 @@
package staros
import (
"bytes"
"context"
"errors"
"io"
"os"
"os/exec"
"strings"
"sync"
"sync/atomic"
"syscall"
"time"
)
//StarCmd Is Here
type StarCmd struct {
CMD *exec.Cmd
outfile io.ReadCloser
infile io.WriteCloser
errfile io.ReadCloser
running int32
//Store AlL of the Standed Outputs
stdout []byte
//Store All of the Standed Errors
errout []byte
runerr error
exitcode int
stdoutBuf *bytes.Buffer
stderrBuf *bytes.Buffer
stdoutpoint int
stderrpoint int
lock sync.Mutex
prewrite []string
prewritetime time.Duration
stopctxfunc context.CancelFunc
stopctx context.Context
}
func Command(command string, args ...string) (*StarCmd, error) {
var err error
shell := new(StarCmd)
shell.running = 0
shell.prewritetime = time.Millisecond * 200
shell.stdoutBuf = bytes.NewBuffer(make([]byte, 0))
shell.stderrBuf = bytes.NewBuffer(make([]byte, 0))
shell.stopctx, shell.stopctxfunc = context.WithCancel(context.Background())
cmd := exec.Command(command, args...)
shell.CMD = cmd
shell.infile, err = shell.CMD.StdinPipe()
if err != nil {
return shell, err
}
shell.errfile, err = shell.CMD.StderrPipe()
if err != nil {
return shell, err
}
shell.outfile, err = shell.CMD.StdoutPipe()
if err != nil {
return shell, err
}
shell.runerr = nil
shell.exitcode = -999
return shell, nil
}
func CommandContext(ctx context.Context, command string, args ...string) (*StarCmd, error) {
var err error
shell := new(StarCmd)
shell.running = 0
shell.stdoutBuf = bytes.NewBuffer(make([]byte, 0))
shell.stderrBuf = bytes.NewBuffer(make([]byte, 0))
shell.prewritetime = time.Millisecond * 200
shell.stopctx, shell.stopctxfunc = context.WithCancel(context.Background())
cmd := exec.CommandContext(ctx, command, args...)
shell.CMD = cmd
shell.infile, err = shell.CMD.StdinPipe()
if err != nil {
return shell, err
}
shell.errfile, err = shell.CMD.StderrPipe()
if err != nil {
return shell, err
}
shell.outfile, err = shell.CMD.StdoutPipe()
if err != nil {
return shell, err
}
shell.runerr = nil
shell.exitcode = -999
return shell, nil
}
func (starcli *StarCmd) queryStdout(ctx context.Context) {
for starcli.IsRunning() && starcli.CMD != nil {
select {
case <-ctx.Done():
return
default:
}
out := make([]byte, 65535)
n, err := starcli.outfile.Read(out)
if n != 0 {
starcli.lock.Lock()
starcli.stdoutBuf.Write(out[:n])
starcli.lock.Unlock()
for _, v := range out[:n] {
starcli.stdout = append(starcli.stdout, v)
}
}
if err != nil {
if err == io.EOF {
break
} else {
if !strings.Contains(err.Error(), "file already closed") {
starcli.runerr = err
}
return
}
}
}
}
func (starcli *StarCmd) queryStderr(ctx context.Context) {
for starcli.IsRunning() && starcli.CMD != nil {
select {
case <-ctx.Done():
return
default:
}
out := make([]byte, 65535)
n, err := starcli.errfile.Read(out)
if n != 0 {
starcli.lock.Lock()
starcli.stderrBuf.Write(out[:n])
starcli.lock.Unlock()
for _, v := range out[:n] {
starcli.errout = append(starcli.errout, v)
}
}
if err != nil {
if err == io.EOF {
break
} else {
if !strings.Contains(err.Error(), "file already closed") {
starcli.runerr = err
}
return
}
}
}
return
}
func (starcli *StarCmd) NowLineOutput() (string, error) {
starcli.lock.Lock()
buf, _ := starcli.stdoutBuf.ReadBytes('\n')
buferr, _ := starcli.stderrBuf.ReadBytes(byte('\n'))
starcli.lock.Unlock()
if len(buferr) != 0 {
return string(buf), errors.New(string(buferr))
}
return string(buf), nil
}
func (starcli *StarCmd) NowLineStdOut() string {
starcli.lock.Lock()
defer starcli.lock.Unlock()
buf, _ := starcli.stdoutBuf.ReadBytes('\n')
return string(buf)
}
func (starcli *StarCmd) NowLineStdErr() error {
starcli.lock.Lock()
defer starcli.lock.Unlock()
buferr, _ := starcli.stderrBuf.ReadBytes(byte('\n'))
if len(buferr) != 0 {
return errors.New(string(buferr))
}
return nil
}
func (starcli *StarCmd) NowAllOutput() (string, error) {
var outstr string
starcli.lock.Lock()
buf := make([]byte, starcli.stdoutBuf.Len())
n, _ := starcli.stdoutBuf.Read(buf)
starcli.lock.Unlock()
if n != 0 {
outstr = string(buf[:n])
}
if starcli.runerr != nil {
return outstr, starcli.runerr
}
starcli.lock.Lock()
buf = make([]byte, starcli.stderrBuf.Len())
n, _ = starcli.stderrBuf.Read(buf)
starcli.lock.Unlock()
if n != 0 {
return outstr, errors.New(string(buf[:n]))
}
return outstr, nil
}
func (starcli *StarCmd) NowStdOut() string {
var outstr string
starcli.lock.Lock()
buf := make([]byte, starcli.stdoutBuf.Len())
n, _ := starcli.stdoutBuf.Read(buf)
starcli.lock.Unlock()
if n != 0 {
outstr = string(buf[:n])
}
return outstr
}
func (starcli *StarCmd) NowStdErr() error {
starcli.lock.Lock()
buf := make([]byte, starcli.stderrBuf.Len())
n, _ := starcli.stderrBuf.Read(buf)
starcli.lock.Unlock()
if n != 0 {
return errors.New(string(buf[:n]))
}
return nil
}
func (starcli *StarCmd) AllOutPut() (string, error) {
err := starcli.runerr
if err == nil && len(starcli.errout) != 0 {
err = errors.New(string(starcli.errout))
}
return string(starcli.stdout), err
}
func (starcli *StarCmd) AllStdOut() string {
return string(starcli.stdout)
}
func (starcli *StarCmd) AllStdErr() error {
err := starcli.runerr
if err == nil && len(starcli.errout) != 0 {
err = errors.New(string(starcli.errout))
}
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 {
if err := starcli.CMD.Start(); err != nil {
return err
}
starcli.setRunning(true)
go func() {
err := starcli.CMD.Wait()
if err != nil {
starcli.runerr = err
}
starcli.stopctxfunc()
starcli.setRunning(false)
if starcli.CMD.ProcessState != nil {
starcli.exitcode = starcli.CMD.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
}
}()
go starcli.queryStdout(starcli.stopctx)
go starcli.queryStderr(starcli.stopctx)
go func(ctx context.Context) {
if len(starcli.prewrite) != 0 {
for _, v := range starcli.prewrite {
select {
case <-ctx.Done():
return
default:
break
}
starcli.WriteCmd(v)
time.Sleep(starcli.prewritetime)
}
}
}(starcli.stopctx)
return nil
}
func (starcli *StarCmd) IsRunning() bool {
return 0 != atomic.LoadInt32(&starcli.running)
}
func (starcli *StarCmd) Stoped() <-chan struct{} {
return starcli.stopctx.Done()
}
func (starcli *StarCmd) Exec(cmd string, wait int) (string, error) {
starcli.infile.Write([]byte(cmd + "\n"))
time.Sleep(time.Millisecond * time.Duration(wait))
return starcli.NowAllOutput()
}
func (starcli *StarCmd) WriteCmd(cmdstr string) {
starcli.infile.Write([]byte(cmdstr + "\n"))
}
func (starcli *StarCmd) PreWrite(cmd ...string) {
for _, v := range cmd {
starcli.prewrite = append(starcli.prewrite, v)
}
}
func (starcli *StarCmd) PreWriteInterval(dt time.Duration) {
starcli.prewritetime = dt
}
func (starcli *StarCmd) ExitCode() int {
return starcli.exitcode
}
func (starcli *StarCmd) Kill() error {
err := starcli.CMD.Process.Kill()
if err != nil {
return err
}
starcli.setRunning(false)
return nil
}
func (starcli *StarCmd) GetPid() int {
return starcli.CMD.Process.Pid
}
func (starcli *StarCmd) Signal(sig os.Signal) error {
return starcli.CMD.Process.Signal(sig)
}
-147
View File
@@ -1,147 +0,0 @@
// +build linux darwin
package staros
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"syscall"
"time"
)
// FindProcessByName 通过进程名来查询应用信息
func FindProcessByName(pname string) (datas []Process, err error) {
var name, main string
var mainb []byte
paths, errs := ioutil.ReadDir("/proc")
if errs != nil {
err = errs
return
}
for _, v := range paths {
if v.IsDir() && Exists("/proc/"+v.Name()+"/comm") {
name, err = readAsString("/proc/" + v.Name() + "/comm")
if err != nil {
return
}
if strings.TrimSpace(name) == pname {
var tmp Process
main, err = readAsString("/proc/" + v.Name() + "/status")
if err != nil {
return
}
data := splitBy(main, ":")
tmp.Name = pname
tmp.Pid, _ = strconv.ParseInt(data["Pid"], 10, 64)
tmp.PPid, _ = strconv.ParseInt(data["PPid"], 10, 64)
tmp.TPid, _ = strconv.ParseInt(data["TracerPid"], 10, 64)
uids := splitBySpace(data["Uid"])
gids := splitBySpace(data["Gid"])
tmp.RUID, _ = strconv.Atoi(uids[0])
tmp.EUID, _ = strconv.Atoi(uids[1])
tmp.RGID, _ = strconv.Atoi(gids[0])
tmp.EGID, _ = strconv.Atoi(gids[1])
mainb, err = ioutil.ReadFile("/proc/" + v.Name() + "/cmdline")
if err != nil {
return
}
args := bytes.Split(mainb, []byte{0})
for _, v := range args {
tmp.Args = append(tmp.Args, string(v))
}
tmp.LocalPath, err = os.Readlink("/proc/" + v.Name() + "/exe")
if err != nil {
return
}
tmp.LocalPath = filepath.Dir(tmp.LocalPath)
tmp.ExecPath, err = os.Readlink("/proc/" + v.Name() + "/cwd")
if err != nil {
return
}
main, err = readAsString("/proc/" + v.Name() + "/stat")
if err != nil {
return
}
times := splitBySpace(main)
uptime, _ := strconv.ParseInt(strings.TrimSpace(times[21]), 10, 64)
tmp.Uptime = time.Unix(StartTime().Unix()+uptime/100, int64((float64(uptime)/100-float64(uptime/100))*1000000000))
datas = append(datas, tmp)
}
}
}
return
}
// FindProcessByPid 通过Pid来查询应用信息
func FindProcessByPid(pid int64) (datas Process, err error) {
var name, main string
var mainb []byte
if !Exists("/proc/" + fmt.Sprint(pid) + "/comm") {
err = errors.New("Not Found")
return
}
name, err = readAsString("/proc/" + fmt.Sprint(pid) + "/comm")
if err != nil {
return
}
main, err = readAsString("/proc/" + fmt.Sprint(pid) + "/status")
if err != nil {
return
}
data := splitBy(main, ":")
datas.Name = strings.TrimSpace(name)
datas.Pid, _ = strconv.ParseInt(data["Pid"], 10, 64)
datas.PPid, _ = strconv.ParseInt(data["PPid"], 10, 64)
datas.TPid, _ = strconv.ParseInt(data["TracerPid"], 10, 64)
uids := splitBySpace(data["Uid"])
gids := splitBySpace(data["Gid"])
datas.RUID, _ = strconv.Atoi(uids[0])
datas.EUID, _ = strconv.Atoi(uids[1])
datas.RGID, _ = strconv.Atoi(gids[0])
datas.EGID, _ = strconv.Atoi(gids[1])
mainb, err = ioutil.ReadFile("/proc/" + fmt.Sprint(pid) + "/cmdline")
if err != nil {
return
}
args := bytes.Split(mainb, []byte{0})
for _, v := range args {
datas.Args = append(datas.Args, string(v))
}
datas.LocalPath, err = os.Readlink("/proc/" + fmt.Sprint(pid) + "/exe")
if err != nil {
return
}
datas.LocalPath = filepath.Dir(datas.LocalPath)
datas.ExecPath, err = os.Readlink("/proc/" + fmt.Sprint(pid) + "/cwd")
if err != nil {
return
}
main, err = readAsString("/proc/" + fmt.Sprint(pid) + "/stat")
if err != nil {
return
}
times := splitBySpace(main)
uptime, _ := strconv.ParseInt(strings.TrimSpace(times[21]), 10, 64)
datas.Uptime = time.Unix(StartTime().Unix()+uptime/100, int64((float64(uptime)/100-float64(uptime/100))*1000000000))
return
}
func Daemon(path string, args ...string) (int, error) {
cmd := exec.Command(path, args...)
cmd.SysProcAttr = &syscall.SysProcAttr{
Setsid: true,
}
if err := cmd.Start(); err != nil {
return -1, err
}
pid := cmd.Process.Pid
err := cmd.Process.Release()
return pid, err
}
+17
View File
@@ -1,10 +1,27 @@
package staros package staros
import ( import (
"context"
"fmt" "fmt"
"testing" "testing"
"time"
) )
func Test_Process(t *testing.T) { func Test_Process(t *testing.T) {
fmt.Println(FindProcessByPid(16652)) fmt.Println(FindProcessByPid(16652))
} }
func Test_StarCmd(t *testing.T) {
ctx, _ := context.WithTimeout(context.Background(), time.Second*5)
cmd, _ := CommandContext(ctx, "cmd.exe", "/c", "ping -t 127.0.0.1")
cmd.Start()
for cmd.IsRunning() {
fmt.Print(cmd.NowLineOutput())
time.Sleep(time.Millisecond * 50)
}
fmt.Println(cmd.NowAllOutput())
fmt.Print("all is ")
fmt.Println(cmd.AllOutPut())
fmt.Println(cmd.ExitCode())
}
+348
View File
@@ -0,0 +1,348 @@
// +build linux darwin
package staros
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"syscall"
"time"
)
//FindProcessByName 通过进程名来查询应用信息
func FindProcessByName(name string) (datas []Process, err error) {
return FindProcess(func(in Process) bool {
if name == in.Name {
return true
}
return false
})
}
// FindProcess 通过进程信息来查询应用信息
func FindProcess(compare func(Process) bool) (datas []Process, err error) {
var name, main string
var mainb []byte
var netErr error
var netInfo []NetConn
paths, err := ioutil.ReadDir("/proc")
if err != nil {
return
}
netInfo, netErr = NetConnections(false, "")
appendNetInfo := func(p *Process) {
if netErr != nil {
p.netErr = netErr
return
}
fds, err := ioutil.ReadDir("/proc/" + strconv.Itoa(int(p.Pid)) + "/fd")
if err != nil && Exists("/proc/"+strconv.Itoa(int(p.Pid))+"/fd") {
p.netErr = err
return
}
for _, fd := range fds {
socket, err := os.Readlink("/proc/" + strconv.Itoa(int(p.Pid)) + "/fd/" + fd.Name())
if err != nil {
p.netErr = err
return
}
start := strings.Index(socket, "[")
if start < 0 {
continue
}
sid := socket[start+1 : len(socket)-1]
for _, v := range netInfo {
if v.Inode == sid {
v.Pid = p.Pid
v.Process = p
p.netConn = append(p.netConn, v)
}
}
}
}
for _, v := range paths {
if v.IsDir() && Exists("/proc/"+v.Name()+"/comm") {
name, err = readAsString("/proc/" + v.Name() + "/comm")
if err != nil {
continue
}
var tmp Process
tmp.LocalPath, err = os.Readlink("/proc/" + v.Name() + "/exe")
tmp.Path = tmp.LocalPath
tmp.LocalPath = filepath.Dir(tmp.LocalPath)
tmp.ExecPath, err = os.Readlink("/proc/" + v.Name() + "/cwd")
tmp.Name = strings.TrimSpace(name)
main, err = readAsString("/proc/" + v.Name() + "/status")
if err != nil {
tmp.Err = err
if compare(tmp) {
appendNetInfo(&tmp)
datas = append(datas, tmp)
continue
}
} else {
data := splitBy(main, ":")
tmp.Pid, _ = strconv.ParseInt(data["Pid"], 10, 64)
tmp.PPid, _ = strconv.ParseInt(data["PPid"], 10, 64)
tmp.TPid, _ = strconv.ParseInt(data["TracerPid"], 10, 64)
uids := splitBySpace(data["Uid"])
gids := splitBySpace(data["Gid"])
tmp.RUID, _ = strconv.Atoi(uids[0])
tmp.EUID, _ = strconv.Atoi(uids[1])
tmp.RGID, _ = strconv.Atoi(gids[0])
tmp.EGID, _ = strconv.Atoi(gids[1])
tmp.VmPeak, _ = strconv.ParseInt(splitBySpace(data["VmPeak"])[0], 10, 64)
tmp.VmSize, _ = strconv.ParseInt(splitBySpace(data["VmSize"])[0], 10, 64)
tmp.VmHWM, _ = strconv.ParseInt(splitBySpace(data["VmHWM"])[0], 10, 64)
tmp.VmRSS, _ = strconv.ParseInt(splitBySpace(data["VmRSS"])[0], 10, 64)
tmp.VmLck, _ = strconv.ParseInt(splitBySpace(data["VmLck"])[0], 10, 64)
tmp.VmData, _ = strconv.ParseInt(splitBySpace(data["VmData"])[0], 10, 64)
tmp.VmLck *= 1024
tmp.VmData *= 1024
tmp.VmPeak *= 1024
tmp.VmSize *= 1024
tmp.VmHWM *= 1024
tmp.VmRSS *= 1024
}
mainb, err = ioutil.ReadFile("/proc/" + v.Name() + "/cmdline")
if err != nil {
tmp.Err = err
if compare(tmp) {
appendNetInfo(&tmp)
datas = append(datas, tmp)
continue
}
} else {
args := bytes.Split(mainb, []byte{0})
for _, v := range args {
tmp.Args = append(tmp.Args, string(v))
}
}
mainb, err = ioutil.ReadFile("/proc/" + v.Name() + "/environ")
if err != nil {
tmp.Err = err
if compare(tmp) {
appendNetInfo(&tmp)
datas = append(datas, tmp)
continue
}
} else {
args := bytes.Split(mainb, []byte{0})
for _, v := range args {
tmp.Env = append(tmp.Env, string(v))
}
}
main, err = readAsString("/proc/" + v.Name() + "/stat")
if err != nil {
tmp.Err = err
if compare(tmp) {
appendNetInfo(&tmp)
datas = append(datas, tmp)
continue
}
} else {
times := splitBySpace(main)
uptime, _ := strconv.ParseInt(strings.TrimSpace(times[21]), 10, 64)
tmp.Uptime = time.Unix(StartTime().Unix()+uptime/100, int64((float64(uptime)/100-float64(uptime/100))*1000000000))
}
if compare(tmp) {
appendNetInfo(&tmp)
datas = append(datas, tmp)
}
}
}
return
}
// FindProcessByPid 通过Pid来查询应用信息
func FindProcessByPid(pid int64) (datas Process, err error) {
var name, main string
var mainb []byte
if !Exists("/proc/" + fmt.Sprint(pid) + "/comm") {
err = errors.New("Not Found")
return
}
netInfo, netErr := NetConnections(false, "")
appendNetInfo := func(p *Process) {
if netErr != nil {
p.netErr = netErr
return
}
fds, err := ioutil.ReadDir("/proc/" + strconv.Itoa(int(p.Pid)) + "/fd")
if err != nil && Exists("/proc/"+strconv.Itoa(int(p.Pid))+"/fd") {
p.netErr = err
return
}
for _, fd := range fds {
socket, err := os.Readlink("/proc/" + strconv.Itoa(int(p.Pid)) + "/fd/" + fd.Name())
if err != nil {
p.netErr = err
return
}
start := strings.Index(socket, "[")
if start < 0 {
continue
}
sid := socket[start+1 : len(socket)-1]
for _, v := range netInfo {
if v.Inode == sid {
v.Pid = p.Pid
v.Process = p
p.netConn = append(p.netConn, v)
}
}
}
}
name, err = readAsString("/proc/" + fmt.Sprint(pid) + "/comm")
if err != nil {
return
}
main, err = readAsString("/proc/" + fmt.Sprint(pid) + "/status")
if err != nil {
return
}
data := splitBy(main, ":")
datas.Name = strings.TrimSpace(name)
datas.Pid, _ = strconv.ParseInt(data["Pid"], 10, 64)
datas.PPid, _ = strconv.ParseInt(data["PPid"], 10, 64)
datas.TPid, _ = strconv.ParseInt(data["TracerPid"], 10, 64)
uids := splitBySpace(data["Uid"])
gids := splitBySpace(data["Gid"])
datas.RUID, _ = strconv.Atoi(uids[0])
datas.EUID, _ = strconv.Atoi(uids[1])
datas.RGID, _ = strconv.Atoi(gids[0])
datas.EGID, _ = strconv.Atoi(gids[1])
datas.VmPeak, _ = strconv.ParseInt(splitBySpace(data["VmPeak"])[0], 10, 64)
datas.VmSize, _ = strconv.ParseInt(splitBySpace(data["VmSize"])[0], 10, 64)
datas.VmHWM, _ = strconv.ParseInt(splitBySpace(data["VmHWM"])[0], 10, 64)
datas.VmRSS, _ = strconv.ParseInt(splitBySpace(data["VmRSS"])[0], 10, 64)
datas.VmLck, _ = strconv.ParseInt(splitBySpace(data["VmLck"])[0], 10, 64)
datas.VmData, _ = strconv.ParseInt(splitBySpace(data["VmData"])[0], 10, 64)
datas.VmLck *= 1024
datas.VmData *= 1024
datas.VmPeak *= 1024
datas.VmSize *= 1024
datas.VmHWM *= 1024
datas.VmRSS *= 1024
appendNetInfo(&datas)
mainb, err = ioutil.ReadFile("/proc/" + fmt.Sprint(pid) + "/cmdline")
if err != nil {
datas.Err = err
err = nil
} else {
args := bytes.Split(mainb, []byte{0})
for _, v := range args {
datas.Args = append(datas.Args, string(v))
}
}
mainb, err = ioutil.ReadFile("/proc/" + fmt.Sprint(pid) + "/environ")
if err != nil {
datas.Err = err
err = nil
} else {
args := bytes.Split(mainb, []byte{0})
for _, v := range args {
datas.Env = append(datas.Env, string(v))
}
}
datas.LocalPath, err = os.Readlink("/proc/" + fmt.Sprint(pid) + "/exe")
datas.Path = datas.LocalPath
datas.LocalPath = filepath.Dir(datas.LocalPath)
datas.ExecPath, err = os.Readlink("/proc/" + fmt.Sprint(pid) + "/cwd")
main, err = readAsString("/proc/" + fmt.Sprint(pid) + "/stat")
if err != nil {
return
}
times := splitBySpace(main)
uptime, _ := strconv.ParseInt(strings.TrimSpace(times[21]), 10, 64)
datas.Uptime = time.Unix(StartTime().Unix()+uptime/100, int64((float64(uptime)/100-float64(uptime/100))*1000000000))
return
}
func Daemon(path string, args ...string) (int, error) {
cmd := exec.Command(path, args...)
cmd.SysProcAttr = &syscall.SysProcAttr{
Setsid: true,
}
if err := cmd.Start(); err != nil {
return -1, err
}
pid := cmd.Process.Pid
err := cmd.Process.Release()
return pid, err
}
func DaemonWithUser(uid, gid uint32, groups []uint32, path string, args ...string) (int, error) {
cmd := exec.Command(path, args...)
cmd.SysProcAttr = &syscall.SysProcAttr{
Credential: &syscall.Credential{
Uid: uid,
Gid: gid,
Groups: groups,
},
Setsid: true,
}
if err := cmd.Start(); err != nil {
return -1, err
}
pid := cmd.Process.Pid
err := cmd.Process.Release()
return pid, err
}
func (starcli *StarCmd) SetRunUser(uid, gid uint32, groups []uint32) {
starcli.CMD.SysProcAttr = &syscall.SysProcAttr{
Credential: &syscall.Credential{
Uid: uid,
Gid: gid,
Groups: groups,
},
Setsid: true,
}
}
func (starcli *StarCmd) Release() error {
if starcli.CMD.SysProcAttr == nil {
starcli.CMD.SysProcAttr = &syscall.SysProcAttr{
Setsid: true,
}
} else {
if !starcli.CMD.SysProcAttr.Setsid {
starcli.CMD.SysProcAttr.Setsid = true
}
}
if !starcli.IsRunning() {
if err := starcli.CMD.Start(); err != nil {
return err
}
}
time.Sleep(time.Millisecond * 10)
return starcli.CMD.Process.Release()
}
func (starcli *StarCmd) SetKeepCaps() error {
_, _, err := syscall.RawSyscall(157 /*SYS PRCTL */, 0x8 /*PR SET KEEPCAPS*/, 1, 0)
if 0 != err {
return err
}
return nil
}
func SetKeepCaps() error {
_, _, err := syscall.RawSyscall(157 /*SYS PRCTL */, 0x8 /*PR SET KEEPCAPS*/, 1, 0)
if 0 != err {
return err
}
return nil
}
+12
View File
@@ -58,3 +58,15 @@ func Daemon(path string, args ...string) (int, error) {
cmd.Process.Release() cmd.Process.Release()
return pid, nil return pid, nil
} }
func (starcli *StarCmd) SetRunUser(uid, gid uint32, groups []uint32) {
}
func (starcli *StarCmd) Release() error {
if err := starcli.CMD.Start(); err != nil {
return err
}
starcli.CMD.Process.Release()
return nil
}
+261
View File
@@ -0,0 +1,261 @@
package sysconf
import (
"bytes"
"errors"
"fmt"
"reflect"
"strconv"
"strings"
)
type CSV struct {
header []string
text [][]string
}
type CSVRow struct {
header []string
data []string
}
type CSVValue struct {
key string
value string
}
func ParseCSV(data []byte, hasHeader bool) (csv CSV, err error) {
strData := strings.Split(string(bytes.TrimSpace(data)), "\n")
if len(strData) < 1 {
err = fmt.Errorf("cannot parse data,invalid data format")
}
var header []string
var text [][]string
if hasHeader {
header = csvAnalyse(strData[0])
strData = strData[1:]
} else {
num := len(csvAnalyse(strData[0]))
for i := 0; i < num; i++ {
header = append(header, strconv.Itoa(i))
}
}
for k, v := range strData {
tmpData := csvAnalyse(v)
if len(tmpData) != len(header) {
err = fmt.Errorf("cannot parse data line %d,got %d values but need %d", k, len(tmpData), len(header))
return
}
text = append(text, tmpData)
}
csv.header = header
csv.text = text
return
}
func (csv *CSV) Header() []string {
return csv.header
}
func (csv *CSV) Data() [][]string {
return csv.text
}
func (csv *CSV) Row(row int) *CSVRow {
if row >= len(csv.Data()) {
return nil
}
return &CSVRow{
header: csv.Header(),
data: csv.Data()[row],
}
}
func (csv *CSVRow) Get(key string) *CSVValue {
for k, v := range csv.header {
if v == key {
return &CSVValue{
key: key,
value: csv.data[k],
}
}
}
return nil
}
func (csv *CSVRow) Col(key int) *CSVValue {
if key >= len(csv.header) {
return nil
}
return &CSVValue{
key: csv.header[key],
value: csv.data[key],
}
}
func (csv *CSVRow) Header() []string {
return csv.header
}
func (csv *CSV) MapData() []map[string]string {
var result []map[string]string
for _, v := range csv.text {
tmp := make(map[string]string)
for k, v2 := range csv.header {
tmp[v2] = v[k]
}
result = append(result, tmp)
}
return result
}
func CsvAnalyse(data string) []string {
return csvAnalyse(data)
}
func csvAnalyse(data string) []string {
var segStart bool = false
var segReady bool = false
var segSign string = ""
var dotReady bool = false
data = strings.TrimSpace(data)
var result []string
var seg string
for k, v := range []rune(data) {
if k == 0 && v != []rune(`"`)[0] {
dotReady = true
}
if v != []rune(`,`)[0] && dotReady {
segSign = `,`
segStart = true
dotReady = false
if v == []rune(`"`)[0] {
segSign = `"`
continue
}
}
if dotReady && v == []rune(`,`)[0] {
//dotReady = false
result = append(result, "")
continue
}
if v == []rune(`"`)[0] && segStart {
if !segReady {
segReady = true
continue
}
seg += `"`
segReady = false
continue
}
if segReady && segSign == `"` && segStart {
segReady = false
segStart = false
result = append(result, seg)
segSign = ``
seg = ""
}
if v == []rune(`"`)[0] && !segStart {
segStart = true
segReady = false
segSign = `"`
continue
}
if v == []rune(`,`)[0] && !segStart {
dotReady = true
}
if v == []rune(`,`)[0] && segStart && segSign == "," {
segStart = false
result = append(result, seg)
dotReady = true
segSign = ``
seg = ""
}
if segStart {
seg = string(append([]rune(seg), v))
}
}
if len(data) != 0 && len(result) == 0 && seg == "" {
result = append(result, data)
} else {
result = append(result, seg)
}
return result
}
func MarshalCSV(header []string, ins interface{}) ([]byte, error) {
var result [][]string
t := reflect.TypeOf(ins)
v := reflect.ValueOf(ins)
if v.Kind() != reflect.Slice && v.Kind() != reflect.Array {
return nil, errors.New("not a Slice or Array")
}
if t.Kind() == reflect.Ptr {
t = t.Elem()
v = v.Elem()
}
for i := 0; i < v.Len(); i++ {
subT := reflect.TypeOf(v.Index(i).Interface())
subV := reflect.ValueOf(v.Index(i).Interface())
if subV.Kind() == reflect.Slice || subV.Kind() == reflect.Array {
if subT.Kind() == reflect.Ptr {
subV = subV.Elem()
}
var tmp []string
for j := 0; j < subV.Len(); j++ {
tmp = append(tmp, fmt.Sprint(reflect.ValueOf(subV.Index(j))))
}
result = append(result, tmp)
}
if subV.Kind() == reflect.Struct {
var tmp []string
if subT.Kind() == reflect.Ptr {
subV = subV.Elem()
}
for i := 0; i < subV.NumField(); i++ {
tmp = append(tmp, fmt.Sprint(subV.Field(i)))
}
result = append(result, tmp)
}
}
return buildCSV(header,result)
}
func buildCSV(header []string, data [][]string) ([]byte, error) {
var result []string
var length int
build := func(slc []string) string {
for k, v := range slc {
if strings.Index(v, `"`) >= 0 {
v = strings.ReplaceAll(v, `"`, `""`)
}
if strings.Index(v,"\n")>=0 {
v=strings.ReplaceAll(v,"\n",`\n`)
}
if strings.Index(v,"\r")>=0 {
v=strings.ReplaceAll(v,"\r",`\r`)
}
v = `"` + v + `"`
slc[k] = v
}
return strings.Join(slc, ",")
}
if len(header) != 0 {
result = append(result, build(header))
length = len(header)
} else {
length = len(data[0])
}
for k, v := range data {
if len(v) != length {
return nil, fmt.Errorf("line %d got length %d ,but need %d", k, len(v), length)
}
result = append(result, build(v))
}
return []byte(strings.Join(result, "\n")), nil
}
+38
View File
@@ -0,0 +1,38 @@
package sysconf
import (
"fmt"
"testing"
)
func Test_csv(t *testing.T) {
//var test Sqlplus
var text=`
姓名,班级,性别,年龄
张三,"我,不""知道",boy,23
"里斯","哈哈",girl,23
`
fmt.Println(csvAnalyse(`请求权,lkjdshck,dsvdsv,"sdvkjsdv,",=dsvdsv,"=,dsvsdv"`))
a,b:=ParseCSV([]byte(text),true)
fmt.Println(b)
fmt.Println(a.Row(0).Col(3).MustInt())
}
type csvtest struct {
A string
B int
}
func Test_Masharl(t *testing.T) {
//var test Sqlplus
/*
var a []csvtest = []csvtest{
{"lala",1},
{"haha",34},
}
*/
var a [][]string
a=append(a,[]string{"a","b","c"})
a=append(a,[]string{"1",`s"s"d`,"3"})
b,_:=MarshalCSV([]string{},a)
fmt.Println(string(b))
}
+120
View File
@@ -0,0 +1,120 @@
package sysconf
import "strconv"
func (csv *CSVValue)Key()string {
return csv.key
}
func (csv *CSVValue)Int()(int,error) {
tmp,err:=strconv.Atoi(csv.value)
return tmp,err
}
func (csv *CSVValue)MustInt()int {
tmp,err:=csv.Int()
if err!=nil {
panic(err)
}
return tmp
}
func (csv *CSVValue)Int64()(int64,error) {
tmp,err:=strconv.ParseInt(csv.value,10,64)
return tmp,err
}
func (csv *CSVValue)MustInt64()int64 {
tmp,err:=csv.Int64()
if err!=nil {
panic(err)
}
return tmp
}
func (csv *CSVValue)Int32()(int32,error) {
tmp,err:=strconv.ParseInt(csv.value,10,32)
return int32(tmp),err
}
func (csv *CSVValue)MustInt32()int32 {
tmp,err:=csv.Int32()
if err!=nil {
panic(err)
}
return tmp
}
func (csv *CSVValue)Uint64()(uint64,error) {
tmp,err:=strconv.ParseUint(csv.value,10,64)
return tmp,err
}
func (csv *CSVValue)MustUint64()uint64 {
tmp,err:=csv.Uint64()
if err!=nil {
panic(err)
}
return tmp
}
func (csv *CSVValue)Uint32()(uint32,error) {
tmp,err:=strconv.ParseUint(csv.value,10,32)
return uint32(tmp),err
}
func (csv *CSVValue)MustUint32()uint32 {
tmp,err:=csv.Uint32()
if err!=nil {
panic(err)
}
return tmp
}
func (csv *CSVValue)String()string {
return csv.value
}
func (csv *CSVValue)Byte()[]byte {
return []byte(csv.value)
}
func (csv *CSVValue)Bool()(bool,error) {
tmp,err:=strconv.ParseBool(csv.value)
return tmp,err
}
func (csv *CSVValue)MustBool()bool {
tmp,err:=csv.Bool()
if err!=nil {
panic(err)
}
return tmp
}
func (csv *CSVValue)Float64()(float64,error) {
tmp,err:=strconv.ParseFloat(csv.value,64)
return tmp,err
}
func (csv *CSVValue)MustFloat64()float64 {
tmp,err:=csv.Float64()
if err!=nil {
panic(err)
}
return tmp
}
func (csv *CSVValue)Float32()(float32,error) {
tmp,err:=strconv.ParseFloat(csv.value,32)
return float32(tmp),err
}
func (csv *CSVValue)MustFloat32()float32 {
tmp,err:=csv.Float32()
if err!=nil {
panic(err)
}
return tmp
}
+30 -15
View File
@@ -9,8 +9,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"b612.me/staros"
) )
type SysConf struct { type SysConf struct {
@@ -47,6 +45,18 @@ type SysNode struct {
lock sync.RWMutex lock sync.RWMutex
} }
func NewIni() *SysConf {
ini := NewSysConf("=")
ini.CommentCR = true
ini.CommentFlag = []string{"#", ";"}
ini.HaveSegMent = true
ini.SegStart = "["
ini.SegEnd = "]"
ini.SpaceStr = " "
ini.EscapeFlag = "\\"
return ini
}
func NewSysConf(EqualFlag string) *SysConf { func NewSysConf(EqualFlag string) *SysConf {
syscnf := new(SysConf) syscnf := new(SysConf)
syscnf.EqualFlag = EqualFlag syscnf.EqualFlag = EqualFlag
@@ -64,15 +74,11 @@ func NewLinuxConf(EqualFlag string) *SysConf {
} }
func (syscfg *SysConf) ParseFromFile(filepath string) error { func (syscfg *SysConf) ParseFromFile(filepath string) error {
if !staros.Exists(filepath) {
return errors.New(filepath + " 不存在")
}
data, err := ioutil.ReadFile(filepath) data, err := ioutil.ReadFile(filepath)
if err != nil { if err != nil {
return err return err
} }
syscfg.Parse(data) return syscfg.Parse(data)
return nil
} }
// Parse 生成INI文件结构 // Parse 生成INI文件结构
@@ -470,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) 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 {
@@ -480,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) 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)
@@ -488,11 +494,17 @@ 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) 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 key != "" && seg == "" && cfg.HaveSegMent {
seg = "unnamed"
}
if oriSeg != "" {
seg = oriSeg
}
if seg == "" || key == "" { if seg == "" || key == "" {
continue continue
} }
@@ -520,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) 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 {
@@ -535,18 +547,21 @@ 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) { 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) 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 != "" {
seg = oriSeg
}
if seg == "" || key == "" { if seg == "" || key == "" {
continue continue
} }
@@ -557,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
} }
+30 -1
View File
@@ -33,6 +33,35 @@ func Test_Parse(t *testing.T) {
fmt.Println(cfg.Parse([]byte(data))) fmt.Println(cfg.Parse([]byte(data)))
cfg.Reverse() cfg.Reverse()
cfg.Data[0].Delete(`pp.com`) cfg.Data[0].Delete(`pp.com`)
//fmt.Println(cfg.Data[0].Comment) //fmt.Println(cfg.Data[0].comment)
fmt.Println(string(cfg.Build())) fmt.Println(string(cfg.Build()))
} }
type slicetest struct {
A string `seg:"s" key:"a"`
B string `seg:"a" key:"b"`
}
type testme struct {
Love slicetest `seg:"love"`
Star slicetest `seg:"star"`
}
func Test_Marshal(t *testing.T) {
var info string = `
[love]
a=abc
b=123
[star]
a=456
b=789
`
var tmp testme
ini := NewIni()
ini.Parse([]byte(info))
ini.Unmarshal(&tmp)
fmt.Printf("%+v\n", tmp)
b, _ := ini.Marshal(tmp)
fmt.Println(string(b))
}
+115
View File
@@ -2,7 +2,9 @@ package staros
import ( import (
"bytes" "bytes"
"errors"
"io/ioutil" "io/ioutil"
"strconv"
"strings" "strings"
) )
@@ -42,3 +44,116 @@ func readAsString(path string) (string, error) {
} }
return string(data), nil return string(data), nil
} }
func remainOne(data, old, new string) string {
data = strings.TrimSpace(data)
if !strings.Contains(data, old) {
return data
}
data = strings.ReplaceAll(data, old, new)
return remainOne(data, old, new)
}
func parseHexIpPort(str string) (string, int, error) {
str = strings.TrimSpace(str)
if len(str) != 13 && len(str) != 37 {
return "", 0, errors.New("Not a valid ip:port addr:" + str)
}
ipPort := strings.Split(str, ":")
if len(ipPort) != 2 {
return "", 0, errors.New("Not a valid ip:port addr:" + str)
}
if len(ipPort[0]) == 8 {
ip, err := parseHexIPv4(ipPort[0])
if err != nil {
return "", 0, err
}
port, err := parseHexPort(ipPort[1])
return ip, port, err
}
if len(ipPort[0]) == 32 {
ip, err := parseHexIPv6(ipPort[0])
if err != nil {
return "", 0, err
}
port, err := parseHexPort(ipPort[1])
return ip, port, err
}
return "", 0, errors.New("Invalid ip address:" + str)
}
func parseHexPort(str string) (int, error) {
tmpUint32, err := strconv.ParseUint(str, 16, 32)
return int(tmpUint32), err
}
func parseHexIPv4(str string) (string, error) {
var result string
if len(str) != 8 {
return "", errors.New("Not a vaild ipv4:" + str)
}
tmpUint64, err := strconv.ParseUint(str, 16, 32)
if err != nil {
return "", err
}
numicIp := uint32(tmpUint64)
for i := 0; i < 4; i++ {
result += strconv.FormatUint(uint64(uint8(numicIp>>(8*uint8(i)))), 10) + "."
}
return result[0 : len(result)-1], nil
}
func parseHexIPv6(str string) (string, error) {
var result string
if len(str) != 32 {
return "", errors.New("Not a vaild ipv6:" + str)
}
for i := 0; i < 4; i++ {
part := str[i*8 : (i+1)*8]
tmpUint64, err := strconv.ParseUint(part, 16, 32)
if err != nil {
return "", err
}
tmpUint32 := uint32(tmpUint64)
//07C2022A
for i := 0; i < 4; i++ {
tmp := strconv.FormatUint(uint64(uint8(tmpUint32>>uint8(8*i))), 16)
if len(tmp) == 1 {
tmp = "0" + tmp
}
result += tmp
if (i+1)%2 == 0 {
result += ":"
}
}
}
ipv6 := result[0 : len(result)-1]
ipv6List := strings.Split(ipv6, ":")
prepareZero := false
alreadyZero := false
for k, v := range ipv6List {
if v == "0000" && !alreadyZero {
ipv6List[k] = ""
prepareZero = true
continue
}
if v != "0000" && prepareZero {
alreadyZero = true
}
var nonZero = 0
for i := 0; i < 4; i++ {
sig := v[i : i+1]
if sig != "0" {
nonZero = i
break
}
}
ipv6List[k] = v[nonZero:4]
}
ipv6 = strings.TrimSuffix(remainOne(strings.Join(ipv6List, ":"), ":::", "::"), "::")
if ipv6 == "" {
ipv6 = "::0"
}
return ipv6, nil
}
+72
View File
@@ -4,6 +4,44 @@ import (
"time" "time"
) )
const (
KB = 1024
MB = KB << 10
GB = MB << 10
TB = GB << 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 {
Name string
RecvBytes uint64
SendBytes uint64
}
type NetSpeed struct {
Name string
RecvSpeeds float64
SendSpeeds float64
RecvBytes uint64
SendBytes uint64
}
// Process 定义一个进程的信息 // Process 定义一个进程的信息
type Process struct { type Process struct {
PPid int64 PPid int64
@@ -11,13 +49,28 @@ type Process struct {
Name string Name string
ExecPath string ExecPath string
LocalPath string LocalPath string
Path string
Args []string Args []string
Env []string
RUID int RUID int
EUID int EUID int
RGID int RGID int
EGID int EGID int
TPid int64 TPid int64
Uptime time.Time Uptime time.Time
VmPeak int64
VmSize int64
VmLck int64
VmHWM int64
VmRSS int64
VmData int64
netConn []NetConn
netErr error
Err error
}
func (p Process) GetNetConns() ([]NetConn, error) {
return p.netConn, p.netErr
} }
type MemStatus struct { type MemStatus struct {
@@ -42,3 +95,22 @@ type DiskStatus struct {
Free uint64 Free uint64
Available uint64 Available uint64
} }
type NetConn struct {
LocalAddr string
LocalPort int
Typed string
RemoteAddr string
RemotePort int
Socket string
Inode string
Status string
TX_Queue int64
RX_Queue int64
TimerActive string
TimerJiffies int64
RtoTimer int64
Pid int64
Uid int64
Process *Process
}