修正文件下载完毕后启动 jar 的错误

master
linbin 2024-09-17 23:28:27 +08:00
parent c1ba437555
commit 3f220825bc
5 changed files with 172 additions and 134 deletions

View File

@ -0,0 +1,132 @@
package org.tianhe.agent;
import com.jfirer.baseutil.STR;
import com.jfirer.baseutil.StringUtil;
import com.jfirer.jnet.common.api.Pipeline;
import lombok.extern.slf4j.Slf4j;
import org.tianhe.common.packet.LogReport;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import static org.tianhe.agent.AgentConfig.*;
@Slf4j
public class PlatformHelper
{
public static List<String> getPidByName(String appName, Pipeline pipeline)
{
List<String> list = new ArrayList<>();
ProcessBuilder processBuilder = AgentConfig.WINDOW ?//
new ProcessBuilder("cmd.exe", "/c", "wmic process where \"name='java.exe' and CommandLine like '%%" + appName + "%%'\" get ProcessId /value | findstr \"=\"")//
: new ProcessBuilder("sh", "-c", "ps aux | grep " + appName + " | grep -v grep | awk '{print $2}'");
try
{
Process process = processBuilder.start();
try (BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8)))
{
String line;
while ((line = input.readLine()) != null)
{
log.debug("命令输出:{}", line);
if (StringUtil.isNotBlank(line))
{
String pid = WINDOW ? line.substring(10) : line;
if (!PID.equalsIgnoreCase(pid))
{
list.add(pid);
}
}
}
}
process.destroy();
String msg = list.isEmpty() ? STR.format("通过应用名称:{}检查,未能发现进程", appName) : STR.format("通过应用名称:{}查询,一共发现 PID:{}", appName, String.join(",", list));
log.debug(msg);
pipeline.fireWrite(new LogReport().setContent(msg));
return list;
}
catch (Throwable e)
{
log.error("通过应用名称:{}获取应用出现异常", appName, e);
pipeline.fireWrite(new LogReport().setContent(STR.format("通过应用名称:{}获取应用出现异常。异常信息:{}", appName, e)));
return list;
}
}
public static void killPid(String pid, Pipeline pipeline)
{
ProcessBuilder builder = WINDOW ? new ProcessBuilder("cmd.exe", "/C", "taskkill /F /PID " + pid) : new ProcessBuilder("kill", "-9", pid);
try
{
Process process = builder.start();
process.waitFor();
process.destroy();
String msg = STR.format("终止进程:{}", pid);
log.debug(msg);
pipeline.fireWrite(new LogReport().setContent(msg));
}
catch (Throwable e)
{
log.error("终止进程:{}出现异常", pid, e);
pipeline.fireWrite(new LogReport().setContent(STR.format("终止进程:{}出现异常。异常信息:{}", pid, e)));
}
}
public static void startJar(String relativePath, Pipeline pipeline)
{
File targetJarFile = new File(DIR_PATH, relativePath);
if (!targetJarFile.exists())
{
pipeline.fireWrite(new LogReport().setContent(STR.format("文件:{}不存在,无法启动对应的 jar", targetJarFile.getAbsolutePath())));
return;
}
String fileName = targetJarFile.getName();
int index = fileName.lastIndexOf(".");
String fileNameWithoutExtension = fileName.substring(0, index);
String extension = fileName.substring(index);
File copyFile = new File(targetJarFile.getParentFile(), fileNameWithoutExtension + "_copy" + extension);
try
{
Files.copy(targetJarFile.toPath(), copyFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
catch (Throwable e)
{
pipeline.fireWrite(new LogReport().setContent(STR.format("复制文件:{}失败,异常信息:{}", copyFile.getAbsolutePath(), e)));
return;
}
pipeline.fireWrite(new LogReport().setContent(STR.format("复制文件:{}成功,现在准备启动", copyFile.getAbsolutePath())));
ProcessBuilder builder = WINDOW ? new ProcessBuilder("java", "-jar", copyFile.getAbsolutePath()) : new ProcessBuilder("nohup", "java", "-jar", copyFile.getAbsolutePath(), "&");
new Thread(() -> {
Process process = null;
try
{
process = builder.start();
try (BufferedReader reader = process.inputReader(StandardCharsets.UTF_8))
{
while (reader.readLine() != null)
{
;
}
}
}
catch (IOException e)
{
throw new RuntimeException(e);
}
finally
{
if (process != null)
{
process.destroy();
}
}
}).start();
}
}

View File

@ -1,12 +1,11 @@
package org.tianhe.agent.control;
import com.jfirer.baseutil.STR;
import com.jfirer.baseutil.StringUtil;
import com.jfirer.jnet.common.api.Pipeline;
import com.jfirer.jnet.common.api.ReadProcessor;
import com.jfirer.jnet.common.api.ReadProcessorNode;
import lombok.extern.slf4j.Slf4j;
import org.tianhe.agent.AgentConfig;
import org.tianhe.agent.PlatformHelper;
import org.tianhe.common.command.Command;
import org.tianhe.common.command.impl.ReBootJar;
import org.tianhe.common.command.impl.StopJar;
@ -16,18 +15,8 @@ import org.tianhe.common.packet.ExecuteCommandReq;
import org.tianhe.common.packet.FileInfoReq;
import org.tianhe.common.packet.LogReport;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import static org.tianhe.agent.AgentConfig.*;
@Slf4j
public class CommandHandler implements ReadProcessor<Object>
{
@ -63,6 +52,9 @@ public class CommandHandler implements ReadProcessor<Object>
next.pipeline().channelContext().setAttach(new FileDownload(updateJarVersionAndReboot));
next.pipeline().fireWrite(new FileInfoReq().setFileId(updateJarVersionAndReboot.getFileId()));
}
case Command.UPDATE_ZIP_VERSION ->
{
}
}
}
else
@ -71,15 +63,15 @@ public class CommandHandler implements ReadProcessor<Object>
}
}
private void rebootJar(ReBootJar reBootJar, Pipeline pipeline)
public static void rebootJar(ReBootJar reBootJar, Pipeline pipeline)
{
String msg = STR.format("收到重启指令,应用名称:{},文件地址为:{}", reBootJar.getJarNameWithoutExtension(), reBootJar.getRelativePath());
log.debug(msg);
LogReport logReport = new LogReport().setContent(msg);
pipeline.fireWrite(logReport);
List<String> pidByName = getPidByName(reBootJar.getJarNameWithoutExtension(), pipeline);
pidByName.forEach(pid -> killPid(pid, pipeline));
startJar(reBootJar.getRelativePath(), pipeline);
List<String> pidByName = PlatformHelper.getPidByName(reBootJar.getJarNameWithoutExtension(), pipeline);
pidByName.forEach(pid -> PlatformHelper.killPid(pid, pipeline));
PlatformHelper.startJar(reBootJar.getRelativePath(), pipeline);
}
private void stopJar(StopJar stopJar, Pipeline pipeline)
@ -88,116 +80,7 @@ public class CommandHandler implements ReadProcessor<Object>
log.debug(msg);
LogReport logReport = new LogReport().setContent(msg);
pipeline.fireWrite(logReport);
List<String> pidByName = getPidByName(stopJar.getJarName(), pipeline);
pidByName.forEach(pid -> killPid(pid, pipeline));
}
private List<String> getPidByName(String appName, Pipeline pipeline)
{
List<String> list = new ArrayList<>();
ProcessBuilder processBuilder = AgentConfig.WINDOW ?//
new ProcessBuilder("cmd.exe", "/c", "wmic process where \"name='java.exe' and CommandLine like '%%" + appName + "%%'\" get ProcessId /value | findstr \"=\"")//
: new ProcessBuilder("sh", "-c", "ps aux | grep " + appName + " | grep -v grep | awk '{print $2}'");
try
{
Process process = processBuilder.start();
try (BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8)))
{
String line;
while ((line = input.readLine()) != null)
{
log.debug("命令输出:{}", line);
if (StringUtil.isNotBlank(line))
{
String pid = WINDOW ? line.substring(10) : line;
if (!PID.equalsIgnoreCase(pid))
{
list.add(pid);
}
}
}
}
process.destroy();
String msg = list.isEmpty() ? STR.format("通过应用名称:{}检查,未能发现进程", appName) : STR.format("通过应用名称:{}查询,一共发现 PID:{}", appName, String.join(",", list));
log.debug(msg);
pipeline.fireWrite(new LogReport().setContent(msg));
return list;
}
catch (Throwable e)
{
log.error("通过应用名称:{}获取应用出现异常", appName, e);
pipeline.fireWrite(new LogReport().setContent(STR.format("通过应用名称:{}获取应用出现异常。异常信息:{}", appName, e)));
return list;
}
}
public void killPid(String pid, Pipeline pipeline)
{
ProcessBuilder builder = WINDOW ? new ProcessBuilder("cmd.exe", "/C", "taskkill /F /PID " + pid) : new ProcessBuilder("kill", "-9", pid);
try
{
Process process = builder.start();
process.waitFor();
process.destroy();
String msg = STR.format("终止进程:{}", pid);
log.debug(msg);
pipeline.fireWrite(new LogReport().setContent(msg));
}
catch (Throwable e)
{
log.error("终止进程:{}出现异常", pid, e);
pipeline.fireWrite(new LogReport().setContent(STR.format("终止进程:{}出现异常。异常信息:{}", pid, e)));
}
}
public void startJar(String relativePath, Pipeline pipeline)
{
File targetJarFile = new File(DIR_PATH, relativePath);
if (!targetJarFile.exists())
{
pipeline.fireWrite(new LogReport().setContent(STR.format("文件:{}不存在,无法启动对应的 jar", targetJarFile.getAbsolutePath())));
return;
}
String fileName = targetJarFile.getName();
int index = fileName.lastIndexOf(".");
String fileNameWithoutExtension = fileName.substring(0, index);
String extension = fileName.substring(index);
File copyFile = new File(targetJarFile.getParentFile(), fileNameWithoutExtension + "_copy" + extension);
try
{
Files.copy(targetJarFile.toPath(), copyFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
catch (Throwable e)
{
pipeline.fireWrite(new LogReport().setContent(STR.format("复制文件:{}失败,异常信息:{}", copyFile.getAbsolutePath(), e)));
return;
}
pipeline.fireWrite(new LogReport().setContent(STR.format("复制文件:{}成功,现在准备启动", copyFile.getAbsolutePath())));
ProcessBuilder builder = WINDOW ? new ProcessBuilder("java", "-jar", copyFile.getAbsolutePath()) : new ProcessBuilder("nohup", "java", "-jar", copyFile.getAbsolutePath(), "&");
new Thread(() -> {
Process process = null;
try
{
process = builder.start();
try (BufferedReader reader = process.inputReader(StandardCharsets.UTF_8))
{
while (reader.readLine() != null)
{
;
}
}
}
catch (IOException e)
{
throw new RuntimeException(e);
}
finally
{
if (process != null)
{
process.destroy();
}
}
}).start();
List<String> pidByName = PlatformHelper.getPidByName(stopJar.getJarName(), pipeline);
pidByName.forEach(pid -> PlatformHelper.killPid(pid, pipeline));
}
}

View File

@ -7,8 +7,8 @@ import com.jfirer.jnet.common.api.ReadProcessor;
import com.jfirer.jnet.common.api.ReadProcessorNode;
import lombok.Data;
import org.tianhe.agent.AgentConfig;
import org.tianhe.agent.PlatformHelper;
import org.tianhe.common.command.Command;
import org.tianhe.common.command.impl.ReBootJar;
import org.tianhe.common.packet.FileInfoResp;
import org.tianhe.common.packet.FileSegmentReq;
import org.tianhe.common.packet.FileSegmentResp;
@ -19,6 +19,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.List;
import static org.tianhe.common.command.Command.UPDATE_JAR_VERSION_AND_REBOOT;
@ -123,8 +124,9 @@ public class DownloadFileHandler implements ReadProcessor<Object>
pipeline.fireWrite(new LogReport().setContent(STR.format("文件:{}更新成功", fileDownload.getRelativePath())));
if (fileDownload.getCommand() == UPDATE_JAR_VERSION_AND_REBOOT)
{
ReBootJar reBootJar = new ReBootJar().setJarNameWithoutExtension(fileDownload.getJarNameWithoutExtension()).setRelativePath(fileDownload.getRelativePath());
next.fireRead(reBootJar);
List<String> pidByName = PlatformHelper.getPidByName(fileDownload.getJarNameWithoutExtension(), pipeline);
pidByName.forEach(pid -> PlatformHelper.killPid(pid, pipeline));
PlatformHelper.startJar(fileDownload.getRelativePath(), pipeline);
}
}
}

View File

@ -6,7 +6,7 @@ public interface Command
int STOP_JAR = 2;
int UPDATE_JAR_VERSION = 3;
int UPDATE_JAR_VERSION_AND_REBOOT = 4;
int UPDATE_ZIP_VERSION = 5;
int commandType();
}

View File

@ -0,0 +1,21 @@
package org.tianhe.common.command.impl;
import lombok.Data;
import lombok.experimental.Accessors;
import org.tianhe.common.command.Command;
@Data
@Accessors(chain = true)
public class UpdateZipVersion implements Command
{
private String relativePath;
private String appName;
private String jarNameWithoutExtension;
private String versionFileDate;
private String fileId;
@Override
public int commandType()
{
return UPDATE_ZIP_VERSION;
}
}