Files
tools/common
Wang Defa 89f24a7fef fix: 修复所有脚本的 process substitution 兼容性问题
## 问题描述

在使用 `set -u` 严格模式时,`source <(curl ...)` 或 `source <(wget ...)`
的 process substitution 方式会在脚本退出时产生错误:

```
/dev/fd/63: line 1: fifo: unbound variable
```

## 根本原因

Process substitution 创建的临时文件描述符(如 /dev/fd/63)在退出时
与 Bash 的 `set -u` 严格模式存在兼容性问题,导致错误消息。

## 修复方案

将 process substitution 替换为临时文件方案:

**旧方案(有问题):**
```bash
source <(curl -fsSL "$url")
```

**新方案(兼容性好):**
```bash
temp_loader=$(mktemp)
curl -fsSL "$url" -o "$temp_loader"
source "$temp_loader"
rm -f "$temp_loader"
```

## 修改的文件

批量修复了所有 7 个脚本的远程加载逻辑:

- oci/create_instance.sh
- linux/create_raid0_array.sh
- linux/install_oh_my_zsh.sh
- linux/repartition_disks.sh
- gcp/create_ai_projects.sh
- gcp/delete_all_projects.sh
- common/demo_usage.sh

## 优势

-  避免 process substitution 的兼容性问题
-  与 `set -u` 严格模式完全兼容
-  显式的临时文件管理,更易理解
-  确保所有分支都正确清理临时文件
-  保持 curl/wget 双重支持不变
2025-12-26 15:20:51 +08:00
..

公共函数库

本目录包含可复用的 Bash 函数库,用于标准化所有脚本的日志输出和错误处理。

📦 包含的库

1. logging.sh - 日志输出库

提供统一的日志输出函数,支持多个日志级别和彩色输出。

功能特性:

  • 5个日志级别DEBUG, INFO, WARNING, ERROR, SUCCESS
  • 彩色控制台输出
  • 可选的时间戳
  • 支持输出到文件
  • 灵活的日志级别控制

使用示例:

#!/bin/bash
source common/logging.sh

# 基本使用
log_info "程序启动"
log_success "操作完成"
log_warning "磁盘空间不足"
log_error "连接失败"
log_debug "调试信息"

# 设置日志级别
log_set_level "DEBUG"  # 显示所有日志

# 输出到文件
log_set_file "/var/log/myapp.log"

# 禁用时间戳
log_disable_timestamp

2. error_handler.sh - 错误处理库

提供统一的错误处理和检查机制。

功能特性:

  • 命令存在性检查
  • 文件/目录检查
  • 变量非空检查
  • Root 权限检查
  • 命令返回值检查
  • 带重试的命令执行
  • 调用栈跟踪

使用示例:

#!/bin/bash
source common/error_handler.sh

# 启用严格错误处理
enable_exit_on_error

# 检查命令是否存在
check_command "git" || error_exit "git 未安装"

# 检查文件
check_file "/etc/config" || error_exit "配置文件不存在"

# 检查 root 权限
check_root || error_exit "需要 root 权限"

# 执行命令并检查结果
run_command "安装失败" apt-get install -y package

# 带重试的命令执行
retry_command 3 5 "下载失败" curl -O https://example.com/file

# 检查变量非空
check_not_empty "$PROJECT_ID" "PROJECT_ID" || error_exit "项目ID不能为空"

🚀 完整示例脚本

#!/bin/bash
# ============================================================================
# 示例脚本:展示如何使用公共函数库
# ============================================================================

# 获取脚本目录
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# 加载公共库
source "${SCRIPT_DIR}/../common/logging.sh"
source "${SCRIPT_DIR}/../common/error_handler.sh"

# 配置日志
log_set_level "INFO"
log_set_file "/tmp/example.log"

# 启用错误处理
enable_exit_on_error

#
# 主函数
#
main() {
    log_info "脚本开始执行"

    # 检查必要的命令
    check_command "git" || error_exit "请先安装 git"

    # 检查参数
    local project_name="$1"
    check_not_empty "$project_name" "project_name" || {
        log_error "用法: $0 <project_name>"
        exit 1
    }

    # 执行操作
    log_info "正在处理项目: $project_name"

    # 带重试的网络操作
    retry_command 3 2 "网络请求失败" curl -f "https://example.com/api"

    log_success "脚本执行完成"
}

# 执行主函数
main "$@"

📖 最佳实践

1. 脚本模板

每个脚本都应遵循以下模板结构:

#!/bin/bash
set -euo pipefail  # 启用严格模式

# 脚本信息
# ============================================================================
# 文件名: script_name.sh
# 描述: 脚本功能描述
# 作者: 作者名
# 版本: 1.0.0
# ============================================================================

# 常量定义
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly SCRIPT_NAME="$(basename "$0")"

# 加载公共库
source "${SCRIPT_DIR}/../common/logging.sh"
source "${SCRIPT_DIR}/../common/error_handler.sh"

# 全局变量
GLOBAL_VAR=""

#
# 显示使用帮助
#
show_usage() {
    cat << EOF
使用方法: $SCRIPT_NAME [选项]

选项:
    -h, --help      显示此帮助信息
    -v, --verbose   启用详细输出

示例:
    $SCRIPT_NAME --verbose
EOF
}

#
# 主函数
#
main() {
    log_info "脚本开始执行"

    # 你的代码逻辑

    log_success "脚本执行完成"
}

# 执行主函数
main "$@"

2. 错误处理建议

  • 总是检查命令返回值
  • 使用 check_* 函数进行前置条件检查
  • 对网络操作使用 retry_command
  • 提供有意义的错误消息

3. 日志使用建议

  • INFO: 正常流程信息
  • SUCCESS: 操作成功完成
  • WARNING: 需要注意但不影响执行的情况
  • ERROR: 错误但可以继续的情况
  • DEBUG: 调试信息(默认不显示)

🔧 环境变量配置

logging.sh 环境变量

# 设置日志级别 (DEBUG=0, INFO=1, WARNING=2, ERROR=3, SUCCESS=4)
export LOG_CURRENT_LEVEL=1

# 设置日志文件路径
export LOG_FILE_PATH="/var/log/myapp.log"

# 启用/禁用时间戳
export LOG_ENABLE_TIMESTAMP=true

error_handler.sh 环境变量

# 错误时是否退出 (true/false)
export ERROR_EXIT_ON_FAIL=true

# 是否显示调用栈 (true/false)
export ERROR_STACK_TRACE=false

📝 维护说明

  • 版本: 1.0.0
  • 最后更新: 2025-12-26
  • 维护者: Cloud Tools Project

🤝 贡献

如需添加新功能或修复 bug

  1. 保持向后兼容性
  2. 添加完整的函数文档注释
  3. 提供使用示例
  4. 更新此 README