当前位置: 首页 > article >正文

go语言获取机器的进程和进程运行参数 获取当前进程的jmx端口 go调用/jstat获取当前Java进程gc情况

这里主要分享go中获取机器进程和进程参数的一些代码

获取当前机器所有的pid:

import "github.com/shirou/gopsutil/process"
pids, err := process.Pids()
for _, pid := range pids {
		proc, err := process.NewProcess(pid)
		if err != nil {
			log.Errorf("get pid %d info error: %s", pid, err.Error())
			continue
		}

		// 获取进程命令行参数
		cmdLine, err := proc.Cmdline()
		if err != nil {
			log.Errorf("get cmdLine of pid %d error: %s", pid, err.Error())
			continue
		}

		log.Infof("cmdline of pid %d is: %s", pid, cmdLine)

		if !strings.Contains(cmdLine, "java") {
			continue
		}
//获取jmx端口:
	// 检查命令行参数是否包含"java"和"Dcom.sun.management.jmxremote.port"
			var jmxPort string
			if strings.Contains(cmdLine, "Dcom.sun.management.jmxremote.port") {
				// 提取JMX端口
				re := regexp.MustCompile(`Dcom.sun.management.jmxremote.port=(\d+)`)
				match := re.FindStringSubmatch(cmdLine)
				if len(match) > 1 {
					jmxPort = match[1]
					log.Infof("PID: %v, JMX Port: %v , %s, cmdLine: %s\n", pid, match[1], jmxPort, cmdLine)
				} else {
					log.Infof("not found jmxremote.port or jmxremote.rmi.port")
					log.Infof("PID: %v, of cmdLine: %s, has no Dcom.sun.management.jmxremote.port \n", pid, cmdLine)
				}
			}

Process.CmdlineWithContext 方法的实现依赖于 callPsWithContext 函数来获取进程的命令行参数。这个方法的实现如下:

func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
    r, err := callPsWithContext(ctx, "command", p.Pid, false)
    if err != nil {
        return "", err
    }
    return strings.Join(r[0], " "), err
}

调用jstat

JSTAT:JSTAT用于监视和收集Java虚拟机(JVM)的各种统计数据,例如垃圾回收情况、类加载情况、线程数量等。它可以实时显示这些统计数据,帮助开发人员了解应用程序的性能状况。
在这里插入图片描述

根据pid获取当前java程序的gc情况:


		Command := "jstat"
		if e.NewJSTAT {
			Command = "/usr/local/jdk/bin/jstat"
		}
		Data, DataErr, Err = util.RunCommandWithTimeout(&util.CommandArgs{
			Cmd:       Command,
			Username:  "root",
			Groupname: "root",
			Args:      []string{"-gcutil", strconv.FormatInt(pid, 10)},
		}, 2*time.Second)


func RunCommandWithTimeout(command *CommandArgs, timeout time.Duration) (stdout, stderr string, err error) {
	userinfo, err := user.Lookup(command.Username)
	if err != nil {
		return "", fmt.Sprintf("lookup user err:%s", err.Error()), err
	}
	uid, _ := strconv.Atoi(userinfo.Uid)
	gid, _ := strconv.Atoi(userinfo.Gid)
	var outb, errb bytes.Buffer
	ctxt, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()
	getBashCommand(command)
	cmd := exec.CommandContext(ctxt, command.Cmd, command.Args...)
	cmd.Stdout = &outb
	cmd.Stderr = &errb
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Credential: &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)},
		Setsid:     true,
	}
	cmd.Env = append(os.Environ(), makeEnv(command.Username)...)
	if command.Env != nil && len(command.Env) != 0 {
		for k, v := range command.Env {
			cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", k, v))
		}
	}
	if err := cmd.Start(); err != nil {
		return outb.String(), errb.String(), err
	}
	if err := cmd.Wait(); err != nil {
		return outb.String(), errb.String(), err
	}
	return outb.String(), errb.String(), err
}

调用jcmd命令:

log.Debugf("process jcmd data")
			JCMD := "jcmd"
			if e.NewJSTAT {
				Command = "/usr/local/jdk/bin/jcmd"
			}
			JcmdData, JcmdDataErr, JcmdErr = util.RunCommandWithTimeout(&util.CommandArgs{
				Cmd:       JCMD,
				Username:  "root",
				Groupname: "root",
				Args:      []string{strconv.FormatInt(pid, 10), "VM.flags"},
			}, 2*time.Second)
			if JcmdErr != nil {
				log.Errorf("RunCommandWithTimeout Jcmd JcmdDataErr %s JcmdErr %v", JcmdDataErr, JcmdErr)
			}

关于jcmd:
jcmd 是一个用于与 Java 虚拟机 (JVM) 进行交互的命令行工具。它是 JDK(Java Development Kit)的一部分,提供了一系列命令来诊断和监控运行中的 Java 应用程序。jcmd 工具可以用于执行各种操作,例如获取线程堆栈、生成堆转储、执行垃圾回收等。

jcmd 的基本用法
jcmd 的基本用法如下:

jcmd <pid | main class> <command> [options]
<pid | main class>:指定目标 JVM 的进程 ID 或主类名。
<command>:要执行的命令。
[options]:命令的可选参数。

常用命令
以下是一些常用的 jcmd 命令:

列出所有可用的命令:

jcmd help
例如:
jcmd 12345 help
列出所有正在运行的 Java 进程:

jcmd

在这里插入图片描述

获取 JVM 版本信息:
jcmd VM.version
例如:
jcmd 12345 VM.version
获取系统属性:
jcmd VM.system_properties
获取 JVM 配置:
jcmd VM.command_line

在docker中执行/jstat

在docker中想执行jstat如下:

func RunDockerPsEfWithTimeout(dockerName string) (stdout, stderr string, err error) {

	// docker exec sr-broker ps -ef | grep broker
	cmd := exec.Command("/usr/bin/docker", "exec", dockerName, "ps", "-ef")
	var outb, errb bytes.Buffer
	cmd.Stdout = &outb
	cmd.Stderr = &errb
	err = cmd.Run()

	return outb.String(), errb.String(), err
}

func RunDockerJstatWithTimeout(dockerName string, dockerPid string) (stdout, stderr string, err error) {
stdout, stderr, err := RunDockerPsEfWithTimeout(dockerName)
		if err != nil {
			log.Errorf("RunDockerCMDWithTimeout dockerPsCmd err %v stderr %s", err, stderr)
			return "", "", "", err
		}
		//获取docker中的pid
		dockerPid := ""
		lines := strings.Split(stdout, "\n")
		for _, line := range lines {
			fields := strings.Fields(line)
			if len(fields) >= 8 {
				if strings.Contains(line, dockerPName) {
					dockerPid = fields[1]
					break
				}
			}
		}
	defer func() {
		if e := recover(); e != nil {
			log.Errorf("RunDockerJstatWithTimeout error %v", e)
		}
	}()

	dockerCmd := []string{"bash", "-c", fmt.Sprintf("source /etc/profile && jstat -gcutil %s", dockerPid)}

	cmd := exec.Command("/usr/bin/docker", "exec", dockerName)
	cmd.Args = append(cmd.Args, dockerCmd...)
	var outb, errb bytes.Buffer
	cmd.Stdout = &outb
	cmd.Stderr = &errb
	err = cmd.Run()

	return outb.String(), errb.String(), err
}


http://www.kler.cn/a/545266.html

相关文章:

  • Redis 集群:从基础到实战的面试指南
  • 20250213编译飞凌的OK3588-C_Linux5.10.209+Qt5.15.10_用户资料_R1
  • 从 Windows Forms 到微服务的经验教训
  • Ubuntu20.04上搭建nginx正向代理提供上网服务
  • rdian是一个结构体,pdian=^Rdian,list泛型做什么用?
  • Android 消息总站 设计思路
  • 修改RAGFlow在docker desktop中的容器名
  • 《刚刚问世》系列初窥篇-Java+Playwright自动化测试-22- 操作鼠标拖拽 - 下篇(详细教程)
  • QT:Button
  • 布隆过滤器(简单介绍)
  • Pro Git --(Windows)总结
  • DeepSeek整理PDF文档以思维导图方式展示
  • TOML介绍
  • Spring Boot(8)深入理解 @Autowired 注解:使用场景与实战示例
  • QML使用ChartView绘制饼状图
  • 从 0 到 1 搭建个人博客:技术选型与实现全解析
  • Java 大视界 -- 边缘计算与 Java 大数据协同发展的前景与挑战(85)
  • Spring Boot 配置JPA数据库主从读写分离失败及解决办法
  • mapbox 从入门到精通 - 目录
  • 股指期货和etf期权哪个更好交易?