2.4 环境变量和 PATH
前置知识:安全地操作文件
预计时间:12 分钟
练习环境:GNU/Linux 上的 Bash;PowerShell 差异见文末
完成标志:能判断命令来源,并解释变量何时传给子进程
文件操作已经顺利完成。现在换一个问题:同样是在提示符后输入名字,为什么 cd 由 Shell 自己处理,python3 却通常要去磁盘上寻找?要回答它,需要把环境变量和 PATH 放到一起看。
Shell 变量与环境变量
unset COURSE_STAGE
COURSE_STAGE=workshop
printf 'shell: <%s>\n' "$COURSE_STAGE"
sh -c 'printf "child before export: <%s>\n" "$COURSE_STAGE"'
export COURSE_STAGE
sh -c 'printf "child after export: <%s>\n" "$COURSE_STAGE"'开头先清除这个练习变量,避免它曾被导出过,影响观察。你应依次看到 shell: <workshop>、child before export: <> 和 child after export: <workshop>。赋值先存在于当前 Shell。export 后,新启动的子进程能继承它;已经运行的进程不会被反向更新,子进程的修改也不会自动传回父进程。
查看指定值:
printf 'HOME=%s\n' "$HOME"
printf 'PATH=%s\n' "$PATH"不要把完整 env 输出随意贴到公开位置,其中可能包含访问令牌、代理地址或其他敏感配置。
PATH 只是命令解析的一部分
PATH 在 Unix Shell 中通常是以冒号分隔的目录列表。查找外部命令时,靠前目录中的同名程序优先;但别名、函数、内建命令和 Shell 的命令缓存也可能先参与解析。
type -a cd
type -a printf
type -a python3
command -v python3type -a 会说明命令究竟是别名、函数、内建命令还是一个或多个外部文件。which 的实现和行为跨平台不一致,不适合作为唯一依据。
在临时目录添加工具
workdir=$(mktemp -d)
mkdir -p "$workdir/bin"
cat > "$workdir/bin/workshop-hello" <<'SCRIPT'
#!/bin/sh
printf '%s\n' 'hello from a private tool directory'
SCRIPT
chmod +x "$workdir/bin/workshop-hello"
original_path=$PATH
PATH="$workdir/bin:$PATH"
export PATH
command -v workshop-hello
workshop-hello不要把空 PATH 片段、. 或其他用户可写目录随意放在系统目录之前;同名程序可能被优先执行。脚本中需要确定程序时,可验证绝对路径或采用可信的运行环境。
不要盲改启动文件
~/.bashrc、~/.bash_profile、~/.profile 和 ~/.zshrc 的读取时机不同,取决于 Shell、是否登录、是否交互和系统配置。$SHELL 通常表示账户的登录 Shell,不保证就是当前进程:
printf 'login shell: %s\n' "$SHELL"
ps -p $$ -o comm=要持久化配置时:确认当前 Shell,阅读对应手册,备份现有文件,手动编辑一小处,再开一个新终端验证。不要用重定向覆盖整个配置文件,也不要把教程片段同时追加到所有启动文件。
PowerShell 的环境变量写作 $env:NAME;Windows 上的 PATH 通常以分号分隔。Bash/Zsh 命令不能原样复制过去。
清理本页练习:
rm -r -- "$workdir"
PATH=$original_path
export PATH
unset original_path COURSE_STAGE