java执行shell并获取shell输出日志方式

 更新时间:2024年04月28日 14:39:08   作者: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();
    }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Spring Bean的线程安全问题

    Spring Bean的线程安全问题

    Spring容器中的Bean是否线程安全,本文主要介绍了Spring Bean的线程安全问题,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • springcloud中Ribbon和RestTemplate实现服务调用与负载均衡

    springcloud中Ribbon和RestTemplate实现服务调用与负载均衡

    这篇文章主要介绍了Ribbon和RestTemplate实现服务调用与负载均衡,想了解负载均衡的同学可以参考下
    2021-04-04
  • java全角、半角字符的关系以及转换详解

    java全角、半角字符的关系以及转换详解

    这篇文章主要介绍了
    2013-11-11
  • Java Web 简单的分页显示实例代码

    Java Web 简单的分页显示实例代码

    这篇文章主要介绍了Java Web 简单的分页显示实例代码的相关资料,本文通过,计算总的页数和查询指定页数据两个方法实现分页效果,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-06-06
  • 剑指Offer之Java算法习题精讲二叉树与链表

    剑指Offer之Java算法习题精讲二叉树与链表

    跟着思路走,之后从简单题入手,反复去看,做过之后可能会忘记,之后再做一次,记不住就反复做,反复寻求思路和规律,慢慢积累就会发现质的变化
    2022-03-03
  • Springboot hibernate envers使用过程详解

    Springboot hibernate envers使用过程详解

    这篇文章主要介绍了Springboot hibernate envers使用过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • Java WebService 简单实例(附实例代码)

    Java WebService 简单实例(附实例代码)

    本篇文章主要介绍了Java WebService 简单实例(附实例代码), Web Service 是一种新的web应用程序分支,他们是自包含、自描述、模块化的应用,可以发布、定位、通过web调用。有兴趣的可以了解一下
    2017-01-01
  • Java中system.exit(0) 和 system.exit(1)区别

    Java中system.exit(0) 和 system.exit(1)区别

    本文主要介绍了Java中system.exit(0) 和 system.exit(1)区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • java struts2框架简介

    java struts2框架简介

    本文主要介绍了java struts2框架的基础知识。具有一定的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • Mybatis-Plus中Mapper的接口文件与xml文件相关的坑记录

    Mybatis-Plus中Mapper的接口文件与xml文件相关的坑记录

    这篇文章主要介绍了Mybatis-Plus中Mapper的接口文件与xml文件相关的坑记录,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01

最新评论