Learn Difference Between Sourcing and Forking in Bash

The main focus of this article is to clearly understand what happens when you run the script vs source the script in bash. First, we will clearly understand how the program is submitted when you call the script in different ways.

NOTE: creating the script with an extension doesn’t matter. Script will run fine even without extensions.

Basically, every script starts with a line called a shebang(#!). The Hash symbol in bash will be interpreted as comments but shebang has a special meaning. It tells bash to submit the program in whatever interpreter you mentioned in shebang.

Below are a sample program and I am specifying bash as my interpreter.

$ cat >> Hello_World.sh
#!/usr/bin/env bash
echo "Hello world"

$ chmod +x Hello_world.sh

Now to run the script, you can do it in two ways.

  • Use a relative path to call the script. Move to the directory where the script is present and run ./Hello_world.sh.
  • Use the absolute path to call the script. From anywhere in the file system type the full path to the script.
$ ./Hello_world.sh
$ pwd
$ /home/karthick/Hello_world
Run Shell Script
Run Shell Script

Now let’s see what happens when you try to submit your program without shebang. In absence of shebang, the program will be submitted to whatever current shell you are running with, In my case, it is Bash (/bin/bash).

Let me demonstrate an example. I am creating a python script without shebang and when I call the program, bash doesn’t know that it should submit this program to the python interpreter instead it will run the program in the current shell.

$ cat > run-py.py
echo $SHELL
print("Hello world")

$ chmod +x run-py.py
$ ./run-py.py
Wrong Interpreter in Script
Wrong Interpreter in Script

In this case, you can call the program by mentioning on which interpreter it should be submitted to or just add the shebang line which is always recommended.

# which python3
$(which python3) /home/karthick/run_py.py
Call Script With Interpreter
Call Script With Interpreter

Now that you know how to call the script, the next step would be to understand what happens when we call the script. When you invoke the script as shown in the above examples it will create a child process (forking) and the script will be submitted to the child process. I ran a sample script that will just run the following command and shows the script is submitted to a child process.

$ ps -ef --forest | grep -i bash
Forking
Forking

There can be multiple child processes as a part of the script and that depends on our code. It is to be noted that environmental variables created by subscript will be dropped once it gets finished. A child process can access variables created by the parent process by exporting them. But parent process cannot access the variables created by the child process.

Take a look at the below articles to understand more about how variables work and how to export the variables.

Sourcing the Script

Source” is a shell built-in command that reads the file passed as an argument to it and runs the code in the current shell environment. An appropriate use case that you use mostly is modifying your configuration in .bashrc or .bash_profile and reloading the changes using the source command.

$ type -a source
Shell Builtin Command
Shell Builtin Command

There are two syntactic ways to run the source command. You can choose anyone from two syntaxes and it is of personal choice.

$ source FILE_NAME [ARGUMENTS]
$ . FILE_NAME [ARGUMENTS]

Let me demonstrate how the source actually works. I am going to create two shell scripts. The first script (Module.sh) is going to hold some variables and functions. The second script (Main.sh) is going to print the variable and call the function.

File Module.sh.

#!/usr/bin/env bash

VAR1=$(echo "Welcome to $1")

function f1(){
  echo “Function f1 is called”
}

File Main.sh.

#!/usr/bin/env bash

echo $VAR1
f1
Sample Script Codes
Sample Script Codes

Set the execution permission for the script and call the main script “main.sh”. Now, this script will try to find the function f1 and variable VAR1 in the current shell environment and will fail with the command not found.

$ bash main.sh
Before Sourcing Script
Before Sourcing Script

Now let’s run the source command inside the script which will load the variable and functions into the current shell environment and that will be accessible by “main.sh”.

File Module.sh.

#!/usr/bin/env bash

VAR1=$(echo "Welcome to $1")

function f1(){
  echo "Function f1 is called"
}

File Main.sh.

#!/usr/bin/env bash

source module.sh Tecmint
echo $VAR1
f1
Sample Script Codes with Sourcing
Sample Script Codes with Sourcing

Now run the script again and see.

$ bash main.sh
After Sourcing Script
After Sourcing Script

The source is very useful in bash to follow the modular programming approach in creating our shell scripts. We can break our code into smaller modules and can be used in many programs. In these ways, we can follow the DRY (Don’t Repeat Yourself) principle.

That’s it for this article. We have briefly discussed the difference between sourcing and forking in bash. Go through the article and share your valuable feedback with us.

Hey TecMint readers,

Exciting news! Every month, our top blog commenters will have the chance to win fantastic rewards, like free Linux eBooks such as RHCE, RHCSA, LFCS, Learn Linux, and Awk, each worth $20!

Learn more about the contest and stand a chance to win by sharing your thoughts below!

Karthick
A passionate software engineer who loves to explore new technologies. He is a public speaker and loves writing about technology, especially about Linux and open source.

Each tutorial at TecMint is created by a team of experienced Linux system administrators so that it meets our high-quality standards.

Join the TecMint Weekly Newsletter (More Than 156,129 Linux Enthusiasts Have Subscribed)
Was this article helpful? Please add a comment or buy me a coffee to show your appreciation.

Got Something to Say? Join the Discussion...

Thank you for taking the time to share your thoughts with us. We appreciate your decision to leave a comment and value your contribution to the discussion. It's important to note that we moderate all comments in accordance with our comment policy to ensure a respectful and constructive conversation.

Rest assured that your email address will remain private and will not be published or shared with anyone. We prioritize the privacy and security of our users.