java执行linux命令查询信息
一、使用方式
方式1:只创建“读取标准输出流”
public Map<String, String> getHostnameAndSystem() {Map<String, String> map = new HashMap<>();InputStream in = null;BufferedReader read = null;Process pro = null;String cmd = "hostnamectl | awk -F': +' '/Static hostname|Operating System/ {printf \"%s,\", $2}' | sed 's/,$//'";String[] cmds = null;try {String result = getSingleResult(cmd, cmds, pro, in, read);logger.info("result:{}", result);String[] split = result.split(",");map.put("hostname", split[0]);map.put("os", split[1]);} catch (IOException | InterruptedException e) {logger.error("-getHostnameAndSystem-Exception:{}", e);return null;} finally {try {if (pro != null) {pro.destroy();}if (read != null) {read.close();}if (in != null) {in.close();}} catch (IOException e) {logger.error("-getHostnameAndSystem-finally-IOException:{}", e);}}return map;
}public static String getSingleResult(String cmd, String[] cmds, Process pro, InputStream in, BufferedReader read) throws IOException, InterruptedException {cmds = new String[]{"/bin/sh", "-c", cmd};logger.info("-cmd:{}", cmd);pro = Runtime.getRuntime().exec(cmds);if (pro.waitFor() == 0) {String line = "";in = pro.getInputStream();read = new BufferedReader(new InputStreamReader(in));while ((line = read.readLine()) != null) {logger.info("-line:{}", line);return line;}}return null;
}
方式2:创建“读取标准输出流”+“读取标准错误流”
public Map<String, String> getHostnameAndSystem() {String[] cmds = null;Process pro = null;InputStream in = null;BufferedReader read = null;String errorMessage = "";try {String cmd = "hostnamectl | awk -F': +' '/Static hostname|Operating System/ {printf \"%s,\", $2}' | sed 's/,$//'";getSingleResult(cmd, cmds, pro, in, read);} catch (Exception e) {e.printStackTrace();logger.error("-kerberosKeytabUpload-e:{}", e.getMessage());List<String> fileContent = null;try {fileContent = FileUtil.getFileContent(FILE_STORE_PATH + "verifyError.txt");} catch (Exception ex) {throw new RuntimeException(ex);}for (String line : fileContent) {errorMessage += line + " ";}}
}public static String getSingleResult(String cmd, String[] cmds, Process pro, InputStream in, BufferedReader read) throws IOException, InterruptedException {cmds = new String[]{"/bin/sh", "-c", cmd};logger.info("ldapPublicKeyUpload-cmd:{}", cmd);pro = Runtime.getRuntime().exec(cmds);int exitCode = pro.waitFor();try (BufferedReader stdInput = new BufferedReader(new InputStreamReader(pro.getInputStream()));BufferedReader stdError = new BufferedReader(new InputStreamReader(pro.getErrorStream()))) {StringBuilder output = new StringBuilder();String line;// 读取标准输出while ((line = stdInput.readLine()) != null) {logger.info("stdInput-line:{}", line);output.append(line).append("\n");}// 读取标准错误StringBuilder errorOutput = new StringBuilder();while ((line = stdError.readLine()) != null) {logger.info("stdError-line:{}", line);errorOutput.append(line).append("\n");}// 检查退出码if (exitCode == 0) {logger.info("Command success with exit exitCode :{}, output: {}", exitCode, output.toString());return output.toString();} else {logger.error("Command failed with exit exitCode :{}, errorOutput: {}", exitCode, errorOutput.toString());throw new IOException(errorOutput.toString());}}
}
二、注意点说明
注意点1
:这两种方式使用场景不一样
- 方式1,适用于查询CPU之类的直接返回结果。
- 方式2,适用于第三方下发命令,比如上传证书之类的,可能成功也可能失败,如果失败想捕获错误信息当接口返回值直接返回。
注意点2
:两种方式实现逻辑不一样,方式1 只是捕获line读取结果直接返回,这种方式可以正确获取想要的结果;但是方式2中line是可以打印到结果的,但是最终拼接output和errorOutput最后值都是空,发现无法拼接进去值,比如如图line打印出来值了,但是最后打印的output和errorOutput都是空白。
问题:如果碰到这样该怎么办呢?
答案
:把错误信息写入到文件中,然后在读取出来,封装返回对象中接口返回。
举例
/**
* Upload ldap public Key* @param multipartFile multipartFile* @param request request* @param id id* @return 结果*/
@ResponseBody
@SuppressWarnings("deprecation")
@RequestMapping("ldapPublicKeyUpload")
public ResultSet ldapPublicKeyUpload(@RequestParam("ldapPublicKeyFile") MultipartFile multipartFile, HttpServletRequest request, @RequestParam("id") Integer id) {logger.info("-ldapPublicKeyUpload-id:{}", id);ResultSet resultSet = new ResultSet();String[] cmds = null;Process pro = null;InputStream in = null;BufferedReader read = null;String errorMessage = "";String FILE_STORE_PATH = "/home/ems/ems_file/ldap/ldapServerConfig/";String imgName = "ldap_keystore.cer";try {if (multipartFile.isEmpty() || multipartFile.getSize() == 0L) {resultSet.setErrorCode(LteResultCodeEnum.FILE_CONTENT_EMPTY.getErrorCode());resultSet.setErrorString(MessageAccessor.getMessage(LteResultCodeEnum.FILE_CONTENT_EMPTY.getErrorCode()));return resultSet;}String originalFilename = multipartFile.getOriginalFilename();File file = new File(FILE_STORE_PATH + "ldap_keystore.jks");String password = new String(Base64.getDecoder().decode(LdapConstants.KEYSTORE_PASSWORD));if (file.exists()) {String cmd = "/home/ems/3rdparty/java/bin/keytool -delete -alias ad-server-cert " + " -keystore " + FILE_STORE_PATH + imgName.split("\\.")[0] + ".jks -storepass " + password;getSingleResult(cmd, cmds, pro, in, read);boolean delete = file.delete();logger.info("execute delete jks file result:{}", delete);}file = new File(FILE_STORE_PATH + originalFilename);if (!file.getParentFile().exists()) {logger.info("Creating directory: " + file.getParentFile());file.getParentFile().mkdirs(); // 递归创建父目录}multipartFile.transferTo(file);if (!originalFilename.toLowerCase().endsWith(".jks")) {String cmd = "/home/ems/3rdparty/java/bin/keytool -import -noprompt -alias ad-server-cert -file " + FILE_STORE_PATH + originalFilename + " -keystore " + FILE_STORE_PATH + imgName.split("\\.")[0] + ".jks -storepass " + password + " > " + FILE_STORE_PATH + "verifyError.txt";String result = getSingleResult(cmd, cmds, pro, in, read);logger.info("-ldapPublicKeyUpload-result:{}", result);if (result != null) {return new ResultSet(originalFilename);}}} catch (Exception e) {e.printStackTrace();logger.error("-kerberosKeytabUpload-e:{}", e.getMessage());List<String> fileContent = null;try {fileContent = FileUtil.getFileContent(FILE_STORE_PATH + "verifyError.txt");} catch (Exception ex) {throw new RuntimeException(ex);}for (String line : fileContent) {errorMessage += line + " ";}}if (errorMessage.contains("Input not an X.509 certificate")) {return new ResultSet(new LteException(LteResultCodeEnum.INPUT_NOT_AN_X509_CERTIFICATE.getErrorCode()));} else {return new ResultSet(new LteException(LteResultCodeEnum.UPLOAD_FILE_FAILED.getErrorCode()));}
}public static String getSingleResult(String cmd, String[] cmds, Process pro, InputStream in, BufferedReader read) throws IOException, InterruptedException {cmds = new String[]{"/bin/sh", "-c", cmd};logger.info("ldapPublicKeyUpload-cmd:{}", cmd);pro = Runtime.getRuntime().exec(cmds);int exitCode = pro.waitFor();try (BufferedReader stdInput = new BufferedReader(new InputStreamReader(pro.getInputStream()));BufferedReader stdError = new BufferedReader(new InputStreamReader(pro.getErrorStream()))) {StringBuilder output = new StringBuilder();String line;// 读取标准输出while ((line = stdInput.readLine()) != null) {logger.info("stdInput-line:{}", line);output.append(line).append("\n");}// 读取标准错误StringBuilder errorOutput = new StringBuilder();while ((line = stdError.readLine()) != null) {logger.info("stdError-line:{}", line);errorOutput.append(line).append("\n");}// 检查退出码if (exitCode == 0) {logger.info("Command success with exit exitCode :{}, output: {}", exitCode, output.toString());return output.toString();} else {logger.error("Command failed with exit exitCode :{}, errorOutput: {}", exitCode, errorOutput.toString());throw new IOException(errorOutput.toString());}}
}