Как написать на Java в стандартный ввод SSH? - PullRequest
5 голосов
/ 20 июня 2011

Все отлично работает в командной строке, но когда я перевожу то, что я хочу, в Java, процесс получения никогда не получает ничего на стандартный ввод.

Вот что у меня есть:

private void deployWarFile(File warFile, String instanceId) throws IOException, InterruptedException {
    Runtime runtime = Runtime.getRuntime();
    // FIXME(nyap): Use Jsch.
    Process deployWarFile = runtime.exec(new String[]{
            "ssh",
            "gateway",
            "/path/to/count-the-bytes"});

    OutputStream deployWarFileStdin = deployWarFile.getOutputStream();
    InputStream deployWarFileStdout = new BufferedInputStream(deployWarFile.getInputStream());
    InputStream warFileInputStream = new FileInputStream(warFile);

    IOUtils.copy(warFileInputStream, deployWarFileStdin);
    IOUtils.copy(deployWarFileStdout, System.out);

    warFileInputStream.close();
    deployWarFileStdout.close();
    deployWarFileStdin.close();

    int status = deployWarFile.waitFor();
    System.out.println("************ Deployed with status " + status + " file handles. ************");
}

Сценарий 'count-the-bytes' прост:

#!/bin/bash

echo "************ counting stdin bytes ************"
wc -c
echo "************ counted stdin bytes ************"

Вывод указывает, что функция зависает в строке 'wc -c' - она ​​никогда не попадает в строку 'countted stdin bytes'.

Что происходит?Поможет ли использование Jsch?

Ответы [ 3 ]

4 голосов
/ 20 июня 2011

Вы можете попытаться закрыть поток вывода, прежде чем ожидать, что wc -c вернется.

IOUtils.copy(warFileInputStream, deployWarFileStdin);
deployWarFileStdin.close();
IOUtils.copy(deployWarFileStdout, System.out);

warFileInputStream.close();
deployWarFileStdout.close();
1 голос
/ 20 июня 2011

Будет ли использование справки Jsch?

Использование JSch поможет, только если вы будете использовать методы канала setInputStream() и setOutputStream() вместо метода IOUtils.copy,так как они управляют копированием в отдельном потоке.

ChannelExec deployWarFile = (ChannelExec)session.openChannel("exec");

deployWarFile.setCommand("/path/to/count-the-bytes");

deployWarFile.setOutputStream(System.out);
deployWarFile.setInputStream(new BufferedInputStream(new FileInputStream(warFile)));

deployWarFile.connect();

(Здесь вам как-то придется ждать, пока другая сторона не закроет канал.)

Если вы просто заменили Runtime.exec наоткрыв ChannelExec (и запустив его после получения потоков), проблема будет полностью такой же, и ее можно будет решить с помощью того же решения, о котором упоминает antlersoft, то есть закрытия ввода перед чтением вывода:

ChannelExec deployWarFile = (ChannelExec)session.openChannel("exec");

deployWarFile.setCommand("/path/to/count-the-bytes");

OutputStream deployWarFileStdin = deployWarFile.getOutputStream();
InputStream deployWarFileStdout = new BufferedInputStream(deployWarFile.getInputStream());
InputStream warFileInputStream = new FileInputStream(warFile);

deployWarFile.connect();

IOUtils.copy(warFileInputStream, deployWarFileStdin);
deployWarFileStdin.close();
warFileInputStream.close();

IOUtils.copy(deployWarFileStdout, System.out);
deployWarFileStdout.close();

(Конечно, если у вас более длинный вывод, вы захотите выполнять ввод и вывод параллельно или просто использовать первый метод.)

0 голосов
/ 20 июня 2011

Возможно, вы получили ошибку, но процесс зависает, потому что вы не читаете поток ошибок .Взятые из процесса JavaDoc

Все его стандартные операции io (т.е. stdin, stdout, stderr) будут перенаправлены в родительский процесс через три потока (Process.getOutputStream (), Process.getInputStream ()Process.getErrorStream ()).Родительский процесс использует эти потоки для подачи входных данных и получения выходных данных из подпроцесса.Поскольку некоторые собственные платформы предоставляют ограниченный размер буфера только для стандартных входных и выходных потоков, невозможность оперативной записи входного потока или чтения выходного потока подпроцесса может привести к блокировке подпроцесса и даже к тупиковой ситуации.

Так что вам нужно прочитать все из них.Использование ProcessBuilder возможно проще

...