Как выполнить несколько команд Windows, используя класс Runtime в java

Я пытаюсь выполнить команды Windows из Java, используя следующий код:

Process p=Runtime.getRuntime().exec("wget www.anyurl.com/index.html);

и это работает, но когда я пытаюсь выполнить другую команду, которая выглядит следующим образом,

Process p1=Runtime.getRuntime().exec("pscp -pw sysadmin c:/mydirectory/mypage.html mahesh@vmstni01:/home/usr");

это не работает. Если я закомментирую первую строку процесса (т.е. процесс p), то процесс p1 работает нормально, он выполняется и показывает, что файл был успешно скопирован. Пожалуйста, кто-нибудь может сказать мне, почему это происходит?


person Mahesh    schedule 24.06.2012    source источник
comment
Определить не получится. Что случается?   -  person JB Nizet    schedule 24.06.2012
comment
нужно ли выполнить первую команду, прежде чем можно будет успешно вызвать вторую?   -  person David Kroukamp    schedule 24.06.2012
comment
Привет, JB Nizet, первая команда работает нормально (т.е. wget), но когда я пытаюсь выполнить pscp, она не работает, и если я прокомментирую первую строку (т.е. Process p=Runtime.getRuntime().exec(wget www.anyurl.com/index .html); ), тогда pscp работает нормально.   -  person Mahesh    schedule 24.06.2012
comment
Это не работает не объясняет, что происходит. Программа зависает? Выдает ли это исключение? Если да, то какова трассировка стека? Делает ли он что-то отличное от того, что вы ожидаете? Если да, то что вы ожидаете от него и что он делает вместо этого? Когда вы идете к врачу, вы не просто говорите: я болен. Вы рассказываете обо всех симптомах, чтобы помочь ему определить, что не так. Сделайте то же самое здесь.   -  person JB Nizet    schedule 24.06.2012


Ответы (1)


Вам нужно очистить потоки первого процесса, иначе программа заблокируется, потому что процесс "wget" производит выходные данные, которые никогда не читаются в вашей текущей реализации. Вам нужно отсортировать потоки вывода и ошибок первого процесса. Посмотрите на ответы, например. еще один вопрос о java-runtime-exec на SO.

Приведенный ниже код работает для справки, но основан на том факте, что wget генерирует вывод в stderr, а pscp — в stdout. Если что-то выводится в другой соответствующий поток, код работает до тех пор, пока вывод помещается в буфер Java-программы (обратите внимание, что размеры этих буферов, как правило, отличаются от платформы к платформе), пока он очищает первый поток. Если буфер переполняется, выполнение команды просто блокируется. Вы должны создать отдельный поток для обоих, stout и stderr, который читает соответствующий поток процесса.

    import java.io.BufferedReader;
    import java.io.InputStreamReader;

...

    Process p=Runtime.getRuntime().exec("wget http://www.duckduckgo.com/");

    BufferedReader perr=new BufferedReader(new InputStreamReader(p.getErrorStream()));
    BufferedReader pout=new BufferedReader(new InputStreamReader(p.getInputStream()));
    // We read stderror first from wget, because it spits the progress information into stderr
    for (String s=perr.readLine(); s!=null; s=perr.readLine())
    {
        System.out.println("Stderr from p: "+s);
    }
    for (String s=pout.readLine(); s!=null; s=pout.readLine())
    {
        System.out.println("Stdout from p: "+s);
    }
    // if you need to check whether the command actually returned normally
    int returnCode = p.waitFor();
    perr.close();
    pout.close();

    System.out.println("Returned from p with exit code "+returnCode);

    p=Runtime.getRuntime().exec("pscp -pw dontuseplainpwusesshkeys index.html [email protected]:");
    perr=new BufferedReader(new InputStreamReader(p.getErrorStream()));
    pout=new BufferedReader(new InputStreamReader(p.getInputStream()));
    // We read stdout of pscp first because pscp spits stuff into stdout.
    // The process will block if the buffer gets full and does not get emptied.
    for (String s=pout.readLine(); s!=null; s=pout.readLine())
    {
        System.out.println("Stdout from p: "+s);
    }
    for (String s=perr.readLine(); s!=null; s=perr.readLine())
    {
        System.out.println("Stderr from p: "+s);
    }

    int returnCode1 = p.waitFor();
    perr.close();
    pout.close();

    System.out.println("Process exited with return code "+returnCode1);
person jpe    schedule 24.06.2012
comment
Привет, Дэвид, первая команда работает нормально до выполнения второй команды. - person Mahesh; 24.06.2012
comment
Привет jpe, я пытаюсь с вашим предложением и вернуться к вам. - person Mahesh; 24.06.2012
comment
Привет, ребята, здесь я предоставляю свой код, пожалуйста, посмотрите на него и скажите мне, что не так с этим кодом, String input; BufferedReader br; br = новый BufferedReader (новый InputStreamReader (System.in)); ввод = br.readLine(); if(input.equals(download)) { Process p=Runtime.getRuntime().exec(wget www.anyurl.com/index.html); } else if(input.equals(upload)) { Process p1=Runtime.getRuntime().exec(pscp -pw sysadmin c:/mydirectory/mypage.html mahesh@vmstni01:/home/usr); } - person Mahesh; 25.06.2012
comment
Посмотрите следующий пост о p.getInputStream() и p.getErrorStream(): stackoverflow.com/a/8597030/1424507 - person jpe; 25.06.2012
comment
Не могли бы вы изменить мой приведенный выше код и сказать мне, как он будет выглядеть. Я попытался с вашим предложением, но до сих пор не добился успеха в моих руках. - person Mahesh; 27.06.2012
comment
@Mahesh Добавлен код для справки, который иллюстрирует вашу проблему, но не содержит окончательной реализации. Прочтите связанные сообщения, а также документацию SDK о runtime.exec(). - person jpe; 27.06.2012
comment
Я пробовал с этим и отлично работал в Windows 7, но когда я запускаю Windows XP, он все еще не показывает никаких результатов. При запуске этой программы в Windows XP не возникает ошибок или исключений. Есть ли какая-либо зависимость от платформы, связанная с этим. - person Mahesh; 28.06.2012
comment
@Mahesh Пожалуйста, прочитайте сообщение. Код ниже работает для справки, но не на 100% верен. В настоящее время он основан на том факте, что все, что отправляется на стандартный вывод, помещается в буфер Java-программы (обратите внимание, что размеры этих буферов, как правило, отличаются от платформы к платформе). Поскольку pscp генерирует вывод на стандартный вывод, вы можете исправить ситуацию для своих целей, выполнив цикл for(String s=pout.readline... перед циклом perr. - person jpe; 28.06.2012
comment
Спасибо, этот код отлично работает на обеих ОС. Спасибо большое за вашу помощь. - person Mahesh; 30.06.2012