The shebang line tells the operating system which interpreter to use to parse the remainder of a file or a script. When we go through different scripts, we’ll often see that the shebang line is different between these scripts.
In this tutorial, let’s discuss some of the types of shebang lines commonly used. We’ll look at what causes the difference in shebang interpreters and determine their suitability.
2. Shebang Directive
The shebang directive is the first line in any Linux shell script. It starts with a character sequence consisting of a hash followed by an exclamation mark (#!).
After the shebang, we add additional parameters. We must add the complete path to the interpreter(an executable binary file or program), followed by optional arguments. The shebang line has the following syntax:
Having a white space after the shebang sequence is optional:
#! /path/to/interpreter arg1 arg2
The presence of a shebang indicates that a file is executable. When the shebang line is missing, #!/bin/bash is the default shell used to execute the file.
We can override and ignore the default shebang line set within the script. We can do this via the command line. For example, in case #!/bin/ksh is the interpreter set in backup.sh, we can override it and use the bash shell to run the file:
$ bash backup.sh
We shouldn’t override the shebang line set within a script unless we’ve got a valid reason to disregard the one set. This is because overriding can result in inconsistent output, which may differ from the expected one.
#!/bin/bash is the frequent shebang line used in most scripts. When we use this line, it tells the system we want to use bash in the /bin directory.
Having it this way is more precise since it gives the full path to bash. However, the downside is that on other systems where bash is missing in the /bin directory, the script fails to execute, and throws an error:
bad interpreter or no such file in the directory
If no shebang line is set, #!/bin/bash is the default used. In some scripts, a dash or double dash exists at the end of the shebang line:
#!/bin/bash - #!/bin/bash --
We append a dash or double dash to the end of the shebang line to signal the end of the last argument and to disable further argument processing. The – improves script security as it prevents script root spoofing attacks.
We can also use flags in the shebang line:
The -v flag prints the shell input lines as it reads the file. We can use the -v flag when troubleshooting.
4. #!/usr/bin/env name
Since we’ve got a variety of Linux distros, the shell is in different locations in some of them. For example, Ubuntu has bash in the /usr/bin/ directory, whereas some Redhat distros have it in the /bin directory. Other users may want to use their customized shells in different locations to run scripts.
To ensure script portability, i.e., to be able to run scripts across UNIX-like systems without breaking, we must use the env command.
The env command allows us to run a program in a modified environment. When we run bash with the env command, env searches for */bash in our $PATH environment variable and runs the first instance it finds. The env command is handy if we don’t know the absolute path to the available interpreter:
Even though this makes our script portable to different Linux distros, it gives inconsistent results. The inconsistency is because it behaves differently depending on which shell runs the file. We should prefer our script to fail rather than give varying results.
Secondly, the env command doesn’t accept passed arguments to the interpreter (affects mainly Perl).
Lastly, when we use this shebang line, we’ll be incapable of running cron jobs. For cron jobs to run correctly, we must have a restricted environment. We lack this environment when we use env.
5. Other Shebang Lines
Apart from the examples we’ve seen, there are more interpreters within our system. We can use the Dash shell as our shebang line:
Similarly, we could use the Korn shell as our shebang line:
Furthermore, we can use scripting languages as our interpreters. For example, we can use languages like Python or Perl in our shebang lines. When we use these interpreters in our shebang lines, we either specify their full path or use the env command:
#!/bin/perl #!/usr/bin/env perl #!/usr/bin/python3 #!/usr/bin/env python3
In this article, we looked at some of the commonly used shebang lines. We discussed some of their best practices and the disadvantages associated with them. Users shouldn’t override the defined shell unless they are in a testing environment. Finally, if we write scripts that run on multiple Linux systems, we must ensure that we set the appropriate interpreter path.