From a10b5be9735027c67275b06114818cf73a10f19a Mon Sep 17 00:00:00 2001 From: "yanng@vidconnect.cyou" Date: Sat, 15 Nov 2025 15:27:15 +0800 Subject: [PATCH] 1.0.0 Allow the concurrent executions of several shell commands --- .settings/.gitignore | 2 + jbang/Splicer.java | 73 ++++++++++++++++++ pom.xml | 74 +++++++++++++++++++ .../java/cyou/vidconnect/splicer/Main.java | 70 ++++++++++++++++++ 4 files changed, 219 insertions(+) create mode 100644 .settings/.gitignore create mode 100644 jbang/Splicer.java create mode 100644 pom.xml create mode 100644 src/main/java/cyou/vidconnect/splicer/Main.java diff --git a/.settings/.gitignore b/.settings/.gitignore new file mode 100644 index 0000000..e2635f0 --- /dev/null +++ b/.settings/.gitignore @@ -0,0 +1,2 @@ +/org.eclipse.jdt.core.prefs +/org.eclipse.m2e.core.prefs diff --git a/jbang/Splicer.java b/jbang/Splicer.java new file mode 100644 index 0000000..19173f7 --- /dev/null +++ b/jbang/Splicer.java @@ -0,0 +1,73 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? + +//DEPS com.fasterxml.jackson.core:jackson-databind:2.18.4 +//DEPS org.apache.commons:commons-exec:1.4.0 + +import java.io.ByteArrayOutputStream; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecutor; +import org.apache.commons.exec.PumpStreamHandler; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class Splicer { + + private static final Logger logger = Logger.getLogger(Splicer.class.getName()); + + public static void main(String[] args) throws InterruptedException, JsonProcessingException { + ExecutorService executorService = Executors.newFixedThreadPool(args.length); + + List> callables = List.of(args).stream() + .map(command -> new Callable() { + @Override + public ExecutionResult call() throws Exception { + return executeShell(command); + } + }).collect(Collectors.toList()); + + List results = executorService.invokeAll(callables).parallelStream().map(f -> { + try { + return f.get(); + } catch (InterruptedException | ExecutionException e) { + logger.log(Level.SEVERE, "Error found!", e); + } + return null; + }).filter(Objects::nonNull).collect(Collectors.toList()); + + executorService.shutdown(); + + System.out.println( + new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(Map.of("results", results))); + } + + public static ExecutionResult executeShell(String command) { + ByteArrayOutputStream tempOut = new ByteArrayOutputStream(); + try { + CommandLine cmdLine = CommandLine.parse(command.trim()); + DefaultExecutor executor = DefaultExecutor.builder().get(); + PumpStreamHandler streamHandler = new PumpStreamHandler(tempOut); + executor.setStreamHandler(streamHandler); + int exitValue = executor.execute(cmdLine); + return new ExecutionResult(command, exitValue, new String(tempOut.toByteArray())); + } catch (Exception e) { + logger.log(Level.SEVERE, "Execute cmd failed: " + command.trim(), e); + } + return new ExecutionResult(command, -1, new String(tempOut.toByteArray())); + } + + public static record ExecutionResult(String command, Integer exitValue, String output) { + + } +} diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..081d542 --- /dev/null +++ b/pom.xml @@ -0,0 +1,74 @@ + + 4.0.0 + cyou.vidconnect + splicer + 1.0.0 + splicer + Run multiple shell commands concurrently + + 2.18.4 + 1.4.0 + + + + + com.fasterxml.jackson + jackson-bom + ${jackson.version} + import + pom + + + + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-databind + + + org.apache.commons + commons-exec + ${commons-exec.version} + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.14.0 + + 17 + 17 + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.1 + + + package + + shade + + + + + cyou.vidconnect.splicer.Main + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/cyou/vidconnect/splicer/Main.java b/src/main/java/cyou/vidconnect/splicer/Main.java new file mode 100644 index 0000000..7223242 --- /dev/null +++ b/src/main/java/cyou/vidconnect/splicer/Main.java @@ -0,0 +1,70 @@ +package cyou.vidconnect.splicer; + +import java.io.ByteArrayOutputStream; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecutor; +import org.apache.commons.exec.PumpStreamHandler; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class Main { + + private static final Logger logger = Logger.getLogger(Main.class.getName()); + + public static void main(String[] args) throws InterruptedException, JsonProcessingException { + ExecutorService executorService = Executors.newFixedThreadPool(args.length); + + List> callables = List.of(args).stream() + .map(command -> new Callable() { + @Override + public ExecutionResult call() throws Exception { + return executeShell(command); + } + }).collect(Collectors.toList()); + + List results = executorService.invokeAll(callables).parallelStream().map(f -> { + try { + return f.get(); + } catch (InterruptedException | ExecutionException e) { + logger.log(Level.SEVERE, "Error found!", e); + } + return null; + }).filter(Objects::nonNull).collect(Collectors.toList()); + + executorService.shutdown(); + + System.out.println( + new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(Map.of("results", results))); + } + + public static ExecutionResult executeShell(String command) { + ByteArrayOutputStream tempOut = new ByteArrayOutputStream(); + try { + CommandLine cmdLine = CommandLine.parse(command.trim()); + DefaultExecutor executor = DefaultExecutor.builder().get(); + PumpStreamHandler streamHandler = new PumpStreamHandler(tempOut); + executor.setStreamHandler(streamHandler); + int exitValue = executor.execute(cmdLine); + return new ExecutionResult(command, exitValue, new String(tempOut.toByteArray())); + } catch (Exception e) { + logger.log(Level.SEVERE, "Execute cmd failed: " + command.trim(), e); + } + return new ExecutionResult(command, -1, new String(tempOut.toByteArray())); + } + + public static record ExecutionResult(String command, Integer exitValue, String output) { + + } +}