APLawrence.com -  Resources for Unix and Linux Systems, Bloggers and the self-employed
RSS Feeds RSS Feeds











(OLDER) <- More Stuff -> (NEWER) (NEWEST)
Printer Friendly Version
->
-> Shebang - What's the point of #!/bin/bash?


Shebang - What's the point of #!/bin/bash?


2013/07/28






If you want the geekish explanation, Wikipedia has a good overview of shebang. Here, I want to look at it from a more pragmatic view.

You've undoubtedly seen shell scripts begin with "#!/bin/bash" and you may have noticed Perl scripts that begin with "#!/usr/bin/perl". You may have also noticed that you seemingly don't really need "#!/bin/bash" but "#!/usr/bin/perl" isn't quite so optional.

Let's take a look at a simple and pointless shell script. We'll run it with and without "#!/bin/bash" and see what happens.


#!/bin/bash
while :
do
sleep 30
done
 

I'll call that "t.sh" and run it as "./t.sh":

$ ./t.sh &
[1] 836
 

A "ps" shows what's running:

  464 ttys001    0:00.02 -bash
  836 ttys001    0:00.00 /bin/bash ./t.sh
  837 ttys001    0:00.00 sleep 300
 

Now we'll make a copy of that ("tcopy.sh") but take out the first line:

while :
do
sleep 30
done
 

We'll run that:

$ ./tcopy.sh &
[2] 848
$ ps
  PID TTY           TIME CMD
  464 ttys001    0:00.02 -bash
  836 ttys001    0:00.00 /bin/bash ./t.sh
  837 ttys001    0:00.00 sleep 30
  848 ttys001    0:00.00 -bash
  849 ttys001    0:00.00 sleep 30
 

One difference stands out: the version with "#!/bin/bash" shows us "t.sh" in the "ps" listing, but the other version just shows "bash" (actually, "-bash", but that's a story for another day).

Let's kill those off:

$ kill 836 848
$ ps
  PID TTY           TIME CMD
  464 ttys001    0:00.03 -bash
  855 ttys001    0:00.00 sleep 30
  992 ttys001    0:00.00 sleep 30
[1]-  Terminated: 15          ./t.sh
[2]+  Terminated: 15          ./tcopy.sh
 

Notice that the "sleep"'s are still running - that too is a story for another day, but they'll go away soon enough. So, right away we see one advantage of the shebang: it lets us see the name of a shell script in "ps".

We're not quite done. Let's create a Perl script:

#!/usr/bin/perl
exec("./t.sh");
 

What happens when we use that?

$ ./t.pl &
[1] 1050
$ ps
  PID TTY           TIME CMD
  464 ttys001    0:00.04 -bash
 1050 ttys001    0:00.01 /bin/bash ./t.sh
 1051 ttys001    0:00.00 sleep 30
 

Same thing, right? How about we exec "tcopy.sh" frp that script instead?

$ cat t.pl
#!/usr/bin/perl
exec("./tcopy.sh");
$ ./t.pl &
[1] 1085
$ ps
  PID TTY           TIME CMD
  464 ttys001    0:00.05 -bash
 1085 ttys001    0:00.01 sh ./tcopy.sh
 1086 ttys001    0:00.00 sleep 30
 

The difference?

 1050 ttys001    0:00.01 /bin/bash ./t.sh
 1085 ttys001    0:00.01 sh ./tcopy.sh
 

So that's another thing: if our shebang-less script is run by something other than bash, it's /bin/sh that ends up running it. Certainly in this case it doesn't matter - sh or bash will do the same thing. But other scripts might have bash specific commands and /bin/sh would fail or behave badly.

So is there any reason to leave out the shebang?

Let's make t.sh and tcopy.sh very simple:

$ cat t.sh; echo " ";cat tcopy.sh
#!/bin/bash
x=1024
echo $x
exit
 
x=1024
echo  $x
exit
 

Now let's have them race each other:

$ time ./t.sh;time ./tcopy.sh
1024

real	0m0.003s
user	0m0.001s
sys	0m0.001s
1024

real	0m0.001s
user	0m0.001s
sys	0m0.001s
 

Whoah! What's that?? Why is the shebangless version faster?

The man page for bash tells us the difference in the "COMMAND EXECUTION" section:

If the search is successful, or if the command name contains one or more slashes, the shell executes the named program in a separate execution environment. Argument 0 is set to the name given, and the remaining arguments to the command are set to the arguments given, if any.

If this execution fails because the file is not in executable format, and the file is not a direc- tory, it is assumed to be a shell script, a file containing shell commands. A subshell is spawned to execute it. This subshell reinitializes itself, so that the effect is as if a new shell had been invoked to handle the script, with the exception that the locations of commands remembered by the parent (see hash below under SHELL BUILTIN COMMANDS) are retained by the child.

If the program is a file beginning with #!, the remainder of the first line specifies an interpreter for the program. The shell executes the specified interpreter on operating systems that do not han- dle this executable format themselves. The arguments to the interpreter consist of a single optional argument following the interpreter name on the first line of the program, followed by the name of the program, followed by the command arguments, if any.

So, it's quicker to fail and run the subshell than to succeed. Not by much, of course, but the difference is real. I can't imagine a circumstance where it would actually matter unless you had some strange system that was constantly firing of short little shell scripts to do this and that - you'd need to be doing an awful lot of that to even notice~




If this page was useful to you, please help others find it:  





Comments?




More Articles by - Find me on Google+



Click here to add your comments
- no registration needed!


Don't miss responses! Subscribe to Comments by RSS or by Email

Click here to add your comments


If you want a picture to show with your comment, go get a Gravatar

Kerio Samepage


Have you tried Searching this site?

Unix/Linux/Mac OS X support by phone, email or on-site: Support Rates

This is a Unix/Linux resource website. It contains technical articles about Unix, Linux and general computing related subjects, opinion, news, help files, how-to's, tutorials and more. We appreciate comments and article submissions.

Publishing your articles here

Jump to Comments



Many of the products and books I review are things I purchased for my own use. Some were given to me specifically for the purpose of reviewing them. I resell or can earn commissions from the sale of some of these items. Links within these pages may be affiliate links that pay me for referring you to them. That's mostly insignificant amounts of money; whenever it is not I have made my relationship plain. I also may own stock in companies mentioned here. If you have any question, please do feel free to contact me.

I am a Kerio reseller. Articles here related to Kerio products reflect my honest opinion, but I do have an obvious interest in selling those products also.

Specific links that take you to pages that allow you to purchase the item I reviewed are very likely to pay me a commission. Many of the books I review were given to me by the publishers specifically for the purpose of writing a review. These gifts and referral fees do not affect my opinions; I often give bad reviews anyway.

We use Google third-party advertising companies to serve ads when you visit our website. These companies may use information (not including your name, address, email address, or telephone number) about your visits to this and other websites in order to provide advertisements about goods and services of interest to you. If you would like more information about this practice and to know your choices about not having this information used by these companies, click here.

pavatar.jpg

This post tagged:

       - Linux
       - MacOSX
       - Scripting
       - Shell















My Troubleshooting E-Book will show you how to solve tough problems on Linux and Unix systems!


book graphic unix and linux troubleshooting guide



Buy Kerio from a dealer
who knows tech:
I sell and support

Kerio Connect Mail server, Control, Workspace and Operator licenses and subscription renewals



Click and enter your name and phone number to call me about Kerio® products right now (Flash required)