Як мені отримати вихід команди оболонки, виконану за допомогою змінної з Jenkinsfile (groovy)?


213

У мене є щось подібне на Jenkinsfile (Groovy), і я хочу записати stdout та вихідний код у змінну, щоб згодом використовувати інформацію.

sh "ls -l"

Як я можу це зробити, тим більше, що здається, що ти не можеш реально запустити будь-який загрозливий код всередині Jenkinsfile?



Відповіді:


391

Остання версія shкроку трубопроводу дозволяє зробити наступне;

// Git committer email
GIT_COMMIT_EMAIL = sh (
    script: 'git --no-pager show -s --format=\'%ae\'',
    returnStdout: true
).trim()
echo "Git committer email: ${GIT_COMMIT_EMAIL}"

Ще одна особливість - це returnStatusваріант.

// Test commit message for flags
BUILD_FULL = sh (
    script: "git log -1 --pretty=%B | grep '\\[jenkins-full]'",
    returnStatus: true
) == 0
echo "Build full flag: ${BUILD_FULL}"

Ці параметри додаються на основі цього питання.

Дивіться офіційну документацію для shкоманди.


11
Схоже, це документально підтверджено -> jenkins.io/doc/pipeline/steps/workflow-durable-task-step/…
zot24

Не працює для мене з префіксом "vars". Коли я просто використовую GIT_COMMIT_EMAIL як ім'я var без префікса, все нормально.
Бастіан Фойт

Будь ласка , допоможіть мені stackoverflow.com/questions/40946697 / ...
Jitesh Sojitra

7
Коли я використовую декларативний синтаксис jenkinsfile, це не працює, повідомлення про помилку:WorkflowScript: 97: Expected a step @ line 97, column 17.
Гайковий ключ

17
Здається, що це працює лише всередині scriptкрокового блоку. jenkins.io/doc/book/pipeline/syntax/#declarative-steps
латунна мавпа

51

Поточна версія трубопроводу спочатку підтримує returnStdoutі returnStatus, що дає змогу отримати вихід / стан з sh/ batкроків.

Приклад:

def ret = sh(script: 'uname', returnStdout: true)
println ret

Офіційна документація .


Чи може хтось допомогти мені для stackoverflow.com/questions/40946697/… ? Спасибі заздалегідь!
Jitesh Sojitra

3
Висловлювання повинні бути завершені script { }кроком.
x-yuri

40

швидка відповідь така:

sh "ls -l > commandResult"
result = readFile('commandResult').trim()

Я думаю, що існує запит на функцію, щоб мати змогу отримати результат sh step, але, наскільки я знаю, на даний момент іншого варіанту немає.

РЕДАКЦІЯ: JENKINS-26133

EDIT2: Не зовсім впевнений, з якої версії, але кроки sh / bat тепер можуть повернути висновок std, просто:

def output = sh returnStdout: true, script: 'ls -l'

1
Крім того, FYI, кроки bat повторюють команду, що виконується, тому вам потрібно запустити команди bat з @, щоб просто отримати вихід (наприклад, "@dir").
Рассел

21

Якщо ви хочете отримати stdout І знати, вдала команда чи ні, просто використовуйте returnStdoutта оберніть її в обробник винятків:

сценарій сценарію

try {
    // Fails with non-zero exit if dir1 does not exist
    def dir1 = sh(script:'ls -la dir1', returnStdout:true).trim()
} catch (Exception ex) {
    println("Unable to read dir1: ${ex}")
}

вихід :

[Pipeline] sh
[Test-Pipeline] Running shell script
+ ls -la dir1
ls: cannot access dir1: No such file or directory
[Pipeline] echo
unable to read dir1: hudson.AbortException: script returned exit code 2

На жаль, hudson.AbortException не вистачає жодного корисного методу для отримання цього статусу виходу, тому, якщо потрібне фактичне значення, вам знадобиться проаналізувати його з повідомлення (так!)

Всупереч Javadoc https://javadoc.jenkins-ci.org/hudson/AbortException.html збірка не виходить з ладу, коли цей виняток знайдено. Виходить з ладу, коли його не спіймали!

Оновлення: Якщо ви також хочете вивести STDERR з команди оболонки, Дженкінс, на жаль, не вдається належним чином підтримати цей звичайний варіант використання. Квиток на 2017 рік JENKINS-44930 застряг у стані самовпевненого пінг-понгу, не роблячи жодного прогресу на шляху до вирішення - будь ласка, подумайте про те, щоб додати його.

Щодо рішення зараз , можливо, існує кілька можливих підходів:

a) Перенаправляйте STDERR на STDOUT 2>&1 - однак тоді ви вирішите розібрати це з основного виводу, але ви не отримаєте висновок, якщо команда не вдалася - тому що ви є обробником винятку.

б) перенаправити STDERR на тимчасовий файл (назва якого ви підготували раніше) 2>filename(але не забудьте очистити файл згодом) - тобто. Основним кодом стає:

def stderrfile = 'stderr.out'
try {
    def dir1 = sh(script:"ls -la dir1 2>${stderrfile}", returnStdout:true).trim()
} catch (Exception ex) {
    def errmsg = readFile(stderrfile)
    println("Unable to read dir1: ${ex} - ${errmsg}")
}

c) Перейдіть в інший спосіб, встановіть returnStatus=trueзамість цього, не обробляйте обробник винятків і завжди фіксуйте вихід у файл, тобто:

def outfile = 'stdout.out'
def status = sh(script:"ls -la dir1 >${outfile} 2>&1", returnStatus:true)
def output = readFile(outfile).trim()
if (status == 0) {
    // output is directory listing from stdout
} else {
    // output is error message from stderr
}

Застереження: наведений вище код є специфічним для Unix / Linux - Windows вимагає зовсім інших команд оболонки.


1
чи є шанс отримати висновок у вигляді "ls: не вдається отримати доступ до dir1: немає такого файлу чи каталогу", а не лише "hudson.AbortException: скрипт повернув вихідний код 2"?
користувач2988257

Я не бачу, як це могло колись працювати. У моєму тестуванні вихідний текст ніколи не призначається, і цього можна очікувати. Виняток, викинутий з кроку оболонки, запобігає призначенню повернутого значення
Якуб

2
returnStatus і returnStdout, на жаль, не працюють одночасно. Ось квиток. Будь ласка, проголосуйте: issues.jenkins-ci.org/browse/JENKINS-44930 .
Олександр Самойлов

1
@AlexanderSamoylov Ви повинні обійтись, використовуючи файл, як у варіанті (c) вище. На жаль, автори цих інструментів часто викликають сумніви і не заздалегідь роздумують над іншими поширеними випадками використання.
Ед Рендалл

1
@Ed Randall, Повністю згоден з тобою. Ось чому я опублікував це питання, сподіваючись, що через більшу кількість голосів вони почнуть щось робити.
Олександр Самойлов

12

це зразок справи, в який я маю сенс вважати!

node('master'){
    stage('stage1'){
    def commit = sh (returnStdout: true, script: '''echo hi
    echo bye | grep -o "e"
    date
    echo lol''').split()


    echo "${commit[-1]} "

    }
}

Я не знаю способу, але ваша відповідь мені дуже допомагає, дякую :)
shaharnakash

5

Для тих, кому потрібно використовувати вихід у наступних командах оболонки, а не groovy, щось подібне можна зробити:

    stage('Show Files') {
        environment {
          MY_FILES = sh(script: 'cd mydir && ls -l', returnStdout: true)
        }
        steps {
          sh '''
            echo "$MY_FILES"
          '''
        }
    }

Я знайшов приклади коду Maven дуже корисними.


-6

Найпростішим способом є використання цього способу

my_var=`echo 2` echo $my_var вихід: 2

Зауважте, що не проста одинарна цитата - це зворотна цитата (`).


Оновлено, але я б запропонував вам показати, що вони повинні бути загорнуті під sh інакше люди можуть подумати, що це круто, особливо якщо вони не знайомі з басовими сценаріями. Я щойно спробував це на Jenkins, використовуючи ls -lзамість цього, echo 2і він працює. Я раніше використовував такий підхід, але шукав альтернативу, оскільки це не дуже надійно. У мене є вихід більш складної команди, захопленої на стандартній оболонці таким чином, але при перенесенні на Дженкінс shзмінна нічого не містить з незрозумілої причини.
Нагев
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.