Linux에서 Java 응용 프로그램을 서비스로 실행


128

표준 가상 호스팅 Linux 솔루션에서 실행되는 Java 서버 응용 프로그램을 작성했습니다. 애플리케이션은 항상 소켓 연결을 청취하고이를위한 새 핸들러를 작성합니다. 클라이언트-서버 애플리케이션에 대한 서버 측 구현입니다.

시작하는 방법은 시작 rc.local 에 포함시키는 것입니다. 은 서버 스크립트에 포함시키는 것입니다. 그러나 일단 시작되면 업데이트를 중지하고 업데이트를 설치하려는 경우 액세스 방법을 모르므로 응용 프로그램을 다시 시작하려면 서버를 다시 시작해야합니다.

Windows PC에서 이러한 유형의 응용 프로그램에 대해 Windows 서비스를 만든 다음 원하는대로 중지하고 시작할 수 있습니다. Linux 상자에 이와 같은 것이 있습니까? 그래서이 응용 프로그램을 시작하면 서버를 완전히 다시 시작하지 않고도 응용 프로그램을 중지하고 다시 시작할 수 있습니다.

내 응용 프로그램은 WebServer.exe입니다. 다음 과 같이 rc.local 에 포함시켜 서버 시작시 시작됩니다 .

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

나는 리눅스에서 약간의 멍청한 놈이므로 어떤 예라도 모든 게시물로 높이 평가 될 것입니다. 그러나 SSH와 Plesk 패널에 대한 액세스뿐만 아니라 모든 업데이트를 설치하기 위해 상자에 대한 전체 FTP 액세스가 있습니다.

답변:


239

여기에 또 다른 간단한 래퍼를 작성했습니다.

#!/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를 위해 전체 튜토리얼을 따라 할 수 여기 와 (우분투 16+) systemd를 위해 여기

출력 로그가 필요한 경우 2

nohup java -jar $PATH_TO_JAR /tmp 2>> /dev/null >> /dev/null &

~에 대한 라인

nohup java -jar $PATH_TO_JAR >> myService.out 2>&1&

@PbxMan 감사합니다. 나는 그것을 갈 수 있고 우리가 어떻게 진행되는지 볼 수 있습니다. 건배.
dreza

2
하지만이 파일을 어떻게 실행할 수 있습니까? 어디에 두어야합니까?
잭 다니엘

3
데비안 자체 및 우분투와 같은 데비안 기반 배포판의 @JackDaniel은 /etc/init.d에 해당 스크립트를 추가 할 수 있습니다. 그런 다음 /etc/init.d/MyService start와 같이 호출 할 수 있습니다. update-rc.d MyService defaults를 실행하여 자동으로 시작되도록 할 수 있습니다.
Andre

1
@ ThorbjørnRavnAndersen Java 프로그램에 따라 다릅니다. Java 프로그램을 종료 할 수없는 경우 stackoverflow.com/questions/2541597/…를 확인하십시오 . kill 대신 MyService-pid를 삭제하고 Java 부분에 deamon 스레드가 있는지 확인합니다.
PbxMan

1
항아리의 출력 파일은 어디에 있습니까? 이름을 어떻게 구성 할 수 있습니까?
M. Schena

48

간단한 해결책은 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하고 완료되면 제거하는 등의 세부 정보를 생략했습니다 .


2
질문 : kill $ PID 명령으로 인해 프로세스가 종료되지 않고 종료되지 않습니까? 데이터베이스와 인터페이스하는 서버 프로그램을 작성 중이며 프로그램이 종료되기 전에 현재 실행중인 모든 스레드를 끝내고 프로그램이 DB 또는 다른 것에 대한 쓰기 도중에 죽지 않도록하고 싶습니다. .
스쿠버 스티브

2
@ scuba-steve 종류의. kill은 TERM 신호를 보내어 제자리에있는 종료 후크를 호출하므로 프로세스를 정상적으로 종료하는 데 사용하십시오. 프로세스가 kill 신호 (즉, kill -9)를 받으면 실행되지 않습니다. 완료하는 데 너무 오래 걸리면 OS가 종료 후크를 중단시킬 수 있으므로 간결하게 유지하십시오.
rjohnston


11

아마도 최고의 dev-ops 솔루션은 아니지만 lan party 또는 이와 유사한 서버를 일반적으로 사용하는 데 적합합니다.

사용 screen에 서버를 실행 한 다음 로그 아웃하기 전에 분리,이 프로세스가 계속 실행됩니다, 당신은 어느 시점에 다시 연결할 수 있습니다.

워크 플로우 :

화면을 시작하십시오. screen

서버를 시작하십시오. java -jar minecraft-server.jar

다음을 눌러 분리하십시오 : Ctl-a,d

다시 부착 : screen -r

자세한 내용은 여기 : https://www.gnu.org/software/screen/manual/screen.html


7

또 다른 대안은 Java Service Wrapper 입니다. 이것은 OSS 커뮤니티에서도 꽤 인기가 있습니다.


건배. 나는 그것에 대한 언급을 보았다. 자세히 살펴볼 것입니다.
dreza



4

다음은 샘플 쉘 스크립트입니다 (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

어떤 이유로 든 항상 서비스가 이미 시작되었다고보고합니다. 이 스크립트 내부에서 실행할 때 pgrep을 0을 반환 나타납니다,하지만 수동으로 pgrep을 명령을 입력하는 경우는 1 반환
HomeIsWhereThePcIs

pgrep가 서비스가 실행되고 있다고 생각하는 이유는 "/ bin / sh / sbin / service MATH start"및 "/ bin / bash /etc/init.d/MATH start"를
감지

3

에서 서비스로 봄 부팅 응용 프로그램 , 나는 파이썬 기반 추천 할 수있는 supervisord응용 프로그램을. 자세한 내용은 스택 오버플로 질문을 참조하십시오. 설정하는 것은 정말 간단합니다.


supervisord모르는 사람들을 위해, 그것은 허용, 대단한 모니터링 서비스 (해야한다 foreground-하지 daemonized), 그 다음 자동 재시작 서비스 (다시 시작이 플러그인을 통해 발생할 때 경고를 이메일로 보낼 수 있습니다) 것
wired00

2

다른 답변은 플랫폼에 따라 사용자 정의 스크립트 및 설정을 제공하는 것이 좋습니다. 그 외에도 다음과 같은 성숙하고 특수한 프로그램이 있습니다.

  • TanukiSoftware의 JSW
  • YAJSW 는 위의 오픈 소스 클론입니다. Java로 작성되었으며 구성에 따라 하위 프로세스 (코드)를 관리하는 보모 프로세스입니다. Windows / Linux에서 작동합니다.
  • JSVC 는 기본 애플리케이션입니다. 보모 프로세스이지만 하위 프로세스가 아닌 JNI를 통해 자녀 응용 프로그램을 호출합니다.


1

에서 봄 부팅 참조 가이드

init.d 서비스로 설치 (System V)

간단히하기 위해 단지를 심볼릭 링크 init.d표준 지원 start, stop, restartstatus명령. / var / myapp에 스프링 부트 애플리케이션이 설치되어 있다고 가정하면 스프링 부트 애플리케이션을 init.d 서비스로 설치하려면 간단히 심볼릭 링크를 작성하십시오.

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

일단 설치되면 일반적인 방법으로 서비스를 시작하고 중지 할 수 있습니다. 예를 들어, 데비안 기반 시스템에서 :

$ service myapp start

팁응용 프로그램이 시작되지 않으면 기록 된 로그 파일 /var/log/<appname>.log에서 오류 를 확인하십시오 .

배포 된 서비스를 보호하는 방법을 알아 보려면 계속 읽으십시오 .

서면으로 한 후 로그에서 다음 오류 메시지로 서비스가 시작되지 않는 것을 발견했습니다. start-stop-daemon : unrecognized option --no-close . 그리고 /var/myapp/myapp.conf다음 내용으로 구성 파일 을 만들어서 수정했습니다.

USE_START_STOP_DAEMON=false

1

Netty Java 응용 프로그램이 있고 systemd를 사용하여 서비스로 실행하고 싶습니다. 불행히도 응용 프로그램은 내가 사용하는 유형에 관계없이 중지됩니다. 결국 나는 자바 시작을 화면에 감쌌다. 구성 파일은 다음과 같습니다.

서비스

[Unit]
Description=Netty service
After=network.target
[Service]
User=user
Type=forking
WorkingDirectory=/home/user/app
ExecStart=/home/user/app/start.sh
TimeoutStopSec=10
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target

스타트

#!/bin/sh
/usr/bin/screen -L -dmS netty_app java -cp app.jar classPath

그 시점부터 사용할 수 있습니다 systemctl [start|stop|status] service.


1

데몬 (서비스)으로 Java 코드를 실행하려면 JNI 기반 스텁을 작성할 수 있습니다.

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

JNI를 기반으로하는 샘플 코드 이 경우 Java로 시작된 코드를 디먼으로 초기화하고 main 루프는 C에서 실행됩니다. 그러나 기본 데몬의 서비스 루프를 Java에 넣을 수도 있습니다.

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

JNI와 함께 즐거운 시간 보내십시오!


0

그러나 일단 시작되면 나는 그것을 막기 위해 그것을 접근하는 방법을 모른다

Java 프로세스에 대해 grep하고 PID를 추출하여 kill을 호출하는 간단한 중지 스크립트를 작성할 수 있습니다. 환상적이지는 않지만 간단합니다. 그와 같은 것이 시작으로 도움이 될 수 있습니다.

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

2
나는 리눅스에서별로 좋지는 않지만 pkill nameofprocess같은 일을하지는 않습니까?
Denys Séguret 2016 년

0

전쟁을 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

Windows 서비스를 포함하여 Spring Boot 문서 에서 찾을 수있는 다른 많은 옵션이 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.