Linux 环境变量与脚本调试:export/echo set -x
一、引言
环境变量是 Linux 系统的血液,决定了命令搜索路径、语言设置、用户偏好等方方面面。掌握环境变量的管理,是理解 Linux 系统行为和编写健壮脚本的基础。
二、环境变量基础
# 查看所有环境变量
env
printenv
查看特定变量
echo $HOME
printenv PATH
echo "用户:$USER,主机:$HOSTNAME,Shell:$SHELL"
常见系统环境变量
HOME - 用户主目录
PATH - 命令搜索路径
USER - 当前用户名
UID - 当前用户 ID
SHELL - 登录 Shell 类型
PWD - 当前工作目录
LANG - 语言和编码设置
HISTSIZE - 历史命令记录数量
PS1 - 主提示符格式
查看所有变量(包括局部变量)
set
三、export 命令详解
# export 命令用法
1. 基本概念:export 使变量传递给子进程
name="张三"
bash -c 'echo $name' # 子 shell 中为空(未 export)
export name
bash -c 'echo $name' # 子 shell 中输出:张三
2. 定义并导出
export MYVAR="hello"
declare -x MYVAR="hello" # 等价
3. 查看导出状态
export -p
4. 取消导出
export -n NAME
5. PATH 操作
export PATH="$PATH:/opt/myapp/bin"
export PATH="/opt/myapp/bin:$PATH"
永久保存:在 ~/.bashrc 中添加
echo 'export JAVA_HOME=/usr/lib/jvm/java-11' >> ~/.bashrc
source ~/.bashrc
四、Shell 调试模式
#!/bin/bash
Shell 调试技巧
1. set -x(追踪执行)
set -x
name="测试用户"
echo "你好,$name"
set +x
2. set -v(打印原始输入行)
set -v
read -p "请输入:" user_input
set +v
3. set -e(脚本遇错即停)
set -e
ping -c 1 192.168.1.1
4. set -u(使用未定义变量时报错)
set -u
5. set -o pipefail(管道中任一命令失败即返回失败状态)
set -o pipefail
false | true | echo "成功"
6. 组合使用(严格模式)
set -euo pipefail
IFS=$'\n\t'
7. 条件断点
debug_mode=true
if $debug_mode; then
set -x
fi
8. DEBUG 陷阱
trap 'echo "即将执行: $BASH_COMMAND"' DEBUG
echo "第一行"
五、trap 信号捕获与调试
#!/bin/bash
trap 信号捕获示例
1. 捕获脚本退出
function cleanup {
echo "脚本退出,执行清理工作..."
rm -f /tmp/lock_file
}
trap cleanup EXIT
2. 捕获 Ctrl+C(SIGINT)
echo "按 Ctrl+C 终止脚本"
trap 'echo "收到 Ctrl+C,但我不退出"' INT
while true; do sleep 1; done
3. 捕获错误(ERR)
function handle_error {
echo "命令执行失败!"
echo "失败的命令:$BASH_COMMAND"
echo "失败行号:$LINENO"
}
trap 'handle_error' ERR
4. 组合使用:严格模式 + 错误追踪
set -euo pipefail
trap 'echo "脚本异常退出,状态码:$?" >&2' EXIT
trap 'echo "命令失败:$BASH_COMMAND" >&2' ERR
六、脚本调试实战
#!/bin/bash
完整调试实战脚本
set -euo pipefail
IFS=$'\n\t'
错误处理函数
error_exit() {
echo "[ERROR] $1" >&2
exit 1
}
参数验证
if [ $# -lt 2 ]; then
echo "用法:$0 <源文件> <目标目录>"
exit 1
fi
src_file="$1"
dest_dir="$2"
使用 trap 进行资源清理
temp_files=()
cleanup() {
echo "清理临时文件..."
for f in "${temp_files[@]}"; do
[ -f "$f" ] && rm -f "$f"
done
}
trap cleanup EXIT
主逻辑
[ -f "$src_file" ] || error_exit "源文件不存在:$src_file"
[ -d "$dest_dir" ] || mkdir -p "$dest_dir" || error_exit "无法创建目录"
cp "$src_file" /tmp/temp_copy_$$.txt
temp_files+=("/tmp/temp_copy_$$.txt")
cp /tmp/temp_copy_$$.txt "$dest_dir/$(basename $src_file)"
DEBUG 模式
if [[ "${DEBUG:-0}" == "1" ]]; then
set -x
ls -la "$dest_dir"
set +x
fi
echo "处理完成!"
七、常见问题(FAQ)
Q1: 登录 Shell 和非登录 Shell 有什么区别?
登录 Shell 会读取 /etc/profile 和 ~/.bash_profile,非登录 Shell 只读取 ~/.bashrc。SSH 登录属于登录 Shell,脚本执行和打开新终端属于非登录 Shell。
Q2: 为什么在 .bashrc 里设置的变量在 SSH 登录后不生效?
SSH 执行远程命令是非登录 Shell,不会读取 .bash_profile。可以在 .bash_profile 中加入 [[ -f ~/.bashrc ]] && source ~/.bashrc 来桥接。
Q3: set -e 会影响 if 条件判断吗?
不会。命令放在 if 条件中时,即使返回非零也不会导致脚本退出。
Q4: 如何调试生产环境的脚本而不中断服务?
可以在脚本开头加 set -x,将调试输出重定向到专门的文件:exec 2> /tmp/debug.log。
八、延伸阅读
- Linux Shell 脚本编程入门:变量、条件判断、循环基础
- Shell 脚本函数与参数传递:函数定义、返回值、作用域
- Bash 常用命令与管道操作:系统环境变量在管道中的使用