纯Java原生代码 实现获取Linux 包括 CPU 内存 硬盘 等系统信息
2019-10-18
阅读 {{counts.readCount}}
评论 {{counts.commentCount}}
## 需求
通过java接口实现简单的linux系统实时监控,
希望尽可能不增加系统算力和内存负担的基础上,
获取到系统信息,方便前端用图表来显示系统情况
## 代码实现
说明:为减少查询本身带来的消耗,基本用java和linux原生语法,没用第三方依赖,代码中的唯一依赖的`StringUtils`,只是做非空判断
例如
```java
if (StringUtils.isNotBlank(string)) {
}
// 等价于
if (string != null && !"".equals(string)) {
}
```
`LinuxUtils.java`
```java
import org.apache.commons.lang.StringUtils;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class LinuxUtils {
/**
* java执行linux命令
*/
public String exec(String cmd) {
try {
String[] cmdA = {"/bin/sh", "-c", cmd};
Process process = Runtime.getRuntime().exec(cmdA);
LineNumberReader br = new LineNumberReader(new InputStreamReader(
process.getInputStream()));
StringBuffer sb = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 格式化linux返回
* 返回一个二维数组
*/
public List<List<String>> format(String string) {
List<List<String>> result = new ArrayList<>();
if (StringUtils.isNotBlank(string)) {
String[] lines = string.split("\n");
for (String line : lines) {
String[] strings = line.split(" ");
List<String> temp = new ArrayList<>();
for (String str : strings) {
if (StringUtils.isNotBlank(str)) {
temp.add(str);
}
}
result.add(temp);
}
}
return result;
}
/**
* 获取linux下 系统盘使用情况
*/
public Map<String, Object> getDeskInfo() {
Map<String, Object> result = new HashMap<>();
try {
String info = exec("df");
List<List<String>> lists = format(info);
for (List<String> list : lists) {
if (list.size() >= 6 && "/".equals(list.get(5))) {
for (int i = 0; i < list.size(); i++) {
// 文件系统名称
result.put("diskName", list.get(0));
// 总空间
result.put("total", list.get(1));
// 已用
result.put("used", list.get(2));
// 可用
result.put("free", list.get(3));
// 百分比
result.put("useRate", list.get(4));
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 获取linux下 内存使用情况
* mem 为内存
* swap为交换区
*/
public Map<String, Object> getRamInfo() {
Map<String, Object> result = new HashMap<>();
try {
String info = exec("free");
List<List<String>> lists = format(info);
for (List<String> list : lists) {
if (StringUtils.isNotBlank(list.get(0)) && list.get(0).toLowerCase().contains("mem")) {
Map<String, Object> mem = new HashMap<>();
mem.put("total", list.get(1));
mem.put("used", list.get(2));
mem.put("free", list.get(3));
mem.put("shared", list.get(4));
mem.put("cache", list.get(5));
mem.put("available", list.get(6));
result.put("mem", mem);
} else if (StringUtils.isNotBlank(list.get(0)) && list.get(0).toLowerCase().contains("swap")) {
Map<String, Object> swap = new HashMap<>();
swap.put("total", list.get(1));
swap.put("used", list.get(2));
swap.put("free", list.get(3));
result.put("swap", swap);
}
}
} catch (
Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 获取linux下 CPU使用情况 (使用top -b -n 1 实现,亲测不是十分准确,暂未使用)
*/
public Map<String, Object> getCPUInfoByTop() {
Map<String, Object> result = new HashMap<>();
try {
String info = exec("top -b -n 1 | sed -n '3p'");
String[] strings = info.split(":")[1].split(",");
for (String string : strings) {
if (StringUtils.isNotBlank(string) && string.toLowerCase().contains("id")) {
String free = string.replace("id", "").trim();
result.put("free", free);
String used = String.valueOf((10000 - Double.parseDouble(free) * 100) / 100);
result.put("used", used);
}
}
} catch (
Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 获取linux下 CPU使用情况 通过采集两次/proc/stat 计算CPU差值对比实现
* 参考:
* https://www.cnblogs.com/shihaiming/p/7048264.html
* https://www.cnblogs.com/gisblogs/p/3985393.html
*/
public Map<String, Object> getCPUInfo() {
Map<String, Object> result = new HashMap<>();
try {
String info = exec("cat /proc/stat");
List<String> cpu1 = format(info).get(0);
// 间隔时间 推荐设置在 200 - 5000 毫秒之间 (小了不准 大了太慢)
Thread.sleep(200);
info = exec("cat /proc/stat");
List<String> cpu2 = format(info).get(0);
// 用初中数学优化了一下网上的算法
float total = Float.parseFloat(cpu2.get(1)) - Float.parseFloat(cpu1.get(1)) +
Float.parseFloat(cpu2.get(2)) - Float.parseFloat(cpu1.get(2)) +
Float.parseFloat(cpu2.get(3)) - Float.parseFloat(cpu1.get(3));
float totalidle = total + Float.parseFloat(cpu2.get(4)) - Float.parseFloat(cpu1.get(4));
float useRate = (total / totalidle) * 100;
result.put("useRate", useRate);
} catch (
Exception e) {
e.printStackTrace();
}
return result;
}
public static void main(String[] args) {
long time = System.currentTimeMillis();
LinuxUtils linuxUtils = new LinuxUtils();
System.out.println(linuxUtils.getDeskInfo());
System.out.println(linuxUtils.getRamInfo());
System.out.println(linuxUtils.getCPUInfo());
System.out.println("消耗时间:" + (System.currentTimeMillis() - time) / 1000.0 + "秒");
}
}
```
### 运行结果
```shell
{diskName=/dev/nvme0n1p5, total=105306896, used=44633952, useRate=45%, free=55280560}
{mem={shared=120712, total=3950000, cache=639268, available=809536, used=2774656, free=536076}, swap={total=8388604, used=3328976, free=5059628}}
{useRate=70.0}
消耗时间:0.277秒
```