bash的shebang行

  

1.名称含义

在Unix中,shebang其实就是指“#!”,它取自#(SHArp)和!(bang)。

2.作用
它是很多脚本文件中第一行的前两个字符,用来告诉Unix系统要用shebang后面指定的解释器来解释该脚本。所以,在很多脚本中,第一行往往都是这么写的:
#! /abs/path/to/interpreter

3.来源
根据wikipedia上的解释,shebang最初由Dennis Ritchie引入的,时间大概是在Version 7和Version 8之间。也正是因为shebang是以#开头,所以很多Unix上的脚本都是用#作为注释的开始。常见的有:
#!/bin/sh
#!/usr/bin/perl -w
#!/bin/awk -f
#!/usr/bin/env python
#!/usr/bin/ruby

4.shebang的路径
shebang没有你想象得这么简单。首先,它后面的解释器路径一般来说必须是绝对路径。(当然了,有人也说像#!python这样的也能执行。)如果不是,可能就会出现类似的错误:
bash: ./foo.py: python: bad interpreter: No such file or directory
因为shell会直接用execve去执行这个文件,出错马上就退出。而execve会通过shebang辨认出这个一个脚本文件,然后尝试用后面的解释器去执行,但它并没有在PATH中寻找解释器,而是完全依靠你给出的路径。如果你不想指定绝对路径或者出于可移植的原因不好指定,那么你应该试试用env(1),就上面的python的shebang一样,它会帮你在PATH中搜索。python之所以更倾向于这个还有个原因,就是env一般固定在/usr/bin目录下,而python的安装位置就相对不那么固定。用env时你应该注意这么一个事实:传递给解释器的argv和你想象得并不一样。下面这个就是不对的:
#!/usr/bin/env perl -w
shell会提示:/usr/bin/env: perl -w: No such file or directory
错误的根源就是perl -w被当成了整体传递给env。
用下面的程序来看一下参数传递过程:
/*test.c*/
#include 
int main(int argc, char** argv) {
int i;
for (i=0; i<ARGC; i++)
fprintf(stdout, “argv[%d]: ”%s” ”, i, argv[i]);
return 0;
}
然后把编译出的test当作解释器:
$ cat invoker.sh
#!/home/wangcong/test -1 -2 -3
结果如下:
$ ./invoker.sh a b c
argv[0]: “/home/wangcong/test”
argv[1]: “-1 -2 -3″
argv[2]: “./invoker.sh”
argv[3]: “a”
argv[4]: “b”
argv[5]: “c”
当然了,并不是所有的Unix都是这样,但最起码Linux上的bash和zsh上就是如此。所以,要编写可移植的脚本,你应该当心这一点!

原文地址:https://www.cnblogs.com/zhaolizhe/p/6924113.html