Использование командной строки из Java - процесс тайм-аута, который занимает слишком много времени - PullRequest
0 голосов
/ 06 февраля 2012

Итак, я пишу программу для запуска процессов командной строки из 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) <5000 классификатор. Я также попытался написать цикл while как: </p>

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 для работы со строкой, но это также, похоже, не приводит к истечению времени ожидания процесса.

Есть еще идеи?

Спасибо!

1 Ответ

0 голосов
/ 06 февраля 2012

Рекомендую прочитать вопрос и ответы здесь .Было бы лучше заменить Process на ProcessBuilder.Прочтите также статью о некоторых распространенных ловушках при вызове внешних команд.

РЕДАКТИРОВАТЬ: Проблема состоит в том, что метод readline блокирует, и поэтому ваш код состояния тайм-аута никогдадостиг.Вы не можете использовать тайм-аут с потоками Java, если только вы не используете NIO .Один из способов сделать это - создать поток для чтения и убить его, когда в основном потоке возникает тайм-аут.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...