2016-09-28 4 views
0

私はシェルサーブレットscript.shをjavaサーブレットと手作業の両方で実行する必要があります。その内容は次のとおりです。Javaサーブレット内で実行されるシェルスクリプトファイルでスリープが必要な理由

service avahi-daemon restart 
instance=MyInstance 
avahi-publish -s -d local $instance _temp._tcp 443 "model=Model1" > /dev/null 2>&1 & 
# update: publish other services. 

更新: avahi-publishが返すwould'tが、一度起動稼働し続け、私は他のサービスを公開する必要があるので、末尾の&を削除することができません。

そして、サーブレットは次のとおりです。

public class DefaultServlet extends HttpServlet{ 

    @Override 
    protected void service(HttpServletRequest request, HttpServletResponse response) { 
     try { 
      Process process = Runtime.getRuntime().exec("bash script.sh"); 
      process.waitFor(); 
     }catch (Exception ex) { 
      System.out.println(ex.getMessage()); 
      ex.printStackTrace(); 
     } 
    } 
} 

問題は、サーブレットがブラウザでアクセスされた場合は、サービスMYINSTANCEが公開されることはありません、です。しかし、sleep 0.1sをスクリプトファイルに追加すると、それが解決されます。

私の質問は、Runtime.exec()には何か魔法があり、なぜsleep命令が必要なのでしょうか?そのため、後続&

+0

シェルスクリプトが 'のavahi-publish'のために(最後に&注意)バックグラウンド・プロセスが開始されているので、スクリプトは'のavahi-publish'が終了する前でも終了します。 – learningloop

+0

@learningloop返信ありがとうございます。しかし、avahi-publishプロセスは 'ps aux'の結果で見つけることができます。 –

+0

多分/ dev/nullへのリダイレクトを削除して、エラーメッセージが出力されていないかどうかを確認してください。 –

答えて

2
avahi-publish -s -d local $instance _temp._tcp 443 "model=Model1" > /dev/null 2>&1 & 

、このスクリプトは終了しますとavahi-publishコマンドが完了する前にProcess.waitFor()が返されます。

末尾の&を削除します。

また、リダイレクトを削除し、サーブレットの出力を消費し、プロセスの終了ステータスをテストする必要があります。そのためにavahi-publishプロセスにはexecを使用します。

+0

他のサービスを公開する必要があるため、後続の&は削除できません。 –

+0

すべてを公開するには本当に単一のスクリプトが必要ですか?サーブレットは一連のプロセスを開始するスクリプトを実行していますが、サーブレットはそれらのプロセスを直接認識しておらず、ステータスを監視することもできません。それぞれのサービスに別々のスクリプトを使うことを考えてください。あるいは、スクリプトを完全に控えて、サーブレットに 'avahi-publish'を直接実行させてください。 – Wyzard

+0

あなたの答えをありがとう、しかし、Runtime.exec()は私のために動作しません。 ProcessBuilderとスレッドは私の問題を解決します。 –

-1

最後に、私はProcessBuilderが私を助けてくれることを発見しました。ここに私のpsudoコードは以下のとおりです。

protected void service(HttpServletRequest request, HttpServletResponse response) { 
    new HandlerThread("avahi-publish","-s","-d", "local","MyInstance", "_https._tcp", 
    "443","model=abc") 
    .start(); 
} 

private static class HandlerThread extends Thread { 
    Process process; 

    HandlerThread(String... args) { 
     ProcessBuilder processBuilder = new ProcessBuilder(args); 
     process = processBuilder.start(); 
    } 

    public void run() { 
     StringBuilder stringBuilder = new StringBuilder(); 

     try { 
      process.waitFor(); 
      readStream(process.getInputStream(),stringBuilder); 
      readStream(process.getErrorStream(),stringBuilder); 
     }catch(IOException|InterruptedException ioe){ 
      System.out.println(ioe.getMessage()); 
     } 
     System.out.println(stringBuilder); 
    } 
    private static String readStream(InputStream inputStream, StringBuilder sb) throws IOException { 
     BufferedReader br = null; 
     try { 
      br = new BufferedReader(new InputStreamReader(inputStream)); 
      String line = null; 
      while ((line = br.readLine()) != null) { 
       sb.append(line); 
       sb.append('\n'); 
      } 
     } finally { 
      if(br!=null) br.close(); 
     } 
     return sb.toString(); 
    } 
} 
+0

それであなたは、あなたの問題を確実に修正した後続の '&'を取り除くことができました。あなたは 'Process.waitFor()'を呼び出す前にストリームを読むべきです。プロセスが大量の出力を生成すると、現在の実装ではデッドロックが発生する可能性があります。 – EJP

+0

'avahi-publish 'は一度起動しても実行されないので、末尾の'& 'は削除しましたが、削除するだけで' waitFor'を呼び出すとサーブレットスレッドがブロックされます。 –

+0

私は 'プロセスを呼び出す前にストリームの読み込みをテストしました。waitFor() 'を呼び出すと、readStreamはブロックされ、waitFor()メソッドには決して実行されません。 –

関連する問題