调用Runtime.getRuntime().exec()执行Linux脚本防挂死和返回脚本输出

1、在实际开发中,使用Runtime.getRuntime().exec()执行Linux脚本时,需要同时读取标准输出流与错误输出流缓冲区数据,因为操作系统缓冲区大小有限制,不及时处理会导致缓冲区占满而挂住,这种问题发生在于开发人员对该接口不了解而引发Bug。

具体可以通过使用两个线程同时去读错误和标准输出流缓冲区数据,然后用proc.waitFor()可以获取执行的结果。这种事最常见的场景,只关注脚本执行结果。

2、但在实际开发中,通过Runtime.getRuntime().exec()执行Linux脚本时,不仅仅要关注脚本执行结果,同时还需要关注脚本执行返回的屏显信息,这个时候使用proc.waitFor()虽然能获取结果,但是屏显信息总是有时候有时候没有,是因为脚本执行完就有结果返回了,但是子线程读取缓冲区数据并不一定就执行完了,所以这种场景下,我们需要等待读取缓冲数据的脚本执行完后,再返回结果。

PS:这个是本人实际开发中遇到的一个问题,使用了父线程等待子线程的方式来实现的,能够解决问题,还有没有其他方式,需要进一步去尝试。

代码主要如下:

import java.util.ArrayList;
import java.util.List;

public class ExecuteScript
{

    public static void main(String[] args)
    {

        System.exit(ececute(args[0], true));

    }

    public static int ececute(String cmd, boolean isNeedPrint)
    {
        Process proc = null;
        int result = -1;
        try
        {
            List<StreamReader> list = new ArrayList<StreamReader>();
            proc = Runtime.getRuntime().exec(cmd);
            StreamReader error = new StreamReader(proc.getErrorStream(), "Error");
            StreamReader output = new StreamReader(proc.getInputStream(), "Output");

            if (isNeedPrint)
            {

                list.add(error);
                list.add(error);
            }

            error.start();
            output.start();
            if (isNeedPrint)
            {
                for (StreamReader sr : list)
                {
                    sr.join();
                }
            }
            result = proc.waitFor();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            proc.destroy();
        }

        return result;
    }

}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class StreamReader extends Thread
{

    InputStream is;

    String type;

    StreamReader(InputStream is, String type)
    {
        this.is = is;
        this.type = type;
    }

    public void run()
    {
        InputStreamReader isr = null;
        BufferedReader br = null;
        try
        {
            isr = new InputStreamReader(is);
            br = new BufferedReader(isr);
            String line = null;
            while ((line = br.readLine()) != null)
            {
                System.out.println(line);
            }
        }
        catch (IOException ioe)
        {
            ioe.printStackTrace();
        }
        finally
        {
            close(isr, br);
        }
    }

    public void close(InputStreamReader isr, BufferedReader br)
    {
        if (null != br)
        {
            try
            {
                br.close();
            }
            catch (IOException e)
            {
                br = null;
            }
        }

        if (null != isr)
        {
            try
            {
                isr.close();
            }
            catch (IOException e)
            {
                isr = null;
            }
        }
    }

}
时间: 2024-12-07 07:03:50

调用Runtime.getRuntime().exec()执行Linux脚本防挂死和返回脚本输出的相关文章

Runtime.getRuntime.exec()执行linux脚本导致程序卡死有关问题

Runtime.getRuntime.exec()执行linux脚本导致程序卡死问题问题: 在Java程序中,通过Runtime.getRuntime().exec()执行一个Linux脚本导致程序被挂住,而在终端上直接执行这个脚本则没有任何问题.原因: 先来看Java代码: public final static void process1(String[] cmdarray) {        Process p = null;        BufferedReader br = null

Java Runtime.getRuntime().exec 执行带空格命令解决办法

String command = OpenOffice_HOME + "program\\soffice -headless -accept=\"socket,host=127.0.0.1,port=8100;urp;\" -nofirststartwizard "; command = "cmd /c start "+command.replaceAll(" ","\" \""); P

通过Runtime.getRuntime().exec调用底层Linux下的程序或脚本

Android Runtime使得直接调用底层Linux下的可执行程序或脚本成为可能 比如Linux下写个测试工具,直接编译后apk中通过Runtime来调用 或者写个脚本,apk中直接调用,省去中间层或者JNI 这个至少效率应该比较高吧 代码: [java] view plaincopy public class test extends Activity { TextView text; /** Called when the activity is first created. */ @O

Android: 通过Runtime.getRuntime().exec调用底层Linux下的程序或脚本

Android Runtime使得直接调用底层Linux下的可执行程序或脚本成为可能 比如Linux下写个测试工具,直接编译后apk中通过Runtime来调用 或者写个脚本,apk中直接调用,省去中间层或者JNI 这个至少效率应该比较高吧 代码: [java] view plaincopy 1 public class test extends Activity { 2 TextView text; 3 4 /** Called when the activity is first create

使用Runtime.getRuntime().exec()在java中调用python脚本

举例有一个Python脚本叫test.py,现在想要在Java里调用这个脚本.假定这个test.py里面使用了拓展的包,使得pythoninterpreter之类内嵌的编译器无法使用,那么只能采用java调用控制台进程,即 Runtime.getRuntime().exec(),来运行这个python脚本. 在windows下运行这个程序,假如是参考了一些百度来的被转载了无数遍的文章,很有可能运行结果是根本没有执行这个脚本.经过测试,在java中执行如下代码可以成功运行test.py文件: --

Runtime.getRuntime().exec(cmd)执行adb shell脚本可能出现的问题

例如:adb shell sendevent /dev/input/event3 1 $((0xca)) 1上面语句中含有$((0xca)) ,执行Runtime.getRuntime().exec("sendevent /dev/input/event3 1 $((0xca)) 1"),不会报错,但也不会生效,解决办法为: (1)先将$((0xca))中的0xca的十六进制转换为十进制202,$((202)),再执行Runtime.getRuntime().exec("se

Runtime.getRuntime().exec()调用外部程序

场景:linux下,在web工程里调用一个C++程序,实现代码如下: StringBuffer cmd = new StringBuffer();cmd.append("nohup "); ……System.out.println("执行程序命令:"+cmd.toString());String[] cmds = { "/bin/sh", "-c", cmd.toString()};Runtime.getRuntime().e

【笔记】【Informatica】Java组件调用ssh客户端远程执行linux系统上的shell脚本

try{    String cmdStr="C:\\SSH\\ssh2.exe [email protected] /home/azik/tmp/echo_date.sh";    Process mypro=Runtime.getRuntime().exec(cmdStr);    mypro.waitFor();    Integer errno=mypro.exitValue();    logInfo("The errorlevel is :"+errno

Runtime.getRuntime().exec中命令含有括号问题

在写批量执行bat工具的时候,想起了之前写的定时小工具里面的执行方法. 使用Runtime.getRuntime().exec方法. Runtime.getRuntime().exec("cmd /c start c:/test.bat") 这样就可以像dos窗口直接执行命令行一样. getRuntime返回Runtime的实例化对象,exec方法是返回Process对象. 查看Process类可以发现: The ProcessBuilder.start() and Runtime.e