如何使用commons-exec执行/ bin / sh?

时间:2011-02-22 15:27:45

标签: java apache-commons-exec

这就是我正在做的事情:

import org.apache.commons.exec.*;
String cmd = "/bin/sh -c \"echo test\"";
new DefaultExecutor().execute(CommandLine.parse(cmd));

这是输出:

/bin/sh: echo test: command not found

我做错了什么?

5 个答案:

答案 0 :(得分:8)

根据the FAQ“建议使用CommandLine.addArgument()代替CommandLine.parse()”。

所以试试

CommandLine commandLine = new CommandLine("/bin/sh");
commandLine.addArgument("-c");
commandLine.addArgument("echo test", false); // false is important to prevent commons-exec from acting stupid
executor.execute(commandLine);

答案 1 :(得分:3)

这个对我有用: -

    CommandLine command = new CommandLine("/bin/sh");
    command.addArguments(new String[] {
            "-c",
            "echo 'test'"
    },false);
    new DefaultExecutor().execute(command);

答案 2 :(得分:0)

我可以从shell命令行重现您的问题:

# /bin/sh -c '"echo test"'
# /bin/sh: echo test: command not found

我会说你应该试着不引用这个命令。

答案 3 :(得分:0)

var obj = JsonConvert.DeserializeObject<Dictionary<int, AClass>>(JsonConvert);


public class AClass
{
    public string key { set; get; }
    public string key2 { set; get; }
}

答案 4 :(得分:0)

该命令不起作用,因为commons-exec对所有参数进行不必要的引用,这些参数有空格或引用。

这种不必要的参数引用由每个参数的handleQuoting标志控制。如果使用构造函数和CommandLine方法创建addArgument对象,则可以将此标志设置为false

像这样:

CommandLine commandLine = new CommandLine("/bin/sh");
commandLine.addArgument("-c");
commandLine.addArgument("echo test", false);

重要的部分是false作为addArgument方法的第二个参数

它有效!但是......手动构造命令行而不是在某个配置文件中定义它是不合理的。

CommandLine.parse始终将handleQuoting标志设置为true!谁知道为什么......

我使用反射来编写这个小帮助方法来修复使用CommandLine创建的“坏”CommandLine.parse对象。

public static CommandLine fixCommandLine(CommandLine badCommandLine) {
    try {
        CommandLine fixedCommandLine = new CommandLine(badCommandLine.getExecutable());
        fixedCommandLine.setSubstitutionMap(badCommandLine.getSubstitutionMap());
        Vector<?> arguments = (Vector<?>) FieldUtils.readField(badCommandLine, "arguments", true);
        arguments.stream()
                .map(badArgument -> {
                    try {
                        return (String) FieldUtils.readField(badArgument, "value", true);
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }
                })
                .forEach(goodArgument -> fixedCommandLine.addArgument(goodArgument, false));
        return fixedCommandLine;
    } catch (Exception e) {
        logger.error("Cannot fix bad command line", e);
        return badCommandLine;
    }
}

它只是克隆给定的CommandLine,将每个参数的handleQuoting标志设置为false。 方法FieldUtils.readField来自commons-lang3库,但如果需要,可以使用纯反射。

它允许解析命令行并仍然成功执行它。

String cmd = "/bin/sh -c 'echo test'";
new DefaultExecutor().execute(fixCommandLine(CommandLine.parse(cmd)));