Я пытаюсь запустить какую-то команду на агенте Windows с cmd
, используя groovy String.execute()
в конвейере Jenkins.
Я знаю, что существует сценарий bat
который я могу использовать, и я намеренно не хочу использовать его в этом конкретном случае c, так как он раздувает журналы, а плагин Blue Ocean имеет ограничение на количество шагов, которые он может показать для любого этапа.
По сути, я имею в виду некоторую функцию очистки, которую я очень часто вызываю, которая выполняет много проверок и запускает несколько команд (в настоящее время с sh
и bat
в дополнение к isUnix()
и аналогичными). Результатом обычно являются очень раздутые журналы шагов, таких как sh
и bat
, которые делают журналы больше и труднее анализировать. Я решил использовать какой-то собственный способ запуска команд оболочки «без вывода сообщений» и выводить только stdout и stderr только в случае сбоя команды. Я написал такую функцию, которая выполняет команду
@ NonCPS
def exec(cmd) {
def isUnix = Jenkins.instance.getNodes().find { it.getNodeName() == env.NODE_NAME }.toComputer().isUnix()
cmd = (isUnix ? ["/bin/bash", "-c"] : ["cmd.exe", "/c"]) + [cmd]
def proc = cmd.execute()
proc.waitFor()
def result = [out: proc.in.text.trim(), err: proc.err.text.trim(), exitCode: proc.exitValue()]
return result
}
. Вышеуказанная функция отлично работает для linux агентов, но не для Windows. Я всегда получаю следующую ошибку:
java.io.IOException: error=2, No such file or directory
at java.base/java.lang.ProcessImpl.forkAndExec(Native Method)
at java.base/java.lang.ProcessImpl.<init>(ProcessImpl.java:340)
at java.base/java.lang.ProcessImpl.start(ProcessImpl.java:271)
at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1107)
at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1071)
at java.base/java.lang.Runtime.exec(Runtime.java:591)
at java.base/java.lang.Runtime.exec(Runtime.java:415)
at java.base/java.lang.Runtime.exec(Runtime.java:312)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1213)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:47)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.methodCall(DefaultInvoker.java:20)
Caused: java.io.IOException: Cannot run program "cmd.exe": error=2, No such file or directory
at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1128)
at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1071)
at java.base/java.lang.Runtime.exec(Runtime.java:591)
at java.base/java.lang.Runtime.exec(Runtime.java:415)
at java.base/java.lang.Runtime.exec(Runtime.java:312)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Или, в основном, следующая строка Cannot run program "cmd.exe": error=2, No such file or directory
. Я попытался заменить "cmd.exe" на полный путь "C: \ Windows \ System32 \ cmd.exe" или "C: \ Windows \ SysWOW64 \ cmd.exe", заменив cmd.exe
на ["start", "cmd.exe", "/C"]
, используя Runtime.getRuntime().exec()
и многие другие, и я не могу заставить его работать.
Если я сделаю "git version".execute()
, это нормально работает, но я не могу выполнить некоторые более сложные команды, такие как "echo hi && git version".execute()
, которые выведут "hi && * git версия "вместо" привет "и реальная git версия. Я подумал, что, возможно, переменная окружения PATH
установлена неправильно, поэтому я выполнил следующую команду "set".execute()
, которая вызвала ту же ошибку, что и выше («установить», нет такого файла или каталога).
Я пытался различные комбинации этого за последние 2 дня и никуда не денутся. Буду признателен за любую оказанную помощь. Заранее спасибо.
Обновление:
Выяснили причину сбоя на Windows, но не на Linux узлах с Дженкинсом и нажали еще один "тяжелее" стена здесь.
Проблема в том, что метод String.exucute () ведет себя внутренне как Runtime.getRuntime (). exe c (), и при этом используется среда выполнения от главного узла, даже если он инкапсулирован в узле. () директива. Это в основном означает, что когда он работал нормально на linux, он фактически работал все время на главном узле, который также linux. Причина, по которой он не может запустить cmd или start или что-либо подобное, заключается в том, что эти команды (очевидно) не существуют в linux.