mirror of
https://gitee.com/dromara/Jpom.git
synced 2024-11-29 18:38:32 +08:00
fix 关闭 Process 方式
This commit is contained in:
parent
e955f59299
commit
9a24a256c6
@ -6,6 +6,7 @@
|
||||
|
||||
1. 【server】优化 支持批量删除构建信息(感谢@奇奇)
|
||||
2. 【server】修复 删除项目、删除分发检查关联构建失败问题
|
||||
3. 【all】优化 关闭 Process 方式
|
||||
|
||||
------
|
||||
|
||||
|
@ -196,7 +196,7 @@ public class AgentFreeWebSocketScriptHandle extends BaseAgentWebSocketHandle {
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
IoUtil.close(inputStream);
|
||||
Optional.ofNullable(process).ifPresent(Process::destroy);
|
||||
CommandUtil.kill(process);
|
||||
try {
|
||||
FileUtil.del(this.scriptFile);
|
||||
} catch (Exception ignored) {
|
||||
|
@ -30,6 +30,7 @@ import cn.hutool.core.io.IoUtil;
|
||||
import cn.keepbx.jpom.log.ILogRecorder;
|
||||
import org.dromara.jpom.JpomApplication;
|
||||
import org.dromara.jpom.common.Const;
|
||||
import org.dromara.jpom.util.CommandUtil;
|
||||
import org.dromara.jpom.util.LogRecorder;
|
||||
|
||||
import java.io.File;
|
||||
@ -110,7 +111,7 @@ public abstract class BaseRunScript implements AutoCloseable, ILogRecorder {
|
||||
public void close() {
|
||||
// windows 中不能正常关闭
|
||||
IoUtil.close(inputStream);
|
||||
Optional.ofNullable(process).ifPresent(Process::destroy);
|
||||
CommandUtil.kill(process);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -38,6 +38,7 @@ import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
@ -350,6 +351,18 @@ public class CommandUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行脚本
|
||||
*
|
||||
* @param scriptFile 脚本文件
|
||||
* @param baseDir 基础路径
|
||||
* @param env 环境变量
|
||||
* @param args 参数
|
||||
* @param consumer 回调
|
||||
* @return 退出码
|
||||
* @throws IOException io
|
||||
* @throws InterruptedException 异常
|
||||
*/
|
||||
public static int execWaitFor(File scriptFile, File baseDir, Map<String, String> env, String args, BiConsumer<String, Process> consumer) throws IOException, InterruptedException {
|
||||
ProcessBuilder processBuilder = new ProcessBuilder();
|
||||
//
|
||||
@ -362,11 +375,13 @@ public class CommandUtil {
|
||||
processBuilder.command(command);
|
||||
Optional.ofNullable(baseDir).ifPresent(processBuilder::directory);
|
||||
Map<String, String> environment = processBuilder.environment();
|
||||
// 新增逻辑,将env和environment里value==null替换成空字符,防止putAll出现空指针报错
|
||||
env.replaceAll((k, v) -> Optional.ofNullable(v).orElse(StrUtil.EMPTY));
|
||||
environment.replaceAll((k, v) -> Optional.ofNullable(v).orElse(StrUtil.EMPTY));
|
||||
// 环境变量
|
||||
Optional.ofNullable(env).ifPresent(environment::putAll);
|
||||
// 新增逻辑,将env和environment里value==null替换成空字符,防止putAll出现空指针报错
|
||||
if (env != null) {
|
||||
// 环境变量
|
||||
env.replaceAll((k, v) -> Optional.ofNullable(v).orElse(StrUtil.EMPTY));
|
||||
environment.putAll(env);
|
||||
}
|
||||
//
|
||||
Process process = processBuilder.start();
|
||||
try (InputStream inputStream = process.getInputStream()) {
|
||||
@ -374,4 +389,35 @@ public class CommandUtil {
|
||||
}
|
||||
return process.waitFor();
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭 Process实例
|
||||
*
|
||||
* @param process Process
|
||||
*/
|
||||
public static void kill(Process process) {
|
||||
if (process == null) {
|
||||
return;
|
||||
}
|
||||
while (true) {
|
||||
process.destroy();
|
||||
if (process.isAlive()) {
|
||||
Object handle = tryGetProcessId(process);
|
||||
log.info("等待关闭进程:{}", handle);
|
||||
process.destroyForcibly();
|
||||
try {
|
||||
process.waitFor(500, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Object tryGetProcessId(Process process) {
|
||||
Object handle = ReflectUtil.getFieldValue(process, "handle");
|
||||
Object pid = ReflectUtil.getFieldValue(process, "pid");
|
||||
return Optional.ofNullable(handle).orElse(pid);
|
||||
}
|
||||
}
|
||||
|
@ -197,7 +197,7 @@ public class BuildExecuteManage implements Runnable {
|
||||
* 取消任务
|
||||
*/
|
||||
private void cancelTask(String desc) {
|
||||
Optional.ofNullable(process).ifPresent(Process::destroy);
|
||||
CommandUtil.kill(process);
|
||||
Integer buildMode = taskData.buildInfoModel.getBuildMode();
|
||||
if (buildMode != null && buildMode == 1) {
|
||||
// 容器构建 删除容器
|
||||
|
137
modules/server/src/test/java/TestProcess.java
Normal file
137
modules/server/src/test/java/TestProcess.java
Normal file
@ -0,0 +1,137 @@
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.io.file.Tailer;
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import org.dromara.jpom.util.CommandUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* @author bwcx_jzy
|
||||
* @since 24/1/3 003
|
||||
*/
|
||||
public class TestProcess {
|
||||
|
||||
@Test
|
||||
public void testWin() throws IOException {
|
||||
AtomicReference<Process> start = new AtomicReference<>();
|
||||
// 执行线程
|
||||
Thread thread = new Thread(() -> {
|
||||
ProcessBuilder processBuilder = new ProcessBuilder();
|
||||
processBuilder.redirectErrorStream(true);
|
||||
processBuilder.command("ping 127.0.0.1 -t".split(" "));
|
||||
try {
|
||||
start.set(processBuilder.start());
|
||||
try (InputStream inputStream = start.get().getInputStream()) {
|
||||
IoUtil.readLines(inputStream, CharsetUtil.CHARSET_GBK, new Tailer.ConsoleLineHandler());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
ThreadUtil.execute(thread);
|
||||
while (true) {
|
||||
Process process = start.get();
|
||||
if (process != null) {
|
||||
break;
|
||||
}
|
||||
// System.out.println("waiting...");
|
||||
}
|
||||
ThreadUtil.sleep(5, TimeUnit.SECONDS);
|
||||
// 关闭线程
|
||||
Thread thread2 = new Thread(() -> {
|
||||
while (true) {
|
||||
Process process = start.get();
|
||||
if (process.isAlive()) {
|
||||
process.destroy();
|
||||
Object handle = ReflectUtil.getFieldValue(process, "handle");
|
||||
System.out.println(handle);
|
||||
try {
|
||||
process.waitFor(1, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
} else {
|
||||
System.out.println("成功终止");
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
thread2.run();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLinux() {
|
||||
AtomicReference<Process> start = new AtomicReference<>();
|
||||
AtomicBoolean running = new AtomicBoolean(true);
|
||||
// 执行线程
|
||||
Thread thread = new Thread(() -> {
|
||||
running.set(true);
|
||||
try {
|
||||
ProcessBuilder processBuilder = new ProcessBuilder();
|
||||
processBuilder.redirectErrorStream(true);
|
||||
// String s = "cd /mnt/d/System-Data/Documents/jpom/server/data/build/5a68e19578654cb2965433584ce84f4c/source && mvn clean package";
|
||||
String[] command = new String[]{"bash", "/home/user/test.sh"};
|
||||
// String[] command = ArrayUtil.append(new String[]{"/bin/bash", "-c"}, s);
|
||||
System.out.println(Arrays.toString(command));
|
||||
processBuilder.command(command);
|
||||
try {
|
||||
start.set(processBuilder.start());
|
||||
try (InputStream inputStream = start.get().getInputStream()) {
|
||||
IoUtil.readLines(inputStream, CharsetUtil.CHARSET_UTF_8, new Tailer.ConsoleLineHandler());
|
||||
}
|
||||
int waitFor = start.get().waitFor();
|
||||
System.out.println("线程结束:" + waitFor);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
running.set(false);
|
||||
}
|
||||
});
|
||||
ThreadUtil.execute(thread);
|
||||
while (true) {
|
||||
Process process = start.get();
|
||||
if (process != null) {
|
||||
|
||||
break;
|
||||
}
|
||||
if (!running.get()) {
|
||||
System.out.println("线程关闭");
|
||||
break;
|
||||
}
|
||||
// System.out.println("waiting...");
|
||||
}
|
||||
Process process = start.get();
|
||||
if (process == null) {
|
||||
return;
|
||||
}
|
||||
ThreadUtil.sleep(20, TimeUnit.SECONDS);
|
||||
// 关闭线程
|
||||
Thread thread2 = new Thread(() -> {
|
||||
while (true) {
|
||||
if (process.isAlive()) {
|
||||
Object handle = CommandUtil.tryGetProcessId(process);
|
||||
System.out.println(handle);
|
||||
process.destroy();
|
||||
try {
|
||||
process.waitFor(1, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
} else {
|
||||
System.out.println("成功终止");
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
thread2.run();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user