4

I have three scripts:

  • My main script: script1.sh
  • Script having function 'logger': script2.sh
  • Script calling the function 'logger': script3.sh

Contents of my script:

script1.sh:

echo"This is script1"
source script2.sh
sh script3.sh
echo "End of script1"

script2.sh:

logger(){
 echo "The calling script name is $BASH_SOURCE"
}

script3.sh:

echo "Script3 start"
logger
echo "End of script3"

When I run sh script1.sh, I want the logger function to print

script3.sh

because that is the script which is calling the function. But instead, it is printing

script2.sh

Is there any way to do this?

6
  • 2
    Pass the name of the script which is calling logger via a parameter? Commented Feb 22, 2018 at 18:17
  • In the beginning, I thought so. But I do not want to hardcode it. Commented Feb 22, 2018 at 18:19
  • this is unlikely. you did not show everything. in bash, functions are not exportable, therefore sourcing script2 in script1 won't make logger visible in script3. you must have done something in script3. Commented Feb 22, 2018 at 18:20
  • 1
    It wouldn't be hardcoding, simply pass $0 as the argument when calling logger. Commented Feb 22, 2018 at 18:20
  • Is running sh script1.sh just prints script2.sh? Am sure it would have printed more. Post the full content Commented Feb 22, 2018 at 18:21

1 Answer 1

6

As I commented, your scripts won't even do what you claimed it does:

this is unlikely. you did not show everything. in bash, functions are not exportable, therefore sourcing script2 in script1 won't make logger visible in script3. you must have done something in script3.

Indeed, copying your code and run it locally indicates what's happening:

$ ./script1.sh 
++ echo 'This is script1'
This is script1
++ source script2.sh
++ sh script3.sh
+ echo Script3 start
Script3 start
+ log
script3.sh: 3: script3.sh: log: not found
+ echo End of script3
End of script3
++ echo 'End of script1'
End of script1

notice the command not found error, which is exactly what I thought.


In fact, if you check bash's manual properly, there is a proper way of achieving what you want exactly:

BASH_SOURCE

An array variable whose members are the source filenames where the corresponding shell function names in the FUNCNAME array variable are defined. The shell function ${FUNCNAME[$i]} is defined in the file ${BASH_SOURCE[$i]} and called from ${BASH_SOURCE[$i+1]}.

read it carefully, it says function defined from ${BASH_SOURCE[$i]} and called from ${BASH_SOURCE[$i+1]}. In this case, logger resides in ${BASH_SOURCE[0]}, and the caller simply resides in ${BASH_SOURCE[1]}.

therefore, change your script2 to following shall work:

$ cat script2.sh 
log(){
 echo "The calling script name is ${BASH_SOURCE[1]}"
}

(except I changed the function name so that it does not collide with my other shell tool.)


demo:

$ ./script1.sh 
This is script1
Script3 start
The calling script name is ./script3.sh
End of script3
End of script1

indeed does the work.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.