web-dev-qa-db-ja.com

LinuxでJavaアプリケーションをサービスとして実行する

標準の仮想ホストLinuxソリューションで実行されるJavaサーバーアプリケーションを作成しました。アプリケーションは常に実行され、ソケット接続をリッスンし、それらの新しいハンドラーを作成します。クライアントサーバーアプリケーションへのサーバー側の実装です。

起動方法は、サーバーの起動rc.localスクリプトに含めることです。しかし、一度起動すると、停止するためにアクセスする方法がわからず、更新プログラムをインストールする必要があるため、アプリケーションを再起動するにはサーバーを再起動する必要があります。

Windows PCでは、このタイプのアプリケーション用にWindowsサービスを作成し、必要に応じて停止および開始できます。 Linuxアプリケーションにはこのようなものがあります。このアプリケーションを起動すると、サーバーを完全に再起動せずに停止して再起動できます。

私のアプリケーションはWebServer.exeと呼ばれます。サーバーの起動時にrc.localなどに含めることで起動します:

Java -jar /var/www/vhosts/myweb.com/phpserv/WebServer.jar &

私はLinuxに少し慣れているので、どんな例でも投稿に感謝します。ただし、SSHがあり、更新プログラムをインストールするためのボックスへの完全なFTPアクセスとPleskパネルへのアクセスがあります。

118
dreza

ここに別の簡単なラッパーを書きました:

#!/bin/sh
SERVICE_NAME=MyService
PATH_TO_JAR=/usr/local/MyProject/MyJar.jar
PID_PATH_NAME=/tmp/MyService-pid
case $1 in
    start)
        echo "Starting $SERVICE_NAME ..."
        if [ ! -f $PID_PATH_NAME ]; then
            Nohup Java -jar $PATH_TO_JAR /tmp 2>> /dev/null >> /dev/null &
            echo $! > $PID_PATH_NAME
            echo "$SERVICE_NAME started ..."
        else
            echo "$SERVICE_NAME is already running ..."
        fi
    ;;
    stop)
        if [ -f $PID_PATH_NAME ]; then
            PID=$(cat $PID_PATH_NAME);
            echo "$SERVICE_NAME stoping ..."
            kill $PID;
            echo "$SERVICE_NAME stopped ..."
            rm $PID_PATH_NAME
        else
            echo "$SERVICE_NAME is not running ..."
        fi
    ;;
    restart)
        if [ -f $PID_PATH_NAME ]; then
            PID=$(cat $PID_PATH_NAME);
            echo "$SERVICE_NAME stopping ...";
            kill $PID;
            echo "$SERVICE_NAME stopped ...";
            rm $PID_PATH_NAME
            echo "$SERVICE_NAME starting ..."
            Nohup Java -jar $PATH_TO_JAR /tmp 2>> /dev/null >> /dev/null &
            echo $! > $PID_PATH_NAME
            echo "$SERVICE_NAME started ..."
        else
            echo "$SERVICE_NAME is not running ..."
        fi
    ;;
esac 

Init.d here およびsystemd(ubuntu 16+) here の完全なチュートリアルに従うことができます。

出力ログが必要な場合は、2を置き換えます

Nohup Java -jar $PATH_TO_JAR /tmp 2>> /dev/null >> /dev/null &

の行

Nohup Java -jar $PATH_TO_JAR >> myService.out 2>&1&
225
PbxMan

簡単な解決策は、Nohupを介してJavaを実行し、PIDをファイルに保存するスクリプトstart.shを作成することです。

Nohup Java -jar myapplication.jar > log.txt 2> errors.txt < /dev/null &
PID=$!
echo $PID > pid.txt

次に、停止スクリプトstop.shがファイルからPIDを読み取り、アプリケーションを強制終了します。

PID=$(cat pid.txt)
kill $PID

もちろん、プロセスが存在するかどうかを確認し、完了したらpid.txtを削除するなど、いくつかの詳細は省略しました。

46
Wernsey

Linuxサービスの初期化スクリプトは/etc/init.dに保存されます。 /etc/init.d/skeletonファイルをコピーしてカスタマイズしてから呼び出すことができます

service [yourservice] start|stop|restart

http://www.ralfebert.de/blog/Java/debian_daemon/ を参照してください。 Debian(つまりUbuntuも)向けですが、より多くのディストリビューションに適合します。

33
Arcadien

たぶん最高の開発者向けソリューションではありませんが、LANパーティなどのサーバーの一般的な使用には適しています。

screenを使用してサーバーを実行し、ログアウトする前に切り離します。これによりプロセスが実行され続け、いつでも再接続できます。

ワークフロー:

画面を開始します:screen

サーバーを起動します:Java -jar minecraft-server.jar

を押して切り離します:Ctl-ad

再接続:screen -r

詳細はこちら: https://www.gnu.org/software/screen/manual/screen.html

10
Peter Peterson

また、非常に人気のある別の選択肢は、 Java Service Wrapper です。これは、OSSコミュニティでも非常に人気があります。

7
carlspring

Spring Boot application as a Service も参照すると、systemdバージョンになります。これは、最も簡単で、冗長で、最新のディストリビューション(さらに、それほど近代的ではないディストリビューションでも)に統合されているためですCentOS 7.xなど)。

5
yglodt

サンプルのシェルスクリプトを次に示します(MATH名をアプリケーションの名前に置き換えてください)。

#!/bin/bash

### BEGIN INIT INFO
# Provides:                 MATH
# Required-Start:           $Java
# Required-Stop:            $Java
# Short-Description:        Start and stop MATH service.
# Description:              -
# Date-Creation:            -
# Date-Last-Modification:   -
# Author:                   -
### END INIT INFO

# Variables
PGREP=/usr/bin/pgrep
Java=/usr/bin/Java
ZERO=0

# Start the MATH
start() {
    echo "Starting MATH..."
    #Verify if the service is running
    $PGREP -f MATH > /dev/null
    VERIFIER=$?
    if [ $ZERO = $VERIFIER ]
    then
        echo "The service is already running"
    else
        #Run the jar file MATH service
        $Java -jar /opt/MATH/MATH.jar > /dev/null 2>&1 &
        #sleep time before the service verification
        sleep 10
        #Verify if the service is running
        $PGREP -f MATH  > /dev/null
        VERIFIER=$?
        if [ $ZERO = $VERIFIER ]
        then
            echo "Service was successfully started"
        else
            echo "Failed to start service"
        fi
    fi
    echo
}

# Stop the MATH
stop() {
    echo "Stopping MATH..."
    #Verify if the service is running
    $PGREP -f MATH > /dev/null
    VERIFIER=$?
    if [ $ZERO = $VERIFIER ]
    then
        #Kill the pid of Java with the service name
        kill -9 $($PGREP -f MATH)
        #Sleep time before the service verification
        sleep 10
        #Verify if the service is running
        $PGREP -f MATH  > /dev/null
        VERIFIER=$?
        if [ $ZERO = $VERIFIER ]
        then
            echo "Failed to stop service"
        else
            echo "Service was successfully stopped"
        fi
    else
        echo "The service is already stopped"
    fi
    echo
}

# Verify the status of MATH
status() {
    echo "Checking status of MATH..."
    #Verify if the service is running
    $PGREP -f MATH > /dev/null
    VERIFIER=$?
    if [ $ZERO = $VERIFIER ]
    then
        echo "Service is running"
    else
        echo "Service is stopped"
    fi
    echo
}

# Main logic
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    status)
        status
        ;;
    restart|reload)
        stop
        start
        ;;
  *)
    echo $"Usage: $0 {start|stop|status|restart|reload}"
    exit 1
esac
exit 0
4
4
Alan Thompson

Spring Boot application as a Service から、Pythonベースのsupervisordアプリケーションを推奨できます。詳細については、スタックオーバーフローの質問を参照してください。設定は本当に簡単です。

3
DuffJ

Thriftサーバー または JMX を使用して、Javaサービスと通信できます。

1
tienthanhakay

Javaコードをデーモン(サービス)として実行するには、JNIベースのスタブを記述できます。

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

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

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

JNIをお楽しみください!

1
Oo.oO

他の回答は、プラットフォームに応じてカスタムスクリプトとセットアップを提供するのに適しています。それらに加えて、私が知っている成熟した特別な目的のプログラムを以下に示します。

  • TanukiSoftwareのJSW
  • YAJSW は上記のオープンソースクローンです。これはJavaで記述されており、構成に従って子プロセス(コード)を管理する乳母プロセスです。 Windows/Linuxで動作します。
  • JSVC はネイティブアプリケーションです。これも乳母プロセスですが、サブプロセスとしてではなく、JNIを通じて子アプリケーションを呼び出します。
1
Mori Bellamy

しかし、一度起動すると、停止するためにアクセスする方法がわかりません

Javaプロセスを模索し、PIDを抽出してkillを呼び出す単純な停止スクリプトを作成できます。それは空想ではありませんが、簡単です。そのような何かが出発点として役立つかもしれません:

#!/bin/bash
PID = ps ax | grep "name of your app" | cut -d ' ' -f 1
kill $PID
0
hovanessyan

From Spring Boot Reference Guide

Init.dサービスとしてのインストール(システムV)

Jarをinit.dにシンボリックリンクして、標準のstartstoprestart、およびstatusコマンドをサポートします。 Spring Bootアプリケーションが/ var/myappにインストールされていると仮定すると、Spring Bootアプリケーションをinit.dサービスとしてインストールするには、単にシンボリックリンクを作成します。

$ Sudo ln -s /var/myapp/myapp.jar /etc/init.d/myapp

インストールしたら、通常の方法でサービスを開始および停止できます。たとえば、Debianベースのシステムの場合:

$ service myapp start

Tip アプリケーションの起動に失敗した場合は、/var/log/<appname>.logに書き込まれたログファイルでエラーを確認してください。

読み続ける デプロイされたサービスを保護する方法を知る。

書かれたとおりに行った後、ログに次のエラーメッセージが表示されてサービスが開始できないことがわかりました: start-stop-daemon:unrecognized option --no-close 。そして、次の内容の構成ファイル/var/myapp/myapp.confを作成することで、それを修正することができました。

USE_START_STOP_DAEMON=false
0
naXa

Linuxサービスとして戦争を実行することは可能です。また、一部のディストリビューションは自動モードで認識されない可能性があるため、パッケージ化する前にpom.xmlファイルを強制することができます。それを行うには、spring-boot-maven-pluginプラグイン内に次のプロパティを追加します。

                    <embeddedLaunchScriptProperties>
                        <mode>service</mode>
                    </embeddedLaunchScriptProperties>

次に、次を使用してinit.dをセットアップします。

ln -s myapp.war /etc/init.d/myapp

そして、あなたは走ることができるでしょう

service myapp start|stop|restart

Spring Boot documentation には、Windowsサービスを含む他の多くのオプションがあります。

0
Eder Luis Jorge