def pname = "netstat -ntlp|grep 8080|awk '{printf \$7}'|cut -d/ -f2"
sh "echo $pname" \ java
if ("java".equals(pname)) { sh "echo 1111" }
The process corresponding to port 8080 is a java process, and the 2nd line print "java". But the body of the if statement just doesn't execute.
You seem to be not executing the command correctly. Please refer to the following sample. Please note the returnStdout: true to return output of the command.
pipeline {
agent any
stages {
stage('Test') {
steps {
script {
def pname = sh(returnStdout: true, script: "netstat -ntlp|grep 8080|awk '{printf \$7}'|cut -d/ -f2").trim()
if (pname == "java") {
echo "echo 1111"
}
}
}
}
}
}
try
"==" for equal
or you can read doc.
https://groovy-lang.org/operators.html#_relational_operators
Related
How do I call a method with arguments from a Jenkinsfile.
def upload_nightly_build(local_filename, remote_filename)
{
sh 'curl --output $local_filename http://someserver:8000/firmware/$remote_filename'
sh 'curl -F upload_file=#$local_filename http://someserver:8000/frontend/file_upload_handler'
sh 'rm $local_filename'
}
pipeline
{
agent
{
dockerfile
{
dir 'dockerfiles'
filename 'Dockerfile-integration.tests'
}
}
stages
{
stage('upload binaries')
{
steps
{
dir ("firmware")
{
upload_nightly_build('iobox-1024-nightly.bin', 'iobox-1024.bin')
}
}
}
}
}
Tried so far
encapsulate usage of arguments in method with braces
define arguments as String
define arguments with def
used named arguments using Map
Whatever I try, in Jenkins console output I will always see
+ curl --output http://someserver:8000/firmware/
curl: no URL specified!
Sigh... found it myself eventually..
sh "curl --output $local_filename http://someserver:8000/firmware/$remote_filename"
Double quote the sh argument... I should've known...
in the first stage, i've shell script to check directory in the remote server and the results will be sent to the next stage. I have tried the following way but it seems the variable is not read in the execute stage, is there another proper way?
pipeline {
agent any
stages
{
stage("validate")
{
steps
{
sh '''
dir_path="/home/servicenamedir"
ssh username#host bash -c "'
if [ -d "$dir" ]
then
checkdir="true"
else
checkdir="false"
fi
'"
'''
}
}
stage("execute")
{
steps
{
sh '''
if [ "$checkdir" == "true" ]
then
echo "directory already exist, please double check";
exit;
elif [ "$checkdir" == "false" ]
then
echo "execute ./install-service.sh"
fi
'''
}
}
}
create variable
def var
use options returnStdout: true. And parse output
Def var = sh ( script " ls -la", returnStdout: true).split("\n")
use var in stage 'execute'
If (var[0] =="true"){...} else {...}
https://www.jenkins.io/doc/pipeline/steps/workflow-durable-task-step/
can i know which part i am doing wrong. The file not in server but however, every time i execute it goes to true statement
pipeline {
agent any
stages{
stage('Test') {
steps{
script{
hasWar = sh(returnStdout: true, script: 'sshpass -p ${password} ssh ${username}#123.12.32.33 \'if [ -f /home/nityo/warFile1.war ]; then echo true; else echo false; fi\'')
if (hasWar) {
echo 'Has war'
} else {
echo 'No war files'
}
}
}
}
}
}
Assuming the script part echos true or false to the console in the expected conditions, there is one more thing you didn't take into account. In Groovy, every non-empty string evaluates to true when used in the context of the boolean variable. It's called Groovy Truth.
If you want to evaluate string value false to an appropriate boolean value, you have to use toBoolean() method that returns false if the string value stores false literal, and true if it stores true literal.
https://docs.groovy-lang.org/latest/html/groovy-jdk/java/lang/String.html#toBoolean()
Also, consider adding trim() to the sh() step so all whitespaces are trimmed from the output when you store it under the hasWar variable.
pipeline {
agent any
stages{
stage('Test') {
steps{
script{
hasWar = sh(returnStdout: true, script: 'sshpass -p ${password} ssh ${username}#123.12.32.33 \'if [ -f /home/nityo/warFile1.war ]; then echo true; else echo false; fi\'').trim()
if (hasWar.toBoolean()) {
echo 'Has war'
} else {
echo 'No war files'
}
}
}
}
}
}
I have defined global variable in Jenkins pipeline
def BUILDNRO = '0'
pipeline { ...
Then i manipulate variable with shell script to enable running builds parallel by using job build number as identifier so we don't mix different docker swarms.
stage('Handle BUILD_NUMBER') {
steps {
script {
BUILDNRO = sh( script: '''#!/bin/bash
Build=`echo ${BUILD_NUMBER} | grep -o '..$'`
# Check if BUILD first character is 0
if [[ $Build:0:1 == "0" ]]; then
# replace BUILD first character from 0 to 5
Build=`echo $Build | sed s/./5/1`
fi
echo $Build
''',returnStdout: true).trim()
}
}
}
i get value out from previos stage and trying to get global variable on next stage
stage('DOCKER: Init docker swarm') {
steps {
echo "BUILDNRO is: ${BUILDNRO}" --> Value is here.
sh '''#!/bin/bash
echo Buildnro is: ${BUILDNRO} --> This is empty.
...
}
}
This will out give global variable empty. why? in previous stage there was value in it.
EDIT 1.
Modified code blocks to reflect current status.
I managed to figure it out. Here is solution how i managed to did it.
BUILDNRO is groovy variable and if wanting to used in bash variable it have to pass using withEnv. BUILD_NUMBER in first stage is bash variable hence it can be used directly script in first stage.
def BUILDNRO = '0'
pipeline {
....
stages {
stage('Handle BUILD_NUMBER') {
steps {
script {
BUILDNRO = sh( script: '''#!/bin/bash
Build=`echo ${BUILD_NUMBER} | grep -o '..$'`
''',returnStdout: true).trim()
}
}
}
stage('DOCKER: Init docker swarm') {
steps {
dir("prose_env/prose_api_dev_env") {
withEnv(["MYNRO=${BUILDNRO}"]) {
sh(returnStdout: false, script: '''#!/bin/bash
echo Buildnro is: ${MYNRO}`
'''.stripIndent())
}
}
}
}
}
}
If you are using single quotes(```) in the shell module, Jenkins treats every variable as a bash variable. The solution is using double quotes(""") but then if you made bash variable you have to escape it. Below an example with working your use case and escaped bash variable
pipeline {
agent any
stages {
stage('Handle BUILD_NUMBER') {
steps {
script {
BUILDNRO = sh(script: 'pwd', returnStdout: true).trim()
echo "BUILDNRO is: ${BUILDNRO}"
}
}
}
stage('DOCKER: Init docker swarm') {
steps {
sh """#!/bin/bash
echo Buildnro is: ${BUILDNRO}
variable=world
echo "hello \${variable}"
sh """
}
}
}
}
output of the second stage:
Buildnro is: /var/lib/jenkins/workspace/stack1
hello world
I have a pipeline stage where I wait to get a certain string back from a sh script, and only when the strings match, continue to next stage, however, it doesn't work as expected:
node('master') {
stage("wait for bash completion") {
waitUntil {
def output = sh returnStdout: true, script: 'cat /tmp/test.txt'
output == "hello"
}
}
stage("execute after bash completed") {
echo "the file says hello!!!"
}
}
The execution is something like that:
+ cat /tmp/test.txt
[Pipeline] }
Will try again after 0.25 sec
[Pipeline] {
[Pipeline] sh
[workspace] Running shell script
+ cat /tmp/test.txt
[Pipeline] }
Will try again after 0.3 sec
[Pipeline] {
[Pipeline] sh
[workspace] Running shell script
+ cat /tmp/test.txt
[Pipeline] }
Will try again after 0.36 sec
...
(so on and so forth)
What am I missing?
From waitUntil's help:
Runs its body repeatedly until it returns true. If it returns false, waits a while and tries again. --
Your execution output looks exactly like that it is waiting for output == "hello" to match. Maybe the content of file /tmp/test.txt is not exactly hello. You might have some whitespace in it, e.g. new line as the last character.
You probably need to add .trim() shell stdout to work, ie
def output = sh(returnStdout: true, script: 'cat /tmp/test.txt').trim()
Otherwise you end up with output showing a newline character at the end.
but probably, the better solution would be to use groovy script:
steps {
sh "echo something > statusfile" // do something in the shell
waitUntil(initialRecurrencePeriod: 15000) {
script {
def status = readFile(file: "statusfile")
if ( status =~ "hello") {
return true
}else {
println("no hello yet!")
return false
}
}
}
}