Как выполнить / bin / sh с помощью commons-exec? - PullRequest
2 голосов
/ 22 февраля 2011

Это то, что я делаю:

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 ]

8 голосов
/ 22 февраля 2011

Согласно часто задаваемым вопросам"Рекомендуется использовать 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);
3 голосов
/ 22 февраля 2011

Этот работает для меня: -

    CommandLine command = new CommandLine("/bin/sh");
    command.addArguments(new String[] {
            "-c",
            "echo 'test'"
    },false);
    new DefaultExecutor().execute(command);
0 голосов
/ 20 июля 2017

Команда не работает, потому что commons-exec делает ненужное цитирование всех аргументов, которые имеют пробел или кавычку.

Это ненужное цитирование аргументов контролируется флагом handleQuoting каждого аргумента.Если вы создаете объект CommandLine, используя его конструктор и методы addArgument, вы можете установить этот флаг на false.

Примерно так:

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

( Theважная часть - 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)));
0 голосов
/ 11 августа 2015
import org.apache.commons.exec.*; 

CommandLine commandLine = new CommandLine("abc.sh");
commandLine.addArgument("param1"); 
final Executor exec = new DefaultExecutor().execute(commandLine);
0 голосов
/ 22 февраля 2011

Я могу воспроизвести вашу проблему из командной строки оболочки:

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

Я бы сказал, что вы должны стараться не заключать в кавычки команду.

...