Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jenkins pipeline sh does not seem to respect pipe in shell command

I am using a Jenkinsfile in a pipeline on version 2.32.2.

For various reasons I want to extract the version string from the pom. I was hoping I wouldn't have to add the maven help plugin and use evaluate.

I quickly came up with a little sed expression to get it out of the pom which uses pipes and works on the commandline in the jenkins workspace on the executor.

$ sed -n '/<version>/,/<version/p' pom.xml | head -1 | sed 's/[[:blank:]]*<\/*version>//g' 1.0.0-SNAPSHOT

It could probably be optimized, but I want to understand why the pipeline seems to be failing on piped sh commands. I've played with various string formats and am currently using a dollar slashy string.

The pipeline step looks like the following to allow for easy output of the command string:

script {
    def ver_script = $/sed -n '/<version>/,/<version/p' pom.xml | head -1 | sed 's/[[:blank:]]*<\/*version>//g'/$
    echo "${ver_script}"
    POM_VERSION = sh(script: "${ver_script}", returnStdout: true)
    echo "${POM_VERSION}"
}

When run in the jenkins pipeline I get the following console output where it seems to be separating the piped commands into separate commands:

[Pipeline] script
[Pipeline] {
[Pipeline] echo
sed -n '/<version>/,/<version/p' pom.xml | head -1 | sed 's/[[:blank:]]*<\/*version>//g'
[Pipeline] sh
[FRA-198-versioned-artifacts-44SD6DBQOGOI54UEF7NYE4ECARE7RMF7VQYXDPBVFOHS5CMSTFLA] Running shell script
+ sed -n /<version>/,/<version/p pom.xml
+ head -1
+ sed s/[[:blank:]]*<\/*version>//g
sed: couldn't write 89 items to stdout: Broken pipe
[Pipeline] }
[Pipeline] // script

Any guidance out there on how to properly use piped commands in a jenkinsfile ?

like image 251
sporkthrower Avatar asked Mar 02 '17 23:03

sporkthrower


People also ask

What is sh in Jenkins pipeline?

On Linux, BSD, and Mac OS (Unix-like) systems, the sh step is used to execute a shell command in a Pipeline. Jenkinsfile (Declarative Pipeline) pipeline { agent any stages { stage('Build') { steps { sh 'echo "Hello World"' sh ''' echo "Multiline shell steps works too" ls -lah ''' } } } }

How do I run a sh file in Windows Jenkins?

The sh.exe which is needed to run shell scripts is in the "bin" sub-directory, i.e. C:\cygwin64\bin. 2 - Tell Jenkins where sh.exe is located. Jenkins web console > Manage Jenkins > Configure System > Under shell, set the "Shell executable" = C:\cygwin64\bin\sh.exe > Click apply & also click save.

What shell does Jenkins use?

Runs a shell script (defaults to sh, but this is configurable) for building the project. If you go to Manage Jenkins --> Configure System you will find an option (called "Shell executable") to set the name or absolute path to the shell that you want your shell scripts to use...


2 Answers

I finally put some thought into it and realized that pipe subshells are probably causing the issue. I know some of the evils of eval but I ended up wrappping this in an eval:

script {
    def ver_script = $/eval "sed -n '/<version>/,/<version/p' pom.xml | head -1 | sed 's/[[:blank:]]*<\/*version>//g'"/$
    echo "${ver_script}"
    POM_VERSION = sh(script: "${ver_script}", returnStdout: true)
    echo "${POM_VERSION}"
}   
like image 181
sporkthrower Avatar answered Sep 24 '22 16:09

sporkthrower


I know this kind of late answer, but whoever you who needs the solution without eval you can use /bin/bash -c "script" to make pipe works

script {
    POM_VERSION = sh(script: "/bin/bash -c 'sed -n \'/<version>/,/<version/p\' pom.xml | head -1 | sed \'s/[[:blank:]]*<\/*version>//g\'\''", returnStdout: true)
    echo "${POM_VERSION}"
}

The only problem with this method is hellish escape yet this way the subshell of pipe will be handled by our boy /bin/bash -c

like image 33
Dimas Rizky Avatar answered Sep 23 '22 16:09

Dimas Rizky