लिनक्स पर एक सेवा के रूप में एक जावा एप्लिकेशन चलाएं


128

मैंने एक जावा सर्वर एप्लिकेशन लिखा है जो एक मानक वर्चुअल होस्टेड लिनक्स समाधान पर चलता है। आवेदन हर समय सॉकेट कनेक्शन के लिए सुनता है और उनके लिए नए हैंडलर बनाता है। यह क्लाइंट-सर्वर एप्लिकेशन के लिए सर्वर साइड कार्यान्वयन है।

जिस तरह से मैं इसे शुरू करता हूं वह सर्वर के स्टार्ट अप लिकलिक स्क्रिप्ट में इसे शामिल करता है। हालांकि एक बार शुरू करने के बाद मुझे नहीं पता कि इसे रोकने के लिए इसे कैसे एक्सेस किया जाए और अगर मैं अपडेट इंस्टॉल करना चाहता हूं, तो मुझे एप्लिकेशन को पुनरारंभ करने के लिए सर्वर को पुनरारंभ करना होगा।

एक विंडोज़ पीसी पर, इस प्रकार के एप्लिकेशन के लिए मैं एक विंडोज़ सेवा बना सकता हूं और फिर मैं इसे बंद कर सकता हूं और इसे शुरू कर सकता हूं जैसा मैं चाहता हूं। क्या लिनक्स बॉक्स पर ऐसा कुछ है जिससे अगर मैं इस एप्लिकेशन को शुरू करता हूं तो मैं इसे रोक सकता हूं और सर्वर को पूरी तरह से पुनरारंभ किए बिना इसे पुनरारंभ कर सकता हूं।

मेरे आवेदन को WebServer.exe कहा जाता है। यह सर्वर स्टार्टअप पर इसे मेरे rc.local में इस तरह से शामिल करके शुरू किया गया है :

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

मैं लिनक्स में एक noob का एक सा हूँ इसलिए किसी भी उदाहरण किसी भी पोस्ट के साथ सराहना की जाएगी। हालाँकि, मेरे पास SSH है, और किसी भी अद्यतन को स्थापित करने के लिए बॉक्स के लिए पूर्ण एफ़टीपी एक्सेस के साथ-साथ एक Plesk पैनल तक भी पहुँच है।

जवाबों:


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 के लिए और 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&

@PbxMan को इसके लिए धन्यवाद। मैं इसे दे सकता हूं और देख सकता हूं कि हम कैसे आगे बढ़ते हैं। चीयर्स।
dreza

2
लेकिन मैं इस फाइल को कैसे चला सकता हूं? मैं इसे कहाँ रखूँ?
जैक डैनियल

3
@JackDaniel डेबियन-आधारित डिस्ट्रोस पर, डेबियन खुद की और ubuntu की तरह, आप उस स्क्रिप्ट को /etc/init.d में जोड़ सकते हैं। फिर आप इसे इस तरह से लागू कर सकते हैं: /etc/init.d/MyService प्रारंभ। और आप इसे अपडेट- rdd MyService चूक से चलाकर स्वचालित रूप से प्रारंभ कर सकते हैं।
आंद्रे

1
@ ThorbjørnRavnAndersen जो आपके जावा प्रोग्राम पर निर्भर करेगा। यदि आप अपने जावा प्रोग्राम को नहीं मार सकते हैं तो stackoverflow.com/questions/2541597/… देखें । मैं मारने के बजाय MyService-pid को हटा देता और जावा भाग में बहरा धागा होता है जो जाँचता है कि यह मौजूद है या नहीं।
PbxMan

1
जार की ouput फ़ाइल कहाँ होगी? मैं यह कैसे नाम कॉन्फ़िगर कर सकते हैं?
एम। शीना

48

एक सरल समाधान एक स्क्रिप्ट start.sh बनाना है जो Java को nohup के माध्यम से चलाता है और फिर PID को एक फ़ाइल में संग्रहीत करता है:

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

तब आपका स्टॉप स्क्रिप्ट स्टॉप.श फाइल से पीआईडी ​​को पढ़ेगा और एप्लिकेशन को मार देगा:

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

बेशक, मैंने कुछ विवरणों को छोड़ दिया है, जैसे कि यह जाँचना कि क्या प्रक्रिया मौजूद है और pid.txtयदि आप कर रहे हैं तो हटा दें।


2
प्रश्न: मार नहीं होगा $ PID आदेश के कारण प्रक्रिया को खत्म किए बिना मार दिया जाएगा? मैं एक सर्वर प्रोग्राम लिख रहा हूं, जो एक डेटाबेस के साथ इंटरफेस करता है, और मैं चाहता हूं कि कार्यक्रम से बाहर निकलने से पहले सभी वर्तमान में थ्रेड चल रहे हों, ताकि यह सुनिश्चित हो सके कि प्रोग्राम डीबी या कुछ लिखने के बीच में नहीं मरता है ।
स्कूबा स्टीव

2
@ स्कूबा-स्टीव की तरह। किल TERM सिग्नल भेजेगा, जो किसी भी शटडाउन हुक को लागू करेगा जो कि जगह में हैं, इसलिए उन्हें अपनी प्रक्रिया को सुखद तरीके से समाप्त करने के लिए उपयोग करें। यदि प्रक्रिया को किल सिग्नल (यानी, किल -9) मिलता है तो वे निष्पादित नहीं करेंगे। यदि वे पूर्ण होने में बहुत अधिक समय ले रहे हैं, तो OS आपके शटडाउन हुक को बाधित कर सकता है, इसलिए उन्हें संक्षिप्त रखें
rjohnston

34

लिनक्स सेवा init स्क्रिप्ट में संग्रहीत हैं /etc/init.d। आप /etc/init.d/skeletonफ़ाइल को कॉपी और कस्टमाइज़ कर सकते हैं , और फिर कॉल कर सकते हैं

service [yourservice] start|stop|restart

http://www.ralfebert.de/blog/java/debian_daemon/ देखें । इसके लिए डेबियन (तो, उबंटू के रूप में अच्छी तरह से), लेकिन अधिक वितरण फिट।


उम्मीद तो दिखती है। मैं इस पर बारीकी से विचार करूंगा। चीयर्स
dreza

11

शायद सबसे अच्छा देव-ऑप्स समाधान नहीं है, लेकिन एक लैन पार्टी या इसी तरह के सर्वर के सामान्य उपयोग के लिए अच्छा है।

screenअपने सर्वर को चलाने के लिए उपयोग करें और फिर लॉग आउट करने से पहले अलग करें, इससे प्रक्रिया चालू रहेगी, आप किसी भी बिंदु पर फिर से संलग्न कर सकते हैं।

कार्यप्रवाह:

एक स्क्रीन शुरू करें: screen

अपना सर्वर शुरू करें: java -jar minecraft-server.jar

दबाने से अलग करें: Ctl-a,d

फिर से देते हैं: screen -r

अधिक जानकारी यहाँ: https://www.gnu.org/software/screen/manual/screen.html


7

एक अन्य विकल्प, जो काफी लोकप्रिय है, जावा सेवा आवरण है । यह ओएसएस समुदाय के आसपास भी काफी लोकप्रिय है।


चीयर्स। मैंने उसका कुछ उल्लेख देखा था। करीब से देख लेंगे।
dreza

5

स्प्रिंग बूट एप्लिकेशन का एक सेवा के रूप में अच्छी तरह से उल्लेख करते हुए , मैं systemdसंस्करण के लिए जाऊंगा , क्योंकि यह सबसे आसान, कम से कम क्रिया है, और आधुनिक डिस्ट्रोस में सबसे अच्छा एकीकृत है (और यहां तक ​​कि सेंटोस 7.x जैसे आधुनिक भी नहीं हैं)।



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 को लगता है कि सेवा चल रही है क्योंकि यह पता लगाता है क्योंकि यह "/ बिन / श / sbin / सेवा MATH प्रारंभ" और "/ bin / bash /etc/init.d/MATH प्रारंभ" का पता लगाता है और 0 देता है
HomeIsWhereThePcIs

3

सेवा के रूप में स्प्रिंग बूट एप्लिकेशन से , मैं पायथन-आधारित supervisordएप्लिकेशन की सिफारिश कर सकता हूं । अधिक जानकारी के लिए स्टैक ओवरफ़्लो प्रश्न देखें। यह स्थापित करने के लिए वास्तव में सीधा है।


supervisordमहान है, उन लोगों के लिए जो नहीं जानते हैं, यह निगरानी सेवाओं (जो होना चाहिए foreground- नहीं daemonized) की अनुमति देता है , यह तब सेवाओं को फिर से शुरू करेगा (और प्लगइन्स के माध्यम से पुनरारंभ होने पर अलर्ट ईमेल कर सकता है)
wired00

2

अन्य उत्तर आपके प्लेटफॉर्म के आधार पर कस्टम स्क्रिप्ट और सेटअप देते हुए एक अच्छा काम करते हैं। उन लोगों के अलावा, यहां परिपक्व, विशेष प्रयोजन कार्यक्रम हैं जो मुझे पता है:

  • TanukiSoftware से JSW
  • YAJSW ऊपर से एक खुला स्रोत क्लोन है। यह जावा में लिखा गया है, और यह एक नानी प्रक्रिया है जो विन्यास के अनुसार बाल प्रक्रिया (आपका कोड) का प्रबंधन करती है। खिड़कियों / लाइन पर काम करता है।
  • JSVC एक मूल अनुप्रयोग है। यह भी एक नानी प्रक्रिया है, लेकिन यह आपके बच्चे के आवेदन को जेएनआई के माध्यम से आमंत्रित करता है, बजाय एक उपप्रकार के।


1

से वसंत बूट संदर्भ गाइड

Init.d सेवा (सिस्टम V) के रूप में संस्थापन

सीधे शब्दों में जार सिमलिंक के लिए init.dमानक का समर्थन करने के start, stop, restartऔर statusआदेशों। यह मानते हुए कि आपके पास स्प्रिंग बूट एप्लिकेशन इनस्टॉल / सर्विस के रूप में स्प्रिंग बूट एप्लिकेशन इंस्टॉल करने के लिए / var / myapp में स्थापित है, बस एक सिमलिंक बनाएँ:

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

एक बार स्थापित होने के बाद, आप सेवा को सामान्य तरीके से शुरू और बंद कर सकते हैं। उदाहरण के लिए, डेबियन आधारित प्रणाली पर:

$ service myapp start

टिपयदि आपका आवेदन शुरू करने में विफल रहता है, तो /var/log/<appname>.logत्रुटियों के लिए लिखी गई लॉग फ़ाइल की जांच करें ।

एक तैनात सेवा को सुरक्षित करने के तरीके जानने के लिए पढ़ना जारी रखें

लिखित रूप में करने के बाद मुझे पता चला है कि मेरी सेवा लॉग में इस त्रुटि संदेश के साथ शुरू करने में विफल रहती है: स्टार्ट-स्टॉप-डेमॉन: अपरिचित विकल्प --नो-करीब । और मैं /var/myapp/myapp.confनिम्नलिखित सामग्री के साथ एक कॉन्फिग फ़ाइल बनाकर इसे ठीक करने में कामयाब रहा

USE_START_STOP_DAEMON=false

1

मैं नेट जावा आवेदन कर रहा हूं और मैं इसे सिस्टमड के साथ सेवा के रूप में चलाना चाहता हूं। दुर्भाग्य से एप्लिकेशन इस बात पर कोई रोक नहीं लगाता है कि मैं किस प्रकार का उपयोग कर रहा हूं। अंत में मैंने स्क्रीन में जावा स्टार्ट लपेटा है। यहाँ विन्यास फाइल हैं:

सर्विस

[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

जावा कोड को डेमॉन (सेवा) के रूप में चलाने के लिए आप जेएनआई आधारित स्टब लिख सकते हैं।

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

एक नमूना कोड के लिए जो JNI पर आधारित है। इस स्थिति में आप उस कोड को डीमॉनेटाइज़ करते हैं जो जावा के रूप में शुरू किया गया था और मुख्य लूप को सी में निष्पादित किया गया है। लेकिन जावा के अंदर मुख्य, डेमन का, सर्विस लूप लगाना भी संभव है।

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

जेएनआई के साथ मज़े करो!


0

हालांकि एक बार शुरू करने के बाद मुझे नहीं पता कि इसे रोकने के लिए इसे कैसे एक्सेस किया जाए

आप एक साधारण स्टॉप स्क्रिप्ट लिख सकते हैं जो आपकी जावा प्रक्रिया के लिए greps, PID को निकालता है और उस पर कॉल मारता है। यह फैंसी नहीं है, लेकिन यह सीधे आगे है। एक शुरुआत के रूप में मदद की तरह कुछ हो सकता है:

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

2
मैं linux में बहुत अच्छा नहीं हूँ लेकिन pkill nameofprocessएक ही चीज़ के बारे में नहीं करता ?
सेज्यूरेट

0

लिनक्स सेवा के रूप में युद्ध को चलाने के लिए संभव है, और आप पैकेजिंग से पहले अपनी pom.xml फ़ाइल में बाध्य करना चाह सकते हैं, क्योंकि कुछ डिस्ट्रो ऑटो मोड में पहचान नहीं सकते हैं। ऐसा करने के लिए, स्प्रिंग-बूट-मावेन-प्लगइन प्लगइन के अंदर निम्नलिखित संपत्ति जोड़ें।

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

इसके बाद, अपना init.d सेटअप करें:

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

और आप चला पाएंगे

service myapp start|stop|restart

कई अन्य विकल्प हैं जो आप विंडोज सेवा सहित स्प्रिंग बूट प्रलेखन में पा सकते हैं ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.