Bash 执行方式
1. 脚本执行方式与底层机制差异
Section titled “1. 脚本执行方式与底层机制差异”执行一个 Shell 脚本 (hello.sh) 有多种方式,其核心区别在于 是否派生子 Shell。
1.1. 派生子 Shell 执行 (Sub-shell)
Section titled “1.1. 派生子 Shell 执行 (Sub-shell)”脚本在一个新创建的独立子 Shell 进程中运行,运行完毕后子 Shell 销毁。脚本内对环境变量(如 cd、export)的修改不会影响父终端。
- 相对路径执行:
./hello.sh(脚本必须拥有执行权限chmod +x,且需要显式加上./防止从全局$PATH中误搜)。 - 绝对路径执行:
/data/project/hello.sh - 作为参数调用:
sh hello.sh或bash hello.sh(此方式无需给脚本赋予+x权限,也无视文件头部的#!/bin/bash声明)。
1.2. 在当前 Shell 中执行 (Current-shell)
Section titled “1.2. 在当前 Shell 中执行 (Current-shell)”脚本直接在当前的终端环境中被解析执行。脚本内部的路径跳转或变量申明会立刻污染/改变当前的终端环境。
- 通过 source 调用:
source hello.sh - 通过小数点调用:
. hello.sh
2. 核心概念:Shell 的运行模式分类
Section titled “2. 核心概念:Shell 的运行模式分类”环境变量能否被正确加载,完全取决于当前 Shell 属于哪种模式组合。
2.1. 分类 A:登录 Shell vs 非登录 Shell
Section titled “2.1. 分类 A:登录 Shell vs 非登录 Shell”- 登录 Shell (Login Shell):需要输入用户名密码(或通过 SSH 密钥认证)建立的终端会话;或通过带
-l/--login参数启动的 Shell(如bash -l,su - user)。- 加载特征:会极其彻底地加载全局系统配置。执行顺序为:
/etc/profile->~/.bash_profile(或~/.bash_login或~/.profile)。
- 加载特征:会极其彻底地加载全局系统配置。执行顺序为:
- 非登录 Shell (Non-login Shell):在图形界面打开一个新的终端标签页,或直接输入
bash,或使用su user(不带横杠)切换用户产生的会话。- 加载特征:只会加载局部环境文件:
~/.bashrc->/etc/bashrc。
- 加载特征:只会加载局部环境文件:
2.2. 分类 B:交互 Shell vs 非交互 Shell
Section titled “2.2. 分类 B:交互 Shell vs 非交互 Shell”- 交互 Shell (Interactive Shell):用户能在终端里敲代码并得到实时反馈的 Shell。
- 非交互 Shell (Non-interactive Shell):通过脚本自动运行的 Shell(例如被 Crontab 定时任务拉起的脚本环境)。
3. 避坑指南:自动化脚本找不到环境变量
Section titled “3. 避坑指南:自动化脚本找不到环境变量”核心痛点:为什么我手动
./test.sh可以跑,把它放到 Crontab 或通过 CI/CD 调用时就报错“命令找不到”?
根本原因:
自动化脚本运行在 非交互、非登录 Shell 中。在这种模式下,系统 既不会加载 /etc/profile 也不会加载 ~/.bashrc。
它仅仅继承父进程传递下来的极少量变量,或仅寻找 $BASH_ENV 变量指向的文件。
解决方案: 在自动化脚本的开头,显式地载入环境变量:
#!/bin/bashsource /etc/profilesource ~/.bashrc# ... 接着写业务逻辑 ...