在现代的微服务架构中,如何高效地管理和启动Java服务,以及如何动态配置应用程序成为关键挑战。本文将详细介绍一套基于Shell脚本的Java服务管理和配置初始化自动化方案,涵盖服务的启动、停止、状态监控和配置文件的动态更新。通过这套方案,可以显著简化服务管理流程,提升系统的稳定性和维护效率。
一、app.sh对焦
Shell脚本目标:用于管理一个Java服务的启动、停止、重启和状态查询。
(一)主要功能概述
- 启动(start):检查服务是否已经运行,如果没有则使用Java命令启动服务,并将进程ID写入PID文件。
- 停止(stop):从PID文件中读取服务进程ID,然后先发送普通kill信号,等待一段时间后检查进程是否停止,如未停止则发送强制kill信号。
- 状态(status):检查服务是否在运行,如果在运行则输出进程ID,否则显示未运行信息。
- 重启(restart):先停止服务,然后再启动服务,实现服务的重启操作。
(二)代码展示
#!/bin/sh
## java env
export JAVA_HOME=/opt/jdk1.8.0
SERVICE_NAME=servicename
JAR_NAME=$SERVICE_NAME-pkgvernum-RELEASE.jar
#PID 代表是PID文件
PID=/home/zhangyanfeng/microsvr/$SERVICE_NAME/$SERVICE_NAME.pid
#使用说明,用来提示输入参数
usage() {
echo "Usage: sh app.sh [start|stop|restart|status]"
exit 1
}
#检查程序是否在运行
is_exist(){
pid=`ps -ef|grep $JAR_NAME|grep -v grep|awk '{print $2}' `
#如果不存在返回1,存在返回0
if [ -z "${pid}" ]; then
return 1
else
return 0
fi
}
#启动方法
start(){
is_exist
if [ $? -eq "0" ]; then
echo ">>> ${SERVICE_NAME} is already running PID=${pid} <<<"
else
nohup $JAVA_HOME/bin/java -Xms256m -Xmx512m -Djava.security.auth.login.config=./config/kafka_zoo_server_jaas.properties -jar $JAR_NAME >/dev/null 2>&1 &
echo $! > $PID
echo ">>> start $SERVICE_NAME successed PID=$! <<<"
fi
}
#停止方法
stop(){
#is_exist
pidf=$(cat $PID)
#echo "$pidf"
echo ">>> ${SERVICE_NAME} PID = $pidf begin kill $pidf <<<"
kill $pidf
rm -rf $PID
sleep 2
is_exist
if [ $? -eq "0" ]; then
echo ">>> ${SERVICE_NAME} 2 PID = $pid begin kill -9 $pid <<<"
kill -9 $pid
sleep 2
echo ">>> $SERVICE_NAME process stopped <<<"
else
echo ">>> ${SERVICE_NAME} is not running <<<"
fi
}
#输出运行状态
status(){
is_exist
if [ $? -eq "0" ]; then
echo ">>> ${SERVICE_NAME} is running PID is ${pid} <<<"
else
echo ">>> ${SERVICE_NAME} is not running <<<"
fi
}
#重启
restart(){
stop
start
}
cd /home/zhangyanfeng/microsvr/$SERVICE_NAME/
#根据输入参数,选择执行对应方法,不输入则执行使用说明
case "$1" in
"start")
start
;;
"stop")
stop
;;
"status")
status
;;
"restart")
restart
;;
*)
usage
;;
esac
exit 0
优点分析
- 功能完整,覆盖了服务的启动、停止、重启和状态查询,使用简单直观。
- 使用了PID文件来跟踪和管理服务进程,确保了操作的精确性。
- 对Java环境的配置和服务启动命令使用了标准化的设置,提高了可移植性和可维护性。
(三)改进空间思考
- 安全性:在获取PID并执行kill操作时,可以增加安全性检查,确保只杀死属于当前用户的进程。
- 错误处理:增加更多的错误处理和日志记录,以便于故障排查和调试。
- 健壮性:在启动和停止服务时,可以增加超时机制或重试逻辑,以应对异常情况。
-
可维护性:脚本中出现了一些硬编码路径(如PID文件路径),可以考虑将这些路径定义为变量,提高代码的灵活性和可维护性。增加注释和文档,解释脚本的各个部分功能和用法,方便他人理解和修改。
-
扩展性:脚本当前只支持单个服务的管理,如需支持多个服务,可以考虑增加参数来动态传递服务名称和相关配置。
(四)改进和优化
可以从几个方面入手,包括安全性、错误处理、可维护性和扩展性等。
增强安全性
- 限制kill权限:在执行kill操作之前,可以添加权限检查,确保只能kill当前用户的进程,防止误操作或恶意行为。
# 在stop函数中添加权限检查
if [ $(id -u) -ne $(stat -c %u $PID) ]; then
echo "Error: You don't have permission to stop this service."
return 1
fi
- 加强PID文件安全性:PID文件应当使用更安全的权限设置,仅限当前用户和相关服务进程访问。
PID=/var/run/$SERVICE_NAME.pid
改进错误处理
-
增加错误日志:在关键操作处增加错误日志,记录到日志文件中,便于后续故障排查和调试。
# 示例:在启动方法中增加错误日志
start(){
is_exist
if [ $? -eq "0" ]; then
echo ">>> ${SERVICE_NAME} is already running PID=${pid} <<<"
else
nohup $JAVA_HOME/bin/java -Xms256m -Xmx512m -Djava.security.auth.login.config=./config/kafka_zoo_server_jaas.properties -jar $JAR_NAME >/dev/null 2>&1 &
echo $! > $PID
if [ $? -eq 0 ]; then
echo ">>> start $SERVICE_NAME successed PID=$! <<<"
else
echo "!!! Failed to start $SERVICE_NAME !!!"
return 1
fi
fi
}
- 超时和重试机制:在停止服务时,可以添加超时和重试机制,确保服务能够在合理的时间内停止。
提高可维护性
-
参数化路径和配置:将硬编码的路径和配置参数化,提高灵活性和可维护性。
# 示例:参数化JAR包路径和PID文件路径
JAR_NAME="$SERVICE_NAME-pkgvernum-RELEASE.jar"
PID_DIR="/var/run/${SERVICE_NAME}"
PID_FILE="${PID_DIR}/${SERVICE_NAME}.pid"
- 增加注释和文档:在关键代码处添加注释,解释脚本的功能和逻辑,以及每个函数的用途和参数说明。
# 示例:增加函数注释和使用说明
# 启动服务
start(){
is_exist
if [ $? -eq "0" ]; then
echo ">>> ${SERVICE_NAME} is already running PID=${pid} <<<"
else
nohup $JAVA_HOME/bin/java -Xms256m -Xmx512m -Djava.security.auth.login.config=./config/kafka_zoo_server_jaas.properties -jar $JAR_NAME >/dev/null 2>&1 &
echo $! > $PID_FILE
if [ $? -eq 0 ]; then
echo ">>> start $SERVICE_NAME successed PID=$! <<<"
else
echo "!!! Failed to start $SERVICE_NAME !!!"
return 1
fi
fi
}
增强扩展性
-
支持多个服务管理:允许脚本通过参数化的方式管理多个不同名称的服务,增强脚本的通用性。
# 示例:支持通过参数管理不同的服务
case "$1" in
"start")
SERVICE_NAME="$2" # 第二个参数为服务名称
start
;;
"stop")
SERVICE_NAME="$2"
stop
;;
...
esac
- 支持配置文件:将常用的配置参数提取到配置文件中,如Java路径、服务名称等,以便统一管理和修改。
(五)优化后的代码展示
#!/bin/bash
#
# app.sh
# Description: Script to manage a Java service
#
# Java environment
export JAVA_HOME=/opt/jdk1.8.0
# Service variables
SERVICE_NAME=servicename
JAR_NAME=$SERVICE_NAME-pkgvernum-RELEASE.jar
PID_DIR=/var/run/${SERVICE_NAME}
PID_FILE=${PID_DIR}/${SERVICE_NAME}.pid
# Usage function
usage() {
echo "Usage: $0 [start|stop|restart|status] [service_name]"
exit 1
}
# Check if the service is running
is_exist() {
pid=$(cat $PID_FILE 2>/dev/null)
if [ -z "$pid" ]; then
return 1 # Not running
else
if ps -p $pid > /dev/null; then
return 0 # Running
else
return 1 # Not running
fi
fi
}
# Start the service
start() {
is_exist
if [ $? -eq 0 ]; then
echo ">>> $SERVICE_NAME is already running with PID=$pid <<<"
else
nohup $JAVA_HOME/bin/java -Xms256m -Xmx512m -Djava.security.auth.login.config=./config/kafka_zoo_server_jaas.properties -jar $JAR_NAME >/dev/null 2>&1 &
echo $! > $PID_FILE
if [ $? -eq 0 ]; then
echo ">>> $SERVICE_NAME started successfully with PID=$(cat $PID_FILE) <<<"
else
echo "!!! Failed to start $SERVICE_NAME !!!"
return 1
fi
fi
}
# Stop the service
stop() {
if [ ! -f $PID_FILE ]; then
echo ">>> $SERVICE_NAME is not running <<<"
return 1
fi
pid=$(cat $PID_FILE)
echo ">>> Stopping $SERVICE_NAME PID=$pid <<<"
kill $pid
sleep 2
if ps -p $pid > /dev/null; then
echo ">>> Force stopping $SERVICE_NAME PID=$pid <<<"
kill -9 $pid
sleep 2
fi
rm -f $PID_FILE
echo ">>> $SERVICE_NAME stopped <<<"
}
# Check the status of the service
status() {
is_exist
if [ $? -eq 0 ]; then
echo ">>> $SERVICE_NAME is running with PID=$(cat $PID_FILE) <<<"
else
echo ">>> $SERVICE_NAME is not running <<<"
fi
}
# Restart the service
restart() {
stop
start
}
# Change directory to the service location
cd /home/zhangyanfeng/microsvr/$SERVICE_NAME/
# Main script execution based on input arguments
case "$1" in
"start")
SERVICE_NAME=${2:-$SERVICE_NAME} # Use provided or default service name
start
;;
"stop")
SERVICE_NAME=${2:-$SERVICE_NAME}
stop
;;
"status")
SERVICE_NAME=${2:-$SERVICE_NAME}
status
;;
"restart")
SERVICE_NAME=${2:-$SERVICE_NAME}
restart
;;
*)
usage
;;
esac
exit 0
二、start.sh对焦
Shell脚本 start.sh
的主要功能和目的是管理一个Java服务的运行环境。
(一)主要功能思考
-
管理日志和配置:确保服务日志和配置文件的管理,包括定时清理旧日志和初始化配置文件。
-
动态配置更新:通过
confd
和writeConfigValue
函数,实现动态更新服务的配置,避免了手动修改配置文件的复杂性和错误风险。 -
服务重启和维护:使用
${MICRODIR}/app.sh restart
命令来管理Java服务的启动和重启,保证配置变更后服务的正常运行。 -
安全和可靠性:通过权限设置和错误处理,保证了脚本执行的安全性和可靠性,避免了意外操作对系统的影响。
这段脚本的设计旨在简化运维工作,自动化配置更新和服务重启,提高了系统的可维护性和稳定性。
(二)具体代码展示
#!/bin/sh
cd /home/
find ./ -maxdepth 1 -name "start*.log" -mtime +7 -exec rm {} \;
TODAY=`date +"%Y%m%d"`
getTimeStamp()
{
echo `date +"%Y-%m-%d %H:%M:%S"`
}
log()
{
echo " $1"
echo "`getTimeStamp` : $1" >> /home/start-${TODAY}.log
}
MICRODIR=/home/zhangyanfeng/microsvr/zyf-service-user
CONFIGDIR=${MICRODIR}/config
TEMPLDIR=/etc/confd/templates
NOWTIME=`date +"%Y%m%d%H%M%S"`
init_confd()
{
log "init confd ..."
if [ ! -f ${TEMPLDIR}/application.tmpl ]
then
log "cp -af ${CONFIGDIR}/application.properties ${TEMPLDIR}/application.tmpl"
cp -af ${CONFIGDIR}/application.properties ${TEMPLDIR}/application.tmpl
else
log "${TEMPLDIR}/application.tmpl is exist, ignore."
fi
if [ ! -f ${TEMPLDIR}/bootstrap.tmpl ]
then
log "cp -af ${CONFIGDIR}/bootstrap.properties ${TEMPLDIR}/bootstrap.tmpl"
cp -af ${CONFIGDIR}/bootstrap.properties ${TEMPLDIR}/bootstrap.tmpl
else
log "${TEMPLDIR}/bootstrap.tmpl is exist, ignore."
fi
chmod 755 -R ${TEMPLDIR}
}
common_softlink()
{
targetdir=$1
sourcedir=$2
if [ ! -d ${targetdir} ]
then
mkdir -p ${targetdir}
log "mkdir -p ${targetdir}"
fi
if [ -L ${sourcedir} ]
then
log "rm ${sourcedir}"
rm ${sourcedir}
fi
if [ -d ${sourcedir} ]
then
log "mv -f ${sourcedir} ${sourcedir}_${NOWTIME}"
mv -f ${sourcedir} ${sourcedir}_${NOWTIME}
fi
ln -s ${targetdir} ${sourcedir}
chmod 755 ${sourcedir}
chown zxin10:root ${sourcedir}
chmod -R 755 ${targetdir}
chown -R zxin10:root ${targetdir}
}
init_softlink()
{
UNAME=`uname -a`
MICRONAME1=`echo $UNAME | cut -d ' ' -f 2`
MICRONAME2=`echo $MICRONAME1 | cut -d '-' -f 1-3`
log_dir=/home/log/$MICRONAME2/$MICRONAME1
common_softlink "${log_dir}" "/home/zhangyanfeng/microsvr/zyf-service-user/logs"
}
start_confd()
{
log "start confd..."
CONFDPID= `ps -ef|grep "confd"|grep -v grep|awk '{print $2}'`
if [ -n "${CONFDPID}" ]
then
log "stop confd"
kill -9 ${CONFDPID}
sleep 3
fi
ETCDCONFPATH="/home/zhangyanfeng/confdconfig/confd-general-config.conf"
ETCD_SERVER_IP=`grep ETCD_SERVER_HOSTIP ${ETCDCONFPATH} | awk -F '=' '{print $2}'`
ETCD_SERVER_PORT=`grep ETCD_SERVER_PORT ${ETCDCONFPATH} | awk -F '=' '{print $2}'`
CONFD_SERVER=${ETCD_SERVER_IP}":"${ETCD_SERVER_PORT}
log "/usr/bin/confd -interval 60 -backend etcd -node http://${CONFD_SERVER} &"
/usr/bin/confd -interval 60 -backend etcd -node http://${CONFD_SERVER} &
}
function getConfigValue
{
[ $# -ne 2 ] && echo "function getConfigValue arguments error"
local fileName=$1
local key=$2
echo `cat ${fileName}| grep "${key}"| grep "=" | awk -F= '{print $2}' | tr -d " "`
}
function writeConfigValue()
{
K8SCONFIGDIR=/home/zhangyanfeng/confdconfig
K8SCONFIGFILE=${K8SCONFIGDIR}/confd-general-config.conf
DBMASTURL=`getConfigValue ${K8SCONFIGFILE} pgconn | awk -F ',' '{print $1}'`
DBSLAVEURL=`getConfigValue ${K8SCONFIGFILE} pgconn | awk -F ',' '{print $2}'`
REDISURL=`getConfigValue ${K8SCONFIGFILE} redisconn`
KAFKAURL=`getConfigValue ${K8SCONFIGFILE} kafkaconn`
ZOOKEEPURL=`getConfigValue ${K8SCONFIGFILE} zkconn`
IPSEGEMENT=`getConfigValue ${K8SCONFIGFILE} innernetworksegement`
LIANCHUANGURL=`getConfigValue ${K8SCONFIGFILE} lianchuang_url`
if [ -f ${CONFIGDIR}/application.properties ]
then
if [ -n ${IPSEGEMENT} ]
then
sed -i -e "/^genid/s/\/[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]./\/${IPSEGEMENT}./g" ${CONFIGDIR}/application.properties
fi
if [ -n ${ZOOKEEPURL} ]
then
sed -i -e "/^spring.cloud.stream.kafka.binder.zk-nodes/s/spring.cloud.stream.kafka.binder.zk-nodes=.*/spring.cloud.stream.kafka.binder.zk-nodes=${ZOOKEEPURL}/" ${CONFIGDIR}/application.properties
fi
if [ -n ${KAFKAURL} ]
then
sed -i -e "/^kafka.binder.brokers/s/kafka.binder.brokers=.*/kafka.binder.brokers=${KAFKAURL}/" ${CONFIGDIR}/application.properties
sed -i -e "/^spring.cloud.stream.kafka.binder.brokers/s/spring.cloud.stream.kafka.binder.brokers=.*/spring.cloud.stream.kafka.binder.brokers=${KAFKAURL}/" ${CONFIGDIR}/application.properties
fi
if [ -n ${LIANCHUANGURL} ]
then
BRFOREVALUE=`getConfigValue ${CONFIGDIR}/application.properties lianchuang.url`
BRFORE=${BRFOREVALUE#*//}
sed -i "s/${BRFORE}/${LIANCHUANGURL}/g" ${CONFIGDIR}/application.properties
fi
fi
if [ -f ${CONFIGDIR}/bootstrap.properties ]
then
if [ -n ${IPSEGEMENT} ]
then
sed -i -e "/^eureka.client.serviceUrl.defaultZone/s/\/[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]./\/${IPSEGEMENT}./g" ${CONFIGDIR}/bootstrap.properties
fi
fi
}
============== MAIN FUNCTION ===============
init_softlink
#init_confd
#start_confd
writeConfigValue
cd ${MICRODIR}
log "${MICRODIR}/app.sh restart"
${MICRODIR}/app.sh restart
export TERM=linux
/usr/sbin/sshd -D
(三)改进空间思考
-
错误处理和日志记录增强:在关键操作前后增加更详细的错误处理和日志记录,特别是在文件操作、进程管理和配置更新过程中,确保可以追踪到每一步的执行情况和可能的异常。
-
参数化和配置文件分离:将脚本中的硬编码路径和配置参数提取为变量,甚至考虑将配置信息存储在单独的配置文件中,这样可以使脚本更具灵活性和可配置性,便于维护和部署到不同的环境。
-
安全性增强:在涉及到重启服务和管理权限的地方,确保操作的安全性。可以考虑使用更严格的权限控制或者使用特定的用户执行关键操作,以防止误操作或者恶意访问。
-
代码重构和模块化:如果脚本变得足够复杂,可以考虑将功能模块化,每个函数尽可能独立和可测试。这样可以简化逻辑,提高代码的复用性和可读性。
-
定时任务和自动化:如果需要定时执行清理日志或者其他操作,可以考虑将脚本集成到系统的定时任务中,或者使用专门的自动化工具来管理和调度任务,避免手动执行。
-
文档和注释:在脚本中增加详细的注释和文档,解释每个函数的作用、输入参数和返回值。这样可以帮助新的开发人员或者维护者快速理解脚本的功能和设计思路。
(四)优化后的代码展示
#!/bin/bash
# Set Java environment
export JAVA_HOME=/opt/jdk1.8.0
# Service configuration
SERVICE_NAME=servicename
JAR_NAME=${SERVICE_NAME}-pkgvernum-RELEASE.jar
PID_FILE=/home/zhangyanfeng/microsvr/${SERVICE_NAME}/${SERVICE_NAME}.pid
# Directories
MICRO_DIR=/home/zhangyanfeng/microsvr/zyf-service-user
CONFIG_DIR=${MICRO_DIR}/config
TEMPLATE_DIR=/etc/confd/templates
LOG_DIR=/home/log
# Log function to timestamp logs
log() {
local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
echo "$timestamp : $1"
echo "$timestamp : $1" >> /home/start-$(date +"%Y%m%d").log
}
# Initialize confd templates
init_confd() {
log "Initializing confd..."
for tmpl_file in "${TEMPLATE_DIR}/application.tmpl" "${TEMPLATE_DIR}/bootstrap.tmpl"; do
if [ ! -f "${tmpl_file}" ]; then
log "Copying ${CONFIG_DIR}/$(basename "${tmpl_file}") to ${TEMPLATE_DIR}"
cp -af "${CONFIG_DIR}/$(basename "${tmpl_file}")" "${tmpl_file}"
else
log "${tmpl_file} already exists, skipping."
fi
done
chmod -R 755 "${TEMPLATE_DIR}"
}
# Function to manage symbolic links
manage_symlink() {
local target_dir="$1"
local source_dir="$2"
if [ ! -d "${target_dir}" ]; then
mkdir -p "${target_dir}"
log "Created directory ${target_dir}"
fi
if [ -L "${source_dir}" ]; then
log "Removing existing symlink ${source_dir}"
rm "${source_dir}"
fi
if [ -d "${source_dir}" ]; then
log "Moving existing directory ${source_dir} to ${source_dir}_${NOWTIME}"
mv "${source_dir}" "${source_dir}_${NOWTIME}"
fi
ln -s "${target_dir}" "${source_dir}"
chmod 755 "${source_dir}"
chown zxin10:root "${source_dir}"
chmod -R 755 "${target_dir}"
chown -R zxin10:root "${target_dir}"
}
# Initialize symbolic links
init_softlink() {
local uname_info=$(uname -a)
local microname1=$(echo "${uname_info}" | cut -d ' ' -f 2)
local microname2=$(echo "${microname1}" | cut -d '-' -f 1-3)
local log_dir="/home/log/${microname2}/${microname1}"
manage_symlink "${log_dir}" "/home/zhangyanfeng/microsvr/zyf-service-user/logs"
}
# Start confd service
start_confd() {
log "Starting confd..."
local confd_pid=$(pgrep -f "confd")
if [ -n "${confd_pid}" ]; then
log "Stopping existing confd process (PID ${confd_pid})"
kill -9 "${confd_pid}"
sleep 3
fi
local confd_config_file="/home/zhangyanfeng/confdconfig/confd-general-config.conf"
local etcd_server_host=$(grep ETCD_SERVER_HOSTIP "${confd_config_file}" | cut -d '=' -f 2)
local etcd_server_port=$(grep ETCD_SERVER_PORT "${confd_config_file}" | cut -d '=' -f 2)
local confd_server="${etcd_server_host}:${etcd_server_port}"
log "Starting confd with backend etcd and node http://${confd_server}"
/usr/bin/confd -interval 60 -backend etcd -node "http://${confd_server}" &
}
# Function to get configuration value from file
getConfigValue() {
if [ $# -ne 2 ]; then
log "getConfigValue arguments error"
return 1
fi
local file_name="$1"
local key="$2"
grep "${key}" "${file_name}" | grep "=" | awk -F '=' '{print $2}' | tr -d " "
}
# Function to write configuration values to application.properties and bootstrap.properties
writeConfigValue() {
local k8s_config_dir="/home/zhangyanfeng/confdconfig"
local k8s_config_file="${k8s_config_dir}/confd-general-config.conf"
local db_master_url=$(getConfigValue "${k8s_config_file}" "pgconn" | awk -F ',' '{print $1}')
local db_slave_url=$(getConfigValue "${k8s_config_file}" "pgconn" | awk -F ',' '{print $2}')
local redis_url=$(getConfigValue "${k8s_config_file}" "redisconn")
local kafka_url=$(getConfigValue "${k8s_config_file}" "kafkaconn")
local zookeeper_url=$(getConfigValue "${k8s_config_file}" "zkconn")
local ip_segment=$(getConfigValue "${k8s_config_file}" "innernetworksegement")
local lianchuang_url=$(getConfigValue "${k8s_config_file}" "lianchuang_url")
if [ -f "${CONFIG_DIR}/application.properties" ]; then
if [ -n "${ip_segment}" ]; then
sed -i -e "/^genid/s/\/[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]./\/${ip_segment}./g" "${CONFIG_DIR}/application.properties"
fi
if [ -n "${zookeeper_url}" ]; then
sed -i -e "/^spring.cloud.stream.kafka.binder.zk-nodes/s/spring.cloud.stream.kafka.binder.zk-nodes=.*/spring.cloud.stream.kafka.binder.zk-nodes=${zookeeper_url}/" "${CONFIG_DIR}/application.properties"
fi
if [ -n "${kafka_url}" ]; then
sed -i -e "/^kafka.binder.brokers/s/kafka.binder.brokers=.*/kafka.binder.brokers=${kafka_url}/" "${CONFIG_DIR}/application.properties"
sed -i -e "/^spring.cloud.stream.kafka.binder.brokers/s/spring.cloud.stream.kafka.binder.brokers=.*/spring.cloud.stream.kafka.binder.brokers=${kafka_url}/" "${CONFIG_DIR}/application.properties"
fi
if [ -n "${lianchuang_url}" ]; then
local before_value=$(getConfigValue "${CONFIG_DIR}/application.properties" "lianchuang.url")
local before=$(echo "${before_value}" | sed 's#^.*//##')
sed -i "s/${before}/${lianchuang_url}/g" "${CONFIG_DIR}/application.properties"
fi
fi
if [ -f "${CONFIG_DIR}/bootstrap.properties" ]; then
if [ -n "${ip_segment}" ]; then
sed -i -e "/^eureka.client.serviceUrl.defaultZone/s/\/[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]./\/${ip_segment}./g" "${CONFIG_DIR}/bootstrap.properties"
fi
fi
}
# Main function
main() {
init_softlink
# init_confd # Uncomment if confd initialization is required
# start_confd # Uncomment if confd start is required
writeConfigValue
cd "${MICRO_DIR}"
log "Restarting ${MICRO_DIR}/app.sh"
"${MICRO_DIR}/app.sh" restart
export TERM=linux
/usr/sbin/sshd -D
}
# Entry point
main
三、总结思考
在这个自动化管理和配置Java服务的方案中,我们通过优化和整合多个脚本,实现了一套完整的管理工具。主要脚本包括 app.sh
和 start.sh
,它们分别负责启动、停止、重启服务,以及初始化配置、软链接管理、动态更新配置文件和日志记录等功能。
通过 app.sh
,我们可以方便地对服务进行操作,包括启动、停止、重启和查询状态,保证了服务的稳定运行。在 start.sh
中,我们实现了对配置文件的动态更新,通过 confd 工具实时同步配置信息,确保服务配置的灵活性和实时性。同时,脚本中的日志记录功能,能够帮助追踪和排查问题,保障服务的可靠性和可维护性。
我们不仅简化了管理流程,提高了运维效率,还增强了服务的可配置性和自动化程度。通过这样的自动化工具链,我们能够更专注于业务逻辑的开发和优化,同时保持对服务稳定性和可管理性的高度把控。