shebang - #!
March 19, 2017
写脚本的时候通常会在脚本的开头加上 shebang, 系统会将这段内容作为解释器指令,比如 bash shell 脚本。
$> cat example
#!/usr/bin/bash
echo "HaHa"
$> chmod +x ./example
$> ./example
HaHa
只要为脚本添加了可执行的属性,那么内核在执行脚本的时候,会调用 shebang 描述的解释器来执行脚本。
./exmaple
其实等价于 /usr/bin/bash ./example
。shebang 描述的解释器需要写其绝对路径或者相对路径,因为内核并不会在用户设置的 PATH
里找解释器。关于 shebang,讨论最多的应该是 兼容性 和 版本控制 问题。
兼容性
Linux 和 Unix 在存放解释器的具体路径不太一致,比如 Linux 会放到 /usr/bin/
中,而 openBSD 会放到 /usr/local/bin/
中。不同包管理器在安装解释器的时候,存放的位置也不尽相同。
当你在 Mac 上写了 shell 脚本,测试并提交到代码库。
结果等到部署的那一天,执行脚本的时候发现找不到解释器了。
为了解决这个问题,可以通过 env
来解决,因为它在 Linux 和 Unix 存放的位置相同。
$> cat exmaple
#!/usr/bin/env bash
echo "HaHa"
env
会在用户设置的 PATH
中查找解释器第一次出现的具体路径。
虽然办法比较 tricky,但是这种方式能解决脚本解释器的兼容性问题。
版本控制
env
会在用户配置的 PATH
中查找解释器第一次出现的具体路径。
这个机制就说明这存在两个问题:
- 不同用户配置的
PATH
内容不同,导致找到的解释器版本会出现不一致 - 很难通过
env
的方式来做到版本控制
所以有些人坚持不用 /usr/bin/env cmd
这种方式。
思考
从部署的角度看,线上机器的环境都是一致的,而且都是通过自动化脚本去安装各种依赖。
版本控制较细,这种情况下,不太建议采用 env
这种方式。如果从开发者的角度看,
还是希望脚本能做到兼容,毕竟开发者的环境千差万别,env
基本上能解决这一大痛点。
不用
env
这种方式,就得确保测试环境和线上机器是一致的,通常 Docker 和 虚拟机都能解决这样的问题。