Ứng dụng Spring Boot là một Dịch vụ


197

Làm cách nào để định cấu hình ứng dụng Spring Boot độc đáo được đóng gói dưới dạng jar thực thi như một Dịch vụ trong hệ thống linux? Đây có phải là cách tiếp cận được đề xuất hay tôi nên chuyển đổi ứng dụng này thành chiến tranh và cài đặt vào Tomcat?

Hiện tại tôi có thể chạy ứng dụng khởi động Spring từ screenphiên, điều này thật tuyệt, nhưng yêu cầu khởi động thủ công sau khi khởi động lại máy chủ.

Những gì tôi đang tìm kiếm là lời khuyên / định hướng chung hoặc init.dtập lệnh mẫu , nếu cách tiếp cận của tôi với jar thực thi là đúng.


Để bắt đầu, phân phối của bạn sử dụng mới bắt đầu hoặc systemd?
yglodt

Câu trả lời:


138

Các công việc sau đây cho springboot 1.3 trở lên:

Là dịch vụ init.d

Jar thực thi có các lệnh khởi động, dừng, khởi động lại và trạng thái thông thường. Nó cũng sẽ thiết lập một tệp PID trong thư mục / var / run thông thường và đăng nhập vào thư mục / var / log thông thường theo mặc định.

Bạn chỉ cần liên kết sym jar của bạn vào /etc/init.d như vậy

sudo link -s /var/myapp/myapp.jar /etc/init.d/myapp

HOẶC LÀ

sudo ln -s ~/myproject/build/libs/myapp-1.0.jar /etc/init.d/myapp_servicename

Sau đó, bạn có thể làm như bình thường

/etc/init.d/myapp start

Sau đó, thiết lập một liên kết trong bất kỳ runlevel nào bạn muốn ứng dụng bắt đầu / dừng khi khởi động nếu muốn.


Là một dịch vụ systemd

Để chạy ứng dụng Spring Boot được cài đặt trong var / myapp, bạn có thể thêm tập lệnh sau vào /etc/systemd/system/myapp.service:

[Unit]
Description=myapp
After=syslog.target

[Service]
ExecStart=/var/myapp/myapp.jar

[Install]
WantedBy=multi-user.target

NB: trong trường hợp bạn đang sử dụng phương pháp này, đừng quên làm cho tệp jar tự thực thi (với chmod + x) nếu không nó sẽ thất bại với lỗi "Quyền bị từ chối".

Tài liệu tham khảo

http://docs.spring.io/spring-boot/docs/civerse-SNAPSHOT/reference/html/deployment-install.html#deployment-service


1
Cách tiếp cận "JAR thực thi đầy đủ" hoạt động như thế nào? Tôi sử dụng CentOS 6.6. Tôi nói thêm <executable>true</executable>để tôi pom.xml, nhưng các tập tin JAR đóng gói không thực hiện (... ./myapp.jar ... cannot execute binary file.)
Abdull

5
Câu trả lời này chỉ hoạt động cho Mốc 1.3 hiện tại, chưa được phát hành. Các chi nhánh 1.1 và 1.2 sẽ cần kiểm tra các phản hồi khác tại đây.
voor

6
Bạn có biết các chàng trai làm thế nào để vượt qua các cuộc tranh luận của mùa xuân như -Dspring.profiles.active=prodcác dịch vụ này không? Câu hỏi - stackoverflow.com/questions/31242291/ Cách
nKognito 6/07/2015

2
Tôi không thể dừng ứng dụng khởi động mùa xuân. /etc/init.d stopkhông dừng ứng dụng, nó cố gắng khởi động lại.
tintin

2
Nếu bạn muốn theo dõi quá trình và khởi động lại nó nếu nó chết mà không viết trình nền hệ thống, hãy kiểm tra patrickgrimard.com/2014/06/06/
ruX

112

Cách tiếp theo là cách dễ nhất để cài đặt ứng dụng Java làm dịch vụ hệ thống trong Linux.

Giả sử bạn đang sử dụng systemd (điều mà bất kỳ bản phân phối hiện đại nào hiện nay):

Đầu tiên, tạo một tệp dịch vụ /etc/systemd/systemcó tên ví dụ javaservice.servicevới nội dung này:

[Unit]
Description=Java Service

[Service]
User=nobody
# The configuration file application.properties should be here:
WorkingDirectory=/data 
ExecStart=/usr/bin/java -Xmx256m -jar application.jar --server.port=8081
SuccessExitStatus=143
TimeoutStopSec=10
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Thứ hai, thông báo systemdvề tệp dịch vụ mới:

systemctl daemon-reload

và kích hoạt nó, để nó chạy khi khởi động:

systemctl enable javaservice.service

Cuối cùng, bạn có thể sử dụng các lệnh sau để bắt đầu / dừng dịch vụ mới của mình:

systemctl start javaservice
systemctl stop javaservice
systemctl restart javaservice
systemctl status javaservice

Miễn là bạn đang sử dụng systemd, đây là cách không xâm phạm và rõ ràng nhất để thiết lập ứng dụng Java dưới dạng dịch vụ hệ thống.

Điều tôi đặc biệt thích về giải pháp này là thực tế là bạn không cần phải cài đặt và định cấu hình bất kỳ phần mềm nào khác. Vận chuyển systemdthực hiện tất cả công việc cho bạn và dịch vụ của bạn hoạt động giống như bất kỳ dịch vụ hệ thống nào khác. Tôi sử dụng nó trong sản xuất một thời gian, trên các bản phát hành khác nhau, và nó chỉ hoạt động như bạn mong đợi.

Một điểm cộng nữa là, bằng cách sử dụng /usr/bin/java, bạn có thể dễ dàng thêm jvmcác tham số như -Xmx256m.

Đồng thời đọc systemdphần trong tài liệu chính thức của Spring Boot: http://docs.spring.io/spring-boot/docs/civerse/reference/html/deployment-install.html


Thật không may systemd không có sẵn cho Centos 6
MariuszS

Làm thế nào để nó biết làm thế nào để ngăn chặn nó? Ghi lại pid và sau đó giết nó?
sương mù

2
Với Spring Boot 1.3+, bạn có thể tạo tệp chiến tranh hoàn toàn có thể thực hiện được, do đó không cần bit java -jar ..., chỉ cần sử dụng tên của tệp ở đó.
Pierre Henry

1
Tôi thích sử dụng dòng lệnh java đầy đủ vì theo cách đó bạn có thể thêm các tham số jvm.
yglodt

1
Đối với một chuỗi khởi động thích hợp, bạn có thể muốn thêm các câu lệnh đặt hàng vào [Unit]phần, ví dụ After=mysql.service, Before=apache2.service.
rustyx

57

Bạn cũng có thể sử dụng giám sát là một trình nền rất tiện dụng, có thể được sử dụng để dễ dàng kiểm soát các dịch vụ. Các dịch vụ này được xác định bởi các tệp cấu hình đơn giản xác định những gì sẽ thực hiện với người dùng trong thư mục nào và vv, có hàng trăm tùy chọn. giám sát có một cú pháp rất đơn giản, vì vậy nó tạo ra một sự thay thế rất tốt để viết các tập lệnh init SysV.

Ở đây một tệp cấu hình giám sát đơn giản cho chương trình bạn đang cố chạy / điều khiển. (đặt cái này vào /etc/supervisor/conf.d/yourapp.conf )

/etc/supervisor/conf.d/yourapp.conf

[program:yourapp]
command=/usr/bin/java -jar /path/to/application.jar
user=usertorun
autostart=true
autorestart=true
startsecs=10
startretries=3
stdout_logfile=/var/log/yourapp-stdout.log
stderr_logfile=/var/log/yourapp-stderr.log

Để kiểm soát ứng dụng, bạn sẽ cần phải thực thi giám sát , nó sẽ hiển thị cho bạn một dấu nhắc nơi bạn có thể bắt đầu, dừng, trạng thái yourapp.

CLI

# sudo supervisorctl
yourapp             RUNNING   pid 123123, uptime 1 day, 15:00:00
supervisor> stop yourapp
supervisor> start yourapp

Nếu supervisordtrình nền đã chạy và bạn đã thêm cấu hình cho serivce của mình mà không khởi động lại trình nền, bạn chỉ cần thực hiện một lệnh rereadupdatetrong trình supervisorctlbao.

Điều này thực sự cung cấp cho bạn tất cả các flexibilite bạn sẽ có khi sử dụng tập lệnh SysV init, nhưng dễ sử dụng và kiểm soát. Hãy xem tài liệu .


Cuối cùng, một cái gì đó làm việc cho tôi ra khỏi hộp. Cảm ơn rất nhiều cho gợi ý giám sát.
Vitaly Sazanovich

Điều này thực hiện công việc tương tự như systemd, được tích hợp trong hầu hết các bản phân phối Linux hiện tại.
rustyx

18

Tôi chỉ loanh quanh để làm điều này một mình, vì vậy sau đây là nơi tôi đang nói về một tập lệnh điều khiển dịch vụ CentOS init.d. Nó hoạt động khá độc đáo cho đến nay, nhưng tôi không phải là hacker Bash, vì vậy tôi chắc chắn có chỗ để cải thiện, vì vậy những suy nghĩ về việc cải thiện nó đều được hoan nghênh.

Trước hết, tôi có một tập lệnh cấu hình ngắn /data/svcmgmt/conf/my-spring-boot-api.shcho mỗi dịch vụ, thiết lập các biến môi trường.

#!/bin/bash
export JAVA_HOME=/opt/jdk1.8.0_05/jre
export APP_HOME=/data/apps/my-spring-boot-api
export APP_NAME=my-spring-boot-api
export APP_PORT=40001

Tôi đang sử dụng CentOS, vì vậy để đảm bảo rằng các dịch vụ của tôi được khởi động sau khi máy chủ khởi động lại, tôi có tập lệnh kiểm soát dịch vụ trong /etc/init.d/my-spring-boot-api:

#!/bin/bash
# description: my-spring-boot-api start stop restart
# processname: my-spring-boot-api
# chkconfig: 234 20 80

. /data/svcmgmt/conf/my-spring-boot-api.sh

/data/svcmgmt/bin/spring-boot-service.sh $1

exit 0

Như bạn có thể thấy, nó gọi tập lệnh cấu hình ban đầu để thiết lập các biến môi trường và sau đó gọi một tập lệnh được chia sẻ mà tôi sử dụng để khởi động lại tất cả các dịch vụ Spring Boot của mình. Kịch bản được chia sẻ đó là nơi tất cả các phần thịt có thể được tìm thấy:

#!/bin/bash

echo "Service [$APP_NAME] - [$1]"

echo "    JAVA_HOME=$JAVA_HOME"
echo "    APP_HOME=$APP_HOME"
echo "    APP_NAME=$APP_NAME"
echo "    APP_PORT=$APP_PORT"

function start {
    if pkill -0 -f $APP_NAME.jar > /dev/null 2>&1
    then
        echo "Service [$APP_NAME] is already running. Ignoring startup request."
        exit 1
    fi
    echo "Starting application..."
    nohup $JAVA_HOME/bin/java -jar $APP_HOME/$APP_NAME.jar \
        --spring.config.location=file:$APP_HOME/config/   \
        < /dev/null > $APP_HOME/logs/app.log 2>&1 &
}

function stop {
    if ! pkill -0 -f $APP_NAME.jar > /dev/null 2>&1
    then
        echo "Service [$APP_NAME] is not running. Ignoring shutdown request."
        exit 1
    fi

    # First, we will try to trigger a controlled shutdown using 
    # spring-boot-actuator
    curl -X POST http://localhost:$APP_PORT/shutdown < /dev/null > /dev/null 2>&1

    # Wait until the server process has shut down
    attempts=0
    while pkill -0 -f $APP_NAME.jar > /dev/null 2>&1
    do
        attempts=$[$attempts + 1]
        if [ $attempts -gt 5 ]
        then
            # We have waited too long. Kill it.
            pkill -f $APP_NAME.jar > /dev/null 2>&1
        fi
        sleep 1s
    done
}

case $1 in
start)
    start
;;
stop)
    stop
;;
restart)
    stop
    start
;;
esac
exit 0

Khi dừng, nó sẽ cố gắng sử dụng Spring Boot Actuator để thực hiện tắt máy có kiểm soát. Tuy nhiên, trong trường hợp Actuator không được cấu hình hoặc không tắt trong khung thời gian hợp lý (tôi cho nó 5 giây, thực sự hơi ngắn một chút), quá trình sẽ bị hủy.

Ngoài ra, tập lệnh đưa ra giả định rằng quy trình java chạy ứng dụng sẽ là người duy nhất có "my-spring-boot-api.jar" trong văn bản của chi tiết quy trình. Đây là một giả định an toàn trong môi trường của tôi và có nghĩa là tôi không cần phải theo dõi các PID.


3
Không cần phải viết kịch bản bắt đầu / dừng của riêng bạn. Điều này được cung cấp kể từ Spring Boot 1.3 trở lên. Xem docs.spring.io/spring-boot/docs/civerse/reference/htmlsingle/ để biết thêm chi tiết.
gregturn

Điều tốt để biết đó là một tùy chọn, nhưng tất cả những gì nó làm là loại bỏ nhu cầu thực thi bằng cách sử dụng java -jar. Phần còn lại của kịch bản vẫn cần thiết.
Steve

Rất hữu ích khi /etc/init.d hoặc systemd không phải là một tùy chọn, cảm ơn vì đã chia sẻ.
bernardn

@Steve: Không. Bạn đang phát minh lại bánh xe. Oh, và chúng tôi có systemd bây giờ.
Martin Schröder

Khi bạn cần truyền tham số cho JVM (như tham số -javaagent hoặc -D), đây là cách duy nhất, tks @Steve!
Dyorgio

14

Nếu bạn muốn sử dụng Spring Boot 1.2.5 với Spring Boot Maven Plugin 1.3.0.M2, đây là giải pháp:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.2.5.RELEASE</version>
</parent>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>1.3.0.M2</version>
            <configuration>
                <executable>true</executable>
            </configuration>
        </plugin>
    </plugins>
</build>

<pluginRepositories>
    <pluginRepository>
        <id>spring-libs-milestones</id>
        <url>http://repo.spring.io/libs-milestone</url>
    </pluginRepository> 
</pluginRepositories>

Sau đó biên dịch thành ususal : mvn clean package, tạo một liên kết tượng trưng ln -s /.../myapp.jar /etc/init.d/myapp, làm cho nó có thể thực thi được chmod +x /etc/init.d/myappvà khởi động nó service myapp start(với Ubuntu Server)


những gì về tập tin WAR runnable? nó không hoạt động với tôi với bố cục WAR.
Radu Toader

Điều thú vị là nó hoạt động với bản phát hành 1.3.0.M2, nhưng tôi đã gặp lỗi khi thử 1.3.0.RC1.
JBCP

Bất cứ ý tưởng về cách làm điều này với gradle thay vì maven?
Geir

Khi sử dụng Gradle, cấu hình này được thực hiện bằng cách sử dụng springBoot { executable = true }khối.
Natix

@RaduToader: Bạn có thể thực thi tệp WAR dưới dạng dịch vụ không?
naveenkumarbv

9

Tôi biết đây là một câu hỏi cũ hơn, nhưng tôi muốn trình bày một cách khác đó là appassembler-maven-plugin . Đây là phần có liên quan từ POM của tôi bao gồm rất nhiều giá trị tùy chọn bổ sung mà chúng tôi thấy hữu ích:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>appassembler-maven-plugin</artifactId>
    <configuration>
        <generateRepository>true</generateRepository>
        <repositoryLayout>flat</repositoryLayout>
        <useWildcardClassPath>true</useWildcardClassPath>
        <includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
        <configurationDirectory>config</configurationDirectory>
        <target>${project.build.directory}</target>
        <daemons>
            <daemon>
                <id>${installer-target}</id>
                <mainClass>${mainClass}</mainClass>
                <commandLineArguments>
                    <commandLineArgument>--spring.profiles.active=dev</commandLineArgument>
                    <commandLineArgument>--logging.config=${rpmInstallLocation}/config/${installer-target}-logback.xml</commandLineArgument>
                </commandLineArguments>
                <platforms>
                    <platform>jsw</platform>
                </platforms>
                <generatorConfigurations>
                    <generatorConfiguration>
                        <generator>jsw</generator>
                        <includes>
                            <include>linux-x86-64</include>
                        </includes>
                        <configuration>
                            <property>
                                <name>wrapper.logfile</name>
                                <value>logs/${installer-target}-wrapper.log</value>
                            </property>
                            <property>
                                <name>wrapper.logfile.maxsize</name>
                                <value>5m</value>
                            </property>
                            <property>
                                <name>run.as.user.envvar</name>
                                <value>${serviceUser}</value>
                            </property>
                            <property>
                                <name>wrapper.on_exit.default</name>
                                <value>RESTART</value>
                            </property>
                        </configuration>
                    </generatorConfiguration>
                </generatorConfigurations>
                <jvmSettings>
                    <initialMemorySize>256M</initialMemorySize>
                    <maxMemorySize>1024M</maxMemorySize>
                    <extraArguments>
                        <extraArgument>-server</extraArgument>
                    </extraArguments>
                </jvmSettings>
            </daemon>
        </daemons>
    </configuration>
    <executions>
        <execution>
            <id>generate-jsw-scripts</id>
            <phase>package</phase>
            <goals>
                <goal>generate-daemons</goal>
            </goals>
        </execution>
    </executions>
</plugin>

6

NHƯ MỘT DỊCH VỤ WINDOWS

Nếu bạn muốn nó chạy trong windows máy, hãy tải xuống winw.exe từ

 http://repo.jenkins-ci.org/releases/com/sun/winsw/winsw/2.1.2/

Sau đó đổi tên thành jar tên tệp (ví dụ: your-app .jar)

winsw.exe -> your-app.exe

Bây giờ hãy tạo một tệp xml your-app.xml và sao chép nội dung sau vào đó

<?xml version="1.0" encoding="UTF-8"?>
<service>
     <id>your-app</id>
     <name>your-app</name>
     <description>your-app as a Windows Service</description>
     <executable>java</executable>
     <arguments>-jar "your-app.jar"</arguments>
     <logmode>rotate</logmode>
</service>

Đảm bảo rằng exexml cùng với jar trong cùng một thư mục.

Sau dấu nhắc lệnh mở này trong Quản trị viên ưu tiên và cài đặt nó vào dịch vụ windows.

your-app.exe install
eg -> D:\Springboot\your-app.exe install

Nếu nó thất bại với

Error: Registry key 'Software\JavaSoft\Java Runtime Environment'\CurrentVersion' has value '1.8', but '1.7' is required.

Sau đó thử các cách sau:

Delete java.exe, javaw.exe and javaws.exe from C:\Windows\System32

đó là nó :) .

Để gỡ cài đặt dịch vụ trong windows

your-app.exe uninstall

Để xem / chạy / dừng dịch vụ: win + r và nhập Công cụ quản trị, sau đó chọn dịch vụ từ đó. Sau đó nhấp chuột phải chọn tùy chọn - chạy / dừng


Tôi đã làm theo các bước tương tự để chạy jar boot spring như dịch vụ windows trong mạng nội bộ của công ty, nhưng dịch vụ không hoạt động. Có một cửa sổ xuất hiện với lỗi: Lỗi: 1067 Quá trình bị chấm dứt bất ngờ Bạn có thể vui lòng giúp đỡ hoặc đề xuất những gì cần phải làm không?
Nikhil Singh Bhadoriya

Bạn có tất cả sự cho phép để làm điều đó? Nếu bạn là quản trị viên, điều này sẽ không gây ra vấn đề gì. Bạn có thể vui lòng kiểm tra bạn có quyền quản trị viên.
Arundev

stackoverflow.com/questions/18205111/ Bạn có thể vui lòng thử điều này có thể sẽ giúp bạn giải quyết vấn đề.
Arundev

cảm ơn vì đã phản hồi nhanh, tôi đã phục vụ và chạy dịch vụ của mình bằng cách sửa lỗi với thẻ trong tệp xml.
Nikhil Singh Bhadoriya

4

Kịch bản SysVInit của tôi cho Centos 6 / RHEL (chưa lý tưởng). Kịch bản lệnh này yêu cầu ApplicationPidListener .

Nguồn gốc của /etc/init.d/app

#!/bin/sh
#
# app Spring Boot Application 
#
# chkconfig:   345 20 80
# description: App Service
#           

### BEGIN INIT INFO
# Provides: App
# Required-Start: $local_fs $network
# Required-Stop: $local_fs $network
# Default-Start: 3 4 5 
# Default-Stop: 0 1 2 6
# Short-Description: Application
# Description:      
### END INIT INFO

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

exec="/usr/bin/java"
prog="app"
app_home=/home/$prog/
user=$prog

[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog

lockfile=/var/lock/subsys/$prog    
pid=$app_home/$prog.pid

start() {

    [ -x $exec ] || exit 5
    [ -f $config ] || exit 6
    # Check that networking is up.
    [ "$NETWORKING" = "no" ] && exit 1
    echo -n $"Starting $prog: "
    cd $app_home
    daemon --check $prog --pidfile $pid --user $user $exec $app_args &
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc -p $pid $prog
    retval=$?
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    stop
    start
}

reload() {
    restart
}

force_reload() {
    restart
}

rh_status() {
    status -p $pid $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}

case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
        restart
        ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
        exit 2
esac
exit $?

Tệp cấu hình mẫu /etc/sysconfig/app:

exec=/opt/jdk1.8.0_05/jre/bin/java

user=myuser
app_home=/home/mysuer/

app_args="-jar app.jar"

pid=$app_home/app.pid

4

Đây là một kịch bản triển khai một jar thực thi như một dịch vụ systemd.

Nó tạo một người dùng cho dịch vụ và tệp .service và đặt tệp jar bên dưới / var và thực hiện một số khóa đặc quyền cơ bản.

#!/bin/bash

# Argument: The jar file to deploy
APPSRCPATH=$1

# Argument: application name, no spaces please, used as folder name under /var
APPNAME=$2

# Argument: the user to use when running the application, may exist, created if not exists
APPUSER=$3

# Help text
USAGE="
Usage: sudo $0 <jar-file> <app-name> <runtime-user>
If an app with the name <app-name> already exist, it is stopped and deleted.
If the <runtime-user> does not already exist, it is created.
"

# Check that we are root
if [ ! "root" = "$(whoami)" ]; then
    echo "Must be root. Please use e.g. sudo"
    echo "$USAGE"
    exit
fi

# Check arguments
if [ "$#" -ne 3 -o ${#APPSRCPATH} = 0 -o ${#APPNAME} = 0 -o ${#APPUSER} = 0 ]; then
    echo "Incorrect number of parameters."
    echo "$USAGE"
    exit
fi

if [ ! -f $APPSRCPATH ]; then
    echo "Can't find jar file $APPSRCPATH"
    echo "$USAGE"
    exit
fi

# Infered values
APPFILENAME=$(basename $APPSRCPATH)
APPFOLDER=/var/javaapps/$APPNAME
APPDESTPATH=$APPFOLDER/$APPFILENAME

# Stop the service if it already exist and is running
systemctl stop $APPNAME >/dev/null 2>&1

# Create the app folder, deleting any previous content
rm -fr $APPFOLDER
mkdir -p $APPFOLDER

# Create the user if it does not exist
if id "$APPUSER" >/dev/null 2>&1; then
    echo "Using existing user $APPUSER"
else
    adduser --disabled-password --gecos "" $APPUSER
    echo "Created user $APPUSER"
fi

# Place app in app folder, setting owner and rights
cp $APPSRCPATH $APPDESTPATH
chown $APPUSER $APPDESTPATH
chmod 500 $APPDESTPATH
echo "Added or updated the $APPDESTPATH file"

# Create the .service file used by systemd
echo "
[Unit]
Description=$APPNAME
After=syslog.target
[Service]
User=$APPUSER
ExecStart=/usr/bin/java -jar $APPDESTPATH
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
" > /etc/systemd/system/$APPNAME.service
echo "Created the /etc/systemd/system/$APPNAME.service file"

# Reload the daemon
systemctl daemon-reload

# Start the deployed app
systemctl start $APPNAME
systemctl status $APPNAME

Thí dụ: nhập mô tả hình ảnh ở đây


4

Tôi đang cố gắng tạo các ứng dụng springboot được trình bày dưới dạng tập lệnh shell kiểu "init.d" với một ứng dụng java được nén ở cuối

Bằng cách liên kết các tập lệnh này từ /etc/init.d/spring-app đến /opt/spring-app.jar và chmod'ing jar để có thể thực thi, có thể thực hiện "/etc/init.d/spring-app bắt đầu "" /etc/init.d/spring-app stop "và các khả năng khác như công việc trạng thái

Có lẽ, vì các tập lệnh kiểu init.d từ springboot trông rằng chúng có các chuỗi ma thuật cần thiết (như # Default-Start: 2 3 4 5) chkconfig sẽ có thể thêm nó dưới dạng "dịch vụ"

Nhưng tôi muốn làm cho nó hoạt động với systemd

Để thực hiện công việc này, tôi đã thử nhiều câu trả lời trong các câu trả lời khác ở trên nhưng không ai trong số họ làm việc cho tôi trên Centos 7.2 với Springboot 1.3 Hầu hết họ sẽ bắt đầu dịch vụ nhưng không thể theo dõi pid

Cuối cùng, tôi thấy những điều sau đây đã làm việc cho tôi, khi liên kết /etc/init.d cũng được đặt ra. Một tập tin tương tự như bên dưới nên được cài đặt như/usr/lib/systemd/system/spring-app.service

[Unit]
Description=My loverly application
After=syslog.target 

[Service]
Type=forking
PIDFile=/var/run/spring-app/spring-app.pid
ExecStart=/etc/init.d/spring-app start
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

4

Tôi đã kết thúc việc làm dịch vụ systemd cho bố trí WAR / JAR

Tôi đang gọi java -jar vì nó linh hoạt hơn. Đã thử cũng đặt ExecStart = spring-mvc.war nhưng mặc dù có thể thực thi được, tôi đã gặp 'Lỗi định dạng Exec'

Dù sao, những ngày này, systemd có mặt trên tất cả các bản phát hành và cung cấp một giải pháp tốt để chuyển hướng nhật ký (syserr rất quan trọng khi dịch vụ của bạn thậm chí không bắt đầu vị trí tệp log4j sẽ trống :)).

cat /etc/systemd/system/spring-mvc.service 
[Unit]
Description=Spring MVC Java Service

[Service]
User=spring-mvc
# The configuration file application.properties should be here:
WorkingDirectory=/usr/local/spring-mvc


# Run ExecStartPre with root-permissions
PermissionsStartOnly=true

ExecStartPre=-/bin/mkdir -p /var/log/spring-mvc


ExecStartPre=/bin/chown -R spring-mvc:syslog /var/log/spring-mvc
ExecStartPre=/bin/chmod -R 775 /var/log/spring-mvc



#https://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart=
ExecStart=/usr/bin/java \
        -Dlog4j.configurationFile=log4j2-spring.xml \
        -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector \
        -Dspring.profiles.active=dev \
        -Denvironment-type=dev \
        -XX:+UseConcMarkSweepGC \
        -XX:CMSInitiatingOccupancyFraction=80 \
        -XX:NewSize=756m \
        -XX:MetaspaceSize=256m \
        -Dsun.net.inetaddr.ttl=5 \
        -Xloggc:/var/log/spring-mvc/gc.log \
        -verbose:gc \
        -verbosegc \
        -XX:+DisableExplicitGC \
        -XX:+PrintGCDetails \
        -XX:+PrintGCDateStamps \
        -XX:+PreserveFramePointer \
        -XX:+StartAttachListener \
        -Xms1024m \
        -Xmx1024m \
        -XX:+HeapDumpOnOutOfMemoryError \
        -jar spring-mvc.war

SuccessExitStatus=143
StandardOutput=journal
StandardError=journal


KillSignal=SIGINT
TimeoutStopSec=20
Restart=always
RestartSec=5
StartLimitInterval=0
StartLimitBurst=10

LimitNOFILE=500000
LimitNPROC=500000

#https://www.freedesktop.org/software/systemd/man/systemd.exec.html#LimitCPU=
#LimitCPU=, LimitFSIZE=, LimitDATA=, LimitSTACK=, LimitCORE=, LimitRSS=, LimitNOFILE=, LimitAS=, LimitNPROC=, LimitMEMLOCK=, LimitLOCKS=, LimitSIGPENDING=, LimitMSGQUEUE=, LimitNICE=, LimitRTPRIO=, LimitRTTIME=¶

SyslogIdentifier=spring-mvc

[Install]
WantedBy=multi-user.target


# https://www.freedesktop.org/software/systemd/man/journalctl.html
#check logs --- journalctl -u spring-mvc -f -o cat

rsyslog - chuyển hướng đầu vào syslog từ ứng dụng đến thư mục / tệp cụ thể

cat /etc/rsyslog.d/30-spring-mvc.conf 
if $programname == 'spring-mvc' then /var/log/spring-mvc/spring-mvc.log
& stop

logrotate

cat /etc/logrotate.d/spring-mvc.conf 
/var/log/spring-mvc/spring-mvc.log
{
    daily
    rotate 30
    maxage 30
    copytruncate
    missingok
    notifempty
    compress
    dateext
    dateformat _%Y-%m-%d_%H-%M
    delaycompress
    create 644 spring-mvc syslog
    su spring-mvc syslog
}

logrotate gc

cat /etc/logrotate.d/spring-mvc-gc.conf 
/var/log/spring-mvc/gc.log
{
    daily
    rotate 30
    maxage 30
    copytruncate
    missingok
    notifempty
    compress
    dateext
    dateformat _%Y-%m-%d_%H-%M
    delaycompress
    create 644 spring-mvc syslog
    su spring-mvc syslog
}

3

Trong câu hỏi này, câu trả lời từ @PbxMan sẽ giúp bạn bắt đầu:

Chạy một ứng dụng Java như một dịch vụ trên Linux

Biên tập:

Có một cách khác, ít hay hơn để bắt đầu quá trình khởi động lại, sử dụng cron:

@reboot user-to-run-under /usr/bin/java -jar /path/to/application.jar

Điều này hoạt động, nhưng cung cấp cho bạn không có giao diện bắt đầu / dừng tốt đẹp cho ứng dụng của bạn. Dù sao bạn vẫn có thể đơn giản là kill...


Không thực sự, bởi vì Spring Boot cung cấp các tính năng đặc biệt để làm điều này.
Tristan

2

Tôi không biết một cách thu nhỏ "chuẩn" để làm điều đó với ứng dụng Java, nhưng chắc chắn đó là một ý tưởng hay (bạn muốn hưởng lợi từ khả năng giám sát và duy trì của hệ điều hành nếu chúng ở đó) . Đó là trên lộ trình để cung cấp một cái gì đó từ hỗ trợ công cụ Spring Boot (maven và gradle), nhưng bây giờ có lẽ bạn sẽ phải tự lăn. Giải pháp tốt nhất mà tôi biết bây giờ là Foreman , có cách tiếp cận khai báo và một dòng lệnh để đóng gói các tập lệnh init cho các định dạng hệ điều hành tiêu chuẩn khác nhau (monit, sys V, upstart, v.v.). Cũng có bằng chứng về những người đã thiết lập công cụ với gradle (ví dụ ở đây ).


2

Bạn đang sử dụng Maven? Sau đó, bạn nên thử Plugin AppAssembler:

Plugin Trình biên dịch ứng dụng là một plugin Maven để tạo các tập lệnh để bắt đầu các ứng dụng java. ... Tất cả các tạo phẩm (phụ thuộc + tạo phẩm từ dự án) được thêm vào đường dẫn lớp trong các tập lệnh bin được tạo.

Các nền tảng được hỗ trợ:

Các biến thể Unix

Windows NT (Windows 9x KHÔNG được hỗ trợ)

Gói dịch vụ Java (JSW)

Xem: http://mojo.codehaus.org/appassembler/appassembler-maven-plugin/index.html


2

Cấu hình sau là bắt buộc trong tệp build.gradle trong các dự án Spring Boot.

xây dựng. nâng cấp

jar {
    baseName = 'your-app'
    version = version
}

springBoot {
    buildInfo()
    executable = true   
    mainClass = "com.shunya.App"
}

thực thi = đúng

Điều này là bắt buộc để tạo jar hoàn toàn có thể thực hiện được trên hệ thống unix (Centos và Ubuntu)

Tạo một tập tin .conf

Nếu bạn muốn định cấu hình các thuộc tính JVM tùy chỉnh hoặc các đối số chạy ứng dụng Spring Boot, thì bạn có thể tạo một tệp .conf có cùng tên với tên ứng dụng Spring Boot và đặt nó song song với tệp jar.

Xem xét rằng-app.jar là tên của ứng dụng Spring Boot của bạn, sau đó bạn có thể tạo tệp sau đây.

JAVA_OPTS="-Xms64m -Xmx64m"
RUN_ARGS=--spring.profiles.active=prod
LOG_FOLDER=/custom/log/folder

Cấu hình này sẽ đặt ram 64 MB cho ứng dụng Spring Boot và kích hoạt hồ sơ prod.

Tạo người dùng mới trong linux

Để tăng cường bảo mật, chúng tôi phải tạo một người dùng cụ thể để chạy ứng dụng Spring Boot dưới dạng dịch vụ.

Tạo người dùng mới

sudo useradd -s /sbin/nologin springboot

Trên Ubuntu / Debian, sửa đổi lệnh trên như sau:

sudo useradd -s /usr/sbin/nologin springboot

Đặt mật khẩu

sudo passwd springboot

Làm cho chủ sở hữu springboot của tập tin thực thi

chown springboot:springboot your-app.jar

Ngăn chặn sửa đổi tệp jar

chmod 500 your-app.jar

Điều này sẽ cấu hình các quyền của jar để nó không thể được viết và chỉ có thể được đọc hoặc thực thi bởi springboot của chủ sở hữu.

Bạn có thể tùy ý làm cho tệp jar của mình là bất biến bằng cách sử dụng lệnh thay đổi thuộc tính (chattr).

sudo chattr +i your-app.jar

Các quyền thích hợp cũng nên được đặt cho tệp .conf tương ứng. .conf chỉ yêu cầu quyền truy cập đọc (Octal 400) thay vì truy cập đọc + thực thi (Octal 500)

chmod 400 your-app.conf

Tạo dịch vụ Systemd

/etc/systemd/system/your-app.service

[Unit]
Description=Your app description
After=syslog.target

[Service]
User=springboot
ExecStart=/var/myapp/your-app.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

Tự động khởi động lại quá trình nếu nó bị hệ điều hành giết

Nối hai thuộc tính dưới đây (Khởi động lại và Khởi động lại) để tự động khởi động lại quá trình khi thất bại.

/etc/systemd/system/your-app.service

[Service]
User=springboot
ExecStart=/var/myapp/your-app.jar
SuccessExitStatus=143
Restart=always
RestartSec=30

Thay đổi sẽ khiến ứng dụng Spring Boot khởi động lại trong trường hợp thất bại với độ trễ 30 giây. Nếu bạn dừng dịch vụ bằng lệnh systemctl thì khởi động lại sẽ không xảy ra.

Lịch trình dịch vụ khi khởi động hệ thống

Để gắn cờ ứng dụng khởi động tự động khi khởi động hệ thống, hãy sử dụng lệnh sau:

Bật ứng dụng Spring Boot khi khởi động hệ thống

sudo systemctl enable your-app.service

Bắt đầu dừng dịch vụ

systemctl có thể được sử dụng trong Ubuntu 16.04 LTS và 18.04 LTS để bắt đầu và dừng quá trình.

Bắt đầu quá trình

sudo systemctl start your-app

Dừng quá trình

sudo systemctl stop your-app

Người giới thiệu

https://docs.spring.io/spring-boot/docs/civerse/reference/html/deployment-install.html


1

Theo dõi câu trả lời tuyệt vời của Chad, nếu bạn gặp lỗi "Lỗi: Không thể tìm thấy hoặc tải lớp chính" - và bạn mất vài giờ để khắc phục sự cố, cho dù việc thực thi tập lệnh shell của bạn có khởi động ứng dụng java hay không từ chính systemd - và bạn biết đường dẫn lớp của bạn đúng 100%, ví dụ: chạy thủ công shell script hoạt động cũng như chạy những gì bạn có trong systemd execstart. Hãy chắc chắn bạn đang chạy mọi thứ như người dùng chính xác! Trong trường hợp của tôi, tôi đã thử nhiều người dùng khác nhau, sau một thời gian khắc phục sự cố - cuối cùng tôi đã có linh cảm, đặt root là người dùng - voila, ứng dụng đã khởi động chính xác. Sau khi xác định đó là một vấn đề người dùng sai, tôichown -R user:user thư mục và các thư mục con và ứng dụng chạy chính xác như người dùng và nhóm được chỉ định để không còn cần thiết để chạy nó dưới quyền root (bảo mật xấu).


1

Trong các tệp đơn vị systemd, bạn có thể đặt thư mục biến môi trường hoặc thông qua một EnvironmentFile. Tôi sẽ đề xuất làm mọi thứ theo cách này vì nó dường như là ít ma sát nhất.

Mẫu đơn vị mẫu

$ cat /etc/systemd/system/hello-world.service
[Unit]
Description=Hello World Service
After=systend-user-sessions.service

[Service]
EnvironmentFile=/etc/sysconfig/hello-world
Type=simple
ExecStart=/usr/bin/java ... hello-world.jar

Sau đó thiết lập một tệp trong /etc/sysconfig/hello-worldđó bao gồm tên viết hoa của các biến Spring Boot của bạn. Ví dụ: một biến được gọi server.portsẽ theo mẫu dưới dạng SERVER_PORTbiến môi trường:

$ cat /etc/sysconfig/hello-world
SERVER_PORT=8081

Cơ chế đang được khai thác ở đây là các ứng dụng Spring Boot sẽ lấy danh sách các thuộc tính và sau đó dịch chúng, làm cho mọi thứ trở thành chữ hoa và thay thế các dấu chấm bằng dấu gạch dưới. Khi ứng dụng Spring Boot trải qua quá trình này, nó sẽ tìm kiếm các biến môi trường phù hợp và sử dụng bất kỳ biến nào được tìm thấy tương ứng.

Điều này được nhấn mạnh chi tiết hơn trong Hỏi & Đáp SO này có tiêu đề: Làm cách nào để đặt thuộc tính Spring Boot có dấu gạch dưới trong tên của nó thông qua Biến môi trường?

Người giới thiệu


1

Nó có thể được thực hiện bằng dịch vụ Systemd trong Ubuntu

[Unit]
Description=A Spring Boot application
After=syslog.target

[Service]
User=baeldung
ExecStart=/path/to/your-app.jar SuccessExitStatus=143

[Install] 
WantedBy=multi-user.target

Bạn có thể theo liên kết này để mô tả chi tiết hơn và các cách khác nhau để làm như vậy. http://www.baeldung.com/spring-boot-app-as-a-service


1

Tạo một tập lệnh với tên your-app.service (rest-app.service). Chúng ta nên đặt tập lệnh này trong thư mục / etc / systemd / system. Đây là nội dung mẫu của kịch bản

[Unit]
Description=Spring Boot REST Application
After=syslog.target

[Service]
User=javadevjournal
ExecStart=/var/rest-app/restdemo.jar
SuccessExitStatus=200

[Install]
WantedBy=multi-user.target

Kế tiếp:

 service rest-app start

Người giới thiệu

nhập mô tả liên kết ở đây


Trông giống như thế này -> stackoverflow.com/a/30497095/516167
MariuszS
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.