代码如下,请高人指点,在output.readLine()无限等待,不知何故.
 public int runCommand(String command)throws IOException {
    try {
logger.debug("enter OPMNUtil runCommand....");
this.command=command;
logger.debug("command----\n"+this.command);
Process process = Runtime.getRuntime().exec(this.command);
BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader error = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line=null;
while((line=output.readLine())!=null)
   {
    logger.debug("output is----"+line);
   }
while((line=error.readLine())!=null)
   {
    logger.debug("error is----"+line);
   }
int exitValue=process.exitValue();
//int exitValue = process.waitFor();
logger.debug("waitcode---------"+exitValue);
return exitValue;

}
    catch(IOException e){
    throw new IOException();
    }
catch (Exception e) {
        e.printStackTrace();
return -1000;
}

   }

解决方案 »

  1.   

    我猜想是你要启动一个thread专门来接收errorStream,在一个command运行的时候,可能同时有err和输出和std的输出,如果你这样接受,感觉是有问题的。
      

  2.   

    是的,在运行command的时候同时会有stdout,stderr输出,而且郁闷的是在xp系统上正常运行,在win2000上就出问题了.
      

  3.   

    你执行什么命令会出现这样的错?
    我试了一下没有问题呀
    不过好象stdout与stderr不会同时输出
      

  4.   

    我调用了Oralce Application Server的一个opmnctl命令,在我自己的XP系统上stdout和stderr都能输出啊,但是在2000 Server上就deadlock 了,郁闷啊.
      

  5.   

    我在2000 server上试的一下,好像可以啊,jdk 1.4.1
    不过我觉得最好还是专门用一个Thread来接收err的流
      

  6.   

    这是我的代码import java.io.*;public class Run
    {    public static void main(String[] args)
        {
            Run r = new Run();
            r.runCommand("opmnctl");
        }    public int runCommand(String command) {
            try {
                System.out.println("enter runCommand....");            System.out.println("command----" + command);
                final Process process = Runtime.getRuntime().exec(command);            BufferedReader output = new BufferedReader
                            (new InputStreamReader(process.getInputStream()));
                String line=null;
                Runnable rr = new Runnable()
                {
                    public void run()
                    {
                        try {
                            BufferedReader error = new BufferedReader
                                (new InputStreamReader(process.getErrorStream()));                        String line2 = null;                        System.out.println("handle err stream");
                            while((line2=error.readLine())!=null)
                            {
                                System.out.println("error is----"+line2);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                };
                (new Thread(rr)).start();            System.out.println("handle std stream");
                while((line=output.readLine())!=null)
                {
                    System.out.println("output is----"+line);
                }            int exitValue=process.exitValue();
                //int exitValue = process.waitFor();
                System.out.println("waitcode---------"+exitValue);
                return exitValue;        }
            catch (Exception e) {
                e.printStackTrace();
                return -1000;
            }
        }
    }另,问一下,你执行“opmnctl”需要多久时间
      

  7.   

    我运行的命令是opmnctl startproc ias-component=OC4J process-type=test 如果OC4J test是正常配置的,只是状态是DOWN,我这边也能执行并把test启动起来,但如果故意把OC4J test配置错误,让它无法启动就出现上述情形了.正常情况下启动test需要1分钟左右.
      

  8.   

    自己重新写了一个,现在可以了,应该还是Stream的问题,参考了More java Pitfall里的实现,不过如果在运行时用鼠标点击Console窗口还是会block掉,那个问题应该是跟输入流没有处理有关了,反正我的程序是做成Windows Service的,所以也不会有那种情况了,谢谢楼上诸位,以下是最新的代码.
    /*
     * Created on 2005-11-29
     *
     * TODO To change the template for this generated file go to
     * Window - Preferences - Java - Code Style - Code Templates
     */import java.io.*;
    import java.io.IOException;
    import cn.zyxel.util.LogHelper;/**
     * @author Simon
     *
     * TODO class OPMNUtil aims to deal with OPMNCTL command 
     */
    public final class OPMNUtil {
       //command to run with OPMNCTL 
       private String command;
       //singleton instance
       private static OPMNUtil opmnUtil;
       private OPMNUtil(){
       
       }
       public static OPMNUtil getInstance(){
        if(opmnUtil==null){
        opmnUtil=new OPMNUtil();
        }
        return opmnUtil;
       }
       
       /**run arbitary OPMNCTL command
     * @param command
     * @return
     * @throws IOException
     */
       public int runCommand(String command)throws IOException {
       
    try { LogHelper.logger.debug("enter OPMNUtil runCommand....");
    this.command=command;
    LogHelper.logger.debug("command----\n"+this.command);
    Runtime rt = Runtime.getRuntime();
        Process proc = rt.exec(this.command);
            StreamGobbler errorGobbler = new
            StreamGobbler(proc.getErrorStream(), "ERROR");
        StreamGobbler outputGobbler = new
        StreamGobbler(proc.getInputStream(), "OUTPUT");
        errorGobbler.start();
        outputGobbler.start();
        int exitVal = proc.waitFor();
        LogHelper.logger.debug("ExitValue:" + exitVal);
        return exitVal;
          } 
    catch(IOException e){
        throw new IOException();
        }
    catch (Throwable t) {
         t.printStackTrace();
         return -1000;
        }

       }
       
       /**get OPMN managed component's status
     * @param componentType
     * @param processType
     * @return
     * @throws IOException
     */
       public String getComponentStatus(String componentType,String processType)throws IOException{
        String status=Constants.EXCEPTION_STATUS;
        try {
        LogHelper.logger.debug("enter OPMNUtil getComponentStatus....");
    this.command="opmnctl status ias-component="+componentType+" process-type="+processType;
    LogHelper.logger.debug("command----\n"+this.command);
    Process process = Runtime.getRuntime().exec(this.command);
    BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream()));
    BufferedReader error = new BufferedReader(new InputStreamReader(process.getErrorStream()));
    String line=null;
    while((line=output.readLine())!=null) {
    if(line.indexOf(processType)!=-1){
        status=line.substring(line.lastIndexOf("|")+1,line.length()).trim();
        }
       
       }
    while((line=error.readLine())!=null) {
       
       }
    int exitValue = process.waitFor();
    LogHelper.logger.debug("exitValue---------"+exitValue);
    return status;

    }
        catch(IOException e){
        throw new IOException();
        }
    catch (Exception e) {
            e.printStackTrace();
    return Constants.EXCEPTION_STATUS;
    }
       
       }
    }/**
     * @author Simon
     *
     * TODO class StreamGobbler aims to kick off stdout,stderr output.
     * So that OPMNUtil will work normally.
     */
    class StreamGobbler extends Thread
     {
          private InputStream is;
          private 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) {
          LogHelper.logger.debug(type + ">" + line);
          System.out.flush();
     }
     } catch (IOException e){
          e.printStackTrace();
     }
    }
    }