mirror of
https://github.com/duke-git/lancet.git
synced 2026-03-01 00:35:28 +08:00
Compare commits
1 Commits
v2.3.3
...
4eb5a5e064
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4eb5a5e064 |
19
README.md
19
README.md
@@ -4,7 +4,7 @@
|
|||||||
<br/>
|
<br/>
|
||||||
|
|
||||||

|

|
||||||
[](https://github.com/duke-git/lancet/releases)
|
[](https://github.com/duke-git/lancet/releases)
|
||||||
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
||||||
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
|
go get github.com/duke-git/lancet/v2 // will install latest version of v2.x.x
|
||||||
```
|
```
|
||||||
|
|
||||||
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.4.4. </b>
|
2. <b>For users who use version below go1.18, you should install v1.x.x. The latest of v1.x.x is v1.4.3. </b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
go get github.com/duke-git/lancet // below go1.18, install latest version of v1.x.x
|
go get github.com/duke-git/lancet // below go1.18, install latest version of v1.x.x
|
||||||
@@ -763,7 +763,7 @@ import "github.com/duke-git/lancet/v2/formatter"
|
|||||||
|
|
||||||
#### Function list:
|
#### Function list:
|
||||||
|
|
||||||
- **<big>Comma</big>** : add comma to a number value by every 3 numbers from right, ahead by a prefix symbol char.
|
- **<big>Comma</big>** : add comma to a number value by every 3 numbers from right, ahead by symbol char.
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/formatter.md#Comma)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/formatter.md#Comma)]
|
||||||
[[play](https://go.dev/play/p/eRD5k2vzUVX)]
|
[[play](https://go.dev/play/p/eRD5k2vzUVX)]
|
||||||
- **<big>Pretty</big>** : pretty print data to JSON string.
|
- **<big>Pretty</big>** : pretty print data to JSON string.
|
||||||
@@ -1879,19 +1879,6 @@ import "github.com/duke-git/lancet/v2/system"
|
|||||||
- **<big>GetOsBits</big>** : return current os bits (32 or 64).
|
- **<big>GetOsBits</big>** : return current os bits (32 or 64).
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/system.md#GetOsBits)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/system.md#GetOsBits)]
|
||||||
[[play](https://go.dev/play/p/ml-_XH3gJbW)]
|
[[play](https://go.dev/play/p/ml-_XH3gJbW)]
|
||||||
- **<big>StartProcess</big>** : start a new process with the specified name and arguments.
|
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/system.md#StartProcess)]
|
|
||||||
[[play](todo)]
|
|
||||||
- **<big>StopProcess</big>** : stop a process by pid.
|
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/system.md#StopProcess)]
|
|
||||||
[[play](todo)]
|
|
||||||
- **<big>KillProcess</big>** : kill a new process with the specified name and arguments.
|
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/system.md#KillProcess)]
|
|
||||||
[[play](todo)]
|
|
||||||
- **<big>GetProcessInfo</big>** : retrieves detailed process information by pid.
|
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/system.md#GetProcessInfo)]
|
|
||||||
[[play](todo)]
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="tuple"> 23. Tuple package implements tuple data type and some operations on it. <a href="#index">index</a></h3>
|
<h3 id="tuple"> 23. Tuple package implements tuple data type and some operations on it. <a href="#index">index</a></h3>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<br/>
|
<br/>
|
||||||
|
|
||||||

|

|
||||||
[](https://github.com/duke-git/lancet/releases)
|
[](https://github.com/duke-git/lancet/releases)
|
||||||
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
||||||
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
|
go get github.com/duke-git/lancet/v2 //安装v2最新版本v2.x.x
|
||||||
```
|
```
|
||||||
|
|
||||||
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.4.4。</b>
|
2. <b>使用 go1.18 以下版本的用户,必须安装 v1.x.x。目前最新的 v1 版本是 v1.4.3。</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
go get github.com/duke-git/lancet// 使用go1.18以下版本, 必须安装v1.x.x版本
|
go get github.com/duke-git/lancet// 使用go1.18以下版本, 必须安装v1.x.x版本
|
||||||
@@ -764,7 +764,7 @@ import "github.com/duke-git/lancet/v2/formatter"
|
|||||||
|
|
||||||
#### 函数列表:
|
#### 函数列表:
|
||||||
|
|
||||||
- **<big>Comma</big>** : 用逗号每隔 3 位分割数字/字符串,支持添加前缀符号。
|
- **<big>Comma</big>** : 用逗号每隔 3 位分割数字/字符串,支持前缀添加符号。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/formatter.md#Comma)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/formatter.md#Comma)]
|
||||||
[[play](https://go.dev/play/p/eRD5k2vzUVX)]
|
[[play](https://go.dev/play/p/eRD5k2vzUVX)]
|
||||||
- **<big>Pretty</big>** : 返回 pretty JSON 字符串。
|
- **<big>Pretty</big>** : 返回 pretty JSON 字符串。
|
||||||
@@ -1881,20 +1881,6 @@ import "github.com/duke-git/lancet/v2/system"
|
|||||||
- **<big>GetOsBits</big>** : 获取当前操作系统位数(32/64)。
|
- **<big>GetOsBits</big>** : 获取当前操作系统位数(32/64)。
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system#GetOsBits)]
|
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system#GetOsBits)]
|
||||||
[[play](https://go.dev/play/p/ml-_XH3gJbW)]
|
[[play](https://go.dev/play/p/ml-_XH3gJbW)]
|
||||||
- **<big>StartProcess</big>** :创建进程。
|
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system.md#StartProcess)]
|
|
||||||
[[play](todo)]
|
|
||||||
- **<big>StopProcess</big>** : 停止进程。
|
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system.md#StopProcess)]
|
|
||||||
[[play](todo)]
|
|
||||||
- **<big>KillProcess</big>** : 杀掉进程。
|
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system.md#KillProcess)]
|
|
||||||
[[play](todo)]
|
|
||||||
- **<big>GetProcessInfo</big>** : 根据进程id获取进程信息。
|
|
||||||
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/system.md#GetProcessInfo)]
|
|
||||||
[[play](todo)]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="tuple"> 23. Tuple 包实现一个元组数据类型。 <a href="#index">回到目录</a></h3>
|
<h3 id="tuple"> 23. Tuple 包实现一个元组数据类型。 <a href="#index">回到目录</a></h3>
|
||||||
|
|
||||||
|
|||||||
@@ -37,12 +37,12 @@ import (
|
|||||||
|
|
||||||
### <span id="Comma">Comma</span>
|
### <span id="Comma">Comma</span>
|
||||||
|
|
||||||
<p>用逗号每隔3位分割数字/字符串,支持添加前缀符号。参数value必须是数字或者可以转为数字的字符串, 否则返回空字符串</p>
|
<p>用逗号每隔3位分割数字/字符串,支持前缀添加符号。参数value必须是数字或者可以转为数字的字符串, 否则返回空字符串</p>
|
||||||
|
|
||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Comma[T constraints.Float | constraints.Integer | string](value T, prefixSymbol string) string
|
func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/eRD5k2vzUVX)</span></b>
|
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/eRD5k2vzUVX)</span></b>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# System
|
# System
|
||||||
|
|
||||||
system 包含 os, 运行time, shell command 相关函数。
|
system 包含 os, runtime, shell command 相关函数。
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -31,11 +31,6 @@ import (
|
|||||||
- [CompareOsEnv](#CompareOsEnv)
|
- [CompareOsEnv](#CompareOsEnv)
|
||||||
- [ExecCommand](#ExecCommand)
|
- [ExecCommand](#ExecCommand)
|
||||||
- [GetOsBits](#GetOsBits)
|
- [GetOsBits](#GetOsBits)
|
||||||
- [StartProcess](#StartProcess)
|
|
||||||
- [StopProcess](#StopProcess)
|
|
||||||
- [KillProcess](#KillProcess)
|
|
||||||
- [GetProcessInfo](#GetProcessInfo)
|
|
||||||
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -253,7 +248,7 @@ func main() {
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
type (
|
type (
|
||||||
Option func(*exec.Cmd)
|
Option func(*exec.Cmd)
|
||||||
)
|
)
|
||||||
func ExecCommand(command string, opts ...Option) (stdout, stderr string, err error)
|
func ExecCommand(command string, opts ...Option) (stdout, stderr string, err error)
|
||||||
```
|
```
|
||||||
@@ -313,132 +308,3 @@ func main() {
|
|||||||
fmt.Println(osBit) // 32 or 64
|
fmt.Println(osBit) // 32 or 64
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### <span id="StartProcess">StartProcess</span>
|
|
||||||
|
|
||||||
<p>创建进程。</p>
|
|
||||||
|
|
||||||
<b>函数签名:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func StartProcess(command string, args ...string) (int, error)
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>示例:<span style="float:right;display:inline-block">[运行](todo)</span></b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/system"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
pid, err := system.StartProcess("sleep", "2")
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(pid)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="StopProcess">StopProcess</span>
|
|
||||||
|
|
||||||
<p>停止进程。</p>
|
|
||||||
|
|
||||||
<b>函数签名:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func StopProcess(pid int) error
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>示例:<span style="float:right;display:inline-block">[运行](todo)</span></b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/system"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
pid, err := system.StartProcess("sleep", "10")
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
|
|
||||||
err = system.StopProcess(pid)
|
|
||||||
|
|
||||||
fmt.Println(err)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// <nil>
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="KillProcess">KillProcess</span>
|
|
||||||
|
|
||||||
<p>杀掉进程。</p>
|
|
||||||
|
|
||||||
<b>函数签名:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func KillProcess(pid int) error
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>示例:<span style="float:right;display:inline-block">[运行](todo)</span></b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/system"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
pid, err := system.StartProcess("sleep", "10")
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
|
|
||||||
err = system.KillProcess(pid)
|
|
||||||
|
|
||||||
fmt.Println(err)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// <nil>
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="GetProcessInfo">GetProcessInfo</span>
|
|
||||||
|
|
||||||
<p>根据进程id获取进程信息。</p>
|
|
||||||
|
|
||||||
<b>函数签名:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func GetProcessInfo(pid int) (*ProcessInfo, error)
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>示例:<span style="float:right;display:inline-block">[运行](todo)</span></b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/system"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
pid, err := system.StartProcess("ls", "-a")
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
processInfo, err := system.GetProcessInfo(pid)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(processInfo)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
@@ -37,12 +37,12 @@ import (
|
|||||||
|
|
||||||
### <span id="Comma">Comma</span>
|
### <span id="Comma">Comma</span>
|
||||||
|
|
||||||
<p>Add comma to a number value by every 3 numbers from right to left. ahead by a prefix symbol char. if value is a invalid number string like "aa", return empty string.</p>
|
<p>Add comma to a number value by every 3 numbers from right to left. ahead by symbol char. if value is a invalid number string like "aa", return empty string.</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func Comma[T constraints.Float | constraints.Integer | string](value T, prefixSymbol string) string
|
func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/eRD5k2vzUVX)</span></b>
|
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/eRD5k2vzUVX)</span></b>
|
||||||
|
|||||||
@@ -31,11 +31,6 @@ import (
|
|||||||
- [CompareOsEnv](#CompareOsEnv)
|
- [CompareOsEnv](#CompareOsEnv)
|
||||||
- [ExecCommand](#ExecCommand)
|
- [ExecCommand](#ExecCommand)
|
||||||
- [GetOsBits](#GetOsBits)
|
- [GetOsBits](#GetOsBits)
|
||||||
- [StartProcess](#StartProcess)
|
|
||||||
- [StopProcess](#StopProcess)
|
|
||||||
- [KillProcess](#KillProcess)
|
|
||||||
- [GetProcessInfo](#GetProcessInfo)
|
|
||||||
|
|
||||||
|
|
||||||
<div STYLE="page-break-after: always;"></div>
|
<div STYLE="page-break-after: always;"></div>
|
||||||
|
|
||||||
@@ -254,7 +249,7 @@ The second parameter of the function is the cmd option control parameter. The ty
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
type (
|
type (
|
||||||
Option func(*exec.Cmd)
|
Option func(*exec.Cmd)
|
||||||
)
|
)
|
||||||
func ExecCommand(command string, opts ...Option) (stdout, stderr string, err error)
|
func ExecCommand(command string, opts ...Option) (stdout, stderr string, err error)
|
||||||
```
|
```
|
||||||
@@ -293,7 +288,7 @@ func main() {
|
|||||||
|
|
||||||
### <span id="GetOsBits">GetOsBits</span>
|
### <span id="GetOsBits">GetOsBits</span>
|
||||||
|
|
||||||
<p>Get current os bits, 32bit or 64bit. return 32 or 64.</p>
|
<p>Get current os bits, 32bit or 64bit. return 32 or 64</p>
|
||||||
|
|
||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
@@ -314,132 +309,3 @@ func main() {
|
|||||||
fmt.Println(osBit) // 32 or 64
|
fmt.Println(osBit) // 32 or 64
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### <span id="StartProcess">StartProcess</span>
|
|
||||||
|
|
||||||
<p>Start a new process with the specified name and arguments.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func StartProcess(command string, args ...string) (int, error)
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:<span style="float:right;display:inline-block">[Run](todo)</span></b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/system"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
pid, err := system.StartProcess("sleep", "2")
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(pid)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="StopProcess">StopProcess</span>
|
|
||||||
|
|
||||||
<p>Stop a process by pid.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func StopProcess(pid int) error
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:<span style="float:right;display:inline-block">[Run](todo)</span></b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/system"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
pid, err := system.StartProcess("sleep", "10")
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
|
|
||||||
err = system.StopProcess(pid)
|
|
||||||
|
|
||||||
fmt.Println(err)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// <nil>
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="KillProcess">KillProcess</span>
|
|
||||||
|
|
||||||
<p>Kill a process by pid.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func KillProcess(pid int) error
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:<span style="float:right;display:inline-block">[Run](todo)</span></b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/system"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
pid, err := system.StartProcess("sleep", "10")
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
|
|
||||||
err = system.KillProcess(pid)
|
|
||||||
|
|
||||||
fmt.Println(err)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// <nil>
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### <span id="GetProcessInfo">GetProcessInfo</span>
|
|
||||||
|
|
||||||
<p>Retrieves detailed process information by pid.</p>
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
func GetProcessInfo(pid int) (*ProcessInfo, error)
|
|
||||||
```
|
|
||||||
|
|
||||||
<b>Example:<span style="float:right;display:inline-block">[Run](todo)</span></b>
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/duke-git/lancet/v2/system"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
pid, err := system.StartProcess("ls", "-a")
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
processInfo, err := system.GetProcessInfo(pid)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(processInfo)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
@@ -14,11 +14,11 @@ import (
|
|||||||
"golang.org/x/exp/constraints"
|
"golang.org/x/exp/constraints"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Comma add comma to a number value by every 3 numbers from right. ahead by prefix symbol char.
|
// Comma add comma to a number value by every 3 numbers from right. ahead by symbol char.
|
||||||
// if value is invalid number string eg "aa", return empty string
|
// if value is invalid number string eg "aa", return empty string
|
||||||
// Comma("12345", "$") => "$12,345", Comma(12345, "$") => "$12,345"
|
// Comma("12345", "$") => "$12,345", Comma(12345, "$") => "$12,345"
|
||||||
// Play: https://go.dev/play/p/eRD5k2vzUVX
|
// Play: https://go.dev/play/p/eRD5k2vzUVX
|
||||||
func Comma[T constraints.Float | constraints.Integer | string](value T, prefixSymbol string) string {
|
func Comma[T constraints.Float | constraints.Integer | string](value T, symbol string) string {
|
||||||
numString := convertor.ToString(value)
|
numString := convertor.ToString(value)
|
||||||
|
|
||||||
_, err := strconv.ParseFloat(numString, 64)
|
_, err := strconv.ParseFloat(numString, 64)
|
||||||
@@ -26,26 +26,17 @@ func Comma[T constraints.Float | constraints.Integer | string](value T, prefixSy
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
isNegative := strings.HasPrefix(numString, "-")
|
|
||||||
if isNegative {
|
|
||||||
numString = numString[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
index := strings.Index(numString, ".")
|
index := strings.Index(numString, ".")
|
||||||
if index == -1 {
|
if index == -1 {
|
||||||
index = len(numString)
|
index = len(numString)
|
||||||
}
|
}
|
||||||
|
|
||||||
for index > 3 {
|
for index > 3 {
|
||||||
index -= 3
|
index = index - 3
|
||||||
numString = numString[:index] + "," + numString[index:]
|
numString = numString[:index] + "," + numString[index:]
|
||||||
}
|
}
|
||||||
|
|
||||||
if isNegative {
|
return symbol + numString
|
||||||
numString = "-" + numString
|
|
||||||
}
|
|
||||||
|
|
||||||
return prefixSymbol + numString
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pretty data to JSON string.
|
// Pretty data to JSON string.
|
||||||
|
|||||||
@@ -28,10 +28,6 @@ func TestComma(t *testing.T) {
|
|||||||
assert.Equal("12,345.6789", Comma(+12345.6789, ""))
|
assert.Equal("12,345.6789", Comma(+12345.6789, ""))
|
||||||
assert.Equal("12,345,678.9", Comma(12345678.9, ""))
|
assert.Equal("12,345,678.9", Comma(12345678.9, ""))
|
||||||
assert.Equal("123,456,789,000", Comma(123456789000, ""))
|
assert.Equal("123,456,789,000", Comma(123456789000, ""))
|
||||||
|
|
||||||
assert.Equal("-999", Comma(-999, ""))
|
|
||||||
assert.Equal("-1,000", Comma(-1000, ""))
|
|
||||||
assert.Equal("-1,234,567", Comma(-1234567, ""))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPretty(t *testing.T) {
|
func TestPretty(t *testing.T) {
|
||||||
|
|||||||
@@ -21,48 +21,21 @@ import (
|
|||||||
// GetInternalIp return internal ipv4.
|
// GetInternalIp return internal ipv4.
|
||||||
// Play: https://go.dev/play/p/5mbu-gFp7ei
|
// Play: https://go.dev/play/p/5mbu-gFp7ei
|
||||||
func GetInternalIp() string {
|
func GetInternalIp() string {
|
||||||
addrs, err := net.InterfaceAddrs()
|
addr, err := net.InterfaceAddrs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err.Error())
|
panic(err.Error())
|
||||||
}
|
}
|
||||||
|
for _, a := range addr {
|
||||||
for _, addr := range addrs {
|
if ipNet, ok := a.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
|
||||||
var ip net.IP
|
if ipNet.IP.To4() != nil {
|
||||||
switch v := addr.(type) {
|
return ipNet.IP.String()
|
||||||
case *net.IPNet:
|
}
|
||||||
ip = v.IP
|
|
||||||
case *net.IPAddr:
|
|
||||||
ip = v.IP
|
|
||||||
}
|
|
||||||
|
|
||||||
if ip != nil && (ip.IsLinkLocalUnicast() || ip.IsGlobalUnicast()) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if ipv4 := ip.To4(); ipv4 != nil {
|
|
||||||
return ipv4.String()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// func GetInternalIp() string {
|
|
||||||
// addr, err := net.InterfaceAddrs()
|
|
||||||
// if err != nil {
|
|
||||||
// panic(err.Error())
|
|
||||||
// }
|
|
||||||
// for _, a := range addr {
|
|
||||||
// if ipNet, ok := a.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
|
|
||||||
// if ipNet.IP.To4() != nil {
|
|
||||||
// return ipNet.IP.String()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return ""
|
|
||||||
// }
|
|
||||||
|
|
||||||
// GetRequestPublicIp return the requested public ip.
|
// GetRequestPublicIp return the requested public ip.
|
||||||
// Play: https://go.dev/play/p/kxU-YDc_eBo
|
// Play: https://go.dev/play/p/kxU-YDc_eBo
|
||||||
func GetRequestPublicIp(req *http.Request) string {
|
func GetRequestPublicIp(req *http.Request) string {
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ func LowerFirst(s string) string {
|
|||||||
return string(r) + s[size:]
|
return string(r) + s[size:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pad pads string on the left and right side if it's shorter than size.
|
// PadStart pads string on the left and right side if it's shorter than size.
|
||||||
// Padding characters are truncated if they exceed size.
|
// Padding characters are truncated if they exceed size.
|
||||||
// Play: https://go.dev/play/p/NzImQq-VF8q
|
// Play: https://go.dev/play/p/NzImQq-VF8q
|
||||||
func Pad(source string, size int, padStr string) string {
|
func Pad(source string, size int, padStr string) string {
|
||||||
|
|||||||
190
system/os.go
190
system/os.go
@@ -6,12 +6,9 @@ package system
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/duke-git/lancet/v2/validator"
|
"github.com/duke-git/lancet/v2/validator"
|
||||||
@@ -135,190 +132,3 @@ func byteToString(data []byte, charset string) string {
|
|||||||
func GetOsBits() int {
|
func GetOsBits() int {
|
||||||
return 32 << (^uint(0) >> 63)
|
return 32 << (^uint(0) >> 63)
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartProcess start a new process with the specified name and arguments.
|
|
||||||
// Play: todo
|
|
||||||
func StartProcess(command string, args ...string) (int, error) {
|
|
||||||
cmd := exec.Command(command, args...)
|
|
||||||
|
|
||||||
if err := cmd.Start(); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return cmd.Process.Pid, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// StopProcess stop a process by pid.
|
|
||||||
// Play: todo
|
|
||||||
func StopProcess(pid int) error {
|
|
||||||
process, err := os.FindProcess(pid)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return process.Signal(os.Kill)
|
|
||||||
}
|
|
||||||
|
|
||||||
// KillProcess kill a process by pid.
|
|
||||||
// Play: todo
|
|
||||||
func KillProcess(pid int) error {
|
|
||||||
process, err := os.FindProcess(pid)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return process.Kill()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessInfo contains detailed information about a process.
|
|
||||||
type ProcessInfo struct {
|
|
||||||
PID int
|
|
||||||
CPU string
|
|
||||||
Memory string
|
|
||||||
State string
|
|
||||||
User string
|
|
||||||
Cmd string
|
|
||||||
Threads []string
|
|
||||||
IOStats string
|
|
||||||
StartTime string
|
|
||||||
ParentPID int
|
|
||||||
NetworkConnections string
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetProcessInfo retrieves detailed process information by pid.
|
|
||||||
// Play: todo
|
|
||||||
func GetProcessInfo(pid int) (*ProcessInfo, error) {
|
|
||||||
var cmd *exec.Cmd
|
|
||||||
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
cmd = exec.Command("tasklist", "/FI", fmt.Sprintf("PID eq %d", pid), "/FO", "CSV", "/V")
|
|
||||||
} else {
|
|
||||||
cmd = exec.Command("ps", "-p", strconv.Itoa(pid), "-o", "pid,%cpu,%mem,state,user,comm")
|
|
||||||
}
|
|
||||||
|
|
||||||
output, err := cmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
processInfo, err := parseProcessInfo(output, pid)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if runtime.GOOS != "windows" {
|
|
||||||
processInfo.Threads, _ = getThreadsInfo(pid)
|
|
||||||
processInfo.IOStats, _ = getIOStats(pid)
|
|
||||||
processInfo.StartTime, _ = getProcessStartTime(pid)
|
|
||||||
processInfo.ParentPID, _ = getParentProcess(pid)
|
|
||||||
processInfo.NetworkConnections, _ = getNetworkConnections(pid)
|
|
||||||
}
|
|
||||||
|
|
||||||
return processInfo, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseProcessInfo parses the output of `ps` or `tasklist` to fill the ProcessInfo structure.
|
|
||||||
func parseProcessInfo(output []byte, pid int) (*ProcessInfo, error) {
|
|
||||||
lines := strings.Split(string(output), "\n")
|
|
||||||
|
|
||||||
if len(lines) < 2 {
|
|
||||||
return nil, fmt.Errorf("no process found with PID %d", pid)
|
|
||||||
}
|
|
||||||
|
|
||||||
var processInfo ProcessInfo
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
fields := strings.Split(lines[1], "\",\"")
|
|
||||||
if len(fields) < 9 {
|
|
||||||
return nil, fmt.Errorf("unexpected tasklist output format")
|
|
||||||
}
|
|
||||||
|
|
||||||
processInfo = ProcessInfo{
|
|
||||||
PID: pid,
|
|
||||||
CPU: "N/A",
|
|
||||||
Memory: fields[4], // Memory usage in K
|
|
||||||
State: fields[5],
|
|
||||||
User: "N/A",
|
|
||||||
Cmd: fields[8],
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fields := strings.Fields(lines[1])
|
|
||||||
if len(fields) < 6 {
|
|
||||||
return nil, fmt.Errorf("unexpected ps output format")
|
|
||||||
}
|
|
||||||
|
|
||||||
processInfo = ProcessInfo{
|
|
||||||
PID: pid,
|
|
||||||
CPU: fields[1],
|
|
||||||
Memory: fields[2],
|
|
||||||
State: fields[3],
|
|
||||||
User: fields[4],
|
|
||||||
Cmd: fields[5],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &processInfo, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getThreadsInfo(pid int) ([]string, error) {
|
|
||||||
cmd := exec.Command("ps", "-T", "-p", strconv.Itoa(pid))
|
|
||||||
output, err := cmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
lines := strings.Split(string(output), "\n")
|
|
||||||
|
|
||||||
var threads []string
|
|
||||||
for _, line := range lines[1:] {
|
|
||||||
if strings.TrimSpace(line) != "" {
|
|
||||||
threads = append(threads, line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return threads, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getIOStats(pid int) (string, error) {
|
|
||||||
filePath := fmt.Sprintf("/proc/%d/io", pid)
|
|
||||||
data, err := os.ReadFile(filePath)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(data), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getProcessStartTime(pid int) (string, error) {
|
|
||||||
cmd := exec.Command("ps", "-p", strconv.Itoa(pid), "-o", "lstart=")
|
|
||||||
output, err := cmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings.TrimSpace(string(output)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getParentProcess(pid int) (int, error) {
|
|
||||||
cmd := exec.Command("ps", "-o", "ppid=", "-p", strconv.Itoa(pid))
|
|
||||||
output, err := cmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ppid, err := strconv.Atoi(strings.TrimSpace(string(output)))
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return ppid, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getNetworkConnections(pid int) (string, error) {
|
|
||||||
cmd := exec.Command("lsof", "-p", strconv.Itoa(pid), "-i")
|
|
||||||
output, err := cmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(output), nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
package system
|
package system
|
||||||
|
|
||||||
import (
|
import "fmt"
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExampleSetOsEnv() {
|
func ExampleSetOsEnv() {
|
||||||
err := SetOsEnv("foo", "abc")
|
err := SetOsEnv("foo", "abc")
|
||||||
@@ -78,56 +75,3 @@ func ExampleGetOsBits() {
|
|||||||
// Output:
|
// Output:
|
||||||
// 64
|
// 64
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleStartProcess() {
|
|
||||||
pid, err := StartProcess("sleep", "2")
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(pid)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleStopProcess() {
|
|
||||||
pid, err := StartProcess("sleep", "10")
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
|
|
||||||
err = StopProcess(pid)
|
|
||||||
|
|
||||||
fmt.Println(err)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// <nil>
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleKillProcess() {
|
|
||||||
pid, err := StartProcess("sleep", "3")
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
|
|
||||||
err = KillProcess(pid)
|
|
||||||
|
|
||||||
fmt.Println(err)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// <nil>
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleGetProcessInfo() {
|
|
||||||
pid, err := StartProcess("ls", "-a")
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
processInfo, err := GetProcessInfo(pid)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(processInfo)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package system
|
package system
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os/exec"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/duke-git/lancet/v2/internal"
|
"github.com/duke-git/lancet/v2/internal"
|
||||||
)
|
)
|
||||||
@@ -55,9 +53,7 @@ func TestExecCommand(t *testing.T) {
|
|||||||
assert := internal.NewAssert(t, "TestExecCommand")
|
assert := internal.NewAssert(t, "TestExecCommand")
|
||||||
|
|
||||||
// linux or mac
|
// linux or mac
|
||||||
stdout, stderr, err := ExecCommand("ls", func(cmd *exec.Cmd) {
|
stdout, stderr, err := ExecCommand("ls")
|
||||||
cmd.Dir = "/"
|
|
||||||
})
|
|
||||||
t.Log("std out: ", stdout)
|
t.Log("std out: ", stdout)
|
||||||
t.Log("std err: ", stderr)
|
t.Log("std err: ", stderr)
|
||||||
assert.Equal("", stderr)
|
assert.Equal("", stderr)
|
||||||
@@ -78,6 +74,16 @@ func TestExecCommand(t *testing.T) {
|
|||||||
assert.IsNotNil(err)
|
assert.IsNotNil(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func TestExecCommandWithOption(t *testing.T) {
|
||||||
|
// assert := internal.NewAssert(t, "TestExecCommandWithOption")
|
||||||
|
|
||||||
|
// stdout, stderr, err := ExecCommand("ls", WithForeground())
|
||||||
|
// t.Log("std out: ", stdout)
|
||||||
|
// t.Log("std err: ", stderr)
|
||||||
|
// assert.Equal("", stderr)
|
||||||
|
// assert.IsNil(err)
|
||||||
|
// }
|
||||||
|
|
||||||
func TestGetOsBits(t *testing.T) {
|
func TestGetOsBits(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
@@ -89,56 +95,3 @@ func TestGetOsBits(t *testing.T) {
|
|||||||
t.Error("os is not 32 or 64 bits")
|
t.Error("os is not 32 or 64 bits")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStartProcess(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestStartProcess")
|
|
||||||
|
|
||||||
pid, err := StartProcess("ls", "-a")
|
|
||||||
|
|
||||||
assert.IsNil(err)
|
|
||||||
assert.Equal(true, pid > 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestKillProcess(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestKillProcess")
|
|
||||||
|
|
||||||
pid, err := StartProcess("ls")
|
|
||||||
assert.IsNil(err)
|
|
||||||
assert.Equal(true, pid > 0)
|
|
||||||
|
|
||||||
err = KillProcess(pid)
|
|
||||||
assert.IsNil(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStopProcess(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestStopProcess")
|
|
||||||
|
|
||||||
pid, err := StartProcess("ls")
|
|
||||||
assert.IsNil(err)
|
|
||||||
assert.Equal(true, pid > 0)
|
|
||||||
|
|
||||||
err = StopProcess(pid)
|
|
||||||
assert.IsNil(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetProcessInfo(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
assert := internal.NewAssert(t, "TestGetProcessInfo")
|
|
||||||
|
|
||||||
pid, err := StartProcess("ls", "-a")
|
|
||||||
assert.IsNil(err)
|
|
||||||
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
|
|
||||||
processInfo, err := GetProcessInfo(pid)
|
|
||||||
assert.IsNil(err)
|
|
||||||
|
|
||||||
t.Log(processInfo)
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user