优化前:
因项目部署在内网环境,只有部分服务可以外网访问。之前部署项目,需要在本地打包,上传到运维机连vpn上传到内网服务器,通过脚本启动。
优化后:
- 使用jenkins打包服务,并通过ssh上传到A服务器
- jenkins执行upload.sh将jar包每9m分割一个文件
- upload.sh调用内网服务器映射出来的上传文件接口,上传到分割后的多个文件到内网服务器
- upload.sh调用内网服务器映射的执行脚本接口,调用内网服务器deploy.sh脚本
- deploy.sh脚本合并文件 并备份发布项目
- 新增查询日志接口 简单使用cat命令
0. shell脚本
0.1 upload.sh 分割文件、调用上传接口
#!/bin/bash
source /etc/profile
JAR_NAME=${1}
JAR_PATH=/mnt/data/iot-supplier-center/iot-supplier-deploy/jars
LOG_PATH=/mnt/data/iot-supplier-center/iot-supplier-deploy/logs/bash.log
echo $(date "+%Y-%m-%d %H:%M:%S") -- JAR_NAME is ${JAR_NAME} >> ${LOG_PATH}
cd ${JAR_PATH}
#每9m分割一个jar包
split -b 9m ${JAR_NAME} split-${JAR_NAME}-
echo $(date "+%Y-%m-%d %H:%M:%S") -- split finished! >> ${LOG_PATH}
for file in $(find /mnt/data/iot-supplier-center/iot-supplier-deploy/jars/ -type f -name "spl*")
do
curl -F "file=@$file" -F "path=/data/platform/jar/upload/" -o /mnt/data/iot-supplier-center/iot-supplier-deploy/logs/upload.log https://xxx.com/deploy-project/upload
done
rm -rf split-${JAR_NAME}-*
echo $(date "+%Y-%m-%d %H:%M:%S") -- upload finished! >> ${LOG_PATH}
echo $(curl -X POST -H "Content-Type: application/json" https://xxx.com/deploy-project/combine-and-deploy -d "{\"jarName\":\"${JAR_NAME}\"}") >>${LOG_PATH}
echo $(date "+%Y-%m-%d %H:%M:%S") -- execute sh finished! >> ${LOG_PATH}
echo ----------end----------
0.2 deploy.sh 合并文件 并发布
#!/bin/sh
source /etc/profile
JAR_NAME=${1}
WORK_PATH='/data/platform/jar/';
PROJECT='province';
if [ -z "$JAR_NAME" ];then
echo "JAR_NAME is null !"
exit
fi
JAR_PATH=/data/platform/jar/upload/
LOG_PATH=/data/platform/jar/upload/logs/bash.log
echo $(date "+%Y-%m-%d %H:%M:%S") -- ----- start ----- >> $LOG_PATH
echo $(date "+%Y-%m-%d %H:%M:%S") -- JAR_NAME is $JAR_NAME >> $LOG_PATH
cd $JAR_PATH
echo $(date "+%Y-%m-%d %H:%M:%S") -- pwd is `pwd` ,jarPath is $JAR_PATH ,jarName is $JAR_NAME ! >> $LOG_PATH
cat split-$JAR_NAME-* > $JAR_NAME
echo $(date "+%Y-%m-%d %H:%M:%S") -- combine fineshed! >> $LOG_PATH
FILE_NAME=$WORK_PATH$JAR_NAME
echo $(date "+%Y-%m-%d %H:%M:%S") -- fileName is $FILE_NAME ! >> $LOG_PATH
COPY_PATH=${JAR_PATH}backup/$(date "+%Y%m%d%H%M%S")-$JAR_NAME
if [ -e "$FILE_NAME" ]; then
echo $(date "+%Y-%m-%d %H:%M:%S") -- true copyPath is $COPY_PATH ! >> $LOG_PATH
cp $FILE_NAME $COPY_PATH
fi
echo $(date "+%Y-%m-%d %H:%M:%S") -- backup fineshed! >> $LOG_PATH
PID=`ps aux | grep $JAR_NAME |grep $PROJECT | grep -v grep | awk '{print $2}'`
echo $(date "+%Y-%m-%d %H:%M:%S") -- PID is $PID >> $LOG_PATH
if [ -n "$PID" ]; then
kill -9 $PID
echo $(date "+%Y-%m-%d %H:%M:%S") -- kill fineshed! pid is $PID >> $LOG_PATH
fi
mv -u $JAR_NAME /data/platform/jar/
echo $(date "+%Y-%m-%d %H:%M:%S") -- mv fineshed! >> $LOG_PATH
echo $(date "+%Y-%m-%d %H:%M:%S") -- start jar service! >> $LOG_PATH
nohup java -Xms512m -Xmx512m -jar $FILE_NAME --spring.profiles.active=$PROJECT > /dev/null 2>&1 &
NEW_PID=`ps aux | grep $JAR_NAME |grep $PROJECT | grep -v grep | awk '{print $2}'`
echo $(date "+%Y-%m-%d %H:%M:%S") -- start jar service fineshed! old is $PID , newPid is $NEW_PID >> $LOG_PATH
echo $(date "+%Y-%m-%d %H:%M:%S") -- ----- end ----- -- >> $LOG_PATH
1.Java代码 调用shell脚本
1.1 文件上传
@PostMapping("upload")
public RestResult<String> upload(@RequestParam("file") MultipartFile multipartFile, @RequestParam("path") String path) {
String originalFilename = multipartFile.getOriginalFilename();
String[] split = originalFilename.split("\\.");
String jarName = split[0];
StringBuilder stringBuffer = new StringBuilder();
stringBuffer.append("path : ").append(path);
stringBuffer.append(" jarName : ").append(jarName);
log.info("originalFilename :{},path :{},", originalFilename, path);
//生成发布所需目录
String deployPath = path + "/logs";
boolean mkdirs = new File(deployPath).mkdirs();
stringBuffer.append(" deployPath mkdirs : ").append(mkdirs);
try {
File file = new File(path + originalFilename);
multipartFile.transferTo(file);
stringBuffer.append(" upload success! ");
} catch (IOException e) {
stringBuffer.append(" " + e);
return RestResult.wrapErrorResponse(stringBuffer.toString());
}
return RestResult.wrapSuccessResponse(stringBuffer.toString());
}
1.2 合并文件并发布
@PostMapping("combine-and-deploy")
public RestResult<String> combineAndDeploy(@RequestBody JarNameParam jarNameParam) {
StringBuilder stringBuffer = new StringBuilder();
String jarName = jarNameParam.getJarName();
stringBuffer.append("jarName : ").append(jarName);
ProcessBuilder builder = new ProcessBuilder("/bin/sh", "-c", "/home/sh/combine-and-deploy.sh " + jarName);
Process process = null;
try {
process = builder.start();
stringBuffer.append("execute bash success ! ");
StreamGobbler streamGobbler = new StreamGobbler(process.getInputStream(), System.out::println);
Future<?> future = Executors.newSingleThreadExecutor().submit(streamGobbler);
int exitCode = process.waitFor();
assert exitCode == 0;
future.get(10, TimeUnit.SECONDS);
} catch (IOException | InterruptedException | ExecutionException | TimeoutException e) {
stringBuffer.append(e);
return RestResult.wrapErrorResponse(stringBuffer.toString());
}
return RestResult.wrapSuccessResponse(stringBuffer.toString());
}
static class StreamGobbler implements Runnable {
private InputStream inputStream;
private Consumer<String> consumeInputLine;
public StreamGobbler(InputStream inputStream, Consumer<String> consumeInputLine) {
this.inputStream = inputStream;
this.consumeInputLine = consumeInputLine;
}
public void run() {
new BufferedReader(new InputStreamReader(inputStream)).lines().forEach(consumeInputLine);
}
}
1.3 查看日志
@PostMapping("returnStream")
public void returnStream(HttpServletResponse response, @RequestBody JarNameParam param) throws IOException {
String command = param.getJarName();
if (!command.startsWith("cat")) {
return;
}
// 执行脚本文件
log.info("开始执行命令:" + command);
//主要在这步写入后调用命令
String[] cmd = {"/bin/sh", "-c", command};
Process process = Runtime.getRuntime().exec(cmd);
try (BufferedReader read = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
Future<String> future = Executors.newSingleThreadExecutor().submit(() -> {
String line;
StringBuilder buffer = new StringBuilder();
while ((line = read.readLine()) != null) {
buffer.append(line).append(System.lineSeparator());
}
return buffer.toString();
});
int exitCode = process.waitFor();
assert exitCode == 0;
String buffer = future.get(10, TimeUnit.SECONDS);
response.setHeader("content-type", "application/octet-stream");
response.setContentType("application/octet-stream;charset=UTF-8");
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(buffer.getBytes());
outputStream.flush();
outputStream.close();
} catch (Exception e) {
log.error("", e);
}
}