2011-06-20 7 views
5

すべてはうまくコマンドラインで動作しますが、私がJavaに必要なものを翻訳すると、受信プロセスはstdin上で何も取得しません。sshのstdinに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. ************"); 
} 

スクリプト「カウントバイト」単純です:

#!/bin/bash 

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

出力機能は「トイレ-c」行でハングことを示しています - それは 'countd stdin bytes'行には決して行きません。

何が起こっているのですか? Jschの助けを借りたいですか?

+0

IOCopyを使用すると、どの値が返されますか? – Snicolas

+0

copyLarge()を使用するようにコードを変更しました。それは返す30054046。 –

答えて

4

wc -cが返ることを期待する前に、出力ストリームを閉じてみてください。

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

warFileInputStream.close(); 
deployWarFileStdout.close(); 
+0

私は元のスクリプト(sshはまだ別のマシン)が動作していなかった理由をデバッグするためにstdoutから読み込みを追加しました。 stdoutから読み込む前にstdinを終了した後、関数は動作するように見えます(ただし、以前は動作していましたが)。 stdoutからの読み込みは、スクリプトが何をしていても終了させますか?それとwaitFor()を呼び出すことの違いは何ですか? –

+0

@Noel:ここでの問題は、 'copy'と' wc'の組み合わせです: 'wc'は入力が閉じられれば何かの出力を開始し、' copy'はスクリプトから何らかの出力が来るまで待ちますそれの終わり)。あなたは 'copy'を置いて別のスレッドに近づけることもできます。 –

0

おそらく、エラーを取得していますが、error streamを読んでいないので、プロセスがハングアップします。 プロセスのJavaDoc

から撮影された全ての標準IO(すなわちSTDIN、STDOUT、標準エラー出力)操作は3つのストリーム(Process.getOutputStream()、Process.getInputStream()、プロセスを介して親プロセスにリダイレクトされます。 getErrorStream())。親プロセスは、これらのストリームを使用して、サブプロセスへの入力を提供し、サブプロセスからの出力を取得します。一部のネイティブ・プラットフォームでは、標準の入力および出力ストリームに対して限られたバッファ・サイズしか提供されないため、入力ストリームを即時に書き込むことができないか、サブプロセスの出力ストリームを読み取らないと、サブプロセスがブロックされ、

あなたはそれらのすべてを読む必要があります。 ProcessBuilderの使用はおそらく簡単です

+0

良いアドバイスですが、この場合エラーは発生しませんでした。 –

1

Jschヘルプを使用しますか?

あなたは、チャネルのsetInputStream()setOutputStream()方法の代わりに、IOUtils.copy方法を使用しているならば、彼らは別のスレッドでコピーを管理するため、JSCHを使用することでのみ、役立つだろう。

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(); 

(ここでは、何らかの形で反対側には、チャネルを閉じるまで待たなければならない。)

あなたは、単にChannelExecを開く(とストリームを取得した後、それを起動する)とRuntime.execを交換した場合、問題となります完全に同じであること、およびすなわち出力を読み込む前に、入力を閉じて、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(); 

とパラに出力llel、または単に最初のメソッドを使用します)。

関連する問題