Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash script - global variable becomes empty when function exits

Information

I have an issue where I want to return a value (array or string) from a bash script function.

I already know the following :

  • A bash script called outputtext=$(functionName) runs in a sub-shell
  • A bash function does not act the same as in 'normal' programming languages, it only kind of returns the text output
  • A bash function can only return an error code as status and can be access via $?

Test Script

A test script I created now to demonstrate what I want to do, and why I can't use output directly

   #!/bin/bash
   declare GLOBAL_VAR
   function callThis(){
      local output="==========================================\n"
      output="$output [START callThis()]\n"
      # For demonstration only - error 5 might be a built-in bash error code, but if caller
      # expects 0/5 they can be handled
      local statusCode=5
      # This variable is empty as soon as it exits the function
      GLOBAL_VAR="Some array value OR text output into GLOBAL_VAR"
      # Because the script has alot of text (echo'd/printf) output, and the function
      # calculates a result (array), I would like to have it as a RESULT
      # for another function.
      output="$output This is some output that will be sent to caller.\n"
      output="$output Test to see if GLOBAL_VAR is assigned:\n"
      output="$output '$GLOBAL_VAR'\n"
      output="$output [END callThis()]\n"
      output="$output ==========================================\n"
      echo -e $output
      return $((statusCode))
   }

   function startHere(){
      OUTPUT=$(callThis)
      STATUS_RESULT=$?
      echo -e "[Text output : $OUTPUT\n]"
      echo -e "[Status Code : $STATUS_RESULT\n]"
      echo -e "[Global VAR in startHere():\n'$GLOBAL_VAR']"
      if [ "$STATUS_RESULT" -eq 5 ]; then
         echo "Success! Status code $STATUS_RESULT found!"
      fi
   }

   echo -e $(startHere)
   echo "Global VAR is now (outside functions): '$GLOBAL_VAR'"

Result above

I am aware echo -e does not give exactly this exact output for this function, besides this topic

   [Text output :
   ========================================== 
   [START callThis()]
    This is some output that will be sent to caller. 
   Test to see if GLOBAL_VAR is assigned: 
   'Some array value OR text output into GLOBAL_VAR' 
   [END callThis()]
   ========================================== ] 
   [Status Code : 5 ] 
   [Global VAR in startHere(): '']
   Success! Status code 5 found!
   Global VAR is now (outside functions): ''

The script above shows most of the things I want to do: I have functions that are quite long and have calculated results array, and handling a exit code.

QUESTION

Since it is a sub-shell created when calling $(startHere), or even within startHere(), the GLOBAL_VAR is empty as soon as callThis() exits.

I do not know how to proceed because I need the value for another function. How can I solve this?

SOLUTION

See @mjrezaee's solution for the example I provided.

It turns out that I do not always need to use sub-shell $() for everything, most of the time call the function directly, and the output, global variables, and even the error code (return code) are available. (I do not work with bash scripts alot). Based on the advise I adapted my 400+ line script and were able to use global variables easily.

like image 759
CvRChameleon Avatar asked Dec 19 '25 04:12

CvRChameleon


1 Answers

As i said in comments, you can use simple function calling, simple changes to your test code will be as follow:

   #!/bin/bash
   declare GLOBAL_VAR
   function callThis(){
      local output="==========================================\n"
      output="$output [START callThis()]\n"
      # For demonstration only - error 5 might be a built-in bash error code, but if caller
      # expects 0/5 they can be handled
      local statusCode=5
      # This variable is empty as soon as it exits the function
      GLOBAL_VAR="Some array value OR text output into GLOBAL_VAR"
      # Because the script has alot of text (echo'd/printf) output, and the function
      # calculates a result (array), I would like to have it as a RESULT
      # for another function.
      output="$output This is some output that will be sent to caller.\n"
      output="$output Test to see if GLOBAL_VAR is assigned:\n"
      output="$output '$GLOBAL_VAR'\n"
      output="$output [END callThis()]\n"
      output="$output ==========================================\n"
      echo -e $output
      return $((statusCode))
   }

   function startHere(){
      # OUTPUT=$(callThis)
      callThis
      STATUS_RESULT=$?
      # echo -e "[Text output : $OUTPUT\n]"
      echo -e "[Status Code : $STATUS_RESULT\n]"
      echo -e "[Global VAR in startHere(): '$GLOBAL_VAR']"
      if [ "$STATUS_RESULT" -eq 5 ]; then
         echo "Success! Status code $STATUS_RESULT found!"
      fi
   }
   # echo -e $(startHere)
   startHere
   echo "Global VAR is now (outside functions): '$GLOBAL_VAR'"

output:

==========================================
 [START callThis()]
 This is some output that will be sent to caller.
 Test to see if GLOBAL_VAR is assigned:
 'Some array value OR text output into GLOBAL_VAR'
 [END callThis()]
 ==========================================

[Status Code : 5
]
[Global VAR in startHere(): 'Some array value OR text output into GLOBAL_VAR']
Success! Status code 5 found!
Global VAR is now (outside functions): 'Some array value OR text output into GLOBAL_VAR'

also this can be helpful as an explanation for other methods for using sub-shell

like image 173
Javad Rezaei Avatar answered Dec 21 '25 21:12

Javad Rezaei



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!