While running this Bash command in an sh """ block I am getting an error in the below Groovy Jenkins code.
I am getting this error:
/home/jenkins/workspace/_api-build_features_SSSVCS-12870#tmp/durable-be642e71/script.sh: line 1: syntax error: unterminated quoted string
for the below 2 lines of Groovy code:
aa = sh(script: "aa=\"\$(helm2 version --short --client|awk '{print substr(\$2,1,2)}'\"; echo \$aa", returnStdout: true).trim()
I am using the variable aa in below if then else loop, Please suggest me.
sh """
if [ aa == v2 ]; then
helm package --save=false ${extraArgs} ${PROJ}
else
helm package ${PROJ}
fi
sh """
In the first line, you miss a closing the bracket ')'. In the second block, consider removing the second sh, otherwise will be part of the whole string between the two """.
Related
I am using the below Jenkinsfile. It is printing the value of upload_id when it is executing with the jq command, but when printing the value it is showing null.
Please help me to fix this variable issue.
sh label: '', script: 'upload_id=$(cat output_file.json | jq -r \'.upload_id\')'
sh "echo \"$upload_id\""**
Output :
[Pipeline] sh
cat output_file.json
jq -r .upload_id
upload_id=8f304c6d-804b-440a-xxxx**
[Pipeline] sh
echo upload_id : null
upload_id : null
[Pipeline] }
I would strongly recommend to go with Matt's answer, because it is the cleanest way.
Anyway, there are situations where there is no other choice than to use the shell, so here is the shell way:
script {
def upload_id = sh label: '',
script: 'echo $(cat output_file.json | jq -r \'.upload_id\')',
returnStdout: true
upload_id = upload_id.trim() // remove extraneous whitespace
sh "echo \"$upload_id\""
}
I've already linked to a more detailed answer of mine but you were probably not getting it to work, because you are using a declarative pipeline. In declarative pipeline, you have to use a script block to be able to store return values of steps.
You can easily do this intrinsically in Jenkins Pipeline to avoid all of the issues with subprocess execution. First, read in and parse the JSON file:
upload_info = readJSON(file: 'output_file.json')
Then, you can access the returned values in the assigned upload_info Map normally:
upload_id = upload_info['upload_id']
I am trying to execute set of commands from jenkinsfile.
The problem is, when I try to assign the value of stdout to a variable it is not working.
I tried different combinations of double quotes and single quotes, but so far no luck.
Here I executed the script with latest version of jenkinsfile as well as old version. Putting shell commands inside """ """ is not allowing to create new variable and giving error like client_name command does not exist.
String nodeLabel = env.PrimaryNode ? env.PrimaryNode : "slave1"
echo "Running on node [${nodeLabel}]"
node("${nodeLabel}"){
sh "p4 print -q -o config.yml //c/test/gradle/hk/config.yml"
def config = readYaml file: 'devops-config.yml'
def out = sh (script:"client_name=${config.BasicVars.p4_client}; " +
'echo "client name: $client_name"' +
" cmd_output = p4 clients -e $client_name" +
' echo "out variable: $cmd_output"',returnStdout: true)
}
I want to assign the stdout from the command p4 clients -e $client_name to variable cmd_output.
But when I execute the code the error that is thrown is:
NoSuchPropertyException: client_name is not defined at line cmd_output = p4 clients -e $client_name
What am I missing here?
Your problem here is that all the $ are interpreted by jenkins when the string is in double quotes. So the first 2 times there's no problem since the first variable comes from jenkins and the second time it's a single quote string.
The the third variable is in a double quote string, therefore jenkins tries to replace the variable with its value but it can't find it since it's generated only when the shell script is executed.
The solution is to escape the $ in $client_name (or define client_name in an environment block).
I rewrote the block:
String nodeLabel = env.PrimaryNode ? env.PrimaryNode : "slave1"
echo "Running on node [${nodeLabel}]"
node("${nodeLabel}"){
sh "p4 print -q -o config.yml //c/test/gradle/hk/config.yml"
def config = readYaml file: 'devops-config.yml'
def out = sh (script: """
client_name=${config.BasicVars.p4_client}
echo "client name: \$client_name"
cmd_output = p4 clients -e \$client_name
echo "out variable: \$cmd_output"
""", returnStdout: true)
}
This question already has an answer here:
Why does this curl command fail when executed in groovy?
(1 answer)
Closed 3 years ago.
I have researched the issue and I think the problem is that I am calling bash from a variable.
There are some great resources including very similar questions on Stackexchange.
The closest match would be this question.
There is an FAQ that tries to help.
I try to call a shell command from groovy script.
Here is a working minimal example:
def working()
{
printf "start\n"
def cmd = "sh -c 'ls'"
def proc = cmd.execute()
proc.waitFor()
if (proc.exitValue() > 1)
{
printf cmd + "\nexitcode:" + proc.exitValue().toString() + "\n"
println "[ERROR] ${proc.getErrorStream()}"
}
printf "end\n"
}
Here is the code that gives me a headache
def notworking()
{
printf "start\n"
def cmd = "sh -c 'command -v ls'"
def proc = cmd.execute()
proc.waitFor()
if (proc.exitValue() > 1)
{
printf cmd + "\nexitcode:" + proc.exitValue().toString() + "\n"
println "[ERROR] ${proc.getErrorStream()}"
}
printf "end\n"
}
I need to use sh in order to call command.
My error output is:
sh -c 'command -v ls'
exitcode:2
[ERROR] -v: 1: -v: Syntax error: Unterminated quoted string
I am pretty sure that this is due to how the arguemnts are actually split.
I am not able to apply any of the array tips from the other questions / responses.
Having done my due dilligance in researching this I am confident this is not a dublicate.
This is also relevant on a broad basis since it can be useful to anyone using jenkins and developing groovy scripts.
I was able to circumvent the split by using an environemnt variable and a different execute function.
def cmd = "sh -c \$args"
def proc = cmd.execute(["args=command -v $command_name"], null)
proc.waitFor()
I found the documentation for the syntax here.
public Process execute(List envp, File dir)
User cfrick points out that there is a better solution here.
Say I have a Jenkinsfile. Within that Jenkinsfile, is the following sh step:
sh "myScript.sh"
Within myScript.sh, the following variable is declared:
MY_VARIABLE="This is my variable"
How can I access MY_VARIABLE, which is declared in myScript.sh, from my Jenkinsfile?
To import the variable defined in your script into the current shell, you can use the source command (see explanation on SU):
# Either via command
source myScript.sh
# Or via built-in synonym
. myScript.sh
Supposing your script does not output anything, you can then instead output the variable to fetch it in Jenkins:
def myVar = sh(returnStdout: true, script: '. myScript.sh && echo $MY_VARIABLE')
If indeed outputs comes from your script, you can fetch the last output either per shell:
(. myScript.sh && echo $MY_VARIABLE) | tail -n1
or via Groovy:
def out = sh(returnStdout: true, script: '. myScript.sh && echo $MY_VARIABLE')
def myVar = out.tokenize('\n')[-1]
The bash variable declared in .sh file is ending with the pipeline step: sh complete.
But you can make you .sh to generate a properties file, then use pipeline step: readProperties to read the file into object for accessing.
// myScript.sh
...
echo MY_VARIABLE=This is my variable > vars.properties
// pipeline
sh 'myScript.sh'
def props = readProperties file: 'vars.properties'
echo props.MY_VARIABLE
I am trying to execute a shell command n groovy
def shellString = "s/\[\|]\|\s\|'\|(\|)//g"
def temp2 = "echo response| sed -e ${shellString}".execute()
It throws compilation error:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 33: unexpected char: '\' # line 33, column 24.
def shellString = "s/\[\|]\|\s\|'\|(\|)//g"
^
1 error
at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:310)
at org.codehaus.groovy.control.ErrorCollector.addFatalError(ErrorCollector.java:150)
at org.codehaus.groovy.control.ErrorCollector.addError(ErrorCollector.java:120)
at org.codehaus.groovy.control.ErrorCollector.addError(ErrorCollector.java:132)
at org.codehaus.groovy.control.SourceUnit.addError(SourceUnit.java:350)
at org.codehaus.groovy.antlr.AntlrParserPlugin.transformCSTIntoAST(AntlrParserPlugin.java:139)
at org.codehaus.groovy.antlr.AntlrParserPlugin.parseCST(AntlrParserPlugin.java:110)
at org.codehaus.groovy.control.SourceUnit.parse(SourceUnit.java:234)
at org.codehaus.groovy.control.CompilationUnit$1.call(CompilationUnit.java:168)
at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:943)
at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:605)
at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:581)
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:558)
at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268)
at groovy.lang.GroovyShell.parseClass(GroovyShell.java:688)
at groovy.lang.GroovyShell.parse(GroovyShell.java:700)
at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.doParse(CpsGroovyShell.java:131)
at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.reparse(CpsGroovyShell.java:125)
at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:560)
at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:521)
at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:330)
at hudson.model.ResourceController.execute(ResourceController.java:97)
at hudson.model.Executor.run(Executor.java:429)
shellString isn't a slashed string, so not sure why a \ would create a problem. Any help is appreciated.
You need to escape slash to avoid compilation errors:
def shellString = "s/\\[\\|]\\|\\s\\|'\\|(\\|)//g"
def temp2 = "echo response| sed -e ${shellString}".execute()
println temp2.text
Output:
response| sed -e s/\[\|]\|\s\|'\|(\|)//g
This will fail on many levels. The biggest problem you will face is the fact, that execute is really just executing a process (not a shell command). So first of all you can not use | at all. Next quoting arguments will not work, because execute will just split at whitespace. So if you want to use "shellisms" use the equivalent of sh -c "..." instead and use execute on a string array. E.g.
["sh", "-c", "..."].execute()
Then you can put your ... shell code in there with all the redirections, quotings, env-vars etc. with the proper Groovy quoting applied as mentioned in the other answer.
And to circumvent all of that: why even bother with sed here? Just use replaceAll on the resulting string on the groovy side of things.