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

Starting Spring Boot as a foreground process from within a bash script

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

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") 获取值,它将 return 空字符串(但是,如果未定义 属性,它通常 returns null)。此外,所有其他属性 return 预期值:

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

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

等等

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

最奇怪的是,如果我在我的控制台中执行 ${cmd}(而不是从脚本中执行),一切都会完美无缺(使用正确的配置文件和正确的端口)。

有人遇到过这么奇怪的问题吗?

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

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

前景。

我试图用一个新的 Spring Boot 实例来重现这个问题。写了一个快速的 bash 脚本,一切顺利!

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

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

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

解决方案是从 export SERVER_PORT="" 中删除 export 或将变量重命名为其他名称(我最终这样做了)。