Jenkins Execute shell if then statement fails with `Bad substitution` - bash

I need an if statement in Jenkins Execute Shell, but it always fails on the same line, regardless of what’s there.
I’m trying to do something like this:
if [ " ${BuildVariants[*]} " =~ " VariantA " ]; then
# fails on this line even this line is just a comment
variant_config=""
fi
it fails when I try to assign a variable there, fails when I try to echo "anything", fails even on comment (as example above)
Reason: Bad substitution
Note: There's anything specified in Configure System, so it should be using default Bash.
What the problem might be?

I don't think =~ works inside of [ ... ] -- use [[ ... ]] instead.
Shellcheck is a great tool for find these types of things; it would show that you've hit SC2074.
re:
fails on this line even this line is just a comment
You cannot have an "empty" then block. You can use just : as code to be executed:
if [[ "$foo" == "bar" ]]; then
:
fi
Next idea: get your code to run in a shell script, then put the code up in Jenkins. You will probably need to mock up some of the Jenkins-supplied input to do that, but it takes one more moving part out of the equation. If the code runs from the command line and doesn't in Jenkins, then you need to start looking for Jenkins-specific causes, like maybe it's being run in a csh instead of Bash (I see you mention this specific possibility already, but maybe there's something else like it -- I don't know Jenkins, sorry).

So the problem was that I supposed Jenkins was giving me an array, but it was giving me a string. (I used with Extended Choice Parameter, with multiple choices).
So the condition should've been [[ "$BuildVariants" == *"VariantA"* ]].

Related

bash rematch as chroot

I'm using this in my script and it works fine on my root server and on some others I tested.
But there's a problem when using it on my webhosting (Hosted Plesk): The chrooted shell, it doesn't output anything. Just quits. My webhoster said I need to use the absolute paths, but I dont know how to apply this on the bash rematch.
#!/bin/bash
str='"<result="Abc1234" />"'
regex='<result="([0-9a-zA-Z._-/:]*)" />'
[[ $str =~ $regex ]] && echo ${BASH_REMATCH[1]}
(My first post here, sorry if I forgot something or misformatted this whole post)
In the discussion below the question it turned out that the issue is related to different default locales on the servers. Make sure that you are running the command with the right locale:
LANG=en_US.UTF-8 bash script.sh
(en_US.UTF-8) turned out to be the right locale in your case.
PS: Please also keep in mind what Ondrej K. says.
Instead of:
regex='<result="([0-9a-zA-Z._-/:]*)" />'
say:
regex='<result="([0-9a-zA-Z._/:-]*)" />'
- is moved to where it no longer can be considered meaning a range.
Actually I am a surprised it worked on the other system. I've replaced && echo ${BASH_REMATCH[1]} with ; echo $? (this was another possible debugging step) and was getting 2 which according to man bash means "syntactically incorrect regular expression".
If this doesn't help. Than we must be seeing different reason, way our shell interpret the script, but in any case printing the return status could then be the next step to take.

Why is executing a ruby command on bash to command file not working?

Code from .command file:
cd "$(dirname "$0")"
g1=Hi-Lo
echo Welcome to Ruby_Games! So far, you can play $g1.
echo What game would you like to play?
read game_choice
if [$game_choice == $g1]
then
ruby Hi-Lo.rb
fi
Output:
Welcome to Ruby_Games! So far, you can play Hi-Lo.
What game would you like to play?
Hi-Lo
/Users/Abbas/Desktop/Ruby_Games/LAUNCHER.command: line 6: [Hi-Lo: command not found
logout
So what exactly is going wrong? Thanks
I believe you need double quotes in your if statement
Similar to example 6.4 here: http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-6.html
cd "$(dirname "$0")"
g1=Hi-Lo
echo Welcome to Ruby_Games! So far, you can play $g1.
echo What game would you like to play?
read game_choice
if [ "$game_choice" = "$g1" ]
then
ruby Hi-Lo.rb
fi
You need spaces between each element of the test (aka [) command. That is, you need a space between [ and $game_choice, between $game_choice and =, etc. Also, as #GregHNZ pointed out, you should use double-quotes around variable references, in case they contain spaces or certain other shell metacharacters. Finally, == in a test expression is a bash extension; use = instead, and it'll work in more basic shells as well. Result:
if [ "$game_choice" = "$g1" ]
Spaces are important delimiters in shell syntax; there are places they're required and places they're forbidden, and very very few places where they're optional. In many languages, you can add or remove spaces to make the code more readable, but that's not the case in shell.
BTW, I recommend using shellcheck.net; it does a pretty good job of spotting errors like this. Actually, it points out a couple I didn't think of: you should add a shebang line to the beginning of the script, and using cd without checking for an error risks the rest of the script running in an unexpected directory. So you should use something like this:
#!/bin/bash
cd "$(dirname "$0")" || {
echo "Error cd'ing to the script's directory" >&2
exit 1
}

Can't check checksum in bash --- apparently, wrong syntax?

I have this bit of code, that is supposed to call reload if current file ($1) is changed:
thehash="`cksum $1`"
while true
do
curhash="`cksum $1`"
if "$curhash" -ne "$thehash"; then
reload
fi
...
done
tl;dr: it doesn't work.
Since I am not very experienced with bash, I can't figure out what did I do wrong. I get this error:
58003725 834183 main.pdf: command not found
Apparently, bash is trying to execute curhash? How do I fix this?
You need brackets around your condition in if or to use the test command, so it should be
if [[ "$curhash" != "$thehash" ]]; then
and note that -ne is for integer comparison, != is for string comparison
Without the [[ or test the variable gets expanded and that becomes a command to run, which is why it was trying to execute the output of cksum: the content of curhash was being treated as a command.
Also, as #Sundeep mentioned the more often preferred way to get the output from the subshell is to use $(...) instead of the backticks. here is a good answer talking about that

Bash script giving me a different result on reboot?

I worked on a Bash script for the last day or so and running and debugging it directly on the shell.
The final script will be executed when the Ubuntu server gets rebooted.
I have started testing this, but my script gives me a different result then what I was expected.
I have narrowed it down to an "or condition" and rewrote a more simpler script to test this anomaly:
A call to this script has been made in /etc/rc.local, with a redirection of the output to a log file (log/reboot.log).
I have this in my script (as a test):
#!/bin/bash
YESTERDAY=20131103
SYS_DATE=20131104
LAST_START=20131104
if [[ $LAST_START = $YESTERDAY || $LAST_START = $SYS_DATE ]];
then
echo "is equal"
else
echo "is not equal"
fi
Executing in the shell I get "is equal" (the right answer). After the reboot in the log I get "is not equal".
Could someone tell me why?
I am guessing here,
But do you realize your /bin/sh is not your SHELL.
In UBUNTU and Debian, /bin/sh is DASH, your login shell is BASH.
So it might be related to your syntax of [[ ]] which is BASH.
Did you right in your top of the script:
#!/bin/sh
or
#!/bin/bash
[[
The [[ builtin is a bashism, and has somewhat better-defined semantics
than [ (a.k.a. test). However, it is still quite reasonable to use [
instead, and portable scripts must do so. Note that argument handling
is not quite the same; as above, use = rather than ==.
See here:
https://wiki.ubuntu.com/DashAsBinSh
the right way to do stuff here
The best solution would be actually to put your script in /etc/init.d and link it to run level 6. Which is the run level executed when rebooting. You should consider reading man 8 init when you have got some spare time. It will help you understand how your system is starting and shuting down.

Trouble Passing Parameter into Simple ShellScript (command not found)

I am trying to write a simple shell-script that prints out the first parameter if there is one and prints "none" if it doesn't. The script is called test.sh
if [$1 = ""]
then
echo "none"
else
echo $1
fi
If I run the script without a parameter everything works. However if I run this command source test.sh -test, I get this error -bash: [test: command not found before the script continues on and correctly echos test. What am I doing wrong?
you need spaces before/after '[',']' chars, i.e.
if [ "$1" = "" ] ; then
#---^---------^ here
echo "none"
else
echo "$1"
fi
And you need to wrap your reference (really all references) to $1 with quotes as edited above.
After you fix that, you may also need to give a relative path to your script, i.e.
source ./test.sh -test
#------^^--- there
When you get a shell error message has you have here, it almost always helps to turn on shell debugging with set -vx before the lines that are causing your trouble, OR very near the top your script. Then you can see each line/block of code that is being executed, AND the value of the variables that the shell is using.
I hope this helps.

Resources