I'm running a declarative Jenkins pipeline on Ubuntu 18.04 slave. My issue is that whenever I'm trying to provide arguments from a sh step to a bash script, the arguments are not there. When running the exact same commands from either a terminal directly or another script file (similarly how Jenkins does it via temp file) the arguments work fine.
The Jenkinsfile looks something like
pipeline {
agent { label "ubuntu" }
options { timeout(time: 1, unit: 'HOURS') }
stages {
stage('Build') {
steps {
sh """
#!/bin/bash
...
. ./Scripts/install_tools.sh "force"
"""
}
}
}
}
The pipeline itself runs smooth and does what I need it to do. The problem is that when calling install_tools.sh no arguments are found. The script looks something like
#!/bin/bash
echo "Running $0"
echo "Args: $#"
...
The line echo "Args: $#" I have tried also with $* and $1 - Each time the arguments are returned as empty, but only when running from the pipeline. It seems to me that this is related to some Groovy stuff, but I have no clue what.
How do I call a bash script during the pipeline and get the arguments passed properly?
put #!/bin/bash into the first line
sh """#!/bin/bash
. ./Scripts/install_tools.sh "force"
"""
otherwise . (dot) command could have different meaning
Related
I'm running a very simple pipeline to create maven projects, the pipeline is to run a single maven install command.
The trouble is substituting variables into the one-liner. I've tried various different things but stuck in a strange place. Take example pipeline below:
node {
stage('Set Vars') {
GIT_HASH = sh (script: "git log -n 1 --pretty=format:'%H'" , returnStdout: true)
echo "git hash is >>>>>>>> $GIT_HASH"
BUILD_NUM="${env.BUILD_NUMBER}"
echo "build no is >>>>>>>> ${BUILD_NUM}"
}
stage('Build Project') {
sh "mvn clean install -PrunInstallPackage -Duser=admin -Dpass=guessing -Dip=200.0.0.1 -Dport=4444 -Dhash=${GIT_HASH} -Dbuildnumber=${BUILD_NUM}"
}
}
I would expect to see the variables substitued in the mvn install command, this does not seem to work this way though.
This build results in:
sh "mvn clean install -PrunInstallPackage -Duser=admin -Dpass=guessing -Dip=200.0.0.1 -Dport=4444 -Dhash=${GIT_HASH}
Both echo commands print out correct output.
Why does the last command get cut off after the first variable substitution?
Also, for some unknown reason, I cannot substitute -Dbuildnumber=${env.BUILD_NUMBER}" directly into the maven command. Seems like something that a user should be able to do. What am I missing here?
Many thanks in advance
I am trying to remember how I solved same issues in the past..
Problem 1
You are using the GIT_HASH variable across two stages, so you have to declare it global to share it across them:
// Global variables declaration
GIT_HASH = null
// Pipeline code
node {
stage('Set Vars') {
GIT_HASH = sh (script: "git log -n 1 --pretty=format:'%H'" , returnStdout: true)
echo "git hash is >>>>>>>> $GIT_HASH"
BUILD_NUM="${env.BUILD_NUMBER}"
echo "build no is >>>>>>>> ${BUILD_NUM}"
}
stage('Build Project') {
sh "mvn clean install -PrunInstallPackage -Duser=admin -Dpass=guessing -Dip=200.0.0.1 -Dport=4444 -Dhash=${GIT_HASH} -Dbuildnumber=${BUILD_NUM}"
}
}
Problem 2
env.BUILD_NUMBER is a Groovy statement, instead mvn gets executed inside a shell instance by the sh command.
For that reason I suggest you to use the BUILD_NUM variable way.
I have a task in a build.gradle file, in which I'd like to run this command:
(export ENV_VAR=/my/path ; /path/to/build.sh)
I tried running this in gradle:
task myTask {
doLast {
exec {
commandLine ['bash', '-c', '"(export ENV_VAR=/my/path ; /path/to/build.sh)"']
}
}
}
Unfortunately, I have an error that says
Successfully started process 'command 'bash''
bash: (export ENV_VAR=/my/path ; /path/to/build.sh): No such file or directory
Now I'm sure the file exists and the specified paths are correct. Running this command manually in the terminal works.
Is there something in gradle that makes a bash -c like this not work? I can't think of another way to make an export like this otherwise.
Try without the extra quotes:
commandLine ['bash', '-c', '(export ENV_VAR=/my/path ; /path/to/build.sh)']
When you run that in the command line, your shell needs the quotes to pass to the command (which happens to be bash) as a single argument, but gradle is already doing that with that syntax, so bash is receiving literally one argument "(export ENV_VAR=/my/path ; /path/to/build.sh)" and since it does not recognize this as internal syntax, tries to run a command with this name.
Im exploring a bit on shell scripts and wrote this script. When the build command fails, it has to provide an error message and exit.
I know that exit 1 would close the current shell its running on. And the exit statement is within a curly braces (meaning that its executed on the same shell). But when this script is run as ./testScript.sh it stops executing test(), testTwo() is not called, and the terminal remains open.
While this is exactly the functionality i'm looking for, my question is why doesn't it close the terminal due to the exit 1; command? Does git bash creates a subshell by default when running a script?
I know its not because its been called within a function. I did try running the exit statement in script without a function, and it still doesnt close the terminal.
Any insights on the actual working of git bash and exit command would be highly useful.
Thanks!
# testScript.sh
function test() {
dotnet build -c Debug sample.csproj || { echo -e "${RED}=== Build Failed"; exit 1; }
}
function testTwo() {
echo "== executing test two function."
}
function all()
{
pushd .
test
testTwo
popd
}
all "$#"
Does git bash creates a subshell by default when running a script?
It's not a "subshell" as in ( ). The shell spawns a separate process that executes the command. The process does not inherit bash variables and functions, only inherits exported variables, i.e. it's not a subshell.
Do not use function name(), just name(). See https://wiki.bash-hackers.org/scripting/obsolete . Check scripts with shellcheck.net .
My shell command works when run in the terminal, but not in a Jenkins pipeline; when the pipeline runs test.sh, the shell is run, but the bug service is not. Why is that, and how can I fix this?
run.sh:
nohup /usr/local/java/1.8/bin/java -Dspring.cloud.config.profile=test -Dspring.cloud.config.uri=http://localhost:8888/ -cp /data/jcpt/service/service-account/jar/.:/data/jcpt/service/service-account/jar/lib/* com.caifubao.jcpt.account.app.AccountApplication >./logs/service-account.log &
Jenkins pipeline:
stage('UPLOAD') {
agent{node { label "TEST" }}
steps {
sh "./test.sh"
}
}
I have a bash shell script executed by Jenkins / Hudson. For some reason when I create a function, the output of that function is not logged back to the console. This is an example of my code:
EDIT!!! - this culprit here is SSH... Is there a way to force its output back to console?
perform_task()
{
ssh jenkins#192.168.100.5 pwd
}
echo "Starting a task";
perform_task || { echo "The Task Failed"; exit 1; }
The output in the console is:
"Starting a task"
if I move the commands outside of the function, I can see their output.
Help on this would be greatly appreciated!
I partially solved the problem by getting the script to echo the command:
#!/bin/bash -ex
This still hides the output of that command, but at least I have insights about what's being run
I just copied your function, added #!/bin/bash -e to the beginning of and pasted it into the "Execute Shell" of Jenkins.
It worked fine!
Is your bash executable actually located at /bin? What OS are you running the script on?
Building remotely on slave_1
[test] $ /bin/bash -xe /tmp/hudson1206345540964396738.sh
+ echo 'Starting a task'
Starting a task
+ perform_task
+ ssh slave_2 pwd
/home/jenkins
Finished: SUCCESS
Not sure about Jenkins or all that, but this worked for me:
perform_task()
{
ls -al
ps aux
pwd
}
echo "Starting a task"
perform_task || ( echo "The Task Failed" ; exit 1 )
add #!/bin/bash as first line of the file
The reason is the basic bourne shell(/bin/sh) does not support some of the features you use.