2015-10-28 3 views
3

Я пытаюсь запустить команду find внутри Jenkins (https://jenkins-ci.org), которая позволяет запускать groovy-скрипты из веб-интерфейса."find: missing argument to -exec", запущенный в Java-процессе builder

Мой код:

ProcessBuilder pb = new ProcessBuilder(); 
pb.directory(new File("/var/lib/jenkins/jobs/myJob"); 
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT); 
pb.redirectError(ProcessBuilder.Redirect.INHERIT); 
command = 'find . -name build.xml -exec echo \"{}\" \\;' 
println(command) 
pb.command(command.split(" ")); 
pb.start().waitFor(); 

Веб-интерфейс будет отображать результат Println:

find . -name build.xml -exec echo "{}" \; 

В то время как Дженкинс журнал (/var/log/jenkins/jenkins.log) регистрирует следующее сообщение об ошибке:

find: missing argument to `-exec' 

Однако, если я бегу, что та же команда, выводимый в веб-интерфейсе (find . -name build.xml -exec echo "{}" \;) через ш Я не получаю такой ошибки.

Кроме того, если я заменяю \; witih +, команда работает!

Так что-то нечисто с ProcessBuilder и \\; передается в качестве аргумента командной строки

ответ

5

Проблема ошибки с \; является что вы смешиваете экранирование/цитирование оболочки с простой передачей параметров функций exec.

Оставьте \ перед ; и он будет работать. ; нуждается в \только в оболочке, так как он используется для разделения команд там. То же самое для цитирования {} - при переходе Params к exec* -Style функций, не оболочки стиль не процитировать/маскирование необходима, так как не оболочка интерпретирует его (если, конечно, вы не запустили sh -c):

def command = 'find . -name build.xml -exec echo {} ;' // XXX 
new ProcessBuilder() 
    .directory(new File("/tmp")) 
    .inheritIO() 
    .command(command.split(" ")) // everything is just a list of strings 
    .start() 

И это в основном то же самое в groovy:

("/tmp" as File).eachFileRecurse{ 
    if (it.name=="build.xml") { 
     println it 
    } 
} 
+1

, всегда лучше использовать 'List' как аргумент для команды. Я имею в виду делать какие-либо расщепления - особенно если аргументы времени исполнения могут быть переданы. Однако +1. – Opal

+1

да, я тоже не люблю раскол. он работает только здесь, потому что в аргументах нет пробелов. – cfrick

+0

уверен. Было бы неплохо указать на это. – Opal

1

Не можете заменить все вышеперечисленное с:

String output = ['bash', '-c', 'find . -name "*.xml" -exec echo "{}" \\;'] 
    .execute(null, new File('/tmp')).text 
+0

Почему беспокоиться с bash? '['find', '/ tmp', '-name', '* .xml', '-exec', 'echo', '{}', ';']. execute(). text'. – cfrick

+0

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

+0

Удивительно, спасибо! Это приемлемая замена того, что я хочу сделать. Ваш ответ также привел меня к тому, чтобы узнать больше, чтобы сделать то, что я действительно хотел сделать с командной строкой: найти файлы и заменить на sed, но groovy обеспечивает отличный IO-apis: http://groovy-lang.org/groovy-dev- kit.html # _working_with_io * Still *, я хотел бы знать, почему ProcessBuilder не может передать '\;', я не могу найти причину, по которой он не работает –