Linux脚本第一行的秘密:#!/usr/bin/env bash 与 #!/bin/bash到底是什么?
在Linux中编写脚本时,习惯性地在最上面写下这行。
#!/usr/bin/env bash
或者
#!/bin/bash
乍一看像是注释…这行到底是什么?两者又有什么区别?本文将深入理解这行代码,并整理何时使用哪种方式。
1. 这不是注释:shebang(#!)是什么?
以 #! 开头的这一行被称为 shebang(#!)。
#!/bin/bash
从shell的角度看,因为以 # 开头,显然像是注释。
但从操作系统(内核)的角度,它并不是注释,而是:
“告诉内核用哪个解释器程序来执行这份脚本”。
也就是说,
#!/bin/bash→ “请用/bin/bash来执行这份文件”#!/usr/bin/env bash→ “通过env找到bash解释器,然后用它来执行这份文件”
2. 内核如何执行脚本?
简化执行流程如下:
- 用户执行具有可执行权限的脚本
chmod +x script.sh
./script.sh
- 内核读取
script.sh - 检查文件前两字符是否为
#! - 若是,则把该行剩余部分视为 * “解释器路径 + 参数” * 并以此程序执行,同时把脚本文件路径作为参数传递
例如 script.sh 的第一行是:
#!/bin/bash
内核实际上会执行:
/bin/bash script.sh
这与我们手动执行 bash script.sh 的效果相同。
备注:
#!前不能有空格,文件首字符必须是#,第二字符是!。
3. #!/bin/bash 的意义与特点
最常见的写法就是这条。
#!/bin/bash
意义
- “这份脚本是 bash 脚本,
bash位于/bin/bash”。 - 内核在执行时始终使用
/bin/bash。
优点
- 明确:总是使用
/bin/bash,可预测。 - 性能/简洁:不经过
env,省去路径搜索。 - 大多数Linux发行版将
/bin/bash视为“标准位置”。
缺点
- 可移植性差:
- 某些系统上
bash可能在/usr/bin/bash、/usr/local/bin/bash等。 - 有些系统根本没有
bash,只有/bin/sh。 - macOS、BSD、NixOS、部分容器环境等路径可能不同。
4. #!/usr/bin/env bash 的意义与特点
现在脚本中常见的写法是这条。
#!/usr/bin/env bash
核心是 /usr/bin/env。
env是“环境变量设置/检查 + 在 PATH 中搜索程序”的工具。- 内核实际上会执行:
bash /usr/bin/env bash script.sh env查看系统的PATH,在其中找到bash并执行。
优点
- 可移植性强:
* 无论
bash位于/bin/bash、/usr/bin/bash、/usr/local/bin/bash,只要在 PATH 中,env都能找到。 - 使用用户自定义的 bash:
* 如果用户在 PATH 中优先放置了某个版本的
bash,脚本会使用该版本。 - Python 等也采用同样模式
python #!/usr/bin/env python3
缺点
- 需要
/usr/bin/env: * 大多数现代Unix/Linux系统都有,但极端环境可能没有。 - PATH 影响:
* PATH 配置不当或意外的
bash在前,可能导致运行不同版本。 - 安全考虑: * 在高度安全的环境中,基于 PATH 的解释器查找可能不受欢迎,倾向于使用绝对路径。
5. 两种方式对比
| 区分 | #!/bin/bash |
#!/usr/bin/env bash |
|---|---|---|
| 解释器定位方式 | 绝对路径固定 | 通过 PATH 搜索 |
| 可移植性 | 低(路径不同会失效) | 高(只要 PATH 中有 bash) |
| 使用的 bash | 总是 /bin/bash |
PATH 中第一个找到的 bash |
| 版本保证 | 较易保证 | 取决于 PATH |
| 安全/控制 | 更强(路径固定) | 稍弱(PATH 依赖) |
| 现代趋势 | 较旧风格 | 更受推荐 |
6. 何时使用哪种方式?
1) 个人/团队开发脚本(常规开发环境)
推荐使用:
#!/usr/bin/env bash
原因:
- 开发者的服务器、本地环境、CI 环境等 bash 位置可能不同。
- PATH 基础查找更灵活,符合现代工具习惯。
2) 针对特定服务器环境的运维脚本
如果公司所有服务器都统一安装在 /bin/bash,且环境固定:
#!/bin/bash
原因:
- 保证使用同一解释器,避免 PATH 变动导致的意外。
3) 追求最大可移植性
若担心某些系统根本没有 bash,可考虑改用 sh:
#!/bin/sh
但需避免使用 bash 专有语法([[ ]]、数组、扩展字符串等)。
7. 使用 #!/usr/bin/env bash 的实战技巧
1) 正确的执行方式
不要仅仅用 bash script.sh,因为那会忽略 shebang。
chmod +x script.sh # 赋予执行权限
./script.sh # 直接执行
这样内核会读取 shebang 并使用指定解释器。
2) 参数传递检查
#!/usr/bin/env bash
echo "解释器: $0"
echo "参数: $@"
执行:
chmod +x test.sh
./test.sh hello world
输出:
解释器: ./test.sh
参数: hello world
$0 是脚本自身路径,内核实际上执行的是 /usr/bin/env bash test.sh hello world。
8. 常见误解
“第一行只是注释,根本不需要写”
- 这是真的,并非总是必需。
- 直接指定解释器执行时:
bash bash myscript.sh python3 myscript.pyshebang 会被忽略。 - 但如果想用
./myscript.sh直接执行,shebang 必不可少。
“#!/usr/bin/env 之外还有 #!/bin/env”
- 有些系统确实有
/bin/env。 - 但
/usr/bin/env更通用,建议使用。
9. 小结
#!/usr/bin/env bash与#!/bin/bash都不是注释,而是告诉内核用哪个解释器执行脚本。#!/bin/bash:总是/bin/bash,可预测但可移植性差。#!/usr/bin/env bash:通过 PATH 查找 bash,灵活可移植,但受 PATH 影响。- 在现代开发/部署环境中,推荐使用
#!/usr/bin/env bash。

目前没有评论。