Use of '#!' in *nix scripts

4

In many Apple/Unix scripts I see stuff preceeded by '#" which as far as I know means it is a remark. However often you see shell calls as below (the line with #!).

## Setting a default route 
#!/bin/sh

/sbin/route add SUBNET $5

I am wondering whether this is also just a comment or that it actually does something. Thanks for your experts' advice :-)

Edgar Wieringa

Posted 2011-02-23T11:18:28.187

Reputation: 41

1nice question! +1 – studiohack – 2011-02-23T14:30:30.750

possible duplicate of What exactly interpret #!/bin/bash line?

– Chris Johnsen – 2011-03-09T03:56:51.043

Answers

16

It's a way of defining of which shell should be invoked during execution of the script. It's called the Shebang.

Example, a file having the following Shebang line:

#!/bin/sh

would invoke the Bourne (sh) shell. So for example, your piece of script:

## Setting a default route 
#!/bin/sh

/sbin/route add SUBNET $5

would make /sbin/route add SUBNET $5 run in the Bourne shell interpreter. /sbin/route add SUBNET $5 is just a comment and doesn't do anything. However, the shebang should be on the first line, therefore that comment at the top will disallow the shebang to do its work, making it a useless addition.

There's a number of interpreters that are widely used and some typical interpreters for shebang lines are:

  • #!/bin/sh — Execute using sh, the Bourne shell (or a compatible shell)
  • #!/bin/csh — Execute using csh, the C shell (or a compatible shell)
  • #!/usr/bin/perl — Execute using Perl
  • #!/usr/bin/python — Execute using Python
  • #!/usr/bin/php — Execute using PHP's command line interpreter

As Olli mentioned in his comments, sometimes env (short for environment) is used to make sure the correct path to the interpreter is chosen.

BloodPhilia

Posted 2011-02-23T11:18:28.187

Reputation: 27 374

4Actually for non-standard things (for example perl, python and php), it's better idea to use env: #!/usr/bin/env perl, for example. That'll automatically choose correct path for perl, even if it's not /usr/bin. – Olli – 2011-02-23T11:42:15.057

@Olli it's just some examples! ;) But you're right of course... – BloodPhilia – 2011-02-23T11:43:04.980

@BloodPhilia: if so, it may be good idea to edit those examples :) – Olli – 2011-02-23T11:44:43.650

9The shebang has to be the first line so the initial commented line would prevent the second line from doing anything. Another style that's often used is #!/usr/bin/env python which will usually cause the script to be run by whatever python occurs first in the PATH. This is useful since sometimes executables are installed in different places so this works without having to modify the script. In a few rare cases, env is located somewhere else, so even this fails. – Paused until further notice. – 2011-02-23T11:46:04.023

1@Olli Happy now xD? – BloodPhilia – 2011-02-23T11:48:32.087

Well, and in a few rare cases there is no /bin/sh available. I would claim that /usr/bin/env is pretty much safe choice nowadays, especially compared to python/perl/php. – Olli – 2011-02-23T11:55:57.257

@Olli In a few rare cases, there's Windows installed... I can't cover every possiblity there ever can be... The OP just wants to know what the line means, not its best practices... – BloodPhilia – 2011-02-23T12:01:55.657

1@Olli: Under the Filesystem Hierarchy Standard, "essential" programs which must be available in single-user mode must be placed in /bin, while /usr is for non-essential programs, so /bin/sh is a safer bet than /usr/bin/env - it's always possible that /usr may not be mounted, after all. I agree that /usr/bin/env perl is definitely better than /usr/bin/perl, though. – Dave Sherohman – 2011-02-23T12:33:25.813

+1 for saying "the Bourne shell (or a compatible shell)". Some systems don't use Bourne shell, but still call it sh. – AndrejaKo – 2011-02-23T14:45:37.373

Thanks all foor the clear answers! Really helpful. Also thanks to BloodPhilia for the better formatting of my question. – Edgar Wieringa – 2011-02-24T04:40:12.903

4

Somewhat more technical explanation:

When you run an executable on UNIX/Linux/Windows/SomeOS/AnyOS the system needs to know how to run it. In UNIX/Linux are special rules for the first few bytes of the files to tell the kernel how to run it. For scripts, the special characters are '#!'. If The kernel sees this as the first two characters, it knows the file is a script and looks at the rest of the line for the executable that runs the script. So if the file /path/to/script.sh starts:

#!/bin/sh

The kernel would see '#!', know it is a script and find and run /bin/sh and pass the script file path /path/to/script.sh as a parameter. Since all script interpreters (bash, perl, csh, python, etc) use '#' as the comment character, they'll all just ignore this 'shebang' line as a comment.

You probably never saw this before because Windows handles this completely differently. On Windows, it doesn't use these 'magic' characters, but instead maps the file extension to the way to run it.

Rich Homolka

Posted 2011-02-23T11:18:28.187

Reputation: 27 121