Jenkinsfile and groovy script - Unexpected End of File - jenkins

I need to have a one-liner sh script such as this
if ! [-s filename.txt ] then echo 'don'\''t do something' exit 2 fi
but when I put this in sh " <>" I am getting the following error
/home/jenkins/workspace/<BLA_BLA>/script.sh: line 1: unexpected EOF while looking for matching `''
Not sure how to fix it. Could someone point me in the right direction?

The first issue is that you need to escape the backslash inside the sh block, so for example:
sh "if ! [-s filename.txt ] then echo 'don'\\''t do something' exit 2 fi"
Then there is probably a problem with the oneliner script you posted as it doesn't work in plain bash for me either.
In the pipeline, you can use multiline string with """, if I reformat the script you posted, it works correctly:
sh """
if ! [ -s filename.txt ]; then
echo 'don'\\''t do something'
exit 2
fi
"""
the output then is:
+ '[' -s filename.txt ']'
+ echo 'don'\''t do something'
don't do something
+ exit 2
ERROR: script returned exit code 2
Would that work for you?

Related

Dollar sign as a string parameter in Jenkins job is doubled

I builded Jenkins with parameters in my configuration:
a = a$
b = b$$
c = c$$$
d = d$$$$
e = e$e$e$e$
I builded my pipeline and it contained this possibilities how to display content of environment variables:
sh """
echo "${env.a}"
echo "\$a"
echo "${env.b}"
echo "\$b"
echo "${env.c}"
echo "\$c"
echo "${env.d}"
echo "\$d"
echo "${env.e}"
echo "\$e"
"""
It returned:
+ echo 'a$'
a$
+ echo 'a$$'
a$$
+ echo 'b$'
b$
+ echo 'b$$'
b$$
+ echo c14
c14
+ echo 'c$$$$'
c$$$$
+ echo d14
d14
+ echo 'd$$$$'
d$$$$
+ echo 'eeee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$14'
eeee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$14
+ echo 'ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$'
ee$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$e$$$$
Anyone who can explain this behaviour?
First of all - very interesting problem. Results are... unusual :)
I couldn't reproduce 100% of your results on my Jenkins, it's probably version/platform dependent. But fortunately the most interesting parameter e returned all that mess. So I'll focus on in.
It looks like parameters are evaluated before they are passed to environment. So each occurrence of $e is replaced by current value of e variable (which is e$e$e$e$ so far). So, we have e then three times $e replaced by e$e$e$e$ and finally $. The result is: e e$e$e$e$ e$e$e$e$ e$e$e$e$ $ (spaces added for readability). And this is value stored in environment. You can see it printed by your last echo (but with every $ replaced by $$).
The longest output (echo "${env.e}") doesn't do anything new - it just takes ee$e$e$e$e$e$e$e$e$e$e$e$$ and evaluates it one more time, replacing every occurrence of $e by ee$e$e$e$e$e$e$e$e$e$e$e$$. And finally, replaces every $ by $$ when printing :)

How can I run a perl script in a jenkins pipeline step

I have configued a pipeline script in jenkins . In one stage , I need to run a perl script with arguments ,like :
pipeline{
agent any
stages {
stage('First Stage')
{
steps
{
dir ("path_to_script")
sh "#!/usr/bin/perl -w test.pl --arg ar1 --arg ar2 --arg ar3"
}
}
This code is not helping me. How can I execute the script test.pl ?
It feels a bit odd to me that you're supplying everything to the shebang. Essentially, you're saying that the interpreter for the remainder of the file is perl with the full set of arguments (which then gets no code to execute supplied). Why I can imagine that this still works, I'd recommend to just call perl:
sh "/usr/bin/perl -w test.pl --arg ar1 --arg ar2 --arg ar3"
and not bring in the shebang definition.
This would only make sense to me, if you would supply a perl script (and then also _Michael J_s' answer would make sense to me because of the multi-line quotes:
sh """#!/usr/bin/perl
use strict;
use warnings;
print "Hello, World!\n";"""
I know this thread is a couple years old now, but just for the record...
steps
{
dir ("path_to_script")
sh "#!/usr/bin/perl -w test.pl --arg ar1 --arg ar2 --arg ar3"
}
Unlike cd, dir is not a command that takes effect and persists. Rather, in keeping with the declarative pipeline, it's a block, for example:
dir ("path_to_script") {
sh "/usr/bin/perl -w ./test.pl --arg ar1"
}
I believe the shebang from the documentation was for if the script was inline. For that matter, if test.pl has the shebang as its first line (#!/usr/bin/perl -w), then this reduces to:
dir ("path_to_script") {
sh "./test.pl --arg ar1"
}
Replace the quotes around your call to perl with three single quotes. This worked for me:
pipeline
{
agent any
stages
{
stage('First Stage')
{
steps
{
sh '''#!/usr/bin/perl -v'''
}
}
}
}

Running an Ansible playbook via Jenkins

I am using Jenkins to take a number of parameters, generate an ansible-playbook command and run it. My Jenkins server is also my Ansible server.
My shell says ::
echo $ESXi_IP
echo $VM_NAME
echo $NIC1_MAC
echo $NIC2_MAC
echo $NIC3_MAC
echo $NIC4_MAC
echo $ESXi_HOSTNAME
echo $PLAYBOOK
ansible-playbook $PLAYBOOK --extra-vars "esxi_ip=$ESXi_IP vm_name=$VM_NAME nic1_mac=$NIC1_MAC nic2_mac=$NIC2_MAC nic3_mac=$NIC3_MAC nic4_mac=$NIC4_MAC esxi_hostname=$ESXi_HOSTNAME"
When I run the Job, the output is ::
+ ansible-playbook /root/ansible/sc-ece.yaml --extra-vars 'esxi_ip=5.232.66.49 vm_name=JenkinsTest nic1_mac=00:50:C0:A8:01:02 nic2_mac=00:50:0A:A9:37:A5 nic3_mac=00:50:0A:FF:FE:4C nic4_mac=00:50:AC:10:01:65 esxi_hostname=tmolab13-14iamesxi4'
ERROR! the playbook: /root/ansible/sc-ece.yaml could not be found
The playbook path is correct. there is no issue in it at all.
What seems to be missing here ?
You are correct Matt & Dave. Permissions to the folder was an issue. Thanks !

How can you activate a conda environment through a Jenkinsfile?

Through the terminal, it's as simple as source activate MyCondaEnv, but if I try in a Jenkinsfile:
sh '. /home/rwardrup/anaconda3/bin/activate MyCondaEnv',
The Jenkins console returns:
Running shell script
+ . /home/rwardrup/anaconda3/bin/activate MyCondaEnv
+ [[ -n ]]
/var/lib/jenkins/workspace/testing/features#tmp/durable-bb4a4c30/script.sh: 4: /home/rwardrup/anaconda3/bin/activate: [[: not found
+ [[ -n ]]
/var/lib/jenkins/workspace/testing/features#tmp/durable-bb4a4c30/script.sh: 7: /home/rwardrup/anaconda3/bin/activate: [[: not found
+ echo Only bash and zsh are supported
Only bash and zsh are supported
+ return 1
I've tried throwing a little shebang in there: sh '$!/bin/bash. /home/rwardrup/anaconda3/bin/activate MyCondaEnv', thinking that it could have to do with that, and I get:
Running shell script
+ /bin/bash. /home/rwardrup/anaconda3/bin/activate MyCondaEnv
/var/lib/jenkins/workspace/testing/features#tmp/durable-2a550d19/script.sh: 2: /var/lib/jenkins/workspace/testing/features#tmp/durable-2a550d19/script.sh: /bin/bash.: not found
Is there any way to activate and use a Conda environment through a Jenkinsfile? I've found some info on using a Django venv in a Jenkinsfile, but that didn't work in my situation.
It looks like an incorrect syntax for shebang and a missng newline after.
Try this:
sh '''#!/bin/bash
. /home/rwardrup/anaconda3/bin/activate MyCondaEnv
'''

how to capture output from rails runner "MyCloud::Deployment.checkuser" on a bash shell

I want to capture the output on the bash shell when running the following command at the bash prompt.
rails runner "MyCloud::Deployment.checkuser"
Basically checkuser() returns a value of either 1 or 0, which I want to capture at the shell that launched the "rails runner" command.
Based on the written value at the shell, I would like to execute some other command. This checkuser() connects to the cloud, accesses the SQL server and returns the value, so I need to load the rails env.
I run this command in hudson "execute shell" window. How do I go about achieving this task?
Does rake help me with this?
Edit:
#to keep things simple:
module MyCloud
class Deployment
def self.checkuser
return 20
end
end
end
I am running the command from ubuntu box:
sreeni#ubuntu:~/work/co/RoR$ res="$(rails runner "MyCloud::Deployment.checkuser")"
sreeni#ubuntu:~/work/co/RoR$ echo $res
sreeni#ubuntu:~/work/co/RoR$
I want to capture the value that is returned from that check_user() to a variable on the bash shell.
Edit: You are confusing return values (objects returned to the same-language caller) with text output. You need to puts 20 to capture it as a string. You cannot capture return values from one language in another language without a foreign function interface or similar mechanism. A rare exception is the interface between *nix shells like Bash and Dash, where you can capture the return value from one in the other because they both implement something similar to a POSIX shell.
To get the exit code, test the command or $?:
rails runner "MyCloud::Deployment.checkuser"
if [ $? -eq 0 ]
then
echo "Success"
else
echo "Failure"
fi
Short form:
if rails runner "MyCloud::Deployment.checkuser"
then
echo "Success"
else
echo "Failure"
fi
To get string output, use a process substitution (and yes, those inner quotes are correct):
result="$(rails runner "MyCloud::Deployment.checkuser")"
if [ "$result" = '0' ]
then
echo "Success"
else
echo "Failure"
fi
Short form:
if [ "$(rails runner "MyCloud::Deployment.checkuser")" = '0' ]
then
echo "Success"
else
echo "Failure"
fi
To capture both output and exit code:
result="$(rails runner "MyCloud::Deployment.checkuser")"
exit_code=$?

Resources