2011-12-11 13 views
1

私はシェルスクリプトを起動するはずのjavaプログラムを持っています。スクリプトには、順番に実行される6つのタスクが含まれています。 Javaプログラムがスクリプトを起動し、起動します(ログが表示されます)。しかし、10-15秒後に、シェルスクリプトの最初のタスクが完了する前に実行が停止します。奇妙なことは、スクリプトをターミナルで起動したときに正常に動作することです。スクリプトの実行中にプログラムがハングする危険を避けるために、別のスレッドで起動します。考えられる理由は何でしょうか?javaからシェルスクリプトを実行中 - 完了していないタスク

のJavaコード -

try { 
      log.info("run cmd - "+optionsRun); 

      String[] cmdLine = (String[]) optionsRun.toArray(new  String[optionsRun.size()]); 

      Process process = Runtime.getRuntime().exec(cmdLine); 
      log.info("end run cmd " + this.getScriptPath()); 

//   
//   BufferedWriter writer = new BufferedWriter(new  OutputStreamWriter(process.getOutputStream())); 
//   writer.write("mypwd"); 
//   writer.flush(); 
//   writer.close(); 


      InputStream is = process.getErrorStream(); 
      String error = inputStreamToStringValue(is); 
      log.trace("Eventual error was : " + error); 

      InputStream os = process.getInputStream(); 
     String output = inputStreamToStringValue(os); 
      log.info("Eventual output was : " + output); 

      if (error!=null & error.length()>0) { 
       throw new ActionProcessingException("An error occurred when  running the script :'"+this.getScriptPath()+"' with following error message : "+error);  
      }else { 
       log.info("Script run ended successfully."); 
      } 

とシェルスクリプトは、このように見える - 事前に

#!/bin/sh 
# ./publish <path-to-publish-home-folder> <workspace_id> <start_date> <end_date> 
# ./publish <path-to-publish-home-folder> 100011 2010-01-06-12:00:00-CET  2012-01-14-19:00:00-CET 

rm -f $1/publish.log 
echo 'Start publish' >> $1/publish.log 
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 >> $1/publish.log 

# lancement de l'export RDF du domaine 
cd $1/1-export-domain 
echo "Starting export domain with the command - ./export.sh $2" >> $1/publish.log 
./export.sh $2 

# lancement de l'export des translations du domaine 
cd $1/2-export-trans 
echo "Starting export domain(translated) with the command - ./export.sh $2" >>   $1/publish.log 
./export.sh $2 
..... 
..... 
a couple of more steps like 1 and 2 
.... 

おかげで、

+0

publish.logにはどのような出力がありますか? –

+0

更新:シェルスクリプトからリソースと時間のかかる作業を削除しようとしましたが、実行が完了しました。しかし、私は多くの時間(とリソース)を取るタスクを実行しようとすると、完了しません。シェルスクリプトがJavaプログラムから実行されているときに、自動タイムアウト(またはそれに類するもの)がありますか? – Ozyman

+0

@AndrewFielden publish.logは、最初のタスクが開始されたことを示します。何もありません。私はそれぞれの仕事のために別々のログを持っています。 10秒または15秒後に、最初のタスクのロギングがただちに終了します(タスクは完了しません)。私は、Linuxのログからさらに情報を見つけることができるかどうかはわかりません。 – Ozyman

答えて

1

私はわからないんだけど、私は2つのリンクをお勧めしますあなたがそれを理解するのに役立つかもしれない。

最初は非常に古いものを約Runtime.exec()です:

http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html

第二は、Runtime.exec()に代わるものでは新しいクラスについてProcessBuilderです:

http://www.java-tips.org/java-se-tips/java.util/from-runtime.exec-to-processbuilder.html

1

私は確認することはできません私の推測では、あなたの方法に問題があるということです。inputStreamToStringValue(is)。それはSTDERRを読み取り、読み取り時にブロックしています。 STDERRから読み込むことは何もないが、プロセスがまだ終了していない場合、あなたは永遠にブロックされます。

私はあなたがProcessBuilderをを使用することをお勧めします:

ProcessBuilder b = new ProcessBuilder(); 
    b.redirectErrorStream(true); 

は今、あなたは一緒にSTDINとSTDERRを読むことができます。

まだ別々に読むには、2つの解決策があります。

まず最初にやっているように、読んでブロックしないようにしてください。つまり、読み込みを呼び出す前にin.available()を呼び出してから、以前に利用可能だったバイト数だけ読み込みます。

第2の方法は、シェルリダイレクトを使用することです。スクリプトを実行し、そのSTDOUTとSTDERRを一時ファイルにリダイレクトします。その後、プロセスが終了してからファイルを読み込むまで待ちます。私は個人的にこのソリューションがより簡単でより堅牢であると考えています。

幸運。

関連する問題