I have a bash script that will look into the list of jobs running on the pipeline and search for 2 specific jobs.
If job A is a match, I want to run one part of the script that in some conditions will retry job B, if job B is found, do another part of the script that will retry job A.
In the solution I have now I do the search before I have the if statements, and that means both if conditions are met and the hole script will run. I don't know how to change my condition to avoid that... I am stuck so any suggestion would be awesome.
Here is a sketch of the script:
keyWord_A="jobA"
keyword_B="jobB"
# get the job_list with curl command
# search the job_list with jq for
# keyWord_A and store the result in match_A
# keyword_B and store the result in match_B
if [[ keyWord_A == match_A ]] ; then
# run this code
if [[ keyWord_B == match_B ]] ; then
# run this code
The solution was simpler than I thought... I can get from the CI the name of the curent job. This way, I can use the name of the current job in my if conditions and get the desired output from the script😊:
keyWord_A="jobA"
keyword_B="jobB"
if [[ keyWord_A == CI_job ]] ; then
# run this code
if [[ keyWord_B == CI_job ]] ; then
# run this code
Since you know if both job A and B are found, you can add conditions to your test, or use a simple else if in order to execute one, or the others, but not both:
if [[ keyWord_A == match_A ]] ; then
# run this code
elif [[ keyWord_B == match_B ]] ; then
# run this code
fi
Here, if both conditions are met, only the first if will be executed. Not both.
Related
(I'm not a linux guy) and I want to check the status of a service when its updating (takes about 10 minutes) to make sure it is successful. I use a function to run the status command and while loop as follow:
get_status() { echo ...my command runs here and return the statue; }
I simply can get the status like $(get_status). Now I want to see what is the status and take action:
while $(get_status) == "PENDING"; do echo retrying... && sleep 5; done
I've tried different ways like single/double brackets but cannot get the while comparison to work properly? Can anybody help please?
The while loop doesn't know anything about comparison tests. It only knows how to check the exit status of a command, and $(get_status) == "PENDING" is not a command. The brackets you want are for either a test command or a bash conditional expression command.
while test "$(get_status)" = "PENDING"; do
or
# [ is a synonym for test, with the added requirement that
# there be a final argument ] to complete the illusion of
# syntax.
while [ "$(get_status) = "PENDING" ]; do
or
while [[ $(get_status) == "PENDING" ]]; do
In the first two cases, = is preferred as the correct equality operator for test/[. In the last case, == may be used, and the quotes can be dropped around $(get_status) because no word-splitting or filename generation is performed on expansions in [[ ... ]]. (The quotes could be dropped around the literal word PENDING in all three cases, but could remain necessary for some right-hand arguments inside [[ ... ]] for reasons beyond the scope of this question.)
I have a config script where users can specify paths as variables in the header section. I want them to be able to use absolute paths, relative paths and variables (because this is actually called from another shell script from where they get the values for the variables). At the end of the script all the paths are written to a text file.
The challenge I have is that variables used within some of the paths can change in the middle of the script. I am having difficulties in re-evaluating the path to get the correct output.
### HEADER SECTION ###
DIR_PATH="$VAR1/STRING1"
InputDir_DEFAULT="$DIR_PATH/Input"
### END HEADER ###
...some code
if [[ some condition ]]; then DIR_PATH="$VAR2/STRING2"; fi
...more code
# $InputDir_DEFAULT needs re-evaluating here
InputDir=$(readlink -m $InputDir_DEFAULT)
echo $InputDir >> $FILE
When I do as above and 'some condition' is met, the return of 'echo' is the absolute path for $VAR1/STRING1/Input, whereas what I want it the abs path for $VAR2/STRING2/Input.
Below is an alternative, where I try to stop InputDir_DEFAULT being evaluated until the end by storing itself as a string.
### HEADER SECTION ###
DIR_PATH="$VAR1/STRING1"
InputDir_DEFAULT='$DIR_PATH/Input' #NOTE: "" marks have changed to ''
### END HEADER ###
if [[ some condition ]]; then DIR_PATH="$VAR2/STRING2"; fi
STRING_TMP=$InputDir_DEFAULT
InputDir=$(readlink -m $STRING_TMP)
echo $InputDir >> $FILE
This time 'echo' returns a mix of the evaluated variables and un-evaluated string: $VAR2/STRING2/$DIR_PATH/Input which (for me) looks like /home/ubuntu/STRING2/$DIR_PATH/Input. It's just the $DIR_PATH/ that shouldn't be there.
This feels like it should be relatively straightforward. I'm hoping I'm on the right path and that it's my use of "" and '' that's at fault. But I've tried lots of variations with no success.
When you initially set InputDir_DEFAULT, it is taking the currently set value for ${DIR_PATH}; even if you update ${DIR_PATH} later on, InputDir_DEFAULT will remain what it was set to earlier. To resolve this in your current script, you could set InputDir_DEFAULT again inside the if statement:
InputDir_DEFAULT=${DIR_PATH}/Input
Additionally, in your second attempt the single quoted value setting translates to the literal string value and does not expand to the variable's value:
InputDir_DEFAULT='$DIR_PATH/Input'
I would recommend referring to the "Quoting" section in the GNU Bash manual.
This is the solution I came to in the end. It's a mix of what was suggested by #ThatsWhatSheCoded and some other stuff to ensure that the user doesn't have to redefine variables anywhere other than in the header.
I expect there's a more elegant way of doing this, but this does work.
### HEADER SECTION ###
DIR_PATH_DEFAULT="$VAR1/STRING1"
InputDir_DEFAULT="$DIR_PATH_DEFAULT/Input"
### END HEADER ###
...some code
if [[ some condition ]]; then DIR_PATH="$VAR2/STRING2"; fi
### Checks whether $DIR_PATH_DEFAULT is used in any variables.
### If so and $DIR_PATH is different, will replace string.
### This will be done for all variables in a list.
if [[ ! "$DIR_PATH_DEFAULT" =~ "$DIR_PATH" ]]; then
for i in ${!var[#]}; do
var_def_val=${var[i]}_DEFAULT
STRING_TMP=${!var_def_val}
var_def=${var[$i]}_DEFAULT
if [[ $STRING_TMP == *"$DIR_PATH_DEFAULT"* ]] && [[ ! $var_def == "DIR_PATH_DEFAULT" ]]; then
STRING_TMP="${STRING_TMP/$DIR_PATH_DEFAULT/$DIR_PATH}"
eval "${var_def}=$STRING_TMP"
fi
done
fi
...more code
InputDir=$(readlink -m $InputDir_DEFAULT)
this is my first stackoverflow question, regarding bash scripting. I am a beginner in this language, so be kind with me.
I am trying to write a comparison script. I tried to store all the outputs into variables, but only the last one is stored.
Example code:
me:1234567
you:2345678
us:3456789
My code:
#!bin/bash
while read -r forName forNumber
do
aName="$forName"
echo "$aName"
aNumber="$forNumber"
echo "$aNumber"
done < "exampleCodeFile.txt"
echo "$aNumber"
For the first time, everything will be printed out fine. However, the second echo will only print out "3456789", but not all the numbers again. Same with $aName. This is a problem because i have another file, which i stored a bunch of numbers to compare $aNumber with, using the same method listed above, called $aMatcher, consisting:
aMatcher:
1234567
2345678
3456789
So if i tried to run a comparison:
if [ "$aNumber" == "$aMatcher" ]; then
echo "match found!"
fi
Expected output (with bash -x "scriptname"):
'['1234567 == 1234567']'
echo "match found!"
Actual output (with bash -x "scriptname"):
'['3456789 == 3456789']'
echo "match found!"
Of course my end product would wish to list out all the matches, but i wish to solve my current issue before attempting anything else. Thanks!
When you run your following code
aNumber="$forNumber"
You are over-writing the variable $aNumber for every line of the file exampleCodeFile.txt rather than appending.
If you really want the values to be appended, change the above line to
aNumber="$aNumber $forNumber"
And while matching with $aMatcher, you again have to use a for/while loop to iterate through every value in $aNumber and $aMatcher.
I have a .sh file in which I have written the following function. The command that calls this function will have the arguments- file1.war, file2.war ... fileN.war and other arguments.
I want to do a certain operation to the .war files and something else for the arguments after it. So I have written a while loop that will run till the arguments are .war files, and when an argument is encountered without .war extention, it will exit the loop and run the code below it for the rest of the arguments.
Here is the function in .sh file :
copyWarFiles()
{
downloadFileName=$1
shift 1
extn=".war"
while [ condition ]
do
log "war file $downloadFileName .."
#some operation..
downloadFileName=$1
shift 1
done
#operations for the rest of the arguments...
}
What should I give as condition that will return true if $downloadFileName ends with .war? I tried giving
$downloadFileName==*".war" (following the accepted answer in this )
and I also tried this :
`test "${downloadFileName#*$extn}" != "$downloadFileName"`
(following the accepted answer here) where extn is another variable I declared and assigned to .war.
But in both the cases, I see that it never enters the while loop. I think I have gone wrong with the syntax or something. Thank you for your help in advance.
What should I give as condition that will return true if $downloadFileName ends with ".war"? I tried giving $downloadFileName==*".war" […]
Bash, unlike typical programming languages, doesn't recognize == as a special operator; it's just yet another argument to the [ command. So you need to set it off with spaces.
Also, the [ command doesn't support having a pattern on the right-hand-side of ==; you need to use the special [[ ... ]] notation.
So:
while [[ $downloadFileName == *".war" ]]
Note, though, that the double-quotes around .war don't actually have any effect: none of the characters in .war are special characters that need to be quoted. Conversely, it's a best practice to always put variable expansions in double-quotes, in case the variables contain special characters. ([[ actually negates most of the problematic behaviors, but it's just a good habit to be in.)
So:
while [[ "$downloadFileName" == *.war ]]
Why not just:
check=`echo $downloadFile | grep '\.war'`
if [ -n "$check" ]; then
echo $downloadFile ends in .war
fi
Can anyone tells me what does this script means found in a .sh file:
[ ! -n "$T_R" ] && echo "Message Appear" && exit 1;
Edit: Correcting for misinformation pointed out by tripleee
The brackets [ ]
are an alias for 'test', which tests whether a condition is met. Not to complicate matters, but do note that this is discrete from the the bash shell keyword [[ ]] (Thanks, tripleee for clearing that up!). See This post for further details. These days, most people seem to use the latter due to its more robust feature set.
Between the brackets, the script is testing to determine whether the variable "$T_R" is an empty string.
The -n operator returns true if the length of the string passed to it as an argument is non-empty.
The ! inverts the case (the test succeeds if the result is not
true). So in this case, test suceeds (returns 0) if the length of
the string variable "$T_R" is **not non-zero ** (i.e. if the
variable is an empty-string, or is non-existant).
The double-ampersand, && operator means only execute the subsequent code in the event of success, so the message "Message Appear" will only be echoed in the event the test succeeds (again, if "$T_R" is empty or unset).
Finally, the && exit 1 says to exit returning status 1 after successfully echoing the Message Appear message.
The bash and test man pages are extremely helpful on all of these topics and should be consulted for further details.
The chained && is a common short-circuit idiom.
Instead of writing
if true; then
if true; then
echo moo
fi
fi
you can abbreviate to just true && true && echo moo.
echo will usually succeed so true && echo moo && exit 1 will execute both the echo and the exit if true succeeds (which obviously it always will).
(There are probably extreme corner cases where echo could fail, but if that happens, you are toast anyways so I don't think it makes sense to try to guard against those.)
The [ is an alias for test which is a general comparison helper for shell scripts (in Bash, it's even a built-in). test -n checks whether a string is non-empty.
! is the general negation operator, so it inverts the test to checking for an empty string.
(This is slightly unidiomatic, because there is a separate test -z "$T_R" which checks specifically for the string being empty.)