`

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调用linux shell脚本的方法

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

    java运行shell脚本方法示例

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

    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提供的一种用于生成新的进程、连接到它们的输入/输出/错误管道以及获取它们的返回码的...

    java代码中调用linux/unix命令

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

    java_dos_shell_bat

    在处理系统级任务时,Java可以利用特定的功能来执行DOS命令、Shell脚本以及BAT(批处理)文件。这些功能允许开发者在Java程序中调用操作系统提供的功能,从而实现自动化任务或者与系统进行更深度的交互。 首先,...

    java开源包1

    github-java-api 是 Github 网站 API 的 Java 语言版本。 java缓存工具 SimpleCache SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对...

    java开源包10

    github-java-api 是 Github 网站 API 的 Java 语言版本。 java缓存工具 SimpleCache SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对...

    shell编程大全

    在本文中,我们将深入探讨Shell编程的核心概念,常用命令,以及如何编写高效的Shell脚本。 1. **Shell基础** - Shell的定义:Shell是操作系统提供的一个用户界面,它接收用户的命令并执行相应的系统操作。 - 常见...

    JAVA上百实例源码以及开源项目

    Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字  Java波浪文字,一个利用Java处理字符的实例,可以设置运动方向参数,显示文本的字符数组,高速文本颜色,显示字体的 FontMetrics对象...

    JAVA上百实例源码以及开源项目源代码

    Java 源码包 Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来...

    shell编程入门.doc

    1. **脚本开头**:在编写Shell脚本时,文件的第一行必须是`#!/bin/bash`,这个称为Shebang,用于告诉系统使用哪个解释器来执行脚本。 2. **执行权限**:为了让脚本可执行,需要使用`chmod +x filename`命令添加执行...

    java开源包4

    github-java-api 是 Github 网站 API 的 Java 语言版本。 java缓存工具 SimpleCache SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对...

    java开源包6

    github-java-api 是 Github 网站 API 的 Java 语言版本。 java缓存工具 SimpleCache SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对...

    java开源包101

    github-java-api 是 Github 网站 API 的 Java 语言版本。 java缓存工具 SimpleCache SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对...

    java开源包9

    github-java-api 是 Github 网站 API 的 Java 语言版本。 java缓存工具 SimpleCache SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对...

    java开源包5

    github-java-api 是 Github 网站 API 的 Java 语言版本。 java缓存工具 SimpleCache SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对...

    java开源包8

    github-java-api 是 Github 网站 API 的 Java 语言版本。 java缓存工具 SimpleCache SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对...

Global site tag (gtag.js) - Google Analytics