java获取linux服务的系统信息(cpu使用率、内存使用率、系统负载)
文章目录1 代码1.1 工具类1.2 辅助bean2 问题2.1 java使用Runtime.exec执行linux命令不成功问题2.1.1 问题说明2.1.2 问题原因2.1.3 解决方案1 代码1.1 工具类说明:cpu使用率,可以采用jdk8原生的方法,但是有博客说不太准确,这里不做说明。import cn.hzp.util.linuxinfo.bean.CpuInfoBean;import
·
1 代码
1.1 工具类
说明:
- cpu使用率,可以采用jdk工具类的方法,但是有博客说不太准确,这里不采用,通过/proc/stat方式实现。
- 内存使用率,采用jdk工具类的方法实现。
- 系统负载,采用uptime命令通过计算来实现。
import com.sun.management.OperatingSystemMXBean;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.math.BigDecimal;
import java.util.StringTokenizer;
@Slf4j
public class LinuxInfoUtil {
private static final String CPU_FILE = "/proc/stat";
private static final String LOAD_COMMAND = "uptime";
/**
* 获得Linux cpu使用率 pcpu =100* (total-idle)/total
* total = total2-total1
* idle = idle2 -idle1
* total1 = user1+nice1+system1+idle1+iowait1+irq1+softirq1+stealstolen1+guest1+guest_nice1
*/
public static BigDecimal getCpuInfo() {
try {
File file = new File(CPU_FILE);
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
StringTokenizer procStatFirstLine = new StringTokenizer(br.readLine());
CpuInfoBean cpuInfoBean1 = new CpuInfoBean(procStatFirstLine);
BigDecimal total1 = cpuInfoBean1.getCpuTotal();
Thread.sleep(1000);
br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
procStatFirstLine = new StringTokenizer(br.readLine());
CpuInfoBean cpuInfoBean2 = new CpuInfoBean(procStatFirstLine);
BigDecimal total2 = cpuInfoBean2.getCpuTotal();
BigDecimal total = total2.subtract(total1);
BigDecimal idle = cpuInfoBean2.getIdle().subtract(cpuInfoBean1.getIdle());
BigDecimal pcpu = new BigDecimal(100).multiply(total.subtract(idle)).divide(total, 0, BigDecimal.ROUND_HALF_UP);
br.close();
return pcpu;
} catch (Exception e) {
log.info(e.toString());
return new BigDecimal(0);
}
}
// 获取内存使用率
public static BigDecimal getMemory() {
OperatingSystemMXBean osmxb = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
BigDecimal total = new BigDecimal(osmxb.getTotalPhysicalMemorySize());
BigDecimal free = new BigDecimal(osmxb.getFreePhysicalMemorySize());
BigDecimal pmem = new BigDecimal(100).multiply(total.subtract(free)).divide(total, 0, BigDecimal.ROUND_HALF_UP);
return pmem;
}
/**
* 获取系统负载:top的15分钟平均值/(逻辑cpu核数*0.7)
*/
public static BigDecimal getLoad() {
try {
Runtime r = Runtime.getRuntime();
BigDecimal cpuPerformance = new BigDecimal(0.7).multiply(new BigDecimal(r.availableProcessors()));
Process pro = r.exec(LOAD_COMMAND);
BufferedReader br = new BufferedReader(new InputStreamReader(pro.getInputStream()));
String topLoad = br.readLine();
BigDecimal load = new BigDecimal(topLoad.substring(topLoad.lastIndexOf(" ")+1));
BigDecimal pload = new BigDecimal(100).multiply(load).divide(cpuPerformance, 0, BigDecimal.ROUND_HALF_UP);
br.close();
pro.destroy();
return pload;
} catch (Exception e) {
log.info(e.toString());
return new BigDecimal(0);
}
}
}
1.2 辅助bean
- 构造方法写的有点啰嗦,博友如有更好的方式欢迎留言
import lombok.Data;
import java.math.BigDecimal;
import java.util.StringTokenizer;
@Data
public class CpuInfoBean {
// /proc/stat中cpu数据10元组
private BigDecimal user, nice, system, idle, iowait, irq, softirq, stealstolen, guest, guest_nice;
public CpuInfoBean(StringTokenizer procStatFirstLine) {
procStatFirstLine.nextToken();
this.user = procStatFirstLine.hasMoreTokens() ? new BigDecimal(procStatFirstLine.nextToken()) : BigDecimal.ZERO;
this.nice = procStatFirstLine.hasMoreTokens() ? new BigDecimal(procStatFirstLine.nextToken()) : BigDecimal.ZERO;
this.system = procStatFirstLine.hasMoreTokens() ? new BigDecimal(procStatFirstLine.nextToken()) : BigDecimal.ZERO;
this.idle = procStatFirstLine.hasMoreTokens() ? new BigDecimal(procStatFirstLine.nextToken()) : BigDecimal.ZERO;
this.iowait = procStatFirstLine.hasMoreTokens() ? new BigDecimal(procStatFirstLine.nextToken()) : BigDecimal.ZERO;
this.irq = procStatFirstLine.hasMoreTokens() ? new BigDecimal(procStatFirstLine.nextToken()) : BigDecimal.ZERO;
this.softirq = procStatFirstLine.hasMoreTokens() ? new BigDecimal(procStatFirstLine.nextToken()) : BigDecimal.ZERO;
this.stealstolen = procStatFirstLine.hasMoreTokens() ? new BigDecimal(procStatFirstLine.nextToken()) : BigDecimal.ZERO;
this.guest = procStatFirstLine.hasMoreTokens() ? new BigDecimal(procStatFirstLine.nextToken()) : BigDecimal.ZERO;
this.guest_nice = procStatFirstLine.hasMoreTokens() ? new BigDecimal(procStatFirstLine.nextToken()) : BigDecimal.ZERO;
}
public BigDecimal getCpuTotal() {
return user.add(nice).add(system).add(idle).add(iowait).add(irq).add(softirq).add(stealstolen).add(guest).add(guest_nice);
}
}
2 问题
2.1 java使用Runtime.exec执行linux命令不成功问题
2.1.1 问题说明
获取cpu逻辑核数失败,命令为“cat /proc/cpuinfo | grep processor | wc -l”
2.1.2 问题原因
- 可能因为管道符“|”导致命令失败,具体不知,如有知道的博友欢迎留言回复。
- 博友回复:直接用exec执行,会导致该命令作为一个进程执行,无法查询结果。但是通过sh -c的方式以后,该命令通过管道符分解为3个子进程,分别执行"cat /proc/cpuinfo"、“grep processor”、“wc -l”,前面进程的结果通过管道作为下一个进程的输入,从而查询到了具体的结果。
2.1.3 解决方案
解决方式一(采用,有局限性):
用java自带工具实现Runtime.getRuntime().availableProcessors()
解决方式二:
命令参数改为数组
String[] command = {"sh", "-c", "cat /proc/cpuinfo | grep processor | wc -l"};
或 String[] command = { "/bin/sh", "-c", "cat /proc/cpuinfo | grep processor | wc -l"};
更多推荐
已为社区贡献1条内容
所有评论(0)