我需要使用"sudo“和"su”将不同的sh命令从我的java应用程序传递到使用java.lang.ProcessBuilder的linux。
这些命令非常相似,但有些不起作用。当我从日志中复制粘贴命令时,ALL命令工作。
在此之后:
processBuilder = new ProcessBuilder("sudo", "su", "- USER66 -c", "'ssh remote.mycomp.org < " + workingDir + "/script_cluster.sh'");我有:
su : option invalide -- ' '
Usage: (...)但这个:
processBuilder = new ProcessBuilder("sudo", "su", "- USER66 -c", "'scp remote.mycomp.org:" + clusterWorkingDir + "/" + filename + " " + workingDir + "/resultat/" + dir + "/'");效果很好。
就像我前面说的,如果我从日志中复制第一个命令,它就会在没有任何警告的情况下工作。
日志代码:
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();
}我在这里错过了什么?我还能做些什么来了解到底发生了什么?
发布于 2019-09-24 12:50:41
好吧,我找到了一个解决这个问题的惊人方法:
诀窍不是拆分参数,而是使用"bash -c“重新组合它们:
processBuilder = new ProcessBuilder("bash", "-c", "sudo su - USER66 -c 'ssh remote.mycomp.org < " + workingDir + "/script_cluster.sh'");注意,这是多么的不直观,因为没有人会像这样在shell中这样编写它,而且用正确的嵌套转义方式在shell命令中翻译它可能会变得非常困难。另外,如果将这3条命令与空格连接在一起,则它不会形成有效的命令。
发布于 2019-09-23 17:03:36
ProcessBuilder构造函数对每个参数都需要一个分隔的字符串。在您的代码中,几个参数合并在一个字符串中。试试这个:
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调用命令时,参数在传递给下划线本机系统方法之前也会被拆分到数组中。
https://stackoverflow.com/questions/58066630
复制相似问题