pom.xml jar 包支持
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.53</version>
</dependency>
注意点:不同版本的Linux 执行的命令返回的数据是不一样的 具体问题还得具体分析
package com.learn.service;
import com.jcraft.jsch.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
/**
* 远程调用Linux shell 命令
* @author yuyihao 2019.10.12
*/
public class LinuxStateForShell {
public static final String CPU_MEM_SHELL = "top -b -n 1"; // liunx 命令用戶獲取系統信息
public static final String FILES_SHELL = "df -hl"; // 查看磁盘占用情况
public static final String[] COMMANDS = {CPU_MEM_SHELL, FILES_SHELL}; // 命令數組
/**
* 在java中存在一些转义字符,比如"\n"为换行符, JDK自带的一些操作符 System.getProperty("line.separator");
* 这也是换行符,功能和"\n"是一致的,用此方法能区分 Windows和Linux环境的换行。
* 开发中与不是同一个环境,可以用 System.getProperty("line.separator"); 来控制换行
*/
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
private static Session session;
/**
* 连接到指定的HOST
* @return isConnect
* @throws JSchException JSchException
*/
private static boolean connect(String user, String passwd, String host) {
JSch jsch = new JSch();
try {
session = jsch.getSession(user, host, 22);
session.setPassword(passwd);
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
} catch (JSchException e) {
e.printStackTrace();
System.out.println("connect error !");
return false;
}
return true;
}
/**
* 远程连接Linux 服务器 执行相关的命令
* @param commands 执行的脚本
* @param user 远程连接的用户名
* @param passwd 远程连接的密码
* @param host 远程连接的主机IP
* @return 最终命令返回信息
*/
public static Map<String, String> runDistanceShell(String[] commands, String user, String passwd, String host) throws IOException {
if (!connect(user, passwd, host)) {
return null;
}
Map<String, String> map = new HashMap<>();
StringBuilder stringBuffer;
BufferedReader reader = null;
Channel channel = null;
try {
for (String command : commands) {
stringBuffer = new StringBuilder();
channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
channel.setInputStream(null);
((ChannelExec) channel).setErrStream(System.err);
channel.connect();
InputStream in = channel.getInputStream();
reader = new BufferedReader(new InputStreamReader(in));
String buf;
while ((buf = reader.readLine()) != null) {
//舍弃PID 进程信息
if (buf.contains("PID")) {
break;
}
stringBuffer.append(buf.trim()).append(LINE_SEPARATOR);
}
//每个命令存储自己返回数据-用于后续对返回数据进行处理
map.put(command, stringBuffer.toString());
}
} catch (IOException | JSchException e) {
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if (channel != null) {
channel.disconnect();
}
session.disconnect();
}
return map;
}
/**
* 处理 shell 返回的信息
* 具体处理过程以服务器返回数据格式为准
* 不同的Linux 版本返回信息格式不同
* @param result shell 返回的信息
* @return 最终处理后的信息
*/
private static String disposeResultMessage(Map<String, String> result) {
StringBuilder buffer = new StringBuilder();
for (String command : COMMANDS) {
String commandResult = result.get(command);
if (null == commandResult) continue;
if (command.equals(CPU_MEM_SHELL)) {
String[] strings = commandResult.split(LINE_SEPARATOR);
//将返回结果按换行符分割
for (String line : strings) {
line = line.toUpperCase();//转大写处理
//处理CPU Cpu(s): 10.8%us, 0.9%sy, 0.0%ni, 87.6%id, 0.7%wa, 0.0%hi, 0.0%si, 0.0%st
if (line.startsWith("CPU(S):")) { //有的不带% 有的带- 此处是不带的系统
String cpuStr = "CPU 用户使用占有率:";
try {
cpuStr += line.split(":")[1].split(",")[0].replace("US", "");
} catch (Exception e) {
e.printStackTrace();
cpuStr += "计算过程出错";
}
buffer.append(cpuStr).append(LINE_SEPARATOR);
//处理内存 Mem: 66100704k total, 65323404k used, 777300k free, 89940k buffers
} else if (line.startsWith("MEM")) {
String memStr = "内存使用情况:";
try {
memStr += line.split(":")[1]
.replace("TOTAL", "总计")
.replace("USED", "已使用")
.replace("FREE", "空闲")
.replace("BUFFERS", "缓存");
} catch (Exception e) {
e.printStackTrace();
memStr += "计算过程出错";
buffer.append(memStr).append(LINE_SEPARATOR);
continue;
}
buffer.append(memStr).append(LINE_SEPARATOR);
}
}
} else if (command.equals(FILES_SHELL)) {
//处理系统磁盘状态
buffer.append("系统磁盘状态:");
try {
buffer.append(disposeFilesSystem(commandResult)).append(LINE_SEPARATOR);
} catch (Exception e) {
e.printStackTrace();
buffer.append("计算过程出错").append(LINE_SEPARATOR);
}
}
}
return buffer.toString();
}
//处理系统磁盘状态
/**
* @param commandResult 处理系统磁盘状态shell执行结果
* @return 处理后的结果
*/
/**
* 最终处理的结果
* CPU 用户使用占有率: 0.2%
* 内存使用情况: 1020344K 总计, 160248K 已使用, 860096K 空闲, 14176K 缓存
* 系统磁盘状态:大小 7.66G , 已使用2.93G ,空闲4.73G
*/
private static String disposeFilesSystem(String commandResult) {
String[] strings = commandResult.split(LINE_SEPARATOR);
// final String PATTERN_TEMPLATE = "([a-zA-Z0-9%_/]*)\\s";
Double size = 0d;
Double used = 0d;
for (int i = 1; i < strings.length; i++) {//第一行 标题不需要
String[] row = strings[i].split("\\s+");
size += disposeUnit(row[1]); // 第二列 size
used += disposeUnit(row[2]); // 第三列 used
}
return new StringBuilder().append("大小 ").append(Math.round(size * 100)/100d).append("G , 已使用").append(Math.round(used * 100)/100d).append("G ,空闲")
.append(Math.round((size - used) * 100)/100d).append("G").toString();
}
/**
* 处理单位转换
* K/KB/M/T 最终转换为G 处理
* @param s 带单位的数据字符串
* @return 以G 为单位处理后的数值
*/
private static Double disposeUnit(String s) {
try {
s = s.toUpperCase();
String lastIndex = s.substring(s.length() - 1);
String num = s.substring(0, s.length() - 1);
Double parseInt = Double.parseDouble(num);
if (lastIndex.equals("G")) {
return parseInt;
} else if (lastIndex.equals("T")) {
return parseInt * 1024;
} else if (lastIndex.equals("M")) {
return parseInt / 1024;
} else if (lastIndex.equals("K") || lastIndex.equals("KB")) {
return parseInt / (1024 * 1024);
}
} catch (NumberFormatException e) {
e.printStackTrace();
return 0d;
}
return 0d;
}
public static void main(String[] args) throws IOException {
Map<String, String> result = runDistanceShell(COMMANDS, "root", "root123", "192.168.56.101");
System.out.println(disposeResultMessage(result));
}
}