TLDR
# Runs the hi.sh script within the parent process.
# - parent process env variables are affected.
source /tmp/hi.sh
# Creates child process to run hi.sh script in.
# - parent process env variables are not affected
/tmp/hi.shPID: Process ID
PID
Details
Lets say you have a script /tmp/hi.sh
Which has the following ($$ prints pid)
echo "My PID: $$"If you run it as
/tmp/hi.shYou will get PID that is different from parent process.
But if you run it as
source /tmp/hi.shYou will get the same PID as your parent process.
Example code:
echo 'echo pid in /tmp/hi.sh: $$' > /tmp/hi.sh
chmod +x /tmp/hi.sh
echo "PID of parent process is: $$"
echo "Running /tmp/hi.sh"
/tmp/hi.sh
echo "Source /tmp/hi.sh"
source /tmp/hi.shEnv Variables example
Env Variables. Example: source ./scratch2.sh (does change ENV variables)
Lets say you have two files scratch.sh and scratch2.shScratch Shell:
main() {
SOME_ENV="Scratch1 value"
echo "Running Scratch1, PID: $$"
echo.green "SOME_ENV: ${SOME_ENV:?}"
echo "Starting source:"
echo "--------------------------------------------------------------------------------"
source "${SCRATCH_SHELL2:?}"
echo "--------------------------------------------------------------------------------"
echo "Finished source."
echo.green "SOME_ENV: ${SOME_ENV:?}"
}
main "${@}" || exit 1Scratch 2 Shell:
main() {
echo "Running Scratch2, PID: $$"
SOME_ENV="some Scratch2 value"
}
main "${@}" || exit 1When you run scratch 1 shell since you are using source env variables are affected leading to output:
Running Scratch1, PID: 27508
SOME_ENV: Scratch1 value
Starting source:
--------------------------------------------------------------------------------
Running Scratch2, PID: 27508
--------------------------------------------------------------------------------
Finished source.
SOME_ENV: some Scratch2 valueEnv Variables, Example: ./scratch2.sh (does not change parent ENV variables)
# scratch.sh:
main() {
SOME_ENV="Scratch1 value"
echo "Running Scratch1, PID: $$"
echo.green "SOME_ENV: ${SOME_ENV:?}"
echo "Starting source:"
echo "--------------------------------------------------------------------------------"
"${SCRATCH_SHELL2:?}"
echo "--------------------------------------------------------------------------------"
echo "Finished source."
echo.green "SOME_ENV: ${SOME_ENV:?}"
}
main "${@}" || exit 1# scratch2.sh:
main() {
echo "Running Scratch2, PID: $$"
SOME_ENV="some Scratch2 value"
echo.green "SOME_ENV: ${SOME_ENV:?}"
}
main "${@}" || exit 1Output:
Running Scratch1, PID: 27577
SOME_ENV: Scratch1 value
Starting source:
--------------------------------------------------------------------------------
Running Scratch2, PID: 27578
SOME_ENV: some Scratch2 value
--------------------------------------------------------------------------------
Finished source.
SOME_ENV: Scratch1 valueNotice even though we set env variable in scratch2, the change was not reflected from perspective of scratch1 since it was a separate process.
Source Further Dive
Source to pipe
Source to Pipe
Piping output of source makes it so ENV variable changes are not reflected in parent process.
When you pipe you create a sub-process. Hence, you env variable changes would not propagate up to parent, since they were only changed in the child process.
Link to originalExample Code
# scratch1.sh main() { SOME_ENV="Scratch1 value" echo "SOME_ENV: ${SOME_ENV:?} (in Scratch1) (PID: $$, BASHPID: $BASHPID)" echo "--------------------------------------------------------------------------------Starting source" source "${SCRATCH_SHELL2:?}" | tee /tmp/out echo "--------------------------------------------------------------------------------Finished source" echo "SOME_ENV: ${SOME_ENV:?} (in Scratch1) (PID: $$, BASHPID: $BASHPID)" } main "${@}" || exit 1# scratch2.sh main() { SOME_ENV="Scratch2-value" echo "SOME_ENV: ${SOME_ENV:?} (in Scratch2) (PID: $$, BASHPID: $BASHPID)" } main "${@}" || exit 1