从 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
启动后台进程。一切正常,它发送 STDOUT
和 STDERR
到我的 ${LOG_PATH}/console.log
。 console.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
或将变量重命名为其他名称(我最终这样做了)。
我用嵌入式 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
启动后台进程。一切正常,它发送 STDOUT
和 STDERR
到我的 ${LOG_PATH}/console.log
。 console.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
或将变量重命名为其他名称(我最终这样做了)。