web-dev-qa-db-ja.com

Javaプログラムをデーモン化するには?

Linuxシステムでデーモン化したいJavaプログラムがあります。つまり、シェルで実行を開始し、ログアウトした後も実行し続けたい。また、プログラムをきれいに停止できるようにしたいです。

この記事 は、シェルスクリプトとJavaコードの組み合わせを使用してトリックを実行します。

LinuxシステムでJavaプログラムをデーモン化するのに望ましい方法は何ですか?

71
Rich Apodaca

Apache Commons Daemon は、JavaプログラムをLinuxデーモンまたはWinNTサービスとして実行します。

38
Bahaa Zaid

信頼できない場合 Java Service Wrapper 引用 elsewhere (たとえば、SWのパッケージバージョンがないUbuntuで実行している場合)それは昔ながらの方法です:プログラムにそのPIDを/var/run/$progname.pidに書き込ませ、標準のSysV initスクリプト(たとえばntpdのスクリプトを例として使用します、簡単です)を作成します。できれば、LSB準拠にしてください。

基本的に、start関数は、プログラムが既に実行されているかどうかをテストし(/var/run/$progname.pidが存在し、そのファイルの内容が実行中のプロセスのPIDであるかどうかをテストする)、実行されていない場合

logfile=/var/log/$progname.log
pidfile=/var/run/$progname.pid
Nohup Java -Dpidfile=$pidfile $jopts $mainClass </dev/null > $logfile 2>&1

停止機能は/var/run/$progname.pidをチェックし、そのファイルが実行中のプロセスのPIDかどうかをテストし、Java VMであることを確認します(プロセスを強制終了しないように)それは単にJavaデーモンのデッドインスタンスからPIDを再利用し、そのプロセスを強制終了します。

呼び出されると、main()メソッドはSystem.getProperty( "pidfile")で定義されたファイルにPIDを書き込むことから始まります。

ただし、1つの大きなハードル:Javaには、JVMが実行されるプロセスのPIDを取得するための簡単で標準的な方法はありません。

ここに私が思いついたものがあります:

private static String getPid() {
    File proc_self = new File("/proc/self");
    if(proc_self.exists()) try {
        return proc_self.getCanonicalFile().getName();
    }
    catch(Exception e) {
        /// Continue on fall-back
    }
    File bash = new File("/bin/bash");
    if(bash.exists()) {
        ProcessBuilder pb = new ProcessBuilder("/bin/bash","-c","echo $PPID");
        try {
            Process p = pb.start();
            BufferedReader rd = new BufferedReader(new InputStreamReader(p.getInputStream()));
            return rd.readLine();
        }
        catch(IOException e) {
            return String.valueOf(Thread.currentThread().getId());
        }
    }
    // This is a cop-out to return something when we don't have BASH
    return String.valueOf(Thread.currentThread().getId());
}
32
Varkhan

私は頻繁に、基本的にこのように見えるスクリプトやコマンドラインを書いていることに気づきます:

  1. 吐き気の影響を受けないプログラムを実行する
  2. それはそれを生成するシェルから完全に切断され、
  3. Stderrおよびstdoutからログファイルを生成し、その内容も表示されますが、
  4. 進行中のログの表示を停止し、実行中のプロセスを中断せずに他のことを行うことができます

楽しい。

Nohup Java com.me.MyProgram </dev/null 2>&1 | tee logfile.log &
24
Ben Hardy

Nohup コマンドの方が好きです。ブログの投稿にはもっと良い方法があると書かれていますが、それが十分に良いとは思いません。

15
S.Lott

Java Service Wrapper を試してみてください。コミュニティエディションは無料で、ニーズを満たします。

5
John T

Ubuntuでの私の好ましい方法は、libslack「デーモン」ユーティリティを使用することです。これは、JenkinsがUbuntuで使用するものです(これが私が考えた場所です)。Jettyベースのサーバーアプリケーションに使用しましたが、うまく機能します。

デーモンプロセスを停止すると、JVMにシャットダウンのシグナルが送られます。 Runtime.addShutdownHook()でシャットダウンフックを登録することにより、この時点でシャットダウン/クリーンアップコードを実行できます。

4
colini

場合によります。一度だけの場合は、デーモン化してから家に帰りたいのですが、通常は結果を待って、次のようにします。

Nohup Java com.me.MyProgram &

コマンドラインで。それをきれいに殺すには、多くの選択肢があります。 SIGKILLのリスナーがあるか、接続が確立されたらポートでリッスンしてシャットダウンし、定期的にファイルをチェックします。異なるアプローチには異なる弱点があります。本番環境で使用する場合は、もっと考えて、おそらく/etc/init.dにスクリプトを投げて、それをnohupsし、Tomcatのように、より洗練されたシャットダウンを行います。

4
Don Branson

これ 質問は、任意のプログラム(Java固有ではない)をデーモン化することに関するものであるため、回答の一部がケースに当てはまる場合があります。

2
dreeves

DaemonTools:-UNIXでサービスを管理するよりクリーンな方法 https://cr.yp.to/daemontools.html

  1. Urlからデーモンツールをインストールします https://cr.yp.to/daemontools/install.html そこに記載されている指示に従います。問題がある場合は、指示をお試しください https:// Gist。 github.com/rizkyabdilah/85163

  2. / etc/init/svscan.confにファイルを作成し、以下の行を追加します(cent-os-6.7にのみ必要)

 start on runlevel [12345]
 stop on runlevel [^12345]
 respawn
 exec /command/svscanboot
  1. / service/vm /フォルダー内にrunという名前の新しいスクリプトを作成し、以下の行を追加します。
#!/bin/bash    
echo starting VM 
exec Java -jar
/root/learning-/daemon-Java/vm.jar

注:Jarを独自のJarファイルに置き換えます。または任意のJavaクラスファイル。

  1. システムを再起動します

  2. svstat/service/vmが稼働しているはずです!.

  3. svc -d/service/vmはvmを今すぐ停止するはずです!。
  4. svc -u/service/vmはvmを今すぐ起動するはずです!。
2
Velu

ここを見てください:

http://jnicookbook.owsiak.org/recipe-no-022/

jNIに基づいたサンプルコードの場合。この場合、Javaとして開始されたコードをデーモン化し、Cでメインループを実行します。ただし、メインデーモンのサービスループをJava内に配置することもできます。

https://github.com/mkowsiak/jnicookbook/tree/master/recipeNo029

JNIをお楽しみください!

0
Oo.oO
Nohup Java -jar {{your-jar.jar}} > /dev/null &

これでうまくいくかもしれません。

0
fifman