Вопрос по linux, service, java – Запустите приложение Java как службу в Linux

117

Я написал приложение на сервере Java, которое работает на стандартном Linux-решении с виртуальным хостингом. Приложение работает все время, прослушивая сокетные соединения и создавая для них новые обработчики. Это реализация на стороне сервера для клиент-серверного приложения.

То, как я начинаю это, включив его в запускrc.local скрипт сервера. Однако после запуска я не знаю, как получить к нему доступ, чтобы остановить его, и если я хочу установить обновление, поэтому мне нужно перезапустить сервер, чтобы перезапустить приложение.

На ПК под управлением Windows для такого типа приложений я мог бы создать службу Windows, а затем остановить и запустить ее, как захочу. Есть ли что-нибудь подобное на коробке с Linux, чтобы, если я запустил это приложение, я мог остановить его и перезапустить без полной перезагрузки сервера.

Мое приложение называется WebServer.exe. Он запускается при запуске сервера путем включения его в мойrc.local в качестве таких:

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

Я немного новичок в Linux, поэтому любой пример был бы оценен с любыми постами. Однако у меня есть SSH и полный FTP-доступ к коробке для установки любых обновлений, а также доступ к панели Plesk.

Ваш Ответ

15   ответов
3

Приложение Spring Boot как сервисЯ могу порекомендовать Python на основеsupervisord приложение. Смотрите этот вопрос переполнения стека для получения дополнительной информации. Это действительно просто настроить.

supervisord отлично, для тех, кто не знает, это позволяет контролировать услуги (которые должны бытьforeground - нетdaemonized), он будет автоматически перезапускать службы (и может отправлять оповещения по электронной почте, когда перезапуски происходят через плагины)
4

Самый простой способ - это использоватьsupervisord, Пожалуйста, смотрите полную информацию здесь:http://supervisord.org/

Больше информации:

https://askubuntu.com/questions/779830/running-an-executable-jar-file-when-the-system-starts/852485#852485

https://www.digitalocean.com/community/tutorials/how-to-install-and-manage-supervisor-on-ubuntu-and-debian-vps

225

Я написал еще одну простую обертку здесь:

#!/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Вот и для systemd (Ubuntu 16+) Вот

Если вам нужен выходной журнал, замените2

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

линии для

nohup java -jar $PATH_TO_JAR >> myService.out 2>&1&
@JackDaniel в дистрибутивах на основе Debian, таких как Debian и Ubuntu, вы можете добавить этот скрипт в /etc/init.d. Затем вы можете вызвать его так: /etc/init.d/MyService start. И вы можете запустить его автоматически, запустив update-rc.d MyService по умолчанию.
@PbxMan спасибо за это. Я мог бы попробовать и посмотреть, как мы продвигаемся. Приветствия. dreza
но как я могу запустить этот файл? где я должен это поставить?
Где будет выходной файл банки? как я могу настроить его имя?
@ Thorbj & # xF8; rnRavnAndersen Это будет зависеть от вашей Java-программы. Если вы не можете убить свою Java-программуstackoverflow.com/questions/2541597/…, Я бы удалил pid MyService вместо kill и имел бы поток deamon в части Java, который проверяет, существует ли он.
45

Простое решение - создать скрипт start.sh, который запускает Java через nohup, а затем сохраняет PID в файл:

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 если вы сделали.

Вопрос. Не приведет ли команда kill $ PID к завершению процесса без его завершения? Я пишу серверную программу, которая взаимодействует с базой данных, и я хотел бы, чтобы все запущенные в настоящее время потоки заканчивались до завершения программы, чтобы гарантировать, что программа не умирает в середине записи в БД или что-то в этом роде. ,
@ Скуба-Стив вроде. kill отправит сигнал TERM, который вызовет все имеющиеся перехватчики завершения работы, поэтому используйте их для корректного завершения вашего процесса. Они не выполнятся, если процесс получит сигнал уничтожения (то есть, уничтожить -9). ОС может прервать ваши перехватчики завершения работы, если они занимают слишком много времени, поэтому держите их краткими
10

Возможно, не лучшее решение для разработчиков, но оно хорошо для общего использования сервера для локальной вечеринки или чего-то подобного.

использованиеscreen чтобы запустить сервер и затем отключить его перед выходом из системы, процесс останется запущенным, затем вы можете повторно подключить его в любой момент.

Workflow:

Начать экран:screen

Запустите свой сервер:java -jar minecraft-server.jar

Отсоедините нажатием:Ctl-a, d

Заново присоедините:screen -r

Больше информации здесь:https://www.gnu.org/software/screen/manual/screen.html

0

However once started I don't know how to access it to stop it

Вы можете написать простой скрипт остановки, который подготавливает ваш Java-процесс, извлекает PID и вызывает kill. Это не причудливо, но прямо. Нечто подобное может помочь в начале:

#!/bin/bash
PID = ps ax | grep "name of your app" | cut -d ' ' -f 1
kill $PID
Я не очень хорош в Linux, но не оченьpkill nameofprocess делать то же самое?
1

Другие ответы хорошо справляются с заданием пользовательских сценариев и настроек в зависимости от вашей платформы. В дополнение к этим, вот зрелые, специализированные программы, о которых я знаю:

  • JSW from TanukiSoftware
  • YAJSW is an open source clone from the above. It is written in Java, and it is a nanny process that manages the child process (your code) according to configurations. Works on windows / linux.
  • JSVC is a native application. Its also a nanny process, but it invokes your child application through the JNI, rather than as a subprocess.
32

Сценарий инициализации службы Linux хранится в/etc/init.d, Вы можете скопировать и настроить/etc/init.d/skeleton файл, а затем позвоните

service [yourservice] start|stop|restart

увидетьhttp://www.ralfebert.de/blog/java/debian_daemon/, Это для Debian (так же, как и для Ubuntu), но больше подходит для распространения.

Выглядит многообещающе. Я буду более внимательно смотреть на это. ура dreza
0

From Spring Boot Справочное руководство

Installation as an init.d service (System V)

Simply symlink the jar to init.d to support the standard start, stop, restart and status commands. Assuming that you have a Spring Boot application installed in /var/myapp, to install a Spring Boot application as an init.d service simply create a symlink:

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

Once installed, you can start and stop the service in the usual way. For example, on a Debian based system:

$ service myapp start

Tip If your application fails to start, check the log file written to /var/log/<appname>.log for errors.

продолжить чтение знать, как обезопасить развернутый сервис.

После того, как все было сделано, я обнаружил, что моя служба не запускается с этим сообщением об ошибке в журналах:start-stop-daemon: нераспознанная опция --no-close, И мне удалось это исправить, создав файл конфигурации/var/myapp/myapp.conf со следующим содержанием

USE_START_STOP_DAEMON=false
0

Можно запустить war как службу 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 документация, включая службу Windows.

1

Ты можешь использоватьКомиссионный сервер или жеJMX общаться с вашим сервисом Java.

7

Другой альтернативой, которая также довольно популярна, являетсяJava Service Wrapper, Это также довольно популярно в сообществе OSS.

Приветствия. Я видел некоторые упоминания об этом. Присмотритесь. dreza
1

Для запуска кода Java в качестве демона (службы) вы можете написать заглушку на основе JNI.

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

для примера кода, который основан на JNI. В этом случае вы демонизируете код, который был запущен как Java, и основной цикл выполняется на C. Но также возможно поместить основной цикл, демон службы, в Java.

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

Веселитесь вместе с JNI!

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.
Причина, по которой pgrep считает, что служба работает, заключается в том, что она обнаруживает / bin / sh / sbin / service MATH start & quot; и & quot; / bin / bash /etc/init.d/MATH start & quot; и возвращает 0
5

Ссылаясь наПриложение Spring Boot как сервис а я бы пошел наsystemd версия, поскольку она является самой простой, наименее подробной и лучше всего интегрированной в современные дистрибутивы (и даже не такие современные, как CentOS 7.x).

Похожие вопросы