- PR -

JSP ProcessBuilderを使用したbatファイルの実行について

1
投稿者投稿内容
pich
会議室デビュー日: 2006/12/20
投稿数: 8
投稿日時: 2006-12-21 11:13
JSPからbatファイルを実行する処理を作成しています。
(Tomcat 6.0、jdk1.5.0_06を使用)

batファイル自体を単体で動かした場合(ダブルクリック)、
正常に最後まで処理が流れるのですが、
JSPから実行した場合、
batファイルにjavaコマンドがいくつ書かれていても
1つ目のjavaコマンドしか実行されません。

batファイル自体を単体で動かしたときと同じように最後まで処理を流すには
どうしたらよいでしょうか?

JSP、batファイルは以下の通りです。

=======JSPのコード=========================================
// パラメータを取得
String sYear = request.getParameter("year");
String sMonth = request.getParameter("month");

String sYYMM = sYear + sMonth + "15";
String sCmd = "C:\\java\\test.bat";

ProcessBuilder builder = new ProcessBuilder(sCmd,sYYMM);
Process process = builder.start();
===========================================================
=======batファイル=========================================
set SYORI_DATE=%1
cd C:\java\xxx\lib
java jp.co.xxx.WR_06_Kansei.WR_06_Main %SYORI_DATE%
java jp.co.xxx.WR_07_Buhin.WR_07_Main %SYORI_DATE%
java jp.co.xxx.WR_08_Buhin.WR_08_Main %SYORI_DATE%
===========================================================
だっちょ
大ベテラン
会議室デビュー日: 2006/12/05
投稿数: 115
投稿日時: 2006-12-21 11:59
たぶんコマンドが終了しないうちにデータを見に行っているのではないでしょうか?
process.waitFor();
を加えてみたらどうなるでしょう?
pich
会議室デビュー日: 2006/12/20
投稿数: 8
投稿日時: 2006-12-22 12:02
process.waitFor();
process.destroy();

を追加してみました。

Tomcatを終了させるまで、ログをつかんだままです。
1つ目のjavaコマンドだけが実行されます。

だっちょ
大ベテラン
会議室デビュー日: 2006/12/05
投稿数: 115
投稿日時: 2006-12-25 09:19
batファイルから呼び出すアプリケーションを詳しく調べないとわからない状況のようですので、あまり伝えられることはありませんが、私なら次のようにします。

 とりあえずJavaSE6があればjrunscriptで
v=new java.util.Vector();
v.add("C:\\java\\test.bat");
v.add([sYYMMの値]);
builder=new java.lang.ProcessBuilder(v);
process=builder.start();
builder.waitFor();
で処理が終わるかをみます。
 おわらなければ、標準出力を処理できないために
標準出力しようとしてとまっている可能性があるので、
process=builder.start();
の次のbuilder.waitFor();を以下に変えてやり直します。
ins=process.getInputStream();
reader=new java.io.InputStreamReader(ins);
r=new java.io.BufferedReader(reader);
while ((line=r.readLine()!=null) { java.lang.System.out.println(line); }
として処理が完了するかを確認します。
この場合標準出力を消費してやれば問題は解決するような気がします。

 builder.waitFor();で処理が終わってしまうと、本当にJSP動作中のアプリ動作の問題なのでよくわかりません。他のアプリが同じファイルをロックしてたりとか、いろいろありえるので、アプリがどこまで動作しているのかを地道に調べる必要があるでしょう。

pich
会議室デビュー日: 2006/12/20
投稿数: 8
投稿日時: 2006-12-27 17:17
InputStream ins = process.getInputStream();
InputStreamReader reader = new java.io.InputStreamReader(ins);
BufferedReader r = new java.io.BufferedReader(reader);
while ((line=r.readLine())!= null) { java.lang.System.out.println(line); }

をbuilder.waitFor(); の代わりにいれましたが、
waitForを使った場合と同じように1つめのJavaコマンドを
処理中のままログファイルをつかんでしまいます。

batファイルだけを単体で動かすとちゃんと処理が最後まで
流れます。
どうしたら、最後まで処理が流れるようになるのでしょうか?
だっちょ
大ベテラン
会議室デビュー日: 2006/12/05
投稿数: 115
投稿日時: 2006-12-27 17:53
 あまり時間がないので、このあと返信することができませんが、
単純なbatファイルだと2つのjavaコマンドをちゃんと処理できていますので、
実行内容のアプリによるものだろうと思います。
(ログをつかんだままというのがよくわかりません。
ログファイルでデッドロックしているということでしょうか?)
やってみる価値のあることとしては

・コマンドを
"C:\\java\\test.bat"
でなく
"cmd /C C:\\java\\test.bat"
にして試してみる。

 あるいは、とりあえず1つ目のコマンドの中で
とまっているのか、batファイルを修正して確認して、
とまっているアプリの中を調べていくしかないとくらいしか
助言できません。
 2つ目でとまっているならひょっとしたら
1つ目の終了で資源が解放されてないためかもしれないので、
(でもコマンドラインでうまくいっているのだから
 その可能性は低いでしょうが)
batファイルの
java..

cmd /C java...
に直して、どうなるか試してみたい気がします。

 では、よいお年を。


だっちょ
大ベテラン
会議室デビュー日: 2006/12/05
投稿数: 115
投稿日時: 2007-01-04 12:29
 ネットでは挨拶しないのかもしれませんが、一応、

  あけましておめでとうございます。

 さて、年末はあわてて書いたので、ロクな考えを書きませんでしたが、
batから呼び出すアプリが子プロセスで動作できないものなのか
(telnetは確か動作できなかったような気がする)
それともプロセスの呼び出しがよくないのかを切り分ける
ことができないので、まともな回答ができないでいました。

 最初に
・呼び出すアプリはキー入力待ちをしていないですね。
という基本的な質問をしておくべきでした。

 とりあえず以下のプログラムを動作させて
入力待ちになったら、問題のbatコマンドを入力して
動作するか確認する必要があります。

 これで動作しなければ、telnetみたく私にはお手上げです。
 動作すればちゃんとプロセスを呼びだすクラスを作って、
そのクラスを呼び出すようにする必要があります。
(その場合、たぶんキー入力待ちしているのでしょう。)

 お手上げの場合は呼び出しアプリの中を調べる必要があるので、
batファイルでなく直接スクリプト呼び出ししてみます。
もしスクリプト呼び出しで途中で止まれば、
スレッドダンプでとまっているところが見れるようになるでしょう。

cmd /Kを使っているのはvsvars32.batしてclコマンド
が動くようにするためで、私の趣味です。
-----------------------------------
import java.util.*;
import java.io.*;
import java.lang.reflect.*;
import javax.script.*;

/**
* sample
*/
public class Sample {
private static final String LF = System.getProperty("line.separator");
private ScriptEngine m_engine;
private Execution m_execution;

/**
* constructor.
*/
private Sample() throws IOException
{
String engineName = "javascript";
m_engine = new ScriptEngineManager().getEngineByName(engineName);
m_engine.put("engine", m_engine);
m_execution = new Execution();
m_execution.start();
}

/**
* main.
*/
public static void main(String[] args)
{
try {
Sample obj = new Sample();
obj.run();
}
catch (Throwable e) {
e.printStackTrace();
System.exit(-1);
}
System.exit(0);
}

/**
*
*/
public void run() throws Exception
{
System.out.println("script sample start");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
System.out.print("script>");
String line = reader.readLine();

if (line==null) return;
// 改行のみの入力は無視
if (line.length()==0) continue;

// exitで終了
if (line.equals("exit")) {
m_execution.end();
return;
}

try {
// 簡単のため;でおわる場合のみスクリプトコマンドとする
if (line.charAt(line.length()-1)==';') {
Object obj = evaluate(line);
if (obj!=null) System.out.println(obj);
}
// methodコマンド
else if (line.startsWith("method ")) {
String name = line.substring(7).trim();
Object obj = m_engine.get(name);
Class cls = null;
if (obj!=null) {
cls = obj.getClass();
}
else {
cls = Class.forName(name);
}
Method[] methods = cls.getMethods();
for (int i=0;i<methods.length;i++) {
String methodname = methods[i].getName();
Class[] cs = methods[i].getParameterTypes();
System.out.print("<" + i + "> " + methods[i].getReturnType().getSimpleName() + " " + methodname + "(");
for (int j=0;j<cs.length;j++) {
if (j!=0) System.out.print(", ");
System.out.print(cs[j].getSimpleName());
}
System.out.println(")");
}
}
// 変数一覧(vars)
else if (line.equals("vars")) {
Map map = m_engine.getBindings(ScriptContext.ENGINE_SCOPE);
Iterator iter = map.entrySet().iterator();
int count = 0;
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry)iter.next();
System.out.println("<" + count + ">" + entry.getKey() + "=" + entry.getValue());
count++;
}
}
// その他はとりあえずOSコマンドとして処理してみる
else {
execute(line);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}

/**
* スクリプト処理.
*/
private final Object evaluate(String input) throws Exception
{
return(m_engine.eval(input));
}

/**
* OSコマンド処理.
* プロセスは終了しないので、出力が一定時間なければ
* 一応おわったものとして次のキー入力に移る
*/
private final void execute(String line)
{
m_execution.println(line);
long waitTime = 20;
long sleepTime = waitTime;
while (true) {
try {
Thread.sleep(sleepTime);
}
catch (Exception e) {
}
sleepTime = waitTime - m_execution.getWaitTime();
if (sleepTime <= 0) return;
}

}


/**
* 実行スレッド.
*/
private class Execution extends Thread {
private Process m_process;
private PrintStream m_keyin;
private BufferedReader m_reader;
private volatile long m_readTime;

/**
* コンストラクタ.
*/
private Execution() throws IOException
{
ProcessBuilder builder = null;
builder = new ProcessBuilder("cmd", "/K");
builder.redirectErrorStream();
m_process = builder.start();
m_keyin = new PrintStream(m_process.getOutputStream(), true);
m_reader = new BufferedReader(new InputStreamReader(m_process.getInputStream()));
}

/**
* スレッド実体.
*/
public void run()
{
try {
while (true) {
m_readTime = System.currentTimeMillis();
String line = m_reader.readLine();
if (line==null) break;
System.out.println(line);
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
end();
}
}

/**
* キー入力待ち時間
*/
public long getWaitTime()
{
return(System.currentTimeMillis() - m_readTime);
}

/**
* コマンド入力.
*/
synchronized public void println(String line)
{
m_keyin.println(line);
}

/**
* 終了.
*/
private final void end()
{
println("");
println("exit");
try {
m_process.waitFor();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}


1

スキルアップ/キャリアアップ(JOB@IT)