2024-04-10 14:54:11 +08:00

209 lines
4.8 KiB
Go

package mageutil
import (
"fmt"
"github.com/shirou/gopsutil/net"
"github.com/shirou/gopsutil/process"
"os"
"path/filepath"
"runtime"
"strings"
)
func OsArch() string {
os := runtime.GOOS
arch := runtime.GOARCH
if os == "windows" {
return fmt.Sprintf("%s\\%s", os, arch)
}
return fmt.Sprintf("%s/%s", os, arch)
}
func CheckProcessNames(processPath string, expectedCount int) error {
processes, err := process.Processes()
if err != nil {
return fmt.Errorf("failed to get processes: %v", err)
}
runningCount := 0
for _, p := range processes {
exePath, err := p.Exe()
if err != nil {
continue
}
if strings.EqualFold(exePath, processPath) {
runningCount++
}
}
if runningCount == expectedCount {
return nil
} else {
return fmt.Errorf("%s Expected %d processes, but %d running", processPath, expectedCount, runningCount)
}
}
// CheckProcessNamesExist checks if there are any processes running that match the specified path.
func CheckProcessNamesExist(processPath string) bool {
processes, err := process.Processes()
if err != nil {
fmt.Printf("Failed to get processes: %v\n", err)
return false
}
for _, p := range processes {
exePath, err := p.Exe()
if err != nil {
continue
}
if exePath == processPath {
return true // 找到至少一个匹配的进程
}
}
return false
}
// PrintBinaryPorts prints the ports listened by the process of a specified binary file along with its command line arguments.
func PrintBinaryPorts(binaryPath string) {
pids, err := FindPIDsByBinaryPath(binaryPath)
if err != nil {
fmt.Println("Error finding PIDs:", err)
return
}
if len(pids) == 0 {
fmt.Printf("No running processes found for binary: %s\n", binaryPath)
return
}
for _, pid := range pids {
proc, err := process.NewProcess(int32(pid))
if err != nil {
fmt.Printf("Failed to create process object for PID %d: %v\n", pid, err)
continue
}
cmdline, err := proc.Cmdline()
if err != nil {
fmt.Printf("Failed to get command line for PID %d: %v\n", pid, err)
continue
}
connections, err := net.ConnectionsPid("all", int32(pid))
if err != nil {
fmt.Printf("Error getting connections for PID %d: %v\n", pid, err)
continue
}
portsMap := make(map[string]struct{})
for _, conn := range connections {
if conn.Status == "LISTEN" {
port := fmt.Sprintf("%d", conn.Laddr.Port)
portsMap[port] = struct{}{}
}
}
if len(portsMap) == 0 {
PrintGreen(fmt.Sprintf("Cmdline: %s, PID: %d is not listening on any ports.", cmdline, pid))
} else {
ports := make([]string, 0, len(portsMap))
for port := range portsMap {
ports = append(ports, port)
}
PrintGreen(fmt.Sprintf("Cmdline: %s, PID: %d is listening on ports: %s", cmdline, pid, strings.Join(ports, ", ")))
}
}
}
// FindPIDsByBinaryPath finds all matching process PIDs by binary path.
func FindPIDsByBinaryPath(binaryPath string) ([]int, error) {
var pids []int
processes, err := process.Processes()
if err != nil {
return nil, err
}
for _, proc := range processes {
exePath, err := proc.Exe()
if err != nil {
continue
}
if strings.EqualFold(exePath, binaryPath) {
pids = append(pids, int(proc.Pid))
}
}
return pids, nil
}
// KillExistBinary kills all processes matching the given binary file path.
func KillExistBinary(binaryPath string) {
processes, err := process.Processes()
if err != nil {
fmt.Printf("Failed to get processes: %v\n", err)
return
}
for _, p := range processes {
exePath, err := p.Exe()
if err != nil {
continue
}
if strings.Contains(strings.ToLower(exePath), strings.ToLower(binaryPath)) {
//if strings.EqualFold(exePath, binaryPath) {
cmdline, err := p.Cmdline()
if err != nil {
fmt.Printf("Failed to get command line for process %d: %v\n", p.Pid, err)
continue
}
err = p.Terminate()
if err != nil {
err = p.Kill()
if err != nil {
fmt.Printf("Failed to kill process cmdline: %s, pid: %d, err: %v\n", cmdline, p.Pid, err)
} else {
fmt.Printf("Killed process cmdline: %s, pid: %d\n", cmdline, p.Pid)
}
} else {
fmt.Printf("Terminated process cmdline: %s, pid: %d\n", cmdline, p.Pid)
}
}
}
}
// DetectPlatform detects the operating system and architecture.
func DetectPlatform() string {
targetOS, targetArch := runtime.GOOS, runtime.GOARCH
switch targetArch {
case "amd64", "arm64":
default:
fmt.Printf("Unsupported architecture: %s\n", targetArch)
os.Exit(1)
}
return fmt.Sprintf("%s_%s", targetOS, targetArch)
}
// rootDir gets the absolute path of the current directory.
func rootDir() string {
dir, err := os.Getwd()
if err != nil {
fmt.Println("Failed to get current directory:", err)
os.Exit(1)
}
return dir
}
var rootDirPath = rootDir()
var platformsOutputBase = filepath.Join(rootDirPath, "_output/bin/platforms")
var toolsOutputBase = filepath.Join(rootDirPath, "_output/bin/tools")