Jenkins:管道 sh 错误替换错误

Jenkins: Pipeline sh bad substitution error

我的管道中的一个步骤将 .tar 上传到人工服务器。我在传入 env.BUILD_NUMBER 时遇到错误替换错误,但是当数字被硬编码时,相同的命令仍然有效。该脚本是通过 jenkins 在 groovy 中编写的,在 jenkins 工作区中是 运行。

sh 'curl -v --user user:password --data-binary ${buildDir}package${env.BUILD_NUMBER}.tar -X PUT "http://artifactory.mydomain.com/artifactory/release-packages/package${env.BUILD_NUMBER}.tar"'

returns 错误:

[Pipeline] sh
[Package_Deploy_Pipeline] Running shell script
/var/lib/jenkins/workspace/Package_Deploy_Pipeline@tmp/durable-4c8b7958/script.sh: 2: 
/var/lib/jenkins/workspace/Package_Deploy_Pipeline@tmp/durable-4c8b7958/script.sh: Bad substitution
[Pipeline] } //node
[Pipeline] Allocate node : End
[Pipeline] End of Pipeline
ERROR: script returned exit code 2

如果在内部版本号中进行硬编码并换出 ${env.BUILD_NUMBER} 我没有收到任何错误并且代码运行成功。

sh 'curl -v --user user:password --data-binary ${buildDir}package113.tar -X PUT "http://artifactory.mydomain.com/artifactory/release-packages/package113.tar"'

我在同一个脚本的其他 sh 命令中使用 ${env.BUILD_NUMBER} 并且在任何其他地方都没有问题。

原来是语法问题。将命令包装在 ' 中会导致传递 ${env.BUILD_NUMBER 而不是其值。我将整个命令包装在 "s 中并转义了嵌套。现在工作正常。

sh "curl -v --user user:password --data-binary ${buildDir}package${env.BUILD_NUMBER}.tar -X PUT \"http://artifactory.mydomain.com/artifactory/release-packages/package${env.BUILD_NUMBER}.tar\""

通常最常见的问题是:

Bad substitution

错误是使用 sh 而不是 bash

特别是在使用 Jenkins 时,如果您使用 Execute shell,请确保您的 Commandshebang,例如#!/bin/bash -xe#!/usr/bin/env bash.

实际上,您似乎误解了 env 变量。在您的 sh 块中,您应该直接访问 ${BUILD_NUMBER}

Reason/Explanation: env代表脚本里面的环境。这个环境是 used/available 直接对任何被执行的东西,例如shell 个脚本。

另请注意不要向env.*写入任何内容,而是使用withEnv{}块。

我可以肯定地告诉你,这都是关于 sh shell 和 bash shell 的。我通过指定 #!/bin/bash -xe 解决了这个问题,如下所示:

node {
    stage("Preparing"){
        sh'''#!/bin/bash -xe
            colls=( col1 col2 col3 )
            for eachCol in ${colls[@]}
            do
              echo $eachCol
            done
        '''
    }      
}

我在 jar 文件的工件中显示 {env.MAJOR_VERSION} 时遇到问题。通过在 Jenkinsfile 中保留环境步骤来显示我的方法。

pipeline {
agent any
environment {
MAJOR_VERSION = 1
}

stages {
stage('build') {
  steps {
      sh 'ant -f build.xml -v'
 }
}
}
post {
 always{
   archiveArtifacts artifacts: 'dist/*.jar', fingerprint: true
 }
}
}

我解决了问题,然后它没有在我的 Jenkins 构建输出中显示错误替换。所以环境步骤在 Jenkinsfile 中扮演更重要的角色。

为了 将 groovy 参数传递到 Jenkins 管道中的 bash 脚本(有时会导致错误的替换)你有 2 个选项:

The triple double quotes way [ " " " ] OR the triple single quotes way [ ' ' ' ]

  1. 在三重双引号中 你可以使用 ${someVariable} 从 groovy 渲染普通参数,如果它是环境变量 ${env.someVariable} ,如果它是参数注入你的工作${params.someVariable}

例子:

     def YOUR_APPLICATION_PATH= "${WORKSPACE}/myApp/"

      sh """#!/bin/bash
      cd ${YOUR_APPLICATION_PATH}
      npm install
      """
  1. 在三重单引号中事情变得有点棘手,你可以将参数传递给环境参数并由[=16使用它=] 或使用 ''' + someVaraiable + '''
  2. 连接groovy参数

例子:

   def YOUR_APPLICATION_PATH= "${WORKSPACE}/myApp/"

   sh '''#!/bin/bash
          cd ''' + YOUR_APPLICATION_PATH + '''
          npm install
    '''

   pipeline{
     agent { node { label "test" } }
     environment {
       YOUR_APPLICATION_PATH = "${WORKSPACE}/myapp/"
     }

     continue...
     continue...
     continue...

     sh '''#!/bin/bash
          cd "${YOUR_APPLICATION_PATH}"
          npm install
    '''

    //OR
    sh '''#!/bin/bash
          cd "${env.YOUR_APPLICATION_PATH}"
          npm install
    '''

我在为 Amazon S3 应用程序上传 Jenkins 管道工作时遇到了同样的问题。

我的脚本是这样的:

pipeline {  
  agent any
  parameters {
    string(name: 'Bucket', defaultValue: 's3-pipeline-test', description: 'The name of the Amazon S3 Bucket')
    string(name: 'Prefix', defaultValue: 'my-website', description: 'Application directory in the Amazon S3 Bucket')
    string(name: 'Build', defaultValue: 'public/', description: 'Build directory for the application')
  }  
  stages {  
    stage('Build') {  
      steps {
        echo 'Running build phase'
        sh 'npm install' // Install packages
        sh 'npm run build' // Build project 
        sh 'ls' // List project files
      }  
    }  
    stage('Deploy') {  
      steps {  
        echo 'Running deploy phase'
        withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AWSCredentials', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) { 
          sh 'aws s3 ls' // List AWS S3 buckets
          sh 'aws s3 sync "${params.Build}" s3://"${params.Bucket}/${params.Prefix}" --delete' // Sync project files with AWS S3 Bucket project path
        }  
      }   
    }
  }
  post { 
    success {  
      echo 'Deployment to Amazon S3 suceeded'  
    }  
    failure {  
      echo 'Deployment to Amazon S3 failed'  
    }  
  }  
}

这是我修复它的方法:

看到是变量的插值调用,只好把这行脚本中的单引号(' ')换掉:

sh 'aws s3 sync "${params.Build}" s3://"${params.Bucket}/${params.Prefix}" --delete' // Sync project files with AWS S3 Bucket project path

转双引号(" "):

sh "aws s3 sync ${params.Build} s3://${params.Bucket}/${params.Prefix} --delete" // Sync project files with AWS S3 Bucket project path

所以我的脚本之后看起来像这样:

pipeline {  
  agent any
  parameters {
    string(name: 'Bucket', defaultValue: 's3-pipeline-test', description: 'The name of the Amazon S3 Bucket')
    string(name: 'Prefix', defaultValue: 'my-website', description: 'Application directory in the Amazon S3 Bucket')
    string(name: 'Build', defaultValue: 'public/', description: 'Build directory for the application')
  }  
  stages {  
    stage('Build') {  
      steps {
        echo 'Running build phase'
        sh 'npm install' // Install packages
        sh 'npm run build' // Build project 
        sh 'ls' // List project files
      }  
    }  
    stage('Deploy') {  
      steps {  
        echo 'Running deploy phase'
        withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AWSCredentials', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) { 
          sh 'aws s3 ls' // List AWS S3 buckets
          sh "aws s3 sync ${params.Build} s3://${params.Bucket}/${params.Prefix} --delete" // Sync project files with AWS S3 Bucket project path
        }  
      }   
    }
  }
  post { 
    success {  
      echo 'Deployment to Amazon S3 suceeded'  
    }  
    failure {  
      echo 'Deployment to Amazon S3 failed'  
    }  
  }  
}

就这些了

希望对您有所帮助

Jenkins 脚本在“sh”中失败 command-line 例如:

sh 'npm run build' <-- Fails referring to package.json

需要改为:

sh 'npm run ng build....'

... package.json.

找不到 ng $PATH