Запустите приложение Java как службу в Linux
Я написал приложение на сервере 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.
14 ответов
Я написал еще одну простую обертку здесь:
#!/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&
Простое решение - создать скрипт 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
если вы сделали.
Сценарий инициализации службы Linux хранится в /etc/init.d
, Вы можете скопировать и настроить /etc/init.d/skeleton
файл, а затем позвоните
service [yourservice] start|stop|restart
см. http://www.ralfebert.de/blog/java/debian_daemon/. Это для Debian (так же, как и для Ubuntu), но больше подходит для распространения.
Возможно, не лучшее решение для разработчиков, но оно хорошо для общего использования сервера для локальной вечеринки или чего-то подобного.
использование screen
чтобы запустить сервер и затем отключить его перед выходом из системы, процесс останется запущенным, затем вы можете снова присоединить его в любой момент.
Процедура:
Начать экран: screen
Запустите свой сервер: java -jar minecraft-server.jar
Отсоедините нажатием: Ctl-a
, d
Заново присоедините: screen -r
Более подробная информация здесь: https://www.gnu.org/software/screen/manual/screen.html
Другой альтернативой, которая также довольно популярна, является Java Service Wrapper. Это также довольно популярно в сообществе OSS.
Ссылаясь на приложение Spring Boot в качестве службы, я бы пошел на systemd
версия, поскольку она является самой простой, наименее многословной и лучше всего интегрированной в современные дистрибутивы (и даже не такие современные, как CentOS 7.x).
Самый простой способ - это использовать supervisord
, Пожалуйста, смотрите полную информацию здесь: http://supervisord.org/
Больше информации:
https://askubuntu.com/questions/779830/running-an-executable-jar-file-when-the-system-starts/852485
Вот пример сценария оболочки (убедитесь, что вы заменили имя 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
Из приложения Spring Boot как службы я могу порекомендовать Python на основе supervisord
приложение. Смотрите этот вопрос переполнения стека для получения дополнительной информации. Это действительно просто настроить.
Другие ответы отлично справляются с заданием пользовательских сценариев и настроек в зависимости от вашей платформы. В дополнение к этим, вот зрелые, специализированные программы, о которых я знаю:
- JSW от TanukiSoftware
- YAJSW - клон с открытым исходным кодом из вышеперечисленного. Он написан на Java, и это процесс няни, который управляет дочерним процессом (вашим кодом) в соответствии с конфигурациями. Работает на Windows / Linux.
- JSVC является нативным приложением. Это также процесс няни, но он вызывает ваше дочернее приложение через JNI, а не как подпроцесс.
Однако однажды начавшись, я не знаю, как получить к нему доступ, чтобы остановить его
Вы можете написать простой скрипт остановки, который подготавливает ваш Java-процесс, извлекает PID и вызывает kill. Это не модно, но это прямо вперед. Нечто подобное может помочь в начале:
#!/bin/bash
PID = ps ax | grep "name of your app" | cut -d ' ' -f 1
kill $PID
Вы можете использовать сервер Thrift или JMX для связи с вашим сервисом Java.
У меня есть Java-приложение Netty, и я хочу запустить его как службу с помощью systemd. К сожалению, приложение останавливается независимо от того, какой тип я использую. В конце я завернул java start в screen. Вот файлы конфигурации:
служба
[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
.
Из Spring Boot Справочное руководство
Установка в качестве службы init.d (System V)
Просто символическую банку
init.d
поддерживать стандартstart
,stop
,restart
а такжеstatus
команды. Предполагая, что у вас установлено приложение Spring Boot в / var / myapp, чтобы установить приложение Spring Boot в качестве службы init.d, просто создайте символическую ссылку:$ sudo ln -s /var/myapp/myapp.jar /etc/init.d/myapp
После установки вы можете запускать и останавливать службу обычным способом. Например, в системе на основе Debian:
$ service myapp start
Если ваше приложение не запускается, проверьте файл журнала, записанный в
/var/log/<appname>.log
за ошибки.
Продолжайте читать, чтобы узнать, как защитить развернутую службу.
Сделав, как написано, я обнаружил, что моя служба не запускается с этим сообщением об ошибке в журналах: start-stop-daemon: нераспознанная опция --no-close. И мне удалось это исправить, создав файл конфигурации /var/myapp/myapp.conf
со следующим содержанием
USE_START_STOP_DAEMON=false
Чтобы запустить Java-код как демон (сервис), вы можете написать заглушку на основе JNI.
http://jnicookbook.owsiak.org/recipe-no-022/
для примера кода, который основан на JNI. В этом случае вы демонизируете код, который был запущен как Java, и основной цикл выполняется в C. Но также возможно поместить основной цикл, демон, сервисный цикл в Java.
https://github.com/mkowsiak/jnicookbook/tree/master/recipeNo029
Веселитесь вместе с JNI!
It is possible to run the war as a Linux service, and you may want to force in your pom.xml file before packaging, as some distros may not recognize in auto mode. To do it, add the following property inside of spring-boot-maven-plugin plugin.
<embeddedLaunchScriptProperties>
<mode>service</mode>
</embeddedLaunchScriptProperties>
Next, setup your init.d with:
ln -s myapp.war /etc/init.d/myapp
and you will be able to run
service myapp start|stop|restart
There are many other options that you can find in Spring Boot documentation, including Windows service.