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も取得しないとプロセスが終了しないという情報を発見
しかしこれもハズレ
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の深い所も勉強しようと思いました。