Javaでシステムコール

仕様の都合上、どうしてもサーブレットからシステムコールしてbatchを叩かないといけなくなりました。
しかもサーバのOSはwindows


batchの内容は同一LAN内のDBサーバにあるexeを叩くというだけのものです。
batchの中はよくわからないのですが、PsToolsとかいうリモートアクセスツールを使用しているみたいです。


さてJavaシステムコールをする時はいくつか方法があると思いますが、今回は「java.lang.Runtime#exec」を使用しました。

public class foo {

    public void bar(){
        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec("c:/foo/bar.bat");
        process.waitFor();
    }
}


最初、上記のようにしていましたがいくらまっても「waitFor()」から復帰しない。
しかしbatch自体は正常終了しておりリモートのexeも実行されています。


色々調べてみるとProess#getInputStreamのbufferが512バイト以上になると終了コードを取得できずにタイムアウトになるという情報がありました。


dfltweb1.onamae.com – このドメインはお名前.comで取得されています。


しかしbar.batは「@echo off」にしているため512バイト以上はなっていません。
関連してProcess#getErrorStreamも取得しないとプロセスが終了しないという情報を発見


サーブレットからバッチファイルの起動 - QA@IT


しかしこれもハズレ
getErrorStreamで取得したInputStreamインスタンスをBufferdReaderに食わせてwhileでreadLineしているとやはり止る
ハマったかと思ってた所でcmd.exeで実行すればいいという情報を発見


http://oshiete1.watch.impress.co.jp/qa3730481.html?ans_count_asc=1


cmd.exeで実行する事によりシェルの終了が無事取得できました

public class foo {

    public void bar(){
        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec("cmd.exe /c c:/foo/bar.bat");
        process.waitFor();
    }
}


windowsのシェルの概念がわかっておらず、batchを叩けばシェルで実行されると思っていましたが違うようです。
しかしGoogle先生に頼ってばかりでひどい事になっているのでもう少しJavaの深い所も勉強しようと思いました。