#!/bin/bash # 配置加载器 # 统一的配置管理和环境设置 # 默认配置文件路径 DEFAULT_CONFIG_PATHS=( "$(dirname "${BASH_SOURCE[0]}")/../config/app.conf" "/etc/s-hy2/app.conf" "$HOME/.config/s-hy2/app.conf" "./config/app.conf" ) # 已加载的配置文件标记 CONFIG_LOADED=${CONFIG_LOADED:-false} # 加载配置文件 load_config() { if [[ "$CONFIG_LOADED" == "true" ]]; then return 0 fi local config_file="" local custom_config="${1:-}" # 如果指定了自定义配置文件 if [[ -n "$custom_config" ]]; then if [[ -f "$custom_config" ]]; then config_file="$custom_config" else echo "警告: 指定的配置文件不存在: $custom_config" >&2 return 1 fi else # 查找默认配置文件 for path in "${DEFAULT_CONFIG_PATHS[@]}"; do if [[ -f "$path" ]]; then config_file="$path" break fi done fi if [[ -z "$config_file" ]]; then echo "警告: 未找到配置文件,使用默认设置" >&2 setup_default_config return 1 fi # 验证配置文件 if ! validate_config_file "$config_file"; then echo "错误: 配置文件验证失败: $config_file" >&2 return 1 fi # 加载配置文件 if source "$config_file"; then CONFIG_LOADED=true CONFIG_FILE_PATH="$config_file" echo "配置文件已加载: $config_file" >&2 # 应用配置后处理 apply_config_post_processing return 0 else echo "错误: 无法加载配置文件: $config_file" >&2 return 1 fi } # 验证配置文件 validate_config_file() { local config_file="$1" # 检查文件是否可读 if [[ ! -r "$config_file" ]]; then echo "配置文件不可读: $config_file" >&2 return 1 fi # 检查文件大小(防止恶意文件) local file_size file_size=$(stat -c%s "$config_file" 2>/dev/null || echo 0) if [[ $file_size -gt 65536 ]]; then # 64KB echo "配置文件过大: $config_file" >&2 return 1 fi # 基本语法检查 if ! bash -n "$config_file" >/dev/null 2>&1; then echo "配置文件语法错误: $config_file" >&2 return 1 fi # 检查危险命令 if grep -qE '`|\$\(|\|\||&&|;|>|<|\||rm |dd |mkfs|fdisk' "$config_file"; then echo "配置文件包含危险命令: $config_file" >&2 return 1 fi return 0 } # 设置默认配置 setup_default_config() { echo "使用默认配置设置..." >&2 # 项目信息 PROJECT_NAME=${PROJECT_NAME:-"s-hy2"} PROJECT_VERSION=${PROJECT_VERSION:-"1.0.0"} PROJECT_REPO_URL=${PROJECT_REPO_URL:-"https://github.com/sindricn/s-hy2"} PROJECT_RAW_URL=${PROJECT_RAW_URL:-"https://raw.githubusercontent.com/sindricn/s-hy2/main"} # 基本设置 DEFAULT_LISTEN_PORT=${DEFAULT_LISTEN_PORT:-443} MAX_CONCURRENT_JOBS=${MAX_CONCURRENT_JOBS:-8} DEFAULT_DOWNLOAD_TIMEOUT=${DEFAULT_DOWNLOAD_TIMEOUT:-30} MAX_FILE_SIZE=${MAX_FILE_SIZE:-10485760} # 目录设置 HYSTERIA_CONFIG_DIR=${HYSTERIA_CONFIG_DIR:-"/etc/hysteria"} HYSTERIA_LOG_DIR=${HYSTERIA_LOG_DIR:-"/var/log/hysteria"} BACKUP_DIR=${BACKUP_DIR:-"/var/backups/s-hy2"} # 安全设置 ENABLE_SECURE_MODE=${ENABLE_SECURE_MODE:-true} ENABLE_INPUT_VALIDATION=${ENABLE_INPUT_VALIDATION:-true} ENABLE_DOWNLOAD_VERIFICATION=${ENABLE_DOWNLOAD_VERIFICATION:-true} # 日志设置 LOG_LEVEL=${LOG_LEVEL:-1} ENABLE_FILE_LOGGING=${ENABLE_FILE_LOGGING:-true} CONFIG_LOADED=true } # 配置后处理 apply_config_post_processing() { # 处理数组变量 if [[ -n "${MASQUERADE_DOMAINS_STR:-}" ]]; then IFS=' ' read -ra MASQUERADE_DOMAINS <<< "$MASQUERADE_DOMAINS_STR" fi if [[ -n "${SUPPORTED_OS_STR:-}" ]]; then IFS=' ' read -ra SUPPORTED_OS <<< "$SUPPORTED_OS_STR" fi if [[ -n "${REQUIRED_COMMANDS_STR:-}" ]]; then IFS=' ' read -ra REQUIRED_COMMANDS <<< "$REQUIRED_COMMANDS_STR" fi # 验证关键配置 validate_critical_config # 创建必要目录 create_required_directories # 设置环境变量 export PROJECT_NAME PROJECT_VERSION export HYSTERIA_CONFIG_DIR HYSTERIA_LOG_DIR export LOG_LEVEL ENABLE_SECURE_MODE } # 验证关键配置 validate_critical_config() { # 验证端口设置 if [[ ! "$DEFAULT_LISTEN_PORT" =~ ^[0-9]+$ ]] || [[ $DEFAULT_LISTEN_PORT -lt 1 ]] || [[ $DEFAULT_LISTEN_PORT -gt 65535 ]]; then echo "警告: 默认端口设置无效,使用443" >&2 DEFAULT_LISTEN_PORT=443 fi # 验证并发数设置 if [[ ! "$MAX_CONCURRENT_JOBS" =~ ^[0-9]+$ ]] || [[ $MAX_CONCURRENT_JOBS -lt 1 ]] || [[ $MAX_CONCURRENT_JOBS -gt 50 ]]; then echo "警告: 并发数设置无效,使用8" >&2 MAX_CONCURRENT_JOBS=8 fi # 验证日志级别 if [[ ! "$LOG_LEVEL" =~ ^[0-4]$ ]]; then echo "警告: 日志级别无效,使用默认级别1" >&2 LOG_LEVEL=1 fi } # 创建必要目录 create_required_directories() { local dirs=( "$HYSTERIA_CONFIG_DIR" "$HYSTERIA_LOG_DIR" "$BACKUP_DIR" "${CERT_DIR:-$HYSTERIA_CONFIG_DIR/certs}" ) for dir in "${dirs[@]}"; do if [[ ! -d "$dir" ]]; then if mkdir -p "$dir" 2>/dev/null; then echo "创建目录: $dir" >&2 else echo "警告: 无法创建目录: $dir" >&2 fi fi done } # 获取配置值 get_config() { local key="$1" local default_value="${2:-}" # 确保配置已加载 if [[ "$CONFIG_LOADED" != "true" ]]; then load_config fi # 获取配置值 local value="${!key:-$default_value}" echo "$value" } # 设置配置值 set_config() { local key="$1" local value="$2" # 动态设置变量 declare -g "$key"="$value" # 如果有配置文件,可以选择性地写回 if [[ -n "${CONFIG_FILE_PATH:-}" ]] && [[ "$ENABLE_CONFIG_PERSISTENCE" == "true" ]]; then update_config_file "$key" "$value" fi } # 更新配置文件 update_config_file() { local key="$1" local value="$2" local config_file="${CONFIG_FILE_PATH:-}" if [[ -z "$config_file" ]] || [[ ! -w "$config_file" ]]; then return 1 fi # 创建备份 cp "$config_file" "${config_file}.bak.$(date +%s)" # 更新配置 if grep -q "^$key=" "$config_file"; then sed -i "s/^$key=.*/$key=\"$value\"/" "$config_file" else echo "$key=\"$value\"" >> "$config_file" fi } # 显示当前配置 show_config() { if [[ "$CONFIG_LOADED" != "true" ]]; then load_config fi echo "=== 当前配置 ===" echo "配置文件: ${CONFIG_FILE_PATH:-"默认设置"}" echo "项目名称: $PROJECT_NAME" echo "项目版本: $PROJECT_VERSION" echo "默认端口: $DEFAULT_LISTEN_PORT" echo "最大并发: $MAX_CONCURRENT_JOBS" echo "安全模式: $ENABLE_SECURE_MODE" echo "日志级别: $LOG_LEVEL" echo "配置目录: $HYSTERIA_CONFIG_DIR" echo "日志目录: $HYSTERIA_LOG_DIR" } # 导出函数 export -f load_config get_config set_config show_config # 如果作为模块导入,自动加载配置 if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then load_config fi