Linux 环境变量与脚本调试:export/echo set -x

小飞兽 Shell 106 次阅读 2026-07-29

一、引言

环境变量是 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

八、延伸阅读