1

次のコードを使用して、Java から Windows コマンドを実行しようとしています。

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

うまくいかないようです。最初のプロセス行 (つまり Process p) をコメントアウトすると、プロセス p1 が正常に動作し、実行され、ファイルが正常にコピーされたことが示されます。なぜこれが起こっているのか誰か教えてください。

4

1 に答える 1

4

最初のプロセスのストリームをクリーンアップする必要があります。そうしないと、「wget」プロセスが現在の実装で読み取られない出力を生成するため、プログラムがブロックされます。最初のプロセスの出力ストリームとエラー ストリームを整理する必要があります。SO の java-runtime-exec に関する別の質問などへの回答を見てください。

以下のコードは参照のために機能しますが、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 user@10.0.0.11:");
    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);
于 2012-06-24T18:50:51.083 に答える