Bourne | Ash |  #!  | find | ARG_MAX | Shells | portability | permissions | UUOC | ancient | - | ../Various | HOME
"$@" | echo/printf | set -e | test | tty defs | tty chars | $() vs ) | IFS | using siginfo | nanosleep | line charset | locale


The #! magic, details about the shebang/hash-bang mechanism on various Unix flavours

2010-04-06 (see recent changes)

Here you'll find


More reading


Selected issues


Test results from various systems

I used the following as program "showargs":

    #include <stdio.h>
    int main(argc, argv)
	int argc; char** argv;
    {
	int i;
	for (i=0; i<argc; i++)
	    fprintf(stdout, "argv[%d]: \"%s\"\n", i, argv[i]);
	return(0);
    } 

and a one line script named "invoker.sh" to call it, similar to this,

    #!/tmp/showargs -1 -2 -3 

to produce the following results (tried them myself, but i'd like to add your results from yet different systems).

Typically, a result from the above would look like this:

    argv[0]: "/tmp/showargs"
    argv[1]: "-1 -2 -3"
    argv[2]: "./invoker.sh"

... but the following table lists the variations. The meaning of the columns is explained below.

OS (arch) maximum
length of
#! line
cut-off (c),
error (err) or
ENOEXEC ()
only the
1st arg
passed on
each arg
in its own
argv[x]
handle #
like a
comment
argv[0]:
invoker,
instead of
interpreter
not full
path in
argv[0]
remove
trailing
white-
space
convert
tabulator
to
space
accept
inter-
preter
search
current
directory
(x) allow suid
(o) optional
[suid]
4.0BSD 32 [orig] X X X
AIX 3.2.5/4.3.2 (rs6k) 256 X X X
BIG-IP4.2 [big-ip] 4096 err X ? ? X n/a X
EP/IX 2.2.1 (mips) 1024 X ? ?
FreeBSD 1.1- / 4.0-4.4 64 X - / X X n/a ?
FreeBSD 4.5- 128 err X X X n/a ?
FreeBSD 6.0- (i386/amd64) 4096 c X X X
FreeBSD 6.0- (ia64/sparc64/alpha) 8192 c X X X
HP-UX A.08.07/B.09.03 32 X ? ? ?
HP-UX B.10.10 128 X X ? ?
HP-UX B.10.20-11.31 128 X X X
IRIX 4.0.5 (mips) 64 ? ? X X X
IRIX 5.3/6.5 (mips) 256 err X ? X
Linux 0.10 / 0.12-0.99.1 1022 / 127 [early-linux] X ?
Linux 0.99.2-2.2.26 127 c X X ?
Linux 2.4.0-2.6.27.8 / 2.6.27.9- 127 c X   / X X
MacOS X 10.0/.1/.2, xnu 123.5-344 512 ? ? X ? ? ?
MacOS X 10.3, xnu 517 512 X ? ? X X ? ? ?
MacOS X 10.4/.5/.6, xnu 792-1504 512 X X X n/a X o
Minix 2.0.3-3.1.1 257 X X n/a X X X
MUNIX 3.1 (svr3.x, 68k) 32 X ? ? ?
NetBSD 0.8-1.6Q / 1.6R- 64 / 1024 X o
OpenBSD 2.0-3.4 64 X o
OSF1 V4.0B-T5.1 1024 X X X
OpenServer 5.0.6/6.0.0 [sco] 256 err X X X X ?
SINIX 5.20 (mx300/nsc) 32 ? ?
SunOS 4.1.4 (sparc) 32 c X ? ? ?
SunOS 5.x (sparc) 1024 X X X X X
Ultrix 4.0 (µvax 3900) 31 X X X X
Ultrix 4.3 (all), 4.5 (vax3100) 32 c X ? ?
Ultrix 4.5 (risc) 80 c X ? ?
Unicos 9.0.2.2 (cray) 32 X ? ?
Unixware 2, 7 ? ? ? ? ? ? ? ? ? ? ? X
GNU Hurd cvs-20020529 4096 c X ? ? ?

Meaning of the columns:

A questionmark means that a detail couldn't be tested yet (especially if the column was added later or the system had no compiler).
"n/a" means that the attribute is not relevant in this case.

Footnotes in the table:

[orig]             4.0BSD and 386BSD-0.1 don't hand over any argument at all.
The called interpreter only receives argv[0] with it's own path and argv[1] with the script

[big-ip]             This BIG-IP 4.2 (vendor is F5) is based on BSDi BSD/OS 4.1, probably even with very few modifications:
The tools contain the string "BSD/OS 4.1" and there's also a kernel /bsd-generic, which contains "BSDi BSD/OS 4.1".
I had no compiler available on this system, thus some tests are pending.

[sco] John H. DuBois told me that #! was introduced in SCO UNIX 3.2v4.0, but was disabled by default. If you wanted to use it, it had to be enabled by setting hashplingenable in kernel/space.c ("hashpling" because it was implemented by programmers in Britain). It was apparently enabled by default in 3.2v4.2, but even then there were no #! scripts shipped with the OS as a customer might disable it. The first #! scripts (tcl) were shipped in 3.2v5.0 then.

[suid]
  • The SCO OpenServer 6.0 documentation is ambiguous whether setuid scripts are supported:
    "SUID, SGID, and sticky bit clearing on writes" (via Security online docs/Maintainig System Security) states,
    that suid/sgid bit don't work on shell scripts (not mentioning the #! mechanism),
    but chmod(1) states that they do only, if the #! convention is used.
  • On MacOS X, the sysctl kernel variable kern.sugid_scripts determines if suid shell scripts are possible.
  • On Net- and OpenBSD the kernel option SETUIDSCRIPTS must be activated to allow for the setuid/gid-bit with the #! mechanism.
  • For UnixWare, see the online manual for chmod(1).

[early-linux] On linux 0.10 until 0.99.1, argv[0] contains both the interpreter and the arguments: argv[0]: "/tmp/showargs -1 -2 -3"


And why shebang? In music, '#' means sharp. So just shorten #! to sharp-bang. Or it might be derived from "shell bang". All this probably under the influence of the american slang idiom "the whole shebang" (everything, the works, everything involved in what is under consideration). See also the jargon dictionary or Merriam-Websters for the slang idiom.

Sometimes it's also called hash-bang, pound-bang, sha-bang/shabang, hash-exclam, or hash-pling (british, isn't it?).


<http://www.in-ulm.de/~mascheck/various/shebang/>

Sven Mascheck