获取系统序列号在Java中并不是一个直接支持的功能,因为Java语言本身并不提供直接访问硬件级别的信息,如CPU序列号。但是,我们可以使用一些平台特定的工具或命令来实现这一功能。下面我将展示如何使用Java获取Windows和Linux系统上的CPU序列号、磁盘、mac地址等信息,及使用Runtime.getRuntime().exec执行linux命令没反应问题解决。
需要确保你的系统上安装了wmic工具。
/**
* 获取cpu序列号
*
* @return 序列号
*/
public static String getCPUSerialNumber() {
String sysName = System.getProperty("os.name");
if (sysName.contains("Windows")) {//win
String str = runCmd("wmic cpu get ProcessorId", 3);
return str;
} else if (sysName.contains("Linux")) {
String str = runCmd("dmidecode |grep -A16 \"Processor Information$\"", "ID");
if (str != null) {
return str.substring(str.indexOf(":")).trim();
}
} else if (sysName.contains("Mac")) {
String str = runCmd("system_profiler SPHardwareDataType", "Serial Number");
if (str != null) {
return str.substring(str.indexOf(":") + 1).trim();
}
}
return "";
}
/**
* 获取硬盘序列号
*
* @return 硬盘序列号
*/
public static String getHardDiskSerialNumber() {
String sysName = System.getProperty("os.name");
if (sysName.contains("Windows")) {//win
String str = runCmd("wmic path win32_physicalmedia get serialnumber", 3);
return str;
} else if (sysName.contains("Linux")) {
String str = runCmd("dmidecode |grep -A16 \"System Information$\"", "Serial Number");
if (str != null) {
return str.substring(str.indexOf(":")).trim();
}
} else if (sysName.contains("Mac")) {
String str = runCmd("system_profiler SPStorageDataType", "Volume UUID");
if (str != null) {
return str.substring(str.indexOf(":") + 1).trim();
}
}
return "";
}
/**
* 运行命令
*
* @param cmd 命令
* @param line 返回第几行结果,0返回所有
* @return 结果
*/
public static String runCmd(String cmd, int line) {
Process process;
Scanner sc = null;
StringBuffer sb = new StringBuffer();
try {
process = Runtime.getRuntime().exec(cmd);
process.getOutputStream().close();
sc = new Scanner(process.getInputStream());
int i = 0;
while (sc.hasNextLine()) {
i++;
String str = sc.nextLine();
if (line <= 0) {
sb.append(str).append("\r\n");
} else if (i == line) {
return str.trim();
}
}
sc.close();
} catch (Exception e) {
} finally {
IoUtils.close(sc);
}
return sb.toString();
}
/**
* 运行cmd命令
*
* @param cmd 命令
* @param substr 关键字
* @return 包含关键字的行数
*/
public static String runCmd(String cmd, String substr) {
Process process;
Scanner sc = null;
try {
//ProcessBuilder 类提供了一种更灵活的方式来构建和执行外部进程。与 Runtime.exec() 相比,ProcessBuilder 允许你更细致地控制进程的执行环境。
// ProcessBuilder pb = new ProcessBuilder(new String[]{"/bin/sh", "-c", cmd});
// process = pb.start();
//Runtime.getRuntime().exec(String cmd) 方法在 Java 中用于执行外部命令。
process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", cmd});
// process = Runtime.getRuntime().exec(cmd);
process.getOutputStream().close();
sc = new Scanner(process.getInputStream());
while (sc.hasNextLine()) {
String str = sc.nextLine();
if (str != null && str.contains(substr)) {
return str.trim();
}
}
sc.close();
} catch (Exception e) {
} finally {
IoUtils.close(sc);
}
return null;
}
/**
* 获取mac地址
*
* @return mac 列表
*/
public static List<String> getMacList() {
ArrayList<String> list = new ArrayList<>();
StringBuilder sb = new StringBuilder();
try {
java.util.Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
while (en.hasMoreElements()) {
NetworkInterface iface = en.nextElement();
List<InterfaceAddress> addrs = iface.getInterfaceAddresses();
for (InterfaceAddress addr : addrs) {
InetAddress ip = addr.getAddress();
if (ip.isLinkLocalAddress()) {//本地的不要
continue;
}
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
if (network == null) {
continue;
}
byte[] mac = network.getHardwareAddress();
if (mac == null) {
continue;
}
sb.delete(0, sb.length());
for (int i = 0; i < mac.length; i++) {
sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
}
if (!list.contains(sb.toString())) {
list.add(sb.toString());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
process = Runtime.getRuntime().exec(cmd);
使用 Runtime.getRuntime().exec(String cmd) 时,Java 会尝试使用系统的默认 shell(例如 bash、sh、cmd 等)来执行该命令。因此,你可能会遇到一些与 shell 的语法和解析有关的问题,特别是在处理空格、管道符等特殊字符时。
方法一:ProcessBuilder 是一个更现代和灵活的方法,用于构建和执行外部进程。它提供了更多的控制选项,可以更好地处理参数和特殊字符。
ProcessBuilder pb = new ProcessBuilder("yourCommand", "arg1", "arg2");
Process p = pb.start();
方法二:将命令字符串分解为字符串数组,并将它们传递给 exec 方法。这样可以确保每个参数都被正确处理,而不会被视为命令的一部分。
process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", cmd});
白雪却嫌春色晚,故穿庭树作飞花-c表示cmd是一条命令,从而不会被截断