No need for export when running functions in subshell
I have a msource.sh
script that will be sourced:
$ cat msource.sh
#!/usr/bin/env sh
echo "($BASHPID) - sourced ${BASH_SOURCE[0]}" &>> "$logfile"
# logfile is defined by the sourcing script
sourced_var="init sourced var with $BASHPID"
I have a script that will source msource.sh
and call a function
as is and in a subshell
. It will then call another script mscript2.sh
:
$ cat mscript.sh
#!/usr/bin/env sh
logfile=mout.out
rm -f $logfile
source msource.sh
mfun() {
echo "($BASHPID) in ${FUNCNAME}" &>> "$logfile"
echo " avar: '$avar'" &>> "$logfile"
echo " sourced_var: '$sourced_var'" &>> "$logfile"
}
avar="$BASHPID - init"
echo "[mfun] basic call" &>> "$logfile"
mfun
echo -e "\n[mfun &] subshell call" &>> "$logfile"
mfun &
wait $!
## call mscript2.sh
echo -e "\n[mscript2] background call" &>> "$logfile"
bash mscript2.sh &
wait $!
# call mscript2.sh after exporting variables
echo -e "\n[mscript2 &] export and background call" &>> "$logfile"
export logfile
export avar
export sourced_var
bash mscript2.sh &
wait $!
I have another script, mscript2.sh
that will be called by mscript.sh
, as seen above:
$ cat mscript2.sh
#!/usr/bin/env sh
[ -z "${logfile:+x}" ] && logfile=mout2.out || true
echo "($BASHPID) - executing ${BASH_SOURCE[0]}" &>> "$logfile"
echo " avar: '$avar'" &>> "$logfile"
echo " sourced_var: '$sourced_var'" &>> "$logfile"
I run everything:
$ bash script.sh
I get the following outputs:
$ cat mout.out
(13166) - sourced msource.sh
[mfun] basic call
(13166) in mfun
avar: '13166 - init'
sourced_var: 'init sourced var with 13166'
[mfun &] subshell call
(13174) in mfun
avar: '13166 - init'
sourced_var: 'init sourced var with 13166'
[mscript2 &] background call
[mscript2 &] export and background call
(13184) - executing mscript2.sh
avar: '13166 - init'
sourced_var: 'init sourced var with 13166'
and
$ cat mout2.out
(13179) - executing mscript2.sh
avar: ''
sourced_var: ''
So if I call the function as is, the pid
is the same and I don't need to source the msource.sh
nor to export the variables.
If I call the function in a subshell
, sourcing msource.sh
or exporting variables still is not required.
However, calling another script in asubshell
loses all the variables and they need to be exported, even the logfile which will be redefined otherwise.
Can someone clarify what's going on? What's the difference between executing a function in a subshell
and executing another script, that will also be launched in another subshell
? Why don't a parent process' variables have to be exported to be passed to a subshell
ed function?
Solution 1:
This is by design. This answer on Unix & Linux SE explains the issue. The main point is:
A subshell is […] different from executing a script.