Jenkinsfile(groovy)から変数に実行されたシェルコマンドの出力を取得するにはどうすればよいですか?


213

Jenkinsfile(Groovy)にこのようなものがあり、後で情報を使用するためにstdoutと終了コードを変数に記録します。

sh "ls -l"

どうすればこれを行うことができJenkinsfileますか?特に、内部でどんな種類のグルーヴィーなコードも実行できないようですが?



回答:


390

パイプライン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を変数名として使用すると、すべて問題ありません。
Bastian Voigt


6
私は、宣言jenkinsfile構文を使用していた場合、これは、エラーメッセージがない作品ですん:WorkflowScript: 97: Expected a step @ line 97, column 17.
レンチ

16
これはscriptステップブロック内でのみ機能するようです。jenkins.io/doc/book/pipeline/syntax/#declarative-steps
真ちゅう猿

51

現在のパイプラインバージョンはreturnStdoutおよびをネイティブにサポートしておりreturnStatussh/ batステップから出力またはステータスを取得できます。

例:

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

公式ドキュメント


誰かがstackoverflow.com/questions/40946697/…について私を助けてくれますか?前もって感謝します!
Jitesh Sojitra 2016

2
ステートメントは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
また、バットステップは実行中のコマンドをエコーするので、出力を取得するために@でバットコマンドを開始する必要があります(例: "@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には、その終了ステータスを取得するための便利なメソッドがないため、実際の値が必要な場合は、メッセージから解析する必要があります(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
}

警告:上記のコードはUnix / Linux固有です-Windowsでは完全に異なるシェルコマンドが必要です。


1
"ls:cannot dir1:no such file or directory"だけでなく、 "hudson.AbortException:スクリプトが終了コード2を返した"という出力を取得する可能性はありますか?
user2988257 2018年

これがどのように機能するかはわかりません。私のテストでは、出力テキストが割り当てられることはなく、これは予想されることです。シェルステップからスローされた例外により、戻り値を割り当てることができません
Jakub Bochenski

2
残念ながら、returnStatusとreturnStdoutは同時に機能しません。こちらがチケットです。投票してください:issues.jenkins-ci.org/browse/JENKINS-44930
アレクサンダーサモイロフ

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 2017

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.