从Bash脚本中启动Spring Boot作为前台进程

时间:2018-01-18 15:39:27

标签: java spring bash war

我使用嵌入式Tomcat servlet容器打包Spring Boot war。并使用java -jar server.war <Spring Args>将其部署为常规Java应用程序。我编写了一个bash脚本,负责将服务器部署为后台/前台进程:

start_foreground() {
    cmd="$JAVACMD ${JVM_OPTS} -jar ${WAR_FILE} ${SPRING_OPTS}"
    echo "\"${cmd}\""
    eval ${cmd}
    print_log "Server is stopped."
}

start_background() {
    SPRING_OPTS="--spring.pid.file=${PID_FILE} ${SPRING_OPTS}"
    cmd="nohup $JAVACMD ${JVM_OPTS} -jar ${WAR_FILE} ${SPRING_OPTS} &>${LOG_PATH}/console.log &"
    echo "\"${cmd}\""
    eval ${cmd}
    PID=$!
    print_log "Server is started with pid \"${PID}\""
}

如您所见,对于后台处理开始,我使用nohup。一切正常,它会将STDOUTSTDERR发送到我的${LOG_PATH}/console.logconsole.log报告我的服务器在预配置端口上运行(使用Spring配置文件)。我的配置文件dev-https配置了端口8443

spring:
  profiles.active: dev-https
...
---

spring:
    profiles: dev-https
server:
  port: 8443
  ssl:
    enabled: true
    protocol: TLS
    enabled-protocols: TLSv1.2
    key-store: <path>
    key-store-password: <password>

但是,当我尝试将服务器作为前台进程启动时,我会遇到意外行为。每当我使用start_foreground()部署服务器时,它都会正常启动,但端口会重置为默认8080

如果我附加调试器,并尝试使用environment.getProperty("server.port")获取值,它将返回空字符串(但是,如果未定义属性,则通常返回null)。此外,所有其他属性都返回预期值:

environment.getProperty("spring.profiles.active")=dev-https

environment.getProperty("server.ssl.enabled")=true

我尝试将eval替换为exec,甚至在${cmd} bash函数中自行运行start_foreground(),但该端口始终重置为8080,并且server.port返回空字符串。

最奇怪的部分是,如果我在我的控制台中执行${cmd}(而不是在脚本中),一切都可以正常工作(正确的配置文件,并使用正确的端口)。

有没有人遇到过这样奇怪的问题?

2 个答案:

答案 0 :(得分:2)

看起来你正在使用配置(如端口号等...仅用于后台而不用于前台。你还没有声明变量(你错过了这一行)

`SPRING_OPTS="--spring.pid.file=${PID_FILE} ${SPRING_OPTS}"` 

为前景。

答案 1 :(得分:1)

我尝试使用Spring Boot的新实例重现此问题。写了一个快速的bash脚本,一切都很顺利!

然后,我开始玩我的原始脚本,发现我使用的是SERVER_PORT变量(因为我为用户提供了一个可选参数--port <num>。)

显然,Spring Framework也使用了这个环境变量:https://www.concretepage.com/spring-boot/spring-boot-change-default-server-port#server_port

我的错误是导出SERVER_PORT var(但是,出于其他原因我需要它)。

解决方法是从export移除export SERVER_PORT=""或将变量重命名为其他内容(我最终会这样做)。