Answers: <p>There is a simple solution for declarative pipeline which doesn't involve having to write to files - define the variable-to-be-shared <em>outside</em> the <code>pipeline</code> block. This is much neater and means you should still be able to restart the job from the later stage if you need.</p>
  <p>Example:</p>
  <pre><code>def variable = &quot;initial value&quot;
  pipeline {
      agent {
          ...
      }
      stages {
          stage(&quot;Override variable&quot;) {
              steps {
                  script {
                      variable = sh(script: 'some command', returnStdout: true).trim()
                  }
              }
          }
          stage(&quot;Read new value of variable&quot;) {
              steps {
                  script {
                      echo variable
                  }
              }
          }
      }
  }
  </code></pre>
  <p>Further explanation in <a href="https://www.youtube.com/watch?v=41uUsWQjKRw" rel="nofollow noreferrer">video form</a></p>
  
Answers: CC BY-SA 4.0
Answers: 2023-05-22T10:44:16.110Z
Answers: 2023-06-16T22:33:00.717Z
Answers: 2023-06-16T22:33:00.717Z
Answers: Dave
Answers: <p>For Declarative Pipeline:</p>
  
  <p>This question already has a <a href="https://stackoverflow.com/a/44101004/1824868">highly-upvoted answer on StackOverflow</a>:</p>
  
  <blockquote>
    <p>If you want to use a file (since a script is the thing generating the value you need):</p>
  
  <pre><code>pipeline {
    agent { label 'docker' }
    stages {
      stage('one') {
        steps {
          sh 'echo hotness &gt; myfile.txt'
          script {
            // trim removes leading and trailing whitespace from the string
            myVar = readFile('myfile.txt').trim()
          }
          echo "${myVar}" // prints 'hotness'
        }
      }
      stage('two') {
        steps {
          echo "${myVar}" // prints 'hotness'
        }
      }
      // this stage is skipped due to the when expression, so nothing is printed
      stage('three') {
        when {
          expression { myVar != 'hotness' }
        }
        steps {
          echo "three: ${myVar}"
        }
      }
    }
  }
  </code></pre>
  </blockquote>
  
  <p>A second solution would be to write out output from your script directly or with <a href="https://jenkins.io/doc/pipeline/steps/workflow-basic-steps/#writefile-write-file-to-workspace" rel="noreferrer"><code>writeFile</code></a> and then later read it back in with <a href="https://jenkins.io/doc/pipeline/steps/workflow-basic-steps/#readfile-read-file-from-workspace" rel="noreferrer"><code>readFile</code></a>.  However, this comes with the significant caveat that both the reading and writing must take place on the same node, so you can't use this to send data across nodes.</p>
  
  <p>You can also can archive files centrally with <a href="https://jenkins.io/doc/pipeline/steps/core/#archiveartifacts-archive-the-artifacts" rel="noreferrer"><code>archiveArtifact</code></a> and retrieve them with <a href="https://jenkins.io/doc/pipeline/steps/copyartifact/#copyartifacts-copy-artifacts-from-another-project" rel="noreferrer"><code>copyArtifact</code></a> (and then read in the file with <code>readFile</code>).</p>
  
  <p>Finally, there are some answers to a <a href="https://stackoverflow.com/q/47462500/1824868">near-identical question on StackOverflow</a> that offer alternative solutions.</p>
  
  <hr>
  
  <p>However, if you can, I would suggest using Scripted Pipeline instead, which allows a much simpler solution:</p>
  
  <pre><code>def String myVar
  
  stage('my-first-stage') {
    myVar = sh(script: 'my-command', returnStdout: true)
  }
  
  stage('my-second-stage') {
    sh("my-other-command --var='${myVar}'")
  }
  </code></pre>
  
  <p>(I also already answered this question for Scripted Pipeline over on <a href="https://serverfault.com/a/884798/213070">ServerFault</a>.)</p>
  
  <hr>
  
  <p>It looks like some of these solutions have already been proposed in the comments, but you are concerned that they are not elegant enough.  I'm not really sure what kind of elegance you're looking for, because I can't think of any way to simplify these answers in Jenkins-Pipeline-land.</p>
  
Answers: CC BY-SA 4.0
Answers: 2018-10-23T23:18:08.300Z
Answers: 2018-11-26T04:24:55.493Z
Answers: 2018-11-26T04:24:55.493Z
Answers: jayhendren
Body: <p>I have a declarative Jenkins pipeline that looks like the following:</p>
  
  <pre><code>pipeline{
      agent {
          ...
      }
      stages {
          stage("Provision EC2 Instance and Set ENV Variable"){
              steps {
                  dir("docker-image-builder"){
                      sh 'python ./provisonInstance.py'
                  }
              }
          }
          stage("Configure EC2 Instance with Ansible"){
              steps {
                  ansiblePlaybook('./ansible.playbook.yml') {
                      ansibleName('1.9.4')
                  }
              }
          }
      }
  }
  </code></pre>
  
  <p>In my first stage, I have a Python script that provisions an <a href="http://en.wikipedia.org/wiki/Amazon_Elastic_Compute_Cloud" rel="noreferrer">Amazon EC2</a> instance that will be used to create an <a href="https://en.wikipedia.org/wiki/Amazon_Machine_Image" rel="noreferrer">AMI</a>. In the second stage, I will then configure configure my instance before finally creating an AMI and terminating the instance. In order to do this, I need the instance-id of the EC2 instance created in the first stage. <strong>Is there an elegant way to pass values generated by a script between stages, and if so how?</strong></p>
  
  <p>The most obvious method that I can think of is to write the value to a file on the agent in the first stage, and read it in the second stage, but this does not seem like an elegant solution.</p>
  
Comments: CC BY-SA 4.0
Comments: 2018-10-18T15:08:58.790Z
Comments: Not a full answer as we use scripted, not declarative pipelines, but writing to a file is exactly what I ended up doing in our scripts.
Comments: Alex
Comments: CC BY-SA 4.0
Comments: 2018-10-19T13:36:33.033Z
Comments: This question has been answered here https://stackoverflow.com/questions/47155326/reuse-object-property-in-different-stages-of-a-declerative-pipeline-in-jenkins/47158534#47158534
Comments: Ram
Comments: CC BY-SA 4.0
Comments: 2018-10-19T14:12:01.970Z
Comments: @RamKamath The answer to that question is a little different. I am trying to take output from a python script and pass it to a stage. While I think that part of the answer is to create a global environment variable, set it in the first stage, and read it in the second stage, it doesn't provide an elegant way to pass it from the python script at the stage level.
Comments: Preston Martin
Tags: <jenkins><ansible><jenkins-pipeline><python>
Title: Passing variables between scripts in a Jenkins pipeline
UserDisplayName: Preston Martin
ThreadText: # Passing variables between scripts in a Jenkins pipeline
  
  (Asked by: username_0 on 2018-10-17)
  
  I have a declarative Jenkins pipeline that looks like the following:
  
  ```
  pipeline{
      agent {
          ...
      }
      stages {
          stage("Provision EC2 Instance and Set ENV Variable"){
              steps {
                  dir("docker-image-builder"){
                      sh 'python ./provisonInstance.py'
                  }
              }
          }
          stage("Configure EC2 Instance with Ansible"){
              steps {
                  ansiblePlaybook('./ansible.playbook.yml') {
                      ansibleName('1.9.4')
                  }
              }
          }
      }
  }
  
  ```
  
  In my first stage, I have a Python script that provisions an [Amazon EC2](http://en.wikipedia.org/wiki/Amazon_Elastic_Compute_Cloud) instance that will be used to create an [AMI](https://en.wikipedia.org/wiki/Amazon_Machine_Image). In the second stage, I will then configure configure my instance before finally creating an AMI and terminating the instance. In order to do this, I need the instance-id of the EC2 instance created in the first stage. **Is there an elegant way to pass values generated by a script between stages, and if so how?**
  
  The most obvious method that I can think of is to write the value to a file on the agent in the first stage, and read it in the second stage, but this does not seem like an elegant solution.
  
  **Tags:** jenkins, ansible, jenkins-pipeline, python
  
  > **Comments:**
  > **username_1**: Not a full answer as we use scripted, not declarative pipelines, but writing to a file is exactly what I ended up doing in our scripts.  
  > **username_2**: This question has been answered here https://stackoverflow.com/questions/47155326/reuse-object-property-in-different-stages-of-a-declerative-pipeline-in-jenkins/47158534#47158534  
  > **username_0**: @RamKamath The answer to that question is a little different. I am trying to take output from a python script and pass it to a stage. While I think that part of the answer is to create a global environment variable, set it in the first stage, and read it in the second stage, it doesn't provide an elegant way to pass it from the python script at the stage level.  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_4 on 2018-10-23. Score: 9 | Accepted answer
  
  For Declarative Pipeline:
  
  This question already has a [highly-upvoted answer on StackOverflow](https://stackoverflow.com/a/44101004/1824868):
  
  > If you want to use a file (since a script is the thing generating the value you need):
  >
  > ```
  > pipeline {
  >   agent { label 'docker' }
  >   stages {
  >     stage('one') {
  >       steps {
  >         sh 'echo hotness > myfile.txt'
  >         script {
  >           // trim removes leading and trailing whitespace from the string
  >           myVar = readFile('myfile.txt').trim()
  >         }
  >         echo "${myVar}" // prints 'hotness'
  >       }
  >     }
  >     stage('two') {
  >       steps {
  >         echo "${myVar}" // prints 'hotness'
  >       }
  >     }
  >     // this stage is skipped due to the when expression, so nothing is printed
  >     stage('three') {
  >       when {
  >         expression { myVar != 'hotness' }
  >       }
  >       steps {
  >         echo "three: ${myVar}"
  >       }
  >     }
  >   }
  > }
  >
  > ```
  
  A second solution would be to write out output from your script directly or with [`writeFile`](https://jenkins.io/doc/pipeline/steps/workflow-basic-steps/#writefile-write-file-to-workspace) and then later read it back in with [`readFile`](https://jenkins.io/doc/pipeline/steps/workflow-basic-steps/#readfile-read-file-from-workspace). However, this comes with the significant caveat that both the reading and writing must take place on the same node, so you can't use this to send data across nodes.
  
  You can also can archive files centrally with [`archiveArtifact`](https://jenkins.io/doc/pipeline/steps/core/#archiveartifacts-archive-the-artifacts) and retrieve them with [`copyArtifact`](https://jenkins.io/doc/pipeline/steps/copyartifact/#copyartifacts-copy-artifacts-from-another-project) (and then read in the file with `readFile`).
  
  Finally, there are some answers to a [near-identical question on StackOverflow](https://stackoverflow.com/q/47462500/1824868) that offer alternative solutions.
  
  ---
  
  However, if you can, I would suggest using Scripted Pipeline instead, which allows a much simpler solution:
  
  ```
  def String myVar
  
  stage('my-first-stage') {
    myVar = sh(script: 'my-command', returnStdout: true)
  }
  
  stage('my-second-stage') {
    sh("my-other-command --var='${myVar}'")
  }
  
  ```
  
  (I also already answered this question for Scripted Pipeline over on [ServerFault](https://serverfault.com/a/884798/213070).)
  
  ---
  
  It looks like some of these solutions have already been proposed in the comments, but you are concerned that they are not elegant enough. I'm not really sure what kind of elegance you're looking for, because I can't think of any way to simplify these answers in Jenkins-Pipeline-land.
  
  
  ---
  
  ### Answer by username_3 on 2023-05-22. Score: 2
  
  There is a simple solution for declarative pipeline which doesn't involve having to write to files - define the variable-to-be-shared *outside* the `pipeline` block. This is much neater and means you should still be able to restart the job from the later stage if you need.
  
  Example:
  
  ```
  def variable = "initial value"
  pipeline {
      agent {
          ...
      }
      stages {
          stage("Override variable") {
              steps {
                  script {
                      variable = sh(script: 'some command', returnStdout: true).trim()
                  }
              }
          }
          stage("Read new value of variable") {
              steps {
                  script {
                      echo variable
                  }
              }
          }
      }
  }
  
  ```
  
  Further explanation in [video form](https://www.youtube.com/watch?v=41uUsWQjKRw)
  
  
  ---
  
  