Different Methods of Executing A Bash Shell Script And Their Differences
This is the second article in the series "Linux Shell Scripting Tutorial". In the first article, we discussed about what a shell is, and the methods used to configure the shell or alter its behaviour using variables(or placeholders). We will be covering variables in great detail in the next article. We have also created our first shell script that prints a statement to the screen. Although we have executed the script using one of the common methods in that article, we are yet to cover other methods of executing a script..
If you are beginner in shell scripting, I highly recommend going through the first article in this series before proceeding with this one. You can access the first article by clicking the below link.
The small simple shell script that we wrote in the first article is below.
#!/bin/bash echo "This is our first script"
In order to execute the script, you need to first give executable permission to the script file using chmod +x <script> command. Let's now understand the different methods available to execute this shell script.
First Method to Execute a shell script:
This method is quite simple. Just prepend ./, to the script file name as shown below.
This is our first script
Second Method to Execute a Shell Script:
You can alternatively provide the absolute path of the script to execute it.
This is our first script
Third Method to Execute a Shell Script:
Or you can prepend the script file name with the command bash
# bash example_script.sh
This is our first script
Fourth Method to Execute a Shell Script:
You can even use sh command to execute the script(sh command)
# sh example_script.sh
This is our first script
Fifth Method to Execute a Shell Script:
There is yet another method to execute a shell script, as shown below.. ./example_script This is our first script
Let's analyse the very first method shown above. The first method is as simple as specifying the filename of the script itself. In fact the first and the second method are both identical.
The first method executes the script by using ./example_script, which means you are expected to be located in the same directory where the script is located.
. and .. have special meaning in linux operating system. "." stands for current directory & ".." stands for previous parent directory. So if you want to execute a script that is located in the current directory, then you can easily specify the script name by ./scriptfile
So if you want to execute a script in the parent directory of the current directory, you can execute it using ../scriptname
If you are not sure about how . and .. works in linux, then i would recommend reading the below article about inodes in linux. Basically . has an inode number of the current directory & .. has an inode number of the previous parent directory.
Please note the fact that the first . method (or .. method if you want to execute a script located in parent directory) will only work if you have given executable permission to the script file.
So . method, .. method, or even specifying the full absolute path of the script file (/path/to/example_script) are all doing the same thing(ie: its specifying the script file name. Either absolute or relative.)
Another important thing to understand here is...These methods of specifying absolute or relative path of the script will only work if you have shebang in the script.
What is shebang in a shell script?
The very first line in the example script shown above is called the shebang. #!/bin/bash
#! is a magic character with which our script starts. This magic character can be followed by spaces if required. But the next thing that follows the magic character will be considered as the interpreter of the script. #!/bin/bash specified in the first line means that "bash shell" will be used to interpret the script.
As mentioned in the first article of this tutorial series, there are other shells similar to bash. So if you have a shebang #!/bin/bash as the first line of the script, bash will be used to execute the script even if you are executing the script from any other shell.
Bash shell binary is generally inside /bin directory. That's why we are using #!/bin/bash. If you have bash shell binary somewhere else, you will have to use that absolute path of the binary.
The third method (shown previosly), specifies the interpreter in the command line itself. If you are specifying the interpreter in the command line while executing the script(ie: the third method above, /bin/bash example_script.sh OR /bin/bash /path/to/example_script.sh) then the shebang will be ignored. In this case the interpreter specified in the command line will be used instead.
Fouth method is exactly similar to the third method. This is because sh interpreter used in this method(sh example_script.sh) is most of the times symlinked to /bin/bash.
Symbolic linking in linux is very much similar to shortcuts in windows world. Using this method you can access one file from another location using another file name. Basically a linked file will always use the original file it is linked to.
[root@localhost ~]# cd /bin/ [root@localhost bin]# ls -l sh lrwxrwxrwx. 1 root root 4 Oct 7 2015 sh -> bash
You can clearly see from the above ls -l output that sh is symbolically linked to bash in the same directory(ie: /bin). So in Red Hat family of operating system, it does not matter whether you are executing /bin/sh example_script.sh OR /bin/bash example_script.sh, because both are one and the same thing.
In some Debian family of systems, you will see that /bin/sh is symlinked to /bin/dash(shown below.)
root@localhost:~# cd /bin/ root@localhost:/bin# ls -l sh lrwxrwxrwx 1 root root 4 Feb 19 2014 sh -> dash
So what is dash ?. Its a relatively new shell used by Debian family of distrubutions. DASH stands for Debian Almquist shell. Its actually light weight compared to bash shell.
DASH shell is faster compared to bash shell. This is the main reason, Ubuntu and other Debian family of distributions started the default symlink of /bin/sh to /bin/dash. This improved the system boot up time as well(as most of the boot up scripts used /bin/sh. As it is now symlinked to /bin/dash, the scripts will now use dash shell instead of bash.)
dash does not have much features when compared to bash shell. It was designed to be extremly light weight, and fast. So its recommended to test your script using /bin/dash to ensure that it works in dash as well.
The fifth method of executing the shell script is . ./example_script.sh.
Let's consider an example script to understand this method further. Our example script to understand this method is shown below(the script file is named test.sh).
root@localhost:~# cat test.sh #!/bin/bash variable1=somevalue variable2=anothervalue echo "This is a example script"
In the previous article we have learned that variables can be defined by using = operator in bash. We will be covering variables in more detail, in the next article of this series. For now, we have simply defined two variables(variable1 & variable2).
The values are somevalue and anothervalue1.
Let's now execute the script using ./ method(ie: the very first method that we learned in this article.)
root@localhost:~# ./test.sh This is a example script root@ip-10-12-2-73:~# echo $variable1 root@ip-10-12-2-73:~# echo $variable2
The script worked perfectly the way it is required. However the variables are no more accessible to us after the execution of the script.
This is because a new bash shell process is triggered to execute the script. That shell process gets terminated after the script completes execution.
The variables defined in the script is not at all accessible to the current bash shell from where we are executing it. This is why we are not able to see the values of variable1 and variable2 after the script completes execution.
If you want the script to be executed in the current shell process(using which you are triggering the script), you should then use the below method.
root@ip-10-12-2-73:~# . ./test.sh This is a example script root@ip-10-12-2-73:~# echo $variable1 somevalue root@ip-10-12-2-73:~# echo $variable2 anothervalue root@ip-10-12-2-73:~#
You can clearly see from the above example that the variables are still accessible to us even after the script has finished execution. So . ./scriptfile method can be used.
Continue To Next Article in This Tutorial Series: Understanding Variables in Bash Shell with Examples