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. 内核如何执行脚本?

简化执行流程如下:

  1. 用户执行具有可执行权限的脚本
chmod +x script.sh
./script.sh
  1. 内核读取 script.sh
  2. 检查文件前两字符是否为 #!
  3. 若是,则把该行剩余部分视为 * “解释器路径 + 参数” * 并以此程序执行,同时把脚本文件路径作为参数传递

例如 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 并执行。

优点

  1. 可移植性强: * 无论 bash 位于 /bin/bash/usr/bin/bash/usr/local/bin/bash,只要在 PATH 中,env 都能找到。
  2. 使用用户自定义的 bash: * 如果用户在 PATH 中优先放置了某个版本的 bash,脚本会使用该版本。
  3. Python 等也采用同样模式 python #!/usr/bin/env python3

缺点

  1. 需要 /usr/bin/env: * 大多数现代Unix/Linux系统都有,但极端环境可能没有。
  2. PATH 影响: * PATH 配置不当或意外的 bash 在前,可能导致运行不同版本。
  3. 安全考虑: * 在高度安全的环境中,基于 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.py shebang 会被忽略。
  • 但如果想用 ./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

image of shebang in linux script