无法在 Jenkins 管道中的 "sh clause" 中使用变量,可能是什么原因?

Unable to use a variable within a "sh clause" in a Jenkins pipeline, what could be the reason?

我正在编写 Jenkins 管道。

我想用 current directory/.gradle 设置 GRADLE_USER_HOME 变量,所以我用 pwd() 函数填充 cwd 变量,该函数应该 return 当前工作目录。

stage 'Host preparation'
    cwd = pwd()
    withCredentials([ // Use Jenkins credentials ID of artifactory
      [$class: 'UsernamePasswordMultiBinding', credentialsId: artifactory_creds, usernameVariable: 'A_USER', passwordVariable: 'A_PASS'],
    ]){
    sh """
        export NDK_VER="r12b"
        export SDK_VER="r24.4.1"
        export GRADLE_USER_HOME='${cwd}/.gradle'
        echo "CWD OK"
        export NDK_DIR='$GRADLE_USER_HOME/android-ndk-$NDK_VER'
        export SDK_DIR='$GRADLE_USER_HOME/android-sdk-linux'
        export PATH='$PATH:$GRADLE_USER_HOME:$GRADLE_USER_HOME/android-ndk-$NDK_VER:$GRADLE_USER_HOME/android-sdk-linux'
        if [ ! -d $GRADLE_USER_HOME ]; then
            mkdir $GRADLE_USER_HOME
        fi

        if [ ! -f "$GRADLE_USER_HOME/android-sdk-${SDK_VER}-linux.tgz" ]; then
            curl -o "$GRADLE_USER_HOME/android-sdk-${SDK_VER}-linux.tgz" https://dl.google.com/android/android-sdk_$SDK_VER-linux.tgz
        fi

        if [ ! -f "$GRADLE_USER_HOME/android-ndk-${NDK_VER}-linux-x86_64.zip" ]; then # Checks if the sdk tarball exists on system
            curl -o "$GRADLE_USER_HOME/android-ndk-${NDK_VER}-linux-x86_64.zip" https://dl.google.com/android/repository/android-ndk-$NDK_VER-linux-x86_64.zip
        fi

        if [ ! -d "$GRADLE_USER_HOME/android-ndk-$NDK_VER" ]; then
            cd "$GRADLE_USER_HOME" && unzip -o "android-ndk-$NDK_VER-linux-x86_64.zip"
        fi
        if [ ! -d "$GRADLE_USER_HOME/android-sdk-linux" ]; then
            tar -xzf "$GRADLE_USER_HOME/android-sdk-${SDK_VER}-linux.tgz" -C $GRADLE_USER_HOME
            mkdir "$GRADLE_USER_HOME/android-sdk-linux/extras"
        fi

        echo "Installing updates"
        export SDK_TOOLS="${GRADLE_USER_HOME}/android-sdk-linux/tools"
        # Downloads the required SDK tools
        # echo "y" | "${SDK_TOOLS}/android" update sdk -u -a -t 2     # Android SDK Tools, revision 25.2.2 rc1
        # echo "y" | "${SDK_TOOLS}/android" update sdk -u -a -t 3     # Android SDK Platform-tools, revision 24.0.2
        # echo "y" | "${SDK_TOOLS}/android" update sdk -u -a -t 4     # Android SDK Build-tools, revision 24.0.2
        # echo "y" | "${SDK_TOOLS}/android" update sdk -u -a -t 6     # Android SDK Build-tools, revision 24
        # echo "y" | "${SDK_TOOLS}/android" update sdk -u -a -t 7     # Android SDK Build-tools, revision 23.0.3
        # echo "y" | "${SDK_TOOLS}/android" update sdk -u -a -t 8     # Android SDK Build-tools, revision 23.0.2
        # echo "y" | "${SDK_TOOLS}/android" update sdk -u -a -t 10    # Android SDK Build-tools, revision 23 (Obsolete)
        # echo "y" | "${SDK_TOOLS}/android" update sdk -u -a -t 30    # SDK Platform Android 7.0, API 24, revision 2
        # echo "y" | "${SDK_TOOLS}/android" update sdk -u -a -t 31    # SDK Platform Android 6.0, API 23, revision 3
        # echo "y" | "${SDK_TOOLS}/android" update sdk -u -a -t 53    # Android TV Intel x86 Atom System Image, Android API 24, revision 6
        # echo "y" | "${SDK_TOOLS}/android" update sdk -u -a -t 54    # Android Wear ARM EABI v7a System Image, Android API 24, revision 1
        # echo "y" | "${SDK_TOOLS}/android" update sdk -u -a -t 55    # Android Wear Intel x86 Atom System Image, Android API 24, revision 1
        # echo "y" | "${SDK_TOOLS}/android" update sdk -u -a -t 57    # ARM EABI v7a System Image, Android API 24, revision 6
        # echo "y" | "${SDK_TOOLS}/android" update sdk -u -a -t 58    # Intel x86 Atom_64 System Image, Android API 24, revision 6
        # echo "y" | "${SDK_TOOLS}/android" update sdk -u -a -t 59    # Intel x86 Atom System Image, Android API 24, revision 6
        # echo "y" | "${SDK_TOOLS}/android" update sdk -u -a -t 153   # Android Support Repository, revision 36
        # echo "y" | "${SDK_TOOLS}/android" update sdk -u -a -t 160   # Google Play services, revision 32
        # echo "y" | "${SDK_TOOLS}/android" update sdk -u -a -t 161   # Google Repository, revision 32

        # Downloads the constraint-layouts files from Artifactory
        wget --user=${A_USER} --password=${A_PASS} https://artifactory.company.net/android-tmp/m2repository.tar.gz -O -| tar zfxv - -C "${GRADLE_USER_HOME}/android-sdk-linux/extras/"
        """

但是当我 运行 构建时,出现以下错误:

Entering stage Host preparation
Proceeding
[Pipeline] pwd
[Pipeline] withCredentials
[Pipeline] {
[Pipeline] }
[Pipeline] // withCredentials
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
groovy.lang.MissingPropertyException: No such property: GRADLE_USER_HOME for class: groovy.lang.Binding
    at groovy.lang.Binding.getVariable(Binding.java:63)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:224)
    at org.kohsuke.groovy.sandbox.impl.Checker.call(Checker.java:241)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:238)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:221)

为了调试问题,我创建了另一个构建并写道:

node {
    def cwd = pwd()
    stage 'itai'
    sh """
    echo '${cwd}'
    """
}

然后它开始工作,cwd 变量被填充为当前工作目录。但是在我自己的构建中它没有...

我在管道的另一部分使用 pwd() 函数,它在那里工作,所以我不明白为什么它在这里不起作用,请你检查一下是否找到问题?

当您在脚本中放置 $something${something} 时,groovy 会将其扩展为一个变量...

因此,当您输入:$GRADLE_USER_HOME 时,groovy 试图从一个变量扩展它...但是您的 [=30] 中没有 GRADLE_USER_HOME 变量=] 脚本...

您要做的是将 $GRADLE_USER_HOME 输出到您的 shell 脚本中。

因此,只要 Groovy 无法处理,您就需要转义 $...

即:

    export NDK_DIR='$GRADLE_USER_HOME/android-ndk-$NDK_VER'

以及您不希望 groovy 处理的所有其他地方 $

tim_yates是对的,这里要记住Groovy变量和shell变量都使用相同的“$”前缀,所以需要转义你的 shell 变量,这样它们就不会被解释为 Groovy 变量。

但是,在您的情况下,您有另一种解决方案:您也可以将您使用的 shell 变量定义为...作为 Groovy 变量并将它们用作 Groovy 变量,因此避免转义每个“$”符号。

示例:

stage 'Host preparation'
def cwd = pwd()
def ndkVer = "r12b"
def sdkVer = "r24.4.1"
def gradleUserHome = "${cwd}/.gradle"
def sdkTools="$gradleUserHome/android-sdk-linux/tools"
withCredentials([ // Use Jenkins credentials ID of artifactory
                  [$class: 'UsernamePasswordMultiBinding', credentialsId: artifactory_creds, usernameVariable: 'A_USER', passwordVariable: 'A_PASS'],
]){
    sh """
        export NDK_VER=$ndkVer
        export SDK_VER=$sdkVer
        export GRADLE_USER_HOME=$gradleUserHome
        echo "CWD OK"
        export NDK_DIR='$gradleUserHome/android-ndk-$ndkVer'
        export SDK_DIR='$gradleUserHome/android-sdk-linux'
        export PATH='$PATH:$gradleUserHome:$gradleUserHome/android-ndk-$ndkVer:$gradleUserHome/android-sdk-linux'
        if [ ! -d $gradleUserHome ]; then
            mkdir $gradleUserHome
        fi

        if [ ! -f "$gradleUserHome/android-sdk-$sdkVer-linux.tgz" ]; then
            curl -o "$gradleUserHome/android-sdk-$sdkVer-linux.tgz" https://dl.google.com/android/android-sdk_$sdkVer-linux.tgz
        fi

        if [ ! -f "$gradleUserHome/android-ndk-$ndkVer-linux-x86_64.zip" ]; then # Checks if the sdk tarball exists on system
            curl -o "$gradleUserHome/android-ndk-$ndkVer-linux-x86_64.zip" https://dl.google.com/android/repository/android-ndk-$ndkVer-linux-x86_64.zip
        fi

        if [ ! -d "$gradleUserHome/android-ndk-$ndkVer" ]; then
            cd "$gradleUserHome" && unzip -o "android-ndk-$ndkVer-linux-x86_64.zip"
        fi
        if [ ! -d "$gradleUserHome/android-sdk-linux" ]; then
            tar -xzf "$gradleUserHome/android-sdk-$sdkVer-linux.tgz" -C $gradleUserHome
            mkdir "$gradleUserHome/android-sdk-linux/extras"
        fi

        echo "Installing updates"
        export SDK_TOOLS="${gradleUserHome}/android-sdk-linux/tools"
        # Downloads the required SDK tools
        # echo "y" | "$sdkTools/android" update sdk -u -a -t 2     # Android SDK Tools, revision 25.2.2 rc1
        # echo "y" | "$sdkTools/android" update sdk -u -a -t 3     # Android SDK Platform-tools, revision 24.0.2
        # echo "y" | "$sdkTools/android" update sdk -u -a -t 4     # Android SDK Build-tools, revision 24.0.2
        # echo "y" | "$sdkTools/android" update sdk -u -a -t 6     # Android SDK Build-tools, revision 24
        # echo "y" | "$sdkTools/android" update sdk -u -a -t 7     # Android SDK Build-tools, revision 23.0.3
        # echo "y" | "$sdkTools/android" update sdk -u -a -t 8     # Android SDK Build-tools, revision 23.0.2
        # echo "y" | "$sdkTools/android" update sdk -u -a -t 10    # Android SDK Build-tools, revision 23 (Obsolete)
        # echo "y" | "$sdkTools/android" update sdk -u -a -t 30    # SDK Platform Android 7.0, API 24, revision 2
        # echo "y" | "$sdkTools/android" update sdk -u -a -t 31    # SDK Platform Android 6.0, API 23, revision 3
        # echo "y" | "$sdkTools/android" update sdk -u -a -t 53    # Android TV Intel x86 Atom System Image, Android API 24, revision 6
        # echo "y" | "$sdkTools/android" update sdk -u -a -t 54    # Android Wear ARM EABI v7a System Image, Android API 24, revision 1
        # echo "y" | "$sdkTools/android" update sdk -u -a -t 55    # Android Wear Intel x86 Atom System Image, Android API 24, revision 1
        # echo "y" | "$sdkTools/android" update sdk -u -a -t 57    # ARM EABI v7a System Image, Android API 24, revision 6
        # echo "y" | "$sdkTools/android" update sdk -u -a -t 58    # Intel x86 Atom_64 System Image, Android API 24, revision 6
        # echo "y" | "$sdkTools/android" update sdk -u -a -t 59    # Intel x86 Atom System Image, Android API 24, revision 6
        # echo "y" | "$sdkTools/android" update sdk -u -a -t 153   # Android Support Repository, revision 36
        # echo "y" | "$sdkTools/android" update sdk -u -a -t 160   # Google Play services, revision 32
        # echo "y" | "$sdkTools/android" update sdk -u -a -t 161   # Google Repository, revision 32

        # Downloads the constraint-layouts files from Artifactory
        wget --user=${A_USER} --password=${A_PASS} https://artifactory.company.net/android-tmp/m2repository.tar.gz -O -| tar zfxv - -C "$gradleUserHome/android-sdk-linux/extras/"
        """

请注意,我在这里使用驼峰式表示法来区分 Groovy 变量和 shell 变量,当然您也可以使用相同的大写表示法。此外,您会注意到 PATH='$PATH:$gradleUserHome...,其中 $PATH 被转义为 $PATH,因为这次我们使用的是 shell 变量...