首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >无法调试ProcessBuilder

无法调试ProcessBuilder
EN

Stack Overflow用户
提问于 2019-09-23 16:31:23
回答 2查看 83关注 0票数 0

我需要使用"sudo“和"su”将不同的sh命令从我的java应用程序传递到使用java.lang.ProcessBuilder的linux。

这些命令非常相似,但有些不起作用。当我从日志中复制粘贴命令时,ALL命令工作。

在此之后:

代码语言:javascript
运行
复制
processBuilder = new ProcessBuilder("sudo", "su", "- USER66 -c", "'ssh remote.mycomp.org < " + workingDir + "/script_cluster.sh'");

我有:

代码语言:javascript
运行
复制
su : option invalide -- ' '
Usage: (...)

但这个:

代码语言:javascript
运行
复制
processBuilder = new ProcessBuilder("sudo", "su",  "- USER66 -c", "'scp remote.mycomp.org:" + clusterWorkingDir + "/" + filename + " " + workingDir + "/resultat/" + dir + "/'");

效果很好。

就像我前面说的,如果我从日志中复制第一个命令,它就会在没有任何警告的情况下工作。

日志代码:

代码语言:javascript
运行
复制
  logCommand(processBuilder);

  private void logCommand(ProcessBuilder processBuilder) {
    if (logger.isDebugEnabled()) {
      logger.debug("Commande : {}", commandAsString(processBuilder.command()));
    }
  }

  private String commandAsString(List<String> command) {
    StringBuilder result = new StringBuilder();
    for (String cmdElement : command) {
      result.append(cmdElement).append(" ");
    }
    return result.toString();
  }

我在这里错过了什么?我还能做些什么来了解到底发生了什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-09-24 12:50:41

好吧,我找到了一个解决这个问题的惊人方法:

诀窍不是拆分参数,而是使用"bash -c“重新组合它们:

代码语言:javascript
运行
复制
processBuilder = new ProcessBuilder("bash", "-c", "sudo su - USER66 -c 'ssh remote.mycomp.org < " + workingDir + "/script_cluster.sh'");

注意,这是多么的不直观,因为没有人会像这样在shell中这样编写它,而且用正确的嵌套转义方式在shell命令中翻译它可能会变得非常困难。另外,如果将这3条命令与空格连接在一起,则它不会形成有效的命令。

票数 0
EN

Stack Overflow用户

发布于 2019-09-23 17:03:36

ProcessBuilder构造函数对每个参数都需要一个分隔的字符串。在您的代码中,几个参数合并在一个字符串中。试试这个:

代码语言:javascript
运行
复制
new ProcessBuilder( "sudo", "su", "-", "USER66", "-c", "'ssh remote.mycomp.org < /script_cluster.sh'");

(将-c标志的值视为一个参数应该是正确的。)

解释

创建新进程的大多数本机系统方法都要求每个参数作为数组的分离元素(例如,查看训斥文档)。

在运行时,Java将参数编码为一个连续字节数组,然后将其传递给本机JVM方法,后者将调用本机系统方法。例如,"su", "-", "USER66", "-c", "'...'"将被解码为su-USER66-c'...'。单个参数由0字节分隔(我们在字符串中没有看到)。本机JVM方法通过将字符串拆分为0字节分隔符来解码继续的字符串。如果我们将"su - USER66"作为一个参数,它将被错误地编码为本机系统方法的一个参数。

当您从shell或bash调用命令时,参数在传递给下划线本机系统方法之前也会被拆分到数组中。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58066630

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档