Jenkins Pipeline糟糕的替代品

时间:2016-05-13 21:08:48

标签: bash jenkins groovy jenkins-pipeline

我的管道中的一个步骤将.tar上传到artifactory服务器。传入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"'

返回错误:

[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},并且在任何其他地方都没有问题。

7 个答案:

答案 0 :(得分:46)

这结果是一个语法问题。在'中包装命令导致${env.BUILD_NUMBER传递而不是其值。我将整个命令包装在"中,然后转义嵌套。现在工作正常。

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\""

答案 1 :(得分:16)

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

原因/说明: env表示脚本中的环境。该环境直接用于/可用于任何执行的环境,例如, shell脚本。

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

答案 2 :(得分:13)

通常是最常见的问题:

  

糟糕的替换

错误是使用sh而不是bash

特别是在使用Jenkins时,如果您正在使用执行shell ,请确保您的 Command shebang 开头,例如#!/bin/bash -xe#!/usr/bin/env bash

答案 3 :(得分:8)

我可以肯定地告诉你,它全部是关于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
        '''
    }      
}

答案 4 :(得分:1)

我遇到了在jar文件的工件中显示{env.MAJOR_VERSION}的问题。 show我通过在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中扮演着更重要的角色。

答案 5 :(得分:1)

在处理 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'  
    }  
  }  
}

仅此而已

我希望这会有所帮助

答案 6 :(得分:0)

为了将常规参数传递到Jenkins管道中的bash脚本中(有时会导致错误的替换)您有2个选择

  

三重双引号方式[“”“]   要么   三重单引号方式[''']

  1. 三重双引号中,您可以使用function myAlerts() { var ss=SpreadsheetApp.getActiveSpreadsheet(); var sheet=ss.getSheetByName("Campaign List"); var range=sheet.getDataRange(); var values=range.getDisplayValues(); var lastRow=range.getLastRow(); var curDate=values[1][11]; var anyMatches=false; var message=""; var sheetUrl=ss.getUrl(); var email=Session.getActiveUser().getEmail(); var optionalEmail=values[2][12]; if (optionalEmail!=""){ email+="," + optionalEmail; } for (var i=1;i<lastRow;i++) { if (values[i][5].toString()==curDate.toString()) { message+=Utilities.formatString('<strong>%s</strong> will expire on %s <br />\n"',values[i][1],values[i][5]); anyMatches=true; } } message+='<br />\n<font color="red">This is an auto-generated email to remind you of your campaign expiration.</font><br />\n' if (anyMatches) { MailApp.sendEmail({to: email,subject: 'Campaign Expiration Notice!',htmlBody: message}); } } 正常显示参数(如果它是环境变量${someVariable}或注入到您的工作${env.someVariable}中的参数< / li>

示例

${env.someVariable}
  1. 使用三重单引号会变得有些棘手,您可以将参数传递给环境参数,并通过 def YOUR_APPLICATION_PATH= "${WORKSPACE}/myApp/" sh '''#!/bin/bash cd ${YOUR_APPLICATION_PATH} npm install ''' 使用它或将使用 "\${someVaraiable}"
  2. 的常规参数

示例

''' + someVaraiable + '''

OR

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

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