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 이름으로 사용하면 모두 좋습니다.
Bastian Voigt


7
선언적 jenkinsfile 구문을 사용할 때 작동하지 않습니다. 오류 메시지는 다음과 같습니다.WorkflowScript: 97: Expected a step @ line 97, column 17.
Wrench

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 단계의 결과를 얻을 수있는 기능 요청이 있다고 생각하지만, 아는 한 현재 다른 옵션은 없습니다.

편집 : JENKINS-26133

EDIT2 : 어떤 버전인지 확실하지 않지만 sh / bat 단계는 표준 출력을 반환 할 수 있습니다.

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

1
또한, bat 단계는 실행중인 명령을 에코하므로 출력을 얻으려면 @로 bat 명령을 시작해야합니다 (예 : "@dir").
Russell Gallop

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에는 종료 상태를 얻는 데 유용한 방법이 없으므로 실제 값이 필요한 경우 메시지에서 파싱해야합니다 (ugh!)

Javadoc https://javadoc.jenkins-ci.org/hudson/AbortException.html 과 달리이 예외가 발생 해도 빌드가 실패 하지 않습니다 . 잡히지 않으면 실패합니다 !

업데이트 : 쉘 명령에서 STDERR 출력을 원할 경우 Jenkins는 불행히도 일반적인 사용 사례를 올바르게 지원하지 못합니다. 2017 티켓 JENKINS-44930 은 해결책으로 진전을 이루지 않는 동안 평온한 탁구 상태에 빠졌 습니다.

해결책에 관해서는 지금 , 가능한 방법 몇이있을 수 있습니다 :

a) STDERR을 STDOUT으로 리디렉션하십시오 2>&1 -그러나 메인 출력에서 ​​구문 분석하는 것은 당신에게 달려 있습니다. 명령이 실패하면 출력을 얻지 못할 것입니다-예외 처리기에 있기 때문입니다.

b) 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
}

주의 사항 : 위 코드는 유닉스 / 리눅스 전용입니다-윈도우는 완전히 다른 쉘 명령을 필요로합니다.


1
"ls : dir1에 액세스 할 수 없음 : 해당 파일 또는 디렉토리가 없음"으로 출력 될 가능성이 있습니까? "hudson.AbortException : script returns exit code 2"입니까?
user2988257

이것이 어떻게 작동하는지 알 수 없습니다. 내 테스트에서 출력 텍스트는 할당되지 않으며 이것이 예상됩니다. 쉘 단계에서 던진 예외 할당 할 수있는 반환 값 방지
야쿱 Bochenski을

2
불행하게도 returnStatus와 returnStdout이 동시에 작동하지 않습니다. 여기 티켓이 있습니다. 투표하십시오 : issues.jenkins-ci.org/browse/JENKINS-44930 .
Alexander Samoylov

1
@AlexanderSamoylov 위의 옵션 (c)와 같이 파일을 사용하여 해결해야합니다. 불행히도 이러한 도구의 제작자들은 종종 의견을 수렴하고 다른 일반적인 사용 사례에 대해 앞서 생각하지 않습니다.
Ed Randall

1
@ Ed Randall, 전적으로 당신에게 동의합니다 .. 그래서 나는 더 많은 투표로 인해 그들이 무언가를 시작하기를 희망 하면서이 문제를 게시했습니다.
Alexander Samoylov

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, 특히 bash 스크립팅에 익숙하지 않은 경우 사람들이 그루비라고 생각할 수 있음을 보여줄 것을 제안합니다 . 방금 Jenkins에서 ls -l대신 사용해 보았지만 echo 2작동합니다. 나는 실제로이 접근법을 사용했지만 실제로는 신뢰할 수 없기 때문에 대안을 찾고있었습니다. 이런 식으로 표준 쉘에서 캡처 된보다 복잡한 명령의 출력이 있지만 Jenkins로 이식 될 때 sh변수는 알 수없는 이유로 아무것도 보유하지 않습니다.
Nagev
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.