Linux'ta Hizmet Olarak Java Uygulaması Çalıştırın


128

Standart bir sanal barındırılan Linux çözümü üzerinde çalışan bir Java sunucu uygulaması yazdım. Uygulama, soket bağlantılarını dinleyerek ve onlar için yeni işleyiciler oluşturarak her zaman çalışır. Bir istemci-sunucu uygulamasının sunucu tarafı uygulamasıdır.

Başlatma şeklim , onu sunucunun rc.local betiğine dahil etmektir. Ancak bir kez başladıktan sonra onu durdurmak için nasıl erişeceğimi bilmiyorum ve bir güncelleme yüklemek istersem, uygulamayı yeniden başlatmak için sunucuyu yeniden başlatmam gerekiyor.

Bir Windows PC'de, bu tür bir uygulama için bir Windows servisi oluşturabilirim ve sonra onu istediğim gibi durdurabilir ve başlatabilirim. Linux kutusunda buna benzer bir şey var mı, böylece bu uygulamayı başlatırsam sunucuyu tamamen yeniden başlatmadan onu durdurabilir ve yeniden başlatabilirim.

Uygulamamın adı WebServer.exe. Sunucu başlangıcında, rc.local'uma şu şekilde dahil edilerek başlatıldı :

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

Linux'ta biraz acemiyim, bu yüzden herhangi bir örnek herhangi bir gönderi ile takdir edilecektir. Bununla birlikte, herhangi bir güncellemeyi yüklemek ve bir Plesk paneline erişim için kutuya SSH ve tam FTP erişimim var.

Yanıtlar:


239

Buraya başka bir basit paket yazdım:

#!/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 

Burada init.d ve systemd (ubuntu 16+) için tam bir öğreticiyi takip edebilirsiniz. buraya

Çıktı günlüğüne ihtiyacınız varsa, 2

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

hatları için

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

@PbxMan bunun için teşekkürler. Bir deneyebilir ve nasıl devam edeceğimize bakabilirim. Şerefe.
dreza

2
ama bu dosyayı nasıl çalıştırabilirim? nereye koymalıyım?
Jack Daniel

3
Debian'ın kendisi ve ubuntu gibi debian tabanlı dağıtımlarda @JackDaniel, bu betiği /etc/init.d'ye ekleyebilirsiniz. Daha sonra bunu şu şekilde çağırabilirsiniz: /etc/init.d/MyService start. Ayrıca update-rc.d MyService varsayılanlarını çalıştırarak otomatik olarak başlamasını sağlayabilirsiniz.
Andre

1
@ ThorbjørnRavnAndersen Bu sizin java programınıza bağlı olacaktır. Java programınızı öldüremiyorsanız stackoverflow.com/questions/2541597/… adresine bakın . Kill yerine MyService-pid'i silerim ve Java kısmında var olup olmadığını kontrol eden deamon iş parçacığına sahip olurdum.
PbxMan

1
Kavanozun çıktı dosyası nerede olacak? adını nasıl yapılandırabilirim?
M.Schena

48

Basit bir çözüm, Java'yı nohup aracılığıyla çalıştıran ve ardından PID'yi bir dosyaya depolayan bir start.sh betiği oluşturmaktır:

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

Daha sonra stop betiğiniz stop.sh dosyadan PID'yi okur ve uygulamayı kapatır:

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

Elbette, işlemin var olup olmadığını kontrol etme ve pid.txtbittiyseniz kaldırma gibi bazı ayrıntıları atladım.


2
Soru: $ PID'yi öldür komutu, işlemin bitmeden sonlandırılmasına neden olmaz mı? Bir veritabanı ile arabirim oluşturan bir sunucu programı yazıyorum ve programın DB'ye yazılırken ya da başka bir şeyin ortasında ölmemesini sağlamak için şu anda çalışan tüm iş parçacıklarının programdan çıkmadan önce bitirmesini istiyorum. .
Scuba Steve

2
@ scuba-steve bir çeşit. kill, mevcut olan herhangi bir kapatma kancasını çağıracak olan TERM sinyalini gönderir, bu nedenle işleminizi zarif bir şekilde sonlandırmak için bunları kullanın. İşlem bir kill sinyali alırsa (yani, kill -9) çalışmazlar. İşletim sistemi, tamamlanması çok uzun
sürüyorsa

34

Linux hizmet başlatma betiği, içinde saklanır /etc/init.d. Dosyayı kopyalayıp özelleştirebilir /etc/init.d/skeletonve ardından

service [yourservice] start|stop|restart

bkz. http://www.ralfebert.de/blog/java/debian_daemon/ . Debian için (yani Ubuntu) ama daha fazla dağıtıma uygun.


Umut verici görünüyor. Buna daha yakından bakacağım. şerefe
dreza

11

Belki en iyi geliştirme çözümü değil, ancak bir LAN partisi veya benzeri bir sunucunun genel kullanımı için iyi.

screenSunucunuzu çalıştırmak için kullanın ve oturumu kapatmadan önce bağlantısını kesin, bu işlemin devam etmesini sağlar, daha sonra istediğiniz zaman yeniden ekleyebilirsiniz.

İş Akışı:

Bir ekran başlatın: screen

Sunucunuzu başlatın: java -jar minecraft-server.jar

Basarak Ayır: Ctl-a,d

Yeniden takmak: screen -r

Daha fazla bilgi burada: https://www.gnu.org/software/screen/manual/screen.html


7

Oldukça popüler olan bir diğer alternatif ise Java Service Wrapper'dır . Bu, OSS topluluğu çevresinde de oldukça popülerdir.


Şerefe. Bundan bazılarının bahsettiğini görmüştüm. Daha yakından bakacak.
dreza



4

İşte örnek bir kabuk komut dosyası (MATH adını uygulamanızın adıyla değiştirdiğinizden emin olun):

#!/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

Bazı nedenlerden dolayı bu her zaman hizmetin zaten başlatıldığını bildirir. Görünüşe göre pgrep komut dosyasının içinden çalıştırıldığında 0 döndürüyor, ancak pgrep komutunu manuel olarak
girersem

Pgrep'in hizmetin çalıştığını düşünmesinin nedeni, "/ bin / sh / sbin / service MATH start" ve "/ bin / bash /etc/init.d/MATH start"
algılaması

3

Gönderen Hizmet olarak Bahar Boot uygulaması , ben Python tabanlı önerebilir supervisorduygulama. Daha fazla bilgi için bu yığın taşma sorusuna bakın. Kurulumu gerçekten çok basit.


supervisordBilmeyenler için harika, izleme hizmetlerine izin veriyor (öyle olmalı foreground- değil daemonized), daha sonra hizmetleri otomatik olarak yeniden başlatacak (ve eklentiler aracılığıyla yeniden başlatmalar gerçekleştiğinde uyarıları e-postayla
gönderebilir

2

Diğer yanıtlar, platformunuza bağlı olarak özel komut dosyaları ve kurulumlar vererek iyi bir iş çıkarır. Bunlara ek olarak, işte bildiğim olgun, özel amaçlı programlar:

  • TanukiSoftware'den JSW
  • YAJSW , yukarıdan açık kaynaklı bir klondur . Java ile yazılmıştır ve alt süreci (kodunuzu) yapılandırmalara göre yöneten bir dadı işlemidir. Windows / linux üzerinde çalışır.
  • JSVC yerel bir uygulamadır. Aynı zamanda bir dadı sürecidir, ancak çocuğunuzun başvurusunu bir alt işlem yerine JNI aracılığıyla başlatır.


1

Gönderen Bahar Önyükleme Başvuru Kılavuzu'nda

İnit.d hizmeti olarak kurulum (System V)

Basitçe için kavanozu sembolik bir link init.dstandardını destekleyen start, stop, restartve statuskomutları. / Var / myapp içinde bir Spring Boot uygulamanızın kurulu olduğunu varsayarsak, bir init.d hizmeti olarak bir Spring Boot uygulamasını kurmak için bir symlink oluşturmanız yeterlidir:

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

Kurulduktan sonra hizmeti normal şekilde başlatabilir ve durdurabilirsiniz. Örneğin, Debian tabanlı bir sistemde:

$ service myapp start

İpucuUygulamanız başlamazsa, yazılan günlük dosyasını /var/log/<appname>.loghatalar için kontrol edin .

okumaya devam etDağıtılan bir hizmetin güvenliğini nasıl sağlayacağınızı öğrenmek için .

Yazılanları yaptıktan sonra, hizmetimin günlüklerde bu hata mesajıyla başlayamadığını keşfettim: start-stop-daemon: tanınmayan seçenek --no-close . Ve /var/myapp/myapp.confaşağıdaki içeriğe sahip bir yapılandırma dosyası oluşturarak düzeltmeyi başardım

USE_START_STOP_DAEMON=false

1

Netty java uygulamasına sahibim ve systemd ile bir servis olarak çalıştırmak istiyorum. Ne yazık ki, hangi tür kullandığım önemli değil, uygulama duruyor. Sonunda java başlangıcını ekrana sardım. Yapılandırma dosyaları şunlardır:

hizmet

[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

Başlat

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

o noktadan itibaren kullanabilirsiniz systemctl [start|stop|status] service.



0

Ancak bir kez başladığında onu durdurmak için nasıl erişeceğimi bilmiyorum

Java işleminiz için greps yapan, PID'yi çıkaran ve üzerinde kill çağıran basit bir durdurma betiği yazabilirsiniz. Süslü değil ama basit. Bunun gibi bir şey başlangıç ​​olarak yardımcı olabilir:

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

2
Linux'ta pek iyi değilim ama pkill nameofprocessaynı şeyi yapmıyor mu?
Denys Séguret

0

Savaşı bir Linux hizmeti olarak yürütmek mümkündür ve bazı dağıtımlar otomatik modda tanımayabileceğinden, paketlemeden önce pom.xml dosyanızı zorlamak isteyebilirsiniz. Bunu yapmak için, spring-boot-maven-plugin eklentisinin içine aşağıdaki özelliği ekleyin.

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

Ardından, init.d'nizi şu şekilde ayarlayın:

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

ve koşabileceksin

service myapp start|stop|restart

Windows hizmeti de dahil olmak üzere Spring Boot belgelerinde bulabileceğiniz başka birçok seçenek vardır .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.