Mandeep Singh
Mandeep Singh

Reputation: 8234

jenkins pipeline: multiline shell commands with pipe

I am trying to create a Jenkins pipeline where I need to execute multiple shell commands and use the result of one command in the next command or so. I found that wrapping the commands in a pair of three single quotes ''' can accomplish the same. However, I am facing issues while using pipe to feed output of one command to another command. For example

   stage('Test') {
      sh '''
         echo "Executing Tests"
         URL=`curl -s "http://localhost:4040/api/tunnels/command_line" | jq -r '.public_url'`
         echo $URL
         RESULT=`curl -sPOST "https://api.ghostinspector.com/v1/suites/[redacted]/execute/?apiKey=[redacted]&startUrl=$URL" | jq -r '.code'`
         echo $RESULT
      '''
   }

Commands with pipe are not working properly. Here is the jenkins console output:

+ echo Executing Tests
Executing Tests
+ curl -s http://localhost:4040/api/tunnels/command_line
+ jq -r .public_url
+ URL=null
+ echo null
null
+ curl -sPOST https://api.ghostinspector.com/v1/suites/[redacted]/execute/?apiKey=[redacted]&startUrl=null

Upvotes: 55

Views: 171178

Answers (4)

m19v
m19v

Reputation: 2192

Non-quoted backslash \ followed by newline in Jenkinsfile is also treated as a line continuation as in shell environment:

node {
    stage "Example Stage"
        sh 'echo "this is multiline sh command with \
            arg1 \
            arg2 \
            ....\
            argN"'
}

See https://www.gnu.org/software/bash/manual/bash.html#Escape-Character

Upvotes: 1

Ashan Priyadarshana
Ashan Priyadarshana

Reputation: 3649

The following scenario shows a real example that may need to use multiline shell commands. Which is, say you are using a plugin like Publish Over SSH and you need to execute a set of commands in the destination host in a single SSH session:

stage ('Prepare destination host') {
  sh '''
      ssh -t -t user@host 'bash -s << 'ENDSSH'
      if [[ -d "/path/to/some/directory/" ]];
      then
          rm -f /path/to/some/directory/*.jar
      else
          sudo mkdir -p /path/to/some/directory/
          sudo chmod -R 755 /path/to/some/directory/
          sudo chown -R user:user /path/to/some/directory/
      fi
ENDSSH'
     '''
}

Special Notes:

  • The last ENDSSH' should not have any characters before it. So it should be at the starting position of a new line.
  • use ssh -t -t if you have sudo within the remote shell command

Upvotes: 13

Stefan van de Vooren
Stefan van de Vooren

Reputation: 2737

I split the commands with &&

node {
  FOO = world
  stage('Preparation') { // for display purposes
      sh "ls -a && pwd && echo ${FOO}"
  }
}

The example outputs: - ls -a (the files in your workspace - pwd (location workspace) - echo world

Upvotes: -4

Mandeep Singh
Mandeep Singh

Reputation: 8234

I tried entering all these commands in the jenkins snippet generator for pipeline and it gave the following output:

sh '''         echo "Executing Tests"
         URL=`curl -s "http://localhost:4040/api/tunnels/command_line" | jq -r \'.public_url\'`
         echo $URL
         RESULT=`curl -sPOST "https://api.ghostinspector.com/v1/suites/[redacted]/execute/?apiKey=[redacted]&startUrl=$URL" | jq -r \'.code\'`
         echo $RESULT
'''

Notice the escaped single quotes in the commands jq -r \'.public_url\' and jq -r \'.code\'. Using the code this way solved the problem

UPDATE: : After a while even that started to give problems. There were certain commands executing prior to these commands. One of them was grunt serve and the other was ./ngrok http 9000. I added some delay after each of these commands and it solved the problem for now.

Upvotes: 46

Related Questions