java执行shell并获取shell输出日志方式
作者:shy_snow
这篇文章主要介绍了java执行shell并获取shell输出日志方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
java执行shell并获取shell输出日志
获取shell输出日志需要java使用两个线程分别接受shell的标准输入流和错误流并打印出来
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; public class ShellLogRunTest { public static void main(String[] args) throws Exception, SecurityException { Process p = null; Runtime rt = Runtime.getRuntime(); String command = "cmd /c java -version"; command = "cmd /c ping 127.0.0.1 -n 3"; if (args != null && args.length > 0 && args[0] != null && args[0].trim().length() > 0) { command = args[0]; } try { p = rt.exec(command, null, null); // 获取进程的标准输入流 final InputStream is1 = p.getInputStream(); // 获取进城的错误流 final InputStream is2 = p.getErrorStream(); // 启动两个线程,一个线程负责读标准输出流,另一个负责读标准错误流 new Thread() { public void run() { BufferedReader br1 = new BufferedReader(new InputStreamReader(is1, Charset.forName("gb2312"))); // 这里要注意shell返回的类型,windows和linux可能不同 try { String line1 = null; while ((line1 = br1.readLine()) != null) { if (line1 != null) { System.out.println(line1); } } } catch (IOException e) { e.printStackTrace(); } finally { try { is1.close(); System.out.println("is1线程关闭"); } catch (IOException e) { e.printStackTrace(); } } } }.start(); new Thread() { public void run() { BufferedReader br2 = new BufferedReader(new InputStreamReader(is2, Charset.forName("gb2312"))); try { String line2 = null; while ((line2 = br2.readLine()) != null) { if (line2 != null) { System.out.println(line2); } } } catch (IOException e) { e.printStackTrace(); } finally { try { is2.close(); System.out.println("is2线程关闭"); } catch (IOException e) { e.printStackTrace(); } } } }.start(); p.waitFor(); p.destroy(); System.out.println("进程结束"); } catch (Exception e) { try { p.getErrorStream().close(); p.getInputStream().close(); p.getOutputStream().close(); } catch (Exception ee) { ee.printStackTrace(); } } } }
java执行shell命令(分批 多条 走一步看一步的执行)
说明
网上有很多通过java执行命令的程序,但是只能执行一条命令,或者是所有命令一次性执行完毕。
而我想要的是执行一条命令,看一看返回结果,然后在去执行下一条命令,可惜翻遍全网,竟然一个可行的方法都没有!!!
没办法,自己想办法解决吧。
实现代码
废话不多说,直接上代码:
入口类
import core.CmdClient; public class Main { public static void main(String[] args) { CmdClient client = new CmdClient(); client.run("cd /"); client.run("ls"); client.run("exit"); System.out.println("主线程结束"); } }
核心代码类:
这里就尽量不写的太复杂,把多线程直接的交互都给砍掉了。大家可以根据自己需求去修改。
package core; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; public class CmdClient { // 中文有乱码的可以试着改一下编码格式。 private static final Charset charset = StandardCharsets.UTF_8; // 初始化 public CmdClient() { try { /* Runtime.getRuntime().exec()方法本质和windows上的运行一样,只能执行一个命令来启动一个程序。 这里启动的是sh解释器,可以根据需要改成其他shell解释器。适用mac,linux系统。 对于windows,则是运行C:\Windows\System32\cmd.exe,同时执行的也不是shell命令,而是dos命令。 */ Process process = Runtime.getRuntime().exec("/bin/sh"); // 获取程序的输出流和输入流 inputStream = process.getInputStream(); errorStream = process.getErrorStream(); outputStream = process.getOutputStream(); /* 输出数据需要,若执行的命令没有输出结果,就会阻塞读取流的线程。 为了防止主线程被阻塞,所以声明新的线程专门盯着输出数据。 */ new Thread(this::ReadCmdOut).start(); new Thread(this::ReadCmdError).start(); } catch (IOException e) { throw new RuntimeException("cmd初始化异常", e); } System.out.println("控制台初始化完毕"); } private final InputStream inputStream; private final InputStream errorStream; private final OutputStream outputStream; // 运行命令 public void run(String cmd) { try { // 若执行某些命令出现异常,可以尝试更换 \n 为 \r 或 \n\r outputStream.write((cmd + "\n").getBytes(charset)); outputStream.flush(); } catch (Exception e) { throw new RuntimeException("命令执行错误:" + cmd, e); } } private void ReadCmdOut() { try { print(inputStream); } catch (Exception e) { throw new RuntimeException("获取输出流异常", e); } System.out.println("正常输出流结束"); } private void ReadCmdError() { try { print(errorStream); } catch (Exception e) { throw new RuntimeException("获取错误流异常", e); } System.out.println("异常输出流结束"); } /** * 这里直接把数据打印出来了,有其他需求的可以在这里写判来确定下一步来执行什么。 */ private void print(InputStream inputStream) throws IOException { byte[] bytes = new byte[1024]; int i; while (true) { i = inputStream.read(bytes); if (i == -1) break; System.out.print(new String(bytes, 0, i, charset)); } System.out.println(); } }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。