`

JAVA调用Shell脚本--及阻塞的解决办法

    博客分类:
  • JAVA
阅读更多

用java调用shell,使用

Process p=Runtime.getRuntime().exec(String[] cmd);

Runtime.exec方法将产生一个本地的进程,并返回一个Process子类的实例,该实例可用于控制进程或取得进程的相关信息。
由于调用Runtime.exec方法所创建的子进程没有自己的终端或控制台,因此该子进程的标准IO(如stdin,stdou,stderr)都通过
    p.getOutputStream(),
    p.getInputStream(),
    p.getErrorStream()
方法重定向给它的父进程了.用户需要用这些stream来向 子进程输入数据或获取子进程的输出。
    
    例如:Runtime.getRuntime().exec("ls")


另外需要关心的是Runtime.getRuntime().exec()中产生停滞(阻塞,blocking)的问题?


    这个是因为Runtime.getRuntime().exec()要自己去处理stdout和stderr的输出,
    就是说,执行的结果不知道是现有错误输出(stderr),还是现有标准输出(stdout)。
    你无法判断到底那个先输出,所以可能无法读取输出,而一直阻塞。
    例如:你先处理标准输出(stdout),但是处理的结果是先有错误输出(stderr),
    一直在等错误输出(stderr)被取走了,才到标准输出(stdout),这样就产生了阻塞。

解决办法:


    用两个线程将标准输出(stdout)和错误输出(stderr)。

 

参考代码:

 

import java.util.*;
import java.io.*;
class StreamGobbler extends Thread
{
    InputStream is;
    String type;
    
    StreamGobbler(InputStream is, String type)
    {
        this.is = is;
        this.type = type;
    }
    
    public void run()
    {
        try
        {
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line=null;
            while ( (line = br.readLine()) != null)
                System.out.println(type + ">" + line);    
            } catch (IOException ioe)
              {
                ioe.printStackTrace();  
              }
    }
}
public class ExecRunner
{
    public static void main(String args[])
    {
        if (args.length < 1)
        {
            System.out.println("USAGE: java GoodWindowsExec <cmd>");
            System.exit(1);
        }
        
        try
        {            
            String osName = System.getProperty("os.name" );
            String[] cmd = new String[3];
            if( osName.equals( "Windows NT" ) )
            {
                cmd[0] = "cmd.exe" ;
                cmd[1] = "/C" ;
                cmd[2] = args[0];
            }
            else if( osName.equals( "Windows 95" ) )
            {
                cmd[0] = "command.com" ;
                cmd[1] = "/C" ;
                cmd[2] = args[0];
            } else {
            	StringTokenizer st = new StringTokenizer(command, " ");
	            cmd = new String[st.countTokens()];
	            int token = 0;
	            while (st.hasMoreTokens()) {
	                String tokenString = st.nextToken();
	                // System.out.println(tokenString);
	                cmd[token++] = tokenString;
	            }
            }
            
            Runtime rt = Runtime.getRuntime();
            System.out.println("Execing " + cmd[0] + " " + cmd[1] 
                               + " " + cmd[2]);
            Process proc = rt.exec(cmd);
            // any error message?
            StreamGobbler errorGobbler = new 
                StreamGobbler(proc.getErrorStream(), "ERROR");            
            
            // any output?
            StreamGobbler outputGobbler = new 
                StreamGobbler(proc.getInputStream(), "OUTPUT");
                
            // kick them off
            errorGobbler.start();
            outputGobbler.start();
                                    
            // any error???
            int exitVal = proc.waitFor();
            System.out.println("ExitValue: " + exitVal);        
        } catch (Throwable t)
          {
            t.printStackTrace();
          }
    }
}
 

 

 

 

 

 

参考文章:

 

When Runtime.exec() won't

Navigate yourself around pitfalls related to the Runtime.exec() method

 

http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=4

 

 



1
1
分享到:
评论
1 楼 young7 2014-08-28  
不错,特别是那个参考文章

相关推荐

    java调用shell脚本完美封装

    在Java编程中,有时我们需要与操作系统进行交互,执行一些系统级别的任务,比如自动化运维、文件管理等,这时就可能需要用到调用Shell脚本。本文将详细介绍如何在Java中完美封装shell脚本的调用方法,并提供相关的...

    Java调用shell脚本

    下面我们将详细探讨如何在Java中调用shell脚本以及涉及到的相关知识点。 首先,Java调用shell脚本主要通过`Runtime`类或`ProcessBuilder`类来实现。`Runtime.getRuntime().exec()`方法允许我们执行系统命令,而`...

    java调用shell

    本文将深入探讨如何在Java程序中调用Shell脚本,理解其背后的原理,并提供一系列实用代码示例与应用场景。 ### Java调用Shell的基本原理 Java调用Shell主要依赖于`java.lang.Runtime`类中的`exec()`方法。这个方法...

    Java调用linux shell脚本的方法

    首先,调用shell脚本的基本过程分为以下几个步骤: 1. **设置脚本执行权限**:在Linux系统中,执行一个文件(如shell脚本)需要有相应的执行权限。在Java中,我们可以通过`Runtime.getRuntime().exec()`方法来执行...

    Java代码中调用shell脚本和python脚本并获得输出结果(分为小数据量和大数据量).docx

    ### Java调用Shell脚本和Python脚本及处理输出结果详解 #### 一、引言 在实际开发过程中,我们经常需要在Java程序中调用Shell脚本或Python脚本来执行一些特定的任务,比如系统管理任务、数据分析等。Java通过`java...

    java运行shell脚本方法示例

    在Java编程中,有时我们需要在程序中执行操作系统级别的任务,比如运行Linux的Shell脚本。这时,我们可以利用Java内置的`Runtime`类的`execute`方法来实现这一目标。本文将详细讲解如何在Java中使用`Runtime.execute...

    java在win下启动bat和在linux下启动shell脚本

    在Windows和Linux环境中,启动批处理脚本(bat)和shell脚本(sh)是常见的任务,特别是在自动化和脚本执行过程中。`RunScript.java`和`StreamGobbler.java`这两个文件可能就是用来实现这个功能的。 `RunScript....

    利用Python+Java调用Shell脚本时的死锁陷阱详解

    本文将详细探讨如何使用Python和Java调用Shell脚本,并着重讲解在调用过程中可能出现的死锁问题及其解决策略。 首先,Python提供了`subprocess`库来执行外部命令,包括Shell脚本。在Python 3.5之后,`subprocess....

    shell 脚本编程 - v1.11

    【Shell脚本编程 - v1.11】教程主要针对初学者,旨在引导读者逐步掌握Linux Shell编程。Shell是Linux操作系统中的用户界面,它作为用户与操作系统内核之间的桥梁,接收用户输入的命令并负责执行。这个教程适用于已经...

    Shell 脚本实现多线程的代码

    在IT领域,Shell脚本是Linux/Unix系统中常用的一种自动化任务执行工具。它基于Bash或其他Shell环境,能够编写一系列命令,实现批量处理、定时任务等。在标题"Shell 脚本实现多线程的代码"中,我们关注的重点是如何在...

    c 程序实现shell 脚本

    在IT领域,C语言是一种强大的低级编程语言,而Shell脚本则是Unix/Linux系统中用于自动化任务的高级脚本语言。本项目旨在通过C程序来模拟实现Shell脚本中的核心功能,包括管道(pipe)、重定向(redirection)、信号...

    使用python执行shell脚本 并动态传参 及subprocess的使用详解

    本文将深入探讨如何使用Python执行shell脚本、动态传递参数以及`subprocess`模块的详细使用。 首先,`subprocess`模块是Python提供的一种用于生成新的进程、连接到它们的输入/输出/错误管道以及获取它们的返回码的...

    Linux下启动和停止jar包运行的脚本

    本文将深入解析如何利用shell脚本来控制Java应用程序的启动和停止,基于提供的“startTest.sh”和“stopTest.sh”脚本,详细阐述其工作原理及关键知识点。 ### 启动脚本(startTest.sh) #### 脚本详解 ```sh #!/...

    java代码中调用linux/unix命令

    有时,单个命令无法满足需求,这时可以编写Shell脚本,然后通过Java调用。例如,使用`bash -c "your_script.sh"`来执行脚本。 在实际开发中,结合Java和Linux/Unix命令可以极大地提高工作效率,尤其是在系统管理和...

    Java 执行本地脚本携带多参数

    在Java编程中,有时我们需要执行本地的脚本文件,并且可能需要传递多个参数给这些脚本。这在处理自动化任务、系统集成或者调用外部工具时非常常见。本篇文章将详细探讨如何在Java中实现这一功能,同时也会涉及到源码...

    Java开发的SHELL CRaSH

    Java开发的SHELL CRaSH是指在Java编程环境中,开发者可能会遇到的一种运行时错误或异常情况,通常与命令行交互、脚本执行或者系统资源管理有关。在这个话题中,我们将深入探讨Java如何与Shell交互,可能导致CRaSH的...

    shell变量与创建子shell详解

    后台命令不会阻塞Shell脚本的执行,脚本会继续执行后续的命令而不必等待该命令完成。例如,使用"&"符号让一个无限循环的程序在后台执行,脚本会立即打印后续的消息。 第三种方法是使用 "exec" 命令执行程序。使用 ...

    shell脚本常见操作.pdf

    ### Shell脚本常见操作详解 #### 一、文件与目录操作 **1. 创建文件** - **命令**: `touch filename` - **说明**: 使用`touch`命令可以创建一个空文件或更新现有文件的时间戳。 **2. 复制文件** - **命令**: `...

Global site tag (gtag.js) - Google Analytics