Golang如何获取进程状态(运行/停止)
Golang如何获取进程状态(运行/停止) 如何获取进程状态(在Linux虚拟机上),已知程序名称和某些参数。我知道如果知道PID是可以做到的,但我需要通过名称和参数来实现。
一些指导方向就足够了。
谢谢
// 代码示例保留原样
关于使用"ps aux"命令获取进程运行状态(如果进程未运行则无法获取)的方法如何?
更多关于Golang如何获取进程状态(运行/停止)的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Unix系统中,PID是每个进程的唯一标识符。通过PID可以获取进程的相关信息。
Linux系统拥有一个/proc文件系统,其中包含进程信息。/proc目录列表会显示许多以数字命名的目录,每个目录对应一个PID。在这些目录中存在包含各类信息的文件,包括:
/proc/<PID>/comm - 命令名称
以及
/proc/<PID>/cmdline - 命令行参数
您可以通过搜索这些文件来找到包含目标命令名称/参数的PID。
详细内容请参阅proc(5)手册页:
http://manpages.ubuntu.com/manpages/xenial/man5/proc.5.html
要检查您的代码,可以使用
pidof <command_name>
该命令会打印指定名称命令的PID。
在Linux环境下,你可以通过解析/proc文件系统来获取进程状态。以下是一个完整的实现示例,通过进程名称和参数来匹配进程并获取其状态:
package main
import (
"bufio"
"fmt"
"os"
"path/filepath"
"strings"
)
// ProcessStatus 表示进程状态
type ProcessStatus struct {
PID string
Name string
Status string // 运行状态
Command string // 完整命令行
}
// GetProcessStatusByNameAndArgs 通过进程名和参数获取进程状态
func GetProcessStatusByNameAndArgs(processName string, args []string) ([]ProcessStatus, error) {
var results []ProcessStatus
// 遍历 /proc 目录下的所有数字目录(PID目录)
entries, err := os.ReadDir("/proc")
if err != nil {
return nil, err
}
for _, entry := range entries {
if !entry.IsDir() {
continue
}
pid := entry.Name()
// 检查是否为数字目录(PID)
if !isNumeric(pid) {
continue
}
// 读取进程状态文件
statusFile := filepath.Join("/proc", pid, "status")
status, err := parseStatusFile(statusFile)
if err != nil {
continue
}
// 读取命令行文件
cmdlineFile := filepath.Join("/proc", pid, "cmdline")
cmdline, err := parseCmdlineFile(cmdlineFile)
if err != nil {
continue
}
// 检查进程名和参数是否匹配
if matchesProcess(processName, args, cmdline) {
results = append(results, ProcessStatus{
PID: pid,
Name: status["Name"],
Status: status["State"],
Command: cmdline,
})
}
}
return results, nil
}
// parseStatusFile 解析 /proc/[pid]/status 文件
func parseStatusFile(filename string) (map[string]string, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
status := make(map[string]string)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
parts := strings.SplitN(line, ":", 2)
if len(parts) == 2 {
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
status[key] = value
}
}
return status, scanner.Err()
}
// parseCmdlineFile 解析 /proc/[pid]/cmdline 文件
func parseCmdlineFile(filename string) (string, error) {
content, err := os.ReadFile(filename)
if err != nil {
return "", err
}
// cmdline 文件使用 null 字节分隔参数
cmdline := strings.ReplaceAll(string(content), "\x00", " ")
return strings.TrimSpace(cmdline), nil
}
// matchesProcess 检查进程名和参数是否匹配
func matchesProcess(processName string, expectedArgs []string, actualCmdline string) bool {
// 检查进程名是否匹配
if !strings.Contains(actualCmdline, processName) {
return false
}
// 检查所有参数是否都存在
for _, arg := range expectedArgs {
if !strings.Contains(actualCmdline, arg) {
return false
}
}
return true
}
// isNumeric 检查字符串是否为数字
func isNumeric(s string) bool {
for _, c := range s {
if c < '0' || c > '9' {
return false
}
}
return s != ""
}
// 使用示例
func main() {
// 查找包含特定参数的程序
processName := "myapp"
args := []string{"--config", "/etc/myapp.conf"}
processes, err := GetProcessStatusByNameAndArgs(processName, args)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
if len(processes) == 0 {
fmt.Println("No matching processes found")
return
}
for _, proc := range processes {
fmt.Printf("PID: %s, Name: %s, Status: %s\n", proc.PID, proc.Name, proc.Status)
fmt.Printf("Command: %s\n\n", proc.Command)
}
}
这个实现的主要功能:
- 遍历/proc目录:扫描所有进程目录
- 解析状态文件:从
/proc/[pid]/status获取进程状态信息 - 解析命令行:从
/proc/[pid]/cmdline获取完整的命令行参数 - 匹配条件:根据进程名和参数进行匹配
- 返回结果:返回匹配进程的状态信息
进程状态字段说明:
R:运行中 (Running)S:睡眠中 (Sleeping)D:不可中断睡眠Z:僵尸进程T:已停止 (Stopped)
使用示例:
// 查找nginx进程,包含特定配置文件
processes, err := GetProcessStatusByNameAndArgs("nginx", []string{"-c", "/etc/nginx/nginx.conf"})
这种方法不需要预先知道PID,完全基于进程名称和命令行参数进行匹配。

