Bash 核心概念
一句话理解 Bash:
Bash 是一个 “命令解析 + 展开 + 进程调度” 的语言型壳层(Shell)
用户
↓
Bash(解析 / 展开 / 调度)
↓
Kernel(fork / exec / IO / signal)
↓
程序
- Bash 不执行命令
- Bash 决定“如何执行”
- Bash 的核心价值在于:
- 展开规则
- 组合命令
- 控制进程
写 Bash,本质是在写 进程编排逻辑
1. 读取输入
2. 词法分割(tokenize)
3. 展开(Expansion)
4. 重定向(Redirection)
5. fork
6. exec
⚠️ 90% Bash Bug 出现在第 3 步:展开
Bash 的展开顺序是 固定且不可改变的
{a,b,c}
file{1..3}.log
- 最早发生
- 不看变量、不看文件
~
~user
$VAR
${VAR}
高频高级用法(生产必会)
${VAR:-default} # 未定义 -> default
${VAR:=default} # 未定义 -> 赋值
${VAR%/*} # dirname
${VAR##*/} # basename
suspend=${SUSPEND:-n} 就是 标准参数展开最佳实践
$(command)
❌ 旧写法:
`command`
*.log
⚠️ 这是 Bash 行为,不是 ls 行为
ls *.log
# Bash 先展开 -> ls 接收参数
- 保留变量
- 禁止分词
- 禁止 glob
"$var"
- 绝对字面量
- 什么都不展开
'$var'
rm $file
等价于:
rm file1 file2 file3
Bash 安全第一原则:变量永远加引号
- Bash 没有类型
- 一切都是字符串
- “整数比较”是语法层封装
a=10
b=2
[[ $a -gt $b ]]
[ -f file ]
- 是命令
- 靠参数分隔
- 容易炸
[[ -f file ]]
[[ $a == *.log ]]
[[ $s =~ regex ]]
优点:
- 正则
- 无 glob
- 语法安全
BASH_REMATCH 就是 [[ =~ ]] 的高级用法
if command; then
...
fi
if 判断的是 $? == 0
for i in a b c; do
done
for ((i=0; i<10; i++)); do
done
⚠️ 不要:
for i in $(ls)
while read -r line; do
done < file
func() {
local var=1
echo "$var"
}
- 没有 return 值
- 返回靠 stdout
- 状态靠 exit code
- 每个外部命令都是新进程
- 内建命令除外(cd / export)
command &
jobs
fg
bg
文件描述符
| FD | 含义 |
|---|---|
| 0 | stdin |
| 1 | stdout |
| 2 | stderr |
高频写法
command > out.log 2>&1
command &>/dev/null
a | b | c
- 每个 | 都会 fork
- 默认只返回最后一个状态
set -o pipefail
VAR=1 # shell 变量
export VAR # 环境变量
- 环境变量 -> 子进程
- shell 变量 -> 当前 shell
set -euo pipefail
| 选项 | 含义 |
|---|---|
| -e | 错即退 |
| -u | 未定义变量报错 |
| pipefail | 管道失败即失败 |
最值得学的是:
-
Bash 调试模型
- set -x
- trap ERR
- PS4
-
生产级 Bash 规范
- 不炸
- 可维护
- 可迁移
-
Bash -> Go 的抽象迁移
- 哪些逻辑该留在 Bash
- 哪些必须上 Go