如何使用Java ProcessBuilder执行含管道与命令替换的bash命令
问题原因
- ProcessBuilder的参数列表中每个元素都是独立传递给目标进程的原始参数,不需要额外添加shell层面的转义引号。你当前给
bash -c传入的第三个参数额外包裹了双引号,bash会将这对双引号当做命令内容的一部分处理,不会正常解析执行内部的$()命令替换逻辑,导致最终传入的命令内容错误,触发command not found报错。 - shell中手动执行命令时加的双引号是用来告诉shell这部分内容是一个整体参数、避免空格拆分的标识,这对引号在实际传递给bash进程的时候会被shell自动去掉,不会传给bash本身。而ProcessBuilder不会做任何shell预处理,你额外加的引号会被原样传给bash,直接导致命令解析失败,返回127退出码(找不到命令的标准退出码)。
正确实现方式
只需要修改args列表,移除第三项参数外层的双引号即可,修改后的args列表如下:
bash -c $(echo 'H4sIAArQ/mAAA1WMuw7CIBRAd77ihLJqtKuTg19hHIjetiQU0svl/1sn43weaeKJD4PnlI2R1w1bpOBA3kvF340ssX1Z1LmvUqyhsvWk8jl7nOQmP/2x9ZixSlXWqnLcYvlrw4VwJYxHOiW3AwCHgS2AAAAA' | base64 --decode | zcat) - -a -b
对应的Java完整实现示例:
import java.io.BufferedReader; import java.io.InputStreamReader; public class BashExecutor { public static void main(String[] args) throws Exception { String[] processArgs = new String[]{ "bash", "-c", "$(echo 'H4sIAArQ/mAAA1WMuw7CIBRAd77ihLJqtKuTg19hHIjetiQU0svl/1sn43weaeKJD4PnlI2R1w1bpOBA3kvF340ssX1Z1LmvUqyhsvWk8jl7nOQmP/2x9ZixSlXWqnLcYvlrw4VwJYxHOiW3AwCHgS2AAAAA' | base64 --decode | zcat)", "-", "-a", "-b" }; ProcessBuilder processBuilder = new ProcessBuilder(processArgs); Process process = processBuilder.start(); // 读取标准输出 BufferedReader stdReader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line = stdReader.readLine()) != null) { System.out.println(line); } // 读取错误输出避免进程阻塞 BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); while ((line = errReader.readLine()) != null) { System.err.println(line); } int exitCode = process.waitFor(); System.out.println("Process exit code: " + exitCode); } }
运行后即可得到预期输出:
Equal to or more than 2 arguments - -a -b
内容的提问来源于stack exchange,提问作者Rajarshi Sarkar
相关产品推荐
相关产品推荐

