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

用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)。

 

参考代码:

 

Java代码   收藏代码
  1. import java.util.*;  
  2. import java.io.*;  
  3. class StreamGobbler extends Thread  
  4. {  
  5.     InputStream is;  
  6.     String type;  
  7.       
  8.     StreamGobbler(InputStream is, String type)  
  9.     {  
  10.         this.is = is;  
  11.         this.type = type;  
  12.     }  
  13.       
  14.     public void run()  
  15.     {  
  16.         try  
  17.         {  
  18.             InputStreamReader isr = new InputStreamReader(is);  
  19.             BufferedReader br = new BufferedReader(isr);  
  20.             String line=null;  
  21.             while ( (line = br.readLine()) != null)  
  22.                 System.out.println(type + ">" + line);      
  23.             } catch (IOException ioe)  
  24.               {  
  25.                 ioe.printStackTrace();    
  26.               }  
  27.     }  
  28. }  
  29. public class ExecRunner  
  30. {  
  31.     public static void main(String args[])  
  32.     {  
  33.         if (args.length < 1)  
  34.         {  
  35.             System.out.println("USAGE: java GoodWindowsExec <cmd>");  
  36.             System.exit(1);  
  37.         }  
  38.           
  39.         try  
  40.         {              
  41.             String osName = System.getProperty("os.name" );  
  42.             String[] cmd = new String[3];  
  43.             if( osName.equals( "Windows NT" ) )  
  44.             {  
  45.                 cmd[0] = "cmd.exe" ;  
  46.                 cmd[1] = "/C" ;  
  47.                 cmd[2] = args[0];  
  48.             }  
  49.             else if( osName.equals( "Windows 95" ) )  
  50.             {  
  51.                 cmd[0] = "command.com" ;  
  52.                 cmd[1] = "/C" ;  
  53.                 cmd[2] = args[0];  
  54.             } else {  
  55.                 StringTokenizer st = new StringTokenizer(command, " ");  
  56.                 cmd = new String[st.countTokens()];  
  57.                 int token = 0;  
  58.                 while (st.hasMoreTokens()) {  
  59.                     String tokenString = st.nextToken();  
  60.                     // System.out.println(tokenString);  
  61.                     cmd[token++] = tokenString;  
  62.                 }  
  63.             }  
  64.               
  65.             Runtime rt = Runtime.getRuntime();  
  66.             System.out.println("Execing " + cmd[0] + " " + cmd[1]   
  67.                                + " " + cmd[2]);  
  68.             Process proc = rt.exec(cmd);  
  69.             // any error message?  
  70.             StreamGobbler errorGobbler = new   
  71.                 StreamGobbler(proc.getErrorStream(), "ERROR");              
  72.               
  73.             // any output?  
  74.             StreamGobbler outputGobbler = new   
  75.                 StreamGobbler(proc.getInputStream(), "OUTPUT");  
  76.                   
  77.             // kick them off  
  78.             errorGobbler.start();  
  79.             outputGobbler.start();  
  80.                                       
  81.             // any error???  
  82.             int exitVal = proc.waitFor();  
  83.             System.out.println("ExitValue: " + exitVal);          
  84.         } catch (Throwable t)  
  85.           {  
  86.             t.printStackTrace();  
  87.           }  
  88.     }  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值