java如何运行OS命令(转)

时间:2023-03-09 09:12:21
java如何运行OS命令(转)

•javac TestRunTime.java
•java TestRunTime hostname // 执行“hostname”Linux命令
•即可看到输出

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader; public class TestRunTime {
public static void main(String[] args) throws IOException,
InterruptedException {
String cmd = "";
if (args == null || args.length == 0) {
System.out.println("请输入命令行参数");
} else {
for (int i = 0; i < args.length; i++) {
cmd += args[i] + " ";
}
}
try {
Process process = Runtime.getRuntime().exec(cmd);
InputStreamReader ir = new InputStreamReader(
process.getInputStream());
LineNumberReader input = new LineNumberReader(ir);
String line;
while ((line = input.readLine()) != null) {
System.out.println(line);
}
} catch (java.io.IOException e) {
System.err.println("IOException " + e.getMessage());
}
}
}

http://www.cnblogs.com/alipayhutu/archive/2012/06/12/2546214.html

命令执行不成功时,可以将标准错误流的信息打印出来,发现是bat文件的路径只获取到了第一个空格前。所以问题的原因是空格导致文件路径不能被获取。

在正常情况下我们可以用Project.waitfor()的返回值是否等于0的方法来判断java调用外部程序是Pass或者是Fail。

但是这个方法往往会被因进程堵塞而导致程序发生死锁,无法再继续执行外部程序。

因为本地的系统对标准输入和输出所提供的缓冲池有限,所以错误的对标准输出快速的写入和从标准输入快速的读入都有可能造成子进程死锁。问题的关键在缓冲区这个地方:可执行程序的标准输出比较多,而运行窗口的标准缓冲区不够大,所以发生阻塞。接着来分析缓冲区,当Runtime对象调用exec(cmd)后,JVM会启动一个子进程,该进程会与JVM进程建立三个管道连接:标准输入,标准输出和标准错误流。假设该程序不断在向标准输出流和标准错误流写数据,而JVM不读取的话,当缓冲区满之后将无法继续写入数据,最终造成阻塞在waitfor()这里。

但是在其中过程中真正起关键作用的缓冲区是getErrorStream()对应的那个缓冲区没有被清空,意思就是说其实只要及时读取标准错误流缓冲区的数据程序就不会被block。

原先的代码

//run bat file

 Process project = Runtime.getRuntime().exec("cmd.exe /c " + batpath.replaceAll(" ", "\" \""));

 int exitcode=project.waitFor();

 //kill the process

     project.destroy();

            logger.info(exitcode);

            //if the exitcode is 0, the RIA TEST is passed,else the RIA TEST is failed    

            if(exitcode==0){

            logger.info("============ is Passed============");

                 }

            else{

            Boolean resultFlag=false;

            logger.info("============ is Failed============");

            Assert.assertTrue(bugID+"Failed",resultFlag);   

            }   

修改后的代码:

增加两个线程来读取标准输出流和标准错误流

try{

//run bat file

Process project = Runtime.getRuntime().exec("cmd.exe /c " + batpath.replaceAll(" ", "\" \""));

final InputStream br = project.getInputStream();

final InputStream br_error = project.getErrorStream();

//run 2 threads to read the standard InputStream and the ErrorStream to avoid the project.

//waitfor()method blocked
new Thread() {
public void run() {
BufferedReader br1 = new BufferedReader(new InputStreamReader(br));
try {
String line1 = null;
while ((line1 = br1.readLine()) != null) {
if (line1 != null){
logger.info("RIATest info: "+line1);
}
}
} catch (IOException e) {
e.printStackTrace();
}
finally{
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}.start(); //run thread to read the standard ErrorStream
new Thread() {
public void run() {
BufferedReader br2 = new BufferedReader(new InputStreamReader(br_error));
try {
String line2 = null;
while ((line2 = br2.readLine()) != null) {
if (line2 != null){
logger.info("Error: "+line2);
}
}
} catch (IOException e) {
e.printStackTrace();
}
finally{
try {
br_error.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} }.start();
try{
int exitcode=project.waitFor();
//kill the process
project.destroy();
logger.info(exitcode);
//if the exitcode is 0, the RIA TEST is passed,
//else the RIA TEST is failed
    if(exitcode==0){
logger.info("============ is Passed============");
}
else{
Boolean resultFlag=false;
logger.info("============ is Failed============");
Assert.assertTrue(bugID+"Failed",resultFlag);
}
}
catch(Throwable e){
e.printStackTrace();
}
}
catch(IOException e){
e.printStackTrace();
try
{
project.getErrorStream().close();
project.getInputStream().close();
project.getOutputStream().close();
}
catch(Exception ee){
}
}

http://www.cnblogs.com/xriverside/p/4362609.html

Java Runtime.getRuntime().exec() 执行带空格命令

可执行文件路径如果包含空格,则在java中不能被获取到。

此时Debug一下,会发现 project=null. project.waitFor 的返回值为1.但是去源路径单击bat文件是可以正常运行的,说明问题出在文件路径上。

将文件路径中的空格用双引号引起来就可以了

String batpath = file.getCanonicalPath() + "\\resources\\runTest.bat";
//run bat file
Process project = Runtime.getRuntime().exec("cmd.exe /c " + batpath);
int exitcode=project.waitFor();
//kill the process
project.destroy();
logger.info(exitcode);

修改后的代码

//run bat file
Process project = Runtime.getRuntime().exec("cmd.exe /c " + batpath.replaceAll("[\\d]{1,}", "\" \""));

http://www.cnblogs.com/xriverside/p/4362541.html