使用Java中的命令行 - 超时过程需要太长时间

时间:2012-02-06 07:09:25

标签: java command-line timeout

所以我正在编写一个程序来从Java运行命令行进程。这需要在Windows和Linux上运行;虽然,我目前正在Windows 7上进行测试。我还应该提到#之后的任何内容都被视为评论。有了这个,这是我的代码:

import java.io.*;
import java.util.*;

public class myShell
{
    public static void main(String[] args)
    {
        Runtime runtime = Runtime.getRuntime();
        Process process;
        Scanner keyboard = new Scanner(System.in);
        String userInput = "";
        String osName = System.getProperty("os.name" );
        BufferedReader brStdOut = null;
        String stdOut;
        String stdOutNextLine;
        BufferedReader brErrorStream = null;
        String errorStream;
        String errorStreamNextLine;

        while(userInput.compareToIgnoreCase("exit") != 0)
        {
            System.out.println();
            System.out.print("??");

            userInput = keyboard.nextLine();

            int indexOfPound = userInput.indexOf('#');
            if(indexOfPound == 0)
            {
                userInput = "";
            }
            else if(indexOfPound > 0)
            {
                userInput = userInput.substring(0, indexOfPound);
            }
            userInput = userInput.trim();

            try
            {   
                if(osName.contains("Windows"))
                {
                    process = runtime.exec("cmd /c " + userInput);
                }
                else
                {
                    process = runtime.exec(userInput);
                }

                brStdOut = new BufferedReader(new InputStreamReader(
                           process.getInputStream()));
                brErrorStream = new BufferedReader(new InputStreamReader(
                                process.getErrorStream()));

                stdOut = "";
                errorStream = "";
                boolean firstStdOut = true;
                boolean firstErrorStream = true;
                long time = System.currentTimeMillis();

                while(((stdOutNextLine = brStdOut.readLine())  != null) && 
                      ((System.currentTimeMillis() - time) < 5000))
                {
                    if(firstStdOut)
                    {
                        stdOut = stdOutNextLine;
                        firstStdOut = false;
                    }
                    else
                    {
                        stdOut = stdOut + "\n" + stdOutNextLine;
                    }
                }
                time = System.currentTimeMillis();
                while(((errorStreamNextLine = brErrorStream.readLine()) != null)
                      && ((System.currentTimeMillis() - time) < 5000))
                {
                    if(firstErrorStream)
                    {
                        errorStream = errorStreamNextLine;
                        firstErrorStream = false;
                    }
                    else
                    {
                        errorStream = errorStream + "\n" + errorStreamNextLine;
                    }
                }
                System.out.println(stdOut + errorStream);
            }
            catch(Exception e)
            {
                System.out.println("Error executing: " + userInput); 
                System.out.println(e.getMessage());
            }
            try
            {
                brStdOut.close();
            }
            catch(Exception e)
            {
            }
            try
            {
                brErrorStream.close();
            }
            catch(Exception e)
            {
            }
        }
        System.exit(0);
    }
}

所以,我遇到的问题是当我在命令行中运行像date这样的命令时,会请求进一步的用户输入。暂时,我想暂停这些类型的命令并获取在我超时的过程中打印的任何内容。

因此,如果在命令行日期返回2行然后等待用户输入,我只希望我的程序打印这2行然后继续。 问题是,正如所写的那样,用于从命令行获取输出的while循环中的超时似乎没有做任何事情,程序运行完全相同,有或没有(System.currentTimeMillis() - time)&lt; 5000资格赛。我也尝试将while循环写为:

while((stdOutNextLine = brStdOut.readLine())  != null)
{
    if(firstStdOut)
    {
        stdOut = stdOutNextLine;
        firstStdOut = false;
    }
    else
    {
        stdOut = stdOut + "\n" + stdOutNextLine;
    }
    if((System.currentTimeMillis() - time) > 5000)
    {
        throw new TimeoutException();
    }
}

然后捕获TimeoutException以从那里使用String,但这似乎并没有实际超时该过程。

还有其他想法吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

我建议您阅读问题和答案here。用ProcessBuilder替换Process会更好。在调用外部命令时,还要阅读此article以获取一些常见的陷阱。

修改 问题是readline方法是阻塞的,因此永远不会达到超时条件代码。您不能在Java流中使用超时,除非您使用NIO。一种方法是在主线程中发生超时时,生成一个用于读取的线程并将其终止。