Luke Ireland
Luke Ireland

Reputation: 33

Global variable not changing in Bash

I'm having trouble with the below code. runFail is not being changed and can't be accessed at the end resulting in an error.

runFail=1
pylint_run(){
if [ ! -f "$root/$1/$2/__init__.py" ]; then
    cd "$root/$1/$2" || exit
    pylintOutput=$(find . -iname "*.py" -print0 | xargs -0 pylint)
else
    pylintOutput=$(pylint "$root/$1/$2")
fi

echo "${pylintOutput}"
# This then scans for the line in the output containing the score
scoreLine=$(grep rated <<< "$pylintOutput")
IFS=" " read -r -a array <<< "$scoreLine"
# The score is the 6th column in that line
scoreVal=${array[6]}
# Snips the "out of ten" of the end
scoreVal=${scoreVal///10/}
# Sees if the pylint actually ran successfully and produced a score
if [ -z "$scoreVal" ]; then
    echo "Pylint failed to run"
    runFail=0
fi
# Checks if the score is good enough
# If not, it will say the score is too low and indicate a fail.
if (( $(echo "$scoreVal < 8" | bc -l) )); then
    echo "Score is less than 8 for '$2': FAIL"
    runFail=0
fi
echo "=================END OF TEST================"
}
# pylint_run [path/containing/scriptFolder] [scriptFolder]
# The tee command is then used to produce a report to be used as an 
artifact
pylint_run "gocd-helper-scripts/gocdhelp/" "gocdhelp" | tee gocdhelp-
report.txt
pylint_run "metrics-gocd/" "metrics" | tee metrics-report.txt
echo $runFail
if [[ $runFail = 1 ]]; then
    echo "Score is more than 8 for each tool: PASS"
    exit 0
else
    exit 1
fi

It returns 1 instead of 0 at the end and passes when it reaches the code to tell me it's failed.

echo $runFail
if [[ $runFail = 1 ]]; then
    echo "Score is more than 8 for each tool: PASS"
    exit 0
else
    exit 1
fi

Here echo should print 0 (It currently prints 1) and therefore it should exit 1.

Let me know if you need any more details, I'm bewildered and have asked colleagues what's up with my code I've no idea as I've tried the same thing in a bash shell and it works fine.

Realistically, all I'm doing is setting a variable, making a function to change that variable, calling that function and testing that the variable has changed. It clearly gets to the code that changes the variable and yet fails to change the variable globally even though it should be fine.

Similar to this: Value of global variable doesn't change in BASH

Removing the tee pipe from the function runs solves the problem but I'm confused why piping would affect the scopes in this way.

Bash version is 3.2.57 and I'm running in Terminal "./pylint-checker.sh"

Upvotes: 0

Views: 856

Answers (2)

Eric Renouf
Eric Renouf

Reputation: 14490

You're calling your function in a pipe:

pylint_run "gocd-helper-scripts/gocdhelp/" "gocdhelp" | tee gocdhelp-report.txt

that means that both sides are run in a subshell. Subshell's are not able to change the value of the parent environment, so pylint_run called that way cannot change the global variable.

You can use redirection to achieve the same effect without the subshell for the pylint_run process like

pylint_run "gocd-helper-scripts/gocdhelp/" "gocdhelp" > >(tee gocdhelp-report.txt)

which runs tee in a process substitution shell and leaves pylint_run in the parent's shell so it can modify those variables.

Upvotes: 1

Luke Ireland
Luke Ireland

Reputation: 33

I was piping using

| tee filename.txt

I needed to use

> >(tee filename.txt)

Upvotes: 0

Related Questions