Java Runtime.exec命令忽略引号引发参数拆分异常的原因及解决方法
问题原因与修复方案
为什么引号没起作用?
Runtime.getRuntime().exec(String)这个方法不会像终端shell那样解析命令行的引号。它的默认逻辑是直接按空格拆分整个字符串,把拆分后的每一段都当成独立参数——哪怕你加了双引号,引号也会被当成参数内容的一部分,而不是用来包裹空格的分隔符。
所以你的命令字符串里的"2018-01-01 00:00:00"会被拆成"2018-01-01和00:00:00"两个参数,加上第一个1,总共就变成3个参数了,自然触发了参数不足的判断。
修复方法
1. 使用exec(String[])重载方法(直接解决参数拆分问题)
放弃传整串命令,改用字符串数组传递每个独立参数。JVM会把数组里的每一项当成完整的参数,不会拆分带空格的内容:
// 把每个参数单独拆到数组中,不需要加引号! String[] runProjectCommand = { "java", "-jar", "/var/script/projects/project1/target/project1-1.0-SNAPSHOT-jar-with-dependencies.jar", "1", simulatorRun.getStartDateTime().format(formatter) }; Process runSimulatorProcess = Runtime.getRuntime().exec(runProjectCommand);
2. 更推荐:用ProcessBuilder(现代、灵活的写法)
ProcessBuilder是Java 5之后推出的API,比Runtime.exec更易用,还支持设置工作目录、环境变量等额外配置,处理参数也更直观:
ProcessBuilder pb = new ProcessBuilder( "java", "-jar", "/var/script/projects/project1/target/project1-1.0-SNAPSHOT-jar-with-dependencies.jar", "1", simulatorRun.getStartDateTime().format(formatter) ); // 可选:设置进程的工作目录 // pb.directory(new File("/var/script/projects/project1")); Process runSimulatorProcess = pb.start();
额外提醒:你的jar包代码有个隐藏bug
看你project1里的启动逻辑:
agentId = Integer.parseInt(args[0].substring(args[0].indexOf("=") + 1));
但你传的第一个参数是1,根本没有=符号,运行到这里会直接抛出StringIndexOutOfBoundsException!得改成直接读取参数:
if (args.length == 2) { agentId = Integer.parseInt(args[0]); // 直接取第一个参数值 startDateTime = LocalDateTime.parse(args[1], formatter); // 直接取第二个参数值 }
这样参数传对后,代码才能正常工作。
内容的提问来源于stack exchange,提问作者A. Vreeswijk
相关产品推荐
相关产品推荐

