2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
The system composed of multiple Java applications deployed in an offline environment needs to be released frequently during the testing phase. Due to resource constraints, there is no devops or CICD system, so it is simply packaged into jar for release. Before starting, a script was created. Before starting, it is necessary to kill the process received by the port and then start it again, otherwise there will be a port conflict and the startup will fail. One of the optimization points is to support automatic restart of the script, automatically find the corresponding process, and then kill and restart it. Another point is the log file. After restarting, a new log file will be generated according to the service name and current time. When querying the log, if there are multiple files with prefixes, you need to select manually, which is troublesome. So I thought about archiving the historical log files in the backup folder under the current path.
First of all, I declare that I am a novice in shell and I have little use for this.
I prefer to use the lsof command. For example, to query the process occupying port 8080, you can use the following command:
lsof -i:8080
You should all know this, kill -9, don't just use kill, for example, kill the process with PID 12345
kill -9 12345
This is a relatively simple command. The function parameters are used as follows$1
,$2
,$3
...to receive
Because there are multiple Java services, and adhering to the idea of reuse, I want to write a common method to restart the service, and then write scripts corresponding to multiple services to record their respective service names, ports and other information, and pass parameters in the service's respective scripts to call the common service start or restart method.
General service startup or restart script run.sh
#!/bin/bash
start_app(){
# 接收参数
APP_NAME=$1;
APP_PORT=$2;
MEM=$3
ACTION=$4;
CURRENT_TIME=`date +"%Y%m%d%H%M%S"`
#检查程序是否在运行
APP_STATUS=`netstat -nlt|grep ${APP_PORT} |wc -l`;
RUNNING_PID=$(netstat -nlp | grep :$APP_PORT | awk '{print $7}' | awk -F"/" '{ print $1 }');
LOG_FILE=./logs/${APP_NAME}_${CURRENT_TIME}.log;
cd ..;
if [ "${APP_STATUS}" -eq 1 ]; then
if [ "${ACTION}"x == "restart"x ]; then
## 重启前先kill原进程
echo "kill the running app whose PID is ${RUNNING_PID} of ${APP_NAME}";
kill -9 "${RUNNING_PID}";
# 日志归档
cd logs;
for file in `ls ${APP_NAME}* -a`;
do
mv "${file}" backup/;
done
cd ..;
else
echo "exist running ${APP_NAME} and the PID is ${RUNNING_PID}";
exit 0;
fi
fi
echo "start ${APP_NAME} at $CURRENT_TIME";
## 启动程序
nohup java -Xms${MEM}m -Xmx${MEM}m -XX:PermSize=256m -XX:MaxPermSize=512m -jar -Dfile.encoding=utf-8 -Dserver.port=${APP_PORT} -Dspring.profiles.active=prod ${APP_NAME} > ${LOG_FILE} 2>&1 &
pid=`ps -ef|grep java|grep ${APP_NAME}`
echo "${APP_NAME} has started successfully at ${CURRENT_TIME},and the pid is ${pid}"
}
Single service startup script
#!/bin/bash
action=$1
## 引入通用服务启动脚本
source ./run.sh
#启动方法
start(){
# 执行通用服务脚本中的启动方法
start_app xxx.jar 8080 4096 ${action}
}
#程序主入口
start
When the service startup script is executed directly without passing parameters, it will determine whether the service port is occupied. If it is occupied, it will exit directly. If restart is passed, the original service process will be killed and then restarted when the service is started.
The jar package is located in the /opt/app directory, the script is located in the /opt/app/run directory, and the log is placed in the /opt/app/logs directory. Currently, this version can only support execution in the current directory of the script. If the absolute path is used, an error will be reported. It should be due to the fact that some writing methods in the script do not use absolute paths. Each has its pros and cons, so this solution is temporarily retained.
During the test, we encounteredrun.sh: xxx行 $'r' 附近有语法错误
To solve the error, use sed -i 's/r$//' run.sh command to convert it.