shell函数库

set -euo pipefail  # 严格模式:遇到错误退出,未定义变量报错

SCRIPT_NAME=$(basename "$0")
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
LOG_FILE="/var/log/${SCRIPT_NAME%.*}.log"
COMPOSE_VERSION="2.27.1"  # 使用更新的稳定版本

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 日志函数
log() {
    local level=$1
    shift
    local message="$*"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    echo -e "${timestamp} [${level}] ${message}" | tee -a "$LOG_FILE"
}

log_info() { log "INFO" "$@"; }
log_warn() { log "WARN" "${YELLOW}$@${NC}"; }
log_error() { log "ERROR" "${RED}$@${NC}"; }
log_success() { log "SUCCESS" "${GREEN}$@${NC}"; }
# 通用Shell函数库
# 描述: 包含脚本开发中最常用的函数集合

# 设置严格模式
set -euo pipefail

# 颜色定义
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[0;33m'
readonly BLUE='\033[0;34m'
readonly PURPLE='\033[0;35m'
readonly CYAN='\033[0;36m'
readonly WHITE='\033[0;37m'
readonly NC='\033[0m' # No Color

# 日志级别定义
readonly LOG_LEVEL_DEBUG=0
readonly LOG_LEVEL_INFO=1
readonly LOG_LEVEL_WARN=2
readonly LOG_LEVEL_ERROR=3
readonly LOG_LEVEL_FATAL=4

# 全局变量
SCRIPT_NAME=$(basename "$0")
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
LOG_LEVEL=${LOG_LEVEL:-1}
LOG_FILE="${LOG_FILE:-/tmp/${SCRIPT_NAME%.*}.log}"

#==============================================================================
# 日志记录函数
#==============================================================================

# 打印调试信息
log_debug() {
    if [[ $LOG_LEVEL -le $LOG_LEVEL_DEBUG ]]; then
        echo -e "${CYAN}[DEBUG]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $*" | tee -a "$LOG_FILE"
    fi
}

# 打印普通信息
log_info() {
    if [[ $LOG_LEVEL -le $LOG_LEVEL_INFO ]]; then
        echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $*" | tee -a "$LOG_FILE"
    fi
}

# 打印警告信息
log_warn() {
    if [[ $LOG_LEVEL -le $LOG_LEVEL_WARN ]]; then
        echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $*" | tee -a "$LOG_FILE"
    fi
}

# 打印错误信息
log_error() {
    if [[ $LOG_LEVEL -le $LOG_LEVEL_ERROR ]]; then
        echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $*" | tee -a "$LOG_FILE"
    fi
}

# 打印致命错误并退出
log_fatal() {
    if [[ $LOG_LEVEL -le $LOG_LEVEL_FATAL ]]; then
        echo -e "${RED}[FATAL]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $*" | tee -a "$LOG_FILE"
    fi
    exit 1
}

#==============================================================================
# 文件操作函数
#==============================================================================

# 检查文件是否存在
file_exists() {
    [[ -f "$1" ]]
}

# 检查目录是否存在
dir_exists() {
    [[ -d "$1" ]]
}

# 创建目录(如果不存在)
ensure_dir() {
    local dir="$1"
    if [[ ! -d "$dir" ]]; then
        mkdir -p "$dir"
        log_info "创建目录: $dir"
    fi
}

# 安全删除文件
safe_rm() {
    local file="$1"
    if file_exists "$file"; then
        rm -f "$file"
        log_info "删除文件: $file"
    fi
}

# 备份文件
backup_file() {
    local src="$1"
    local backup="${src}.backup.$(date +%Y%m%d_%H%M%S)"

    if file_exists "$src"; then
        cp "$src" "$backup"
        log_info "备份文件: $src -> $backup"
        echo "$backup"
    else
        log_error "源文件不存在: $src"
        return 1
    fi
}

# 获取文件大小(人类可读格式)
get_file_size() {
    local file="$1"
    if file_exists "$file"; then
        du -h "$file" | cut -f1
    else
        echo "0"
    fi
}

# 查找文件
find_files() {
    local pattern="$1"
    local dir="${2:-.}"
    find "$dir" -type f -name "$pattern" 2>/dev/null
}

#==============================================================================
# 字符串处理函数
#==============================================================================

# 字符串转小写
to_lower() {
    echo "$1" | tr '[:upper:]' '[:lower:]'
}

# 字符串转大写
to_upper() {
    echo "$1" | tr '[:lower:]' '[:upper:]'
}

# 去除字符串首尾空格
trim() {
    local str="$1"
    str="${str#"${str%%[![:space:]]*}"}"
    str="${str%"${str##*[![:space:]]}"}"
    echo "$str"
}

# 检查字符串是否为空
is_empty() {
    [[ -z "${1:-}" ]]
}

# 检查字符串是否包含子串
contains() {
    local str="$1"
    local substr="$2"
    [[ "$str" == *"$substr"* ]]
}

# 检查字符串是否以指定前缀开始
starts_with() {
    local str="$1"
    local prefix="$2"
    [[ "$str" == "$prefix"* ]]
}

# 检查字符串是否以指定后缀结束
ends_with() {
    local str="$1"
    local suffix="$2"
    [[ "$str" == *"$suffix" ]]
}

# 替换字符串中的子串
replace_str() {
    local str="$1"
    local old="$2"
    local new="$3"
    echo "${str//$old/$new}"
}

#==============================================================================
# 网络检查函数
#==============================================================================

# 检查网络连接
check_network() {
    local host="${1:-8.8.8.8}"
    local timeout="${2:-3}"

    if ping -c 1 -W "$timeout" "$host" >/dev/null 2>&1; then
        log_info "网络连接正常"
        return 0
    else
        log_error "网络连接失败"
        return 1
    fi
}

# 检查URL是否可访问
check_url() {
    local url="$1"
    local timeout="${2:-10}"

    if command -v curl >/dev/null 2>&1; then
        if curl -s --max-time "$timeout" --head "$url" | head -n 1 | grep -q "200\|301\|302"; then
            log_info "URL可访问: $url"
            return 0
        else
            log_error "URL不可访问: $url"
            return 1
        fi
    else
        log_error "curl命令未找到"
        return 1
    fi
}

# 获取本机IP地址
get_local_ip() {
    local ip
    if command -v ip >/dev/null 2>&1; then
        ip=$(ip route get 1 2>/dev/null | awk '{print $7}' | head -1)
    elif command -v ifconfig >/dev/null 2>&1; then
        ip=$(ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | head -1)
    else
        ip="127.0.0.1"
    fi
    echo "$ip"
}

#==============================================================================
# 系统信息函数
#==============================================================================

# 获取操作系统信息
get_os_info() {
    if [[ -f /etc/os-release ]]; then
        . /etc/os-release
        echo "$NAME $VERSION"
    elif [[ "$OSTYPE" == "darwin"* ]]; then
        echo "macOS $(sw_vers -productVersion)"
    else
        echo "Unknown OS"
    fi
}

# 获取CPU信息
get_cpu_info() {
    if [[ "$OSTYPE" == "darwin"* ]]; then
        sysctl -n machdep.cpu.brand_string
    else
        grep -m1 "model name" /proc/cpuinfo | cut -d':' -f2 | sed 's/^ *//'
    fi
}

# 获取内存信息
get_memory_info() {
    if [[ "$OSTYPE" == "darwin"* ]]; then
        local mem_bytes=$(sysctl -n hw.memsize)
        echo "$((mem_bytes / 1024 / 1024 / 1024))GB"
    else
        free -h | awk '/^Mem:/ {print $2}'
    fi
}

# 检查命令是否存在
command_exists() {
    command -v "$1" >/dev/null 2>&1
}

# 获取当前用户信息
get_user_info() {
    echo "用户: $(whoami)"
    echo "主机: $(hostname)"
    echo "家目录: $HOME"
    echo "Shell: $SHELL"
}

#==============================================================================
# 错误处理函数
#==============================================================================

# 错误处理
handle_error() {
    local exit_code=$?
    local line_number=$1
    log_error "脚本执行失败,退出码: $exit_code,行号: $line_number"
    exit $exit_code
}

# 设置错误陷阱
setup_error_handling() {
    trap 'handle_error $LINENO' ERR
}

# 检查依赖命令
check_dependencies() {
    local missing_deps=()

    for cmd in "$@"; do
        if ! command_exists "$cmd"; then
            missing_deps+=("$cmd")
        fi
    done

    if [[ ${#missing_deps[@]} -gt 0 ]]; then
        log_error "缺少依赖命令: ${missing_deps[*]}"
        return 1
    fi

    return 0
}

#==============================================================================
# 进度显示函数
#==============================================================================

# 显示进度条
show_progress() {
    local current=$1
    local total=$2
    local width=50

    local percentage=$((current * 100 / total))
    local filled=$((width * current / total))
    local empty=$((width - filled))

    printf "\r["
    printf "%${filled}s" | tr ' ' '='
    printf "%${empty}s" | tr ' ' ' '
    printf "] %d%%" "$percentage"

    if [[ $current -eq $total ]]; then
        echo
    fi
}

# 显示旋转进度
show_spinner() {
    local pid=$1
    local delay=0.1
    local spinstr='|/-\'

    while kill -0 "$pid" 2>/dev/null; do
        local temp=${spinstr#?}
        printf " [%c]  " "$spinstr"
        local spinstr=$temp${spinstr%"$temp"}
        sleep $delay
        printf "\b\b\b\b\b\b"
    done
    printf "    \b\b\b\b"
}

#==============================================================================
# 用户交互函数
#==============================================================================

# 确认提示
confirm() {
    local message="${1:-是否继续执行?}"
    local response

    while true; do
        echo -n "$message [y/N]: "
        read -r response
        case $response in
            [yY][eE][sS]|[yY])
                return 0
                ;;
            [nN][oO]|[nN]|"")
                return 1
                ;;
            *)
                echo "请输入 y 或 n"
                ;;
        esac
    done
}

# 输入提示
prompt_input() {
    local prompt="$1"
    local default="${2:-}"
    local input

    if [[ -n "$default" ]]; then
        echo -n "$prompt [$default]: "
    else
        echo -n "$prompt: "
    fi

    read -r input

    if [[ -z "$input" && -n "$default" ]]; then
        echo "$default"
    else
        echo "$input"
    fi
}

# 选择菜单
show_menu() {
    local title="$1"
    shift
    local options=("$@")

    echo
    echo "=== $title ==="
    for i in "${!options[@]}"; do
        echo "$((i+1)). ${options[$i]}"
    done
    echo

    local choice
    while true; do
        echo -n "请选择 [1-${#options[@]}]: "
        read -r choice

        if [[ "$choice" =~ ^[0-9]+$ ]] && [[ $choice -ge 1 ]] && [[ $choice -le ${#options[@]} ]]; then
            echo $((choice-1))
            return 0
        else
            echo "无效选择,请重试"
        fi
    done
}

#==============================================================================
# 时间日期函数
#==============================================================================

# 获取当前时间戳
get_timestamp() {
    date +%s
}

# 获取格式化日期
get_date() {
    local format="${1:-%Y-%m-%d %H:%M:%S}"
    date "+$format"
}

# 计算时间差
time_diff() {
    local start=$1
    local end=$2
    echo $((end - start))
}

#==============================================================================
# 数学计算函数
#==============================================================================

# 检查是否为数字
is_number() {
    [[ "$1" =~ ^-?[0-9]+([.][0-9]+)?$ ]]
}

# 比较数字
compare_numbers() {
    local op="$1"
    local n1="$2"
    local n2="$3"

    case "$op" in
        "eq") [[ "$n1" == "$n2" ]] ;;
        "ne") [[ "$n1" != "$n2" ]] ;;
        "gt") [[ $(echo "$n1 > $n2" | bc -l) == 1 ]] ;;
        "lt") [[ $(echo "$n1 < $n2" | bc -l) == 1 ]] ;;
        "ge") [[ $(echo "$n1 >= $n2" | bc -l) == 1 ]] ;;
        "le") [[ $(echo "$n1 <= $n2" | bc -l) == 1 ]] ;;
        *) return 1 ;;
    esac
}

#==============================================================================
# 初始化函数
#==============================================================================

# 初始化脚本环境
init_script() {
    setup_error_handling

    # 确保日志目录存在
    ensure_dir "$(dirname "$LOG_FILE")"

    log_info "脚本初始化完成"
    log_info "脚本名称: $SCRIPT_NAME"
    log_info "脚本目录: $SCRIPT_DIR"
    log_info "日志文件: $LOG_FILE"
    log_info "操作系统: $(get_os_info)"
}

#==============================================================================
# 使用示例
#==============================================================================

# 使用示例函数
show_usage_example() {
    cat << EOF
使用示例:

# 1. 引入函数库
source common_functions.sh

# 2. 初始化
init_script

# 3. 使用日志函数
log_info "这是一条信息"
log_error "这是一条错误"

# 4. 文件操作
if file_exists "/etc/passwd"; then
    log_info "文件存在"
fi

# 5. 网络检查
if check_network; then
    log_info "网络正常"
fi

# 6. 用户交互
if confirm "是否继续?"; then
    log_info "用户选择了继续"
fi

# 7. 进度显示
for i in {1..10}; do
    show_progress $i 10
    sleep 0.5
done

EOF
}

# 如果直接运行此脚本,显示使用示例
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    show_usage_example
fi

readonly SCRIPT_NAME=$(basename "$0")

# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >&2
}

# 错误处理函数
error_exit() {
    log "错误: $1"
    exit 1
}
==================================================================

#!/bin/bash

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 带颜色和时间的调试函数
debug() {
    echo -e "${BLUE}[DEBUG $(date '+%Y-%m-%d %H:%M:%S')]${NC} $*" >&2
}

info() {
    echo -e "${GREEN}[INFO $(date '+%Y-%m-%d %H:%M:%S')]${NC} $*" >&2
}

warn() {
    echo -e "${YELLOW}[WARN $(date '+%Y-%m-%d %H:%M:%S')]${NC} $*" >&2
}

error() {
    echo -e "${RED}[ERROR $(date '+%Y-%m-%d %H:%M:%S')]${NC} $*" >&2
    exit 1
}

函数库高级版本

#!/bin/bash
# 高级Shell函数库
# 日期: 2025-12-12
# 描述: 包含高级功能的函数集合,如JSON处理、配置管理、加密解密等

# 设置严格模式
set -euo pipefail

# 引入基础函数库
if [[ -f "$(dirname "${BASH_SOURCE[0]}")/common_functions.sh" ]]; then
    source "$(dirname "${BASH_SOURCE[0]}")/common_functions.sh"
fi

#==============================================================================
# JSON处理函数
#==============================================================================

# 检查JSON格式是否有效
is_valid_json() {
    local json="$1"
    if command -v jq >/dev/null 2>&1; then
        echo "$json" | jq . >/dev/null 2>&1
    elif command -v python3 >/dev/null 2>&1; then
        python3 -c "import json; json.loads('$json')" >/dev/null 2>&1
    else
        log_error "未找到JSON解析工具 (jq 或 python3)"
        return 1
    fi
}

# 从JSON中获取值
get_json_value() {
    local json="$1"
    local key="$2"
    
    if command -v jq >/dev/null 2>&1; then
        echo "$json" | jq -r ".$key // empty" 2>/dev/null
    elif command -v python3 >/dev/null 2>&1; then
        python3 -c "import json; data = json.loads('$json'); print(data.get('$key', ''))" 2>/dev/null
    else
        log_error "未找到JSON解析工具"
        return 1
    fi
}

# 设置JSON值
set_json_value() {
    local json="$1"
    local key="$2"
    local value="$3"
    
    if command -v jq >/dev/null 2>&1; then
        echo "$json" | jq ".$key = \"$value\"" 2>/dev/null
    else
        log_error "需要安装jq工具"
        return 1
    fi
}

# 合并两个JSON对象
merge_json() {
    local json1="$1"
    local json2="$2"
    
    if command -v jq >/dev/null 2>&1; then
        echo "$json1" "$json2" | jq -s '.[0] * .[1]' 2>/dev/null
    else
        log_error "需要安装jq工具"
        return 1
    fi
}

#==============================================================================
# 配置文件处理函数
#==============================================================================

# 读取INI配置文件
read_ini_config() {
    local file="$1"
    local section="$2"
    local key="$3"
    
    if [[ ! -f "$file" ]]; then
        log_error "配置文件不存在: $file"
        return 1
    fi
    
    local value
    value=$(awk -F '=' -v section="[$section]" -v key="$key" '
        $0 == section { found=1; next }
        found && /^\[/ { exit }
        found && $1 ~ "^ *"key" *" { gsub(/^[ \t]+|[ \t]+$/, "", $2); print $2; exit }
    ' "$file")
    
    echo "$value"
}

# 写入INI配置文件
write_ini_config() {
    local file="$1"
    local section="$2"
    local key="$3"
    local value="$4"
    
    ensure_dir "$(dirname "$file")"
    
    if [[ ! -f "$file" ]]; then
        echo "[$section]" > "$file"
        echo "$key=$value" >> "$file"
        log_info "创建配置文件: $file"
    else
        # 使用sed更新或添加配置
        if grep -q "^\[$section\]" "$file"; then
            if grep -A 20 "^\[$section\]" "$file" | grep -q "^$key="; then
                sed -i "/^\[$section\]/,/^$/ s/^$key=.*/$key=$value/" "$file"
            else
                sed -i "/^\[$section\]/a $key=$value" "$file"
            fi
        else
            echo "" >> "$file"
            echo "[$section]" >> "$file"
            echo "$key=$value" >> "$file"
        fi
        log_info "更新配置: [$section] $key=$value"
    fi
}

# 读取YAML配置(简单实现)
read_yaml_config() {
    local file="$1"
    local key="$2"
    
    if [[ ! -f "$file" ]]; then
        log_error "YAML文件不存在: $file"
        return 1
    fi
    
    if command -v yq >/dev/null 2>&1; then
        yq eval ".$key" "$file" 2>/dev/null
    else
        # 简单的YAML解析
        grep "^$key:" "$file" | head -1 | cut -d':' -f2- | sed 's/^[ \t]*//'
    fi
}

#==============================================================================
# 加密解密函数
#==============================================================================

# Base64编码
base64_encode() {
    local text="$1"
    if command -v base64 >/dev/null 2>&1; then
        echo -n "$text" | base64
    else
        log_error "base64命令未找到"
        return 1
    fi
}

# Base64解码
base64_decode() {
    local encoded="$1"
    if command -v base64 >/dev/null 2>&1; then
        echo -n "$encoded" | base64 -d
    else
        log_error "base64命令未找到"
        return 1
    fi
}

# MD5哈希
md5_hash() {
    local text="$1"
    if command -v md5sum >/dev/null 2>&1; then
        echo -n "$text" | md5sum | cut -d' ' -f1
    elif command -v md5 >/dev/null 2>&1; then
        echo -n "$text" | md5
    else
        log_error "未找到MD5工具"
        return 1
    fi
}

# SHA256哈希
sha256_hash() {
    local text="$1"
    if command -v sha256sum >/dev/null 2>&1; then
        echo -n "$text" | sha256sum | cut -d' ' -f1
    elif command -v shasum >/dev/null 2>&1; then
        echo -n "$text" | shasum -a 256 | cut -d' ' -f1
    else
        log_error "未找到SHA256工具"
        return 1
    fi
}

# 生成随机字符串
generate_random_string() {
    local length="${1:-16}"
    local chars="A-Za-z0-9"
    
    if command -v openssl >/dev/null 2>&1; then
        openssl rand -base64 "$length" | tr -d "=+/" | cut -c1-"$length"
    elif command -v tr >/dev/null 2>&1; then
        tr -dc "$chars" </dev/urandom | head -c "$length"
    else
        date | md5sum | head -c "$length"
    fi
}

#==============================================================================
# 数据验证函数
#==============================================================================

# 验证邮箱格式
is_valid_email() {
    local email="$1"
    [[ "$email" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]
}

# 验证手机号(中国)
is_valid_phone() {
    local phone="$1"
    [[ "$phone" =~ ^1[3-9][0-9]{9}$ ]]
}

# 验证IP地址
is_valid_ip() {
    local ip="$1"
    local regex='^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
    [[ "$ip" =~ $regex ]]
}

# 验证URL
is_valid_url() {
    local url="$1"
    local regex='^(https?|ftp)://[^\s/$.?#].[^\s]*$'
    [[ "$url" =~ $regex ]]
}

# 验证端口号
is_valid_port() {
    local port="$1"
    [[ "$port" =~ ^[0-9]+$ ]] && [[ $port -ge 1 ]] && [[ $port -le 65535 ]]
}

#==============================================================================
# 系统高级功能函数
#==============================================================================

# 获取进程PID
get_process_pid() {
    local process_name="$1"
    pgrep -f "$process_name" 2>/dev/null || echo ""
}

# 检查进程是否在运行
is_process_running() {
    local process_name="$1"
    pgrep -f "$process_name" >/dev/null 2>&1
}

# 安全杀死进程
safe_kill_process() {
    local process_name="$1"
    local signal="${2:-TERM}"
    
    local pids
    pids=$(get_process_pid "$process_name")
    
    if [[ -n "$pids" ]]; then
        log_info "正在终止进程: $process_name (PID: $pids)"
        kill -"$signal" $pids 2>/dev/null
        
        # 等待进程结束
        local count=0
        while is_process_running "$process_name" && [[ $count -lt 10 ]]; do
            sleep 1
            ((count++))
        done
        
        if is_process_running "$process_name"; then
            log_warn "进程仍在运行,可能需要强制终止"
            return 1
        else
            log_info "进程已成功终止"
            return 0
        fi
    else
        log_warn "未找到进程: $process_name"
        return 1
    fi
}

# 获取系统负载
get_system_load() {
    if [[ "$OSTYPE" == "darwin"* ]]; then
        uptime | awk '{print $(NF-2)}' | sed 's/,//'
    else
        uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | sed 's/,//'
    fi
}

# 获取磁盘使用率
get_disk_usage() {
    local path="${1:-/}"
    df -h "$path" | awk 'NR==2 {print $5}' | sed 's/%//'
}

# 获取内存使用率
get_memory_usage() {
    if [[ "$OSTYPE" == "darwin"* ]]; then
        vm_stat | awk '/Pages active/ {active=$3} /Pages inactive/ {inactive=$3} /Pages wired/ {wired=$3} /Pages free/ {free=$3} END {total=active+inactive+wired+free; used=active+inactive+wired; print int(used/total*100)}' | sed 's/[^0-9]//g'
    else
        free | awk '/Mem:/ {printf("%.0f", $3/$2*100)}'
    fi
}

#==============================================================================
# 备份恢复函数
#==============================================================================

# 创建压缩备份
create_backup() {
    local source="$1"
    local backup_dir="${2:-./backups}"
    local backup_name="${3:-backup_$(date +%Y%m%d_%H%M%S)}"
    
    ensure_dir "$backup_dir"
    
    if [[ -d "$source" ]]; then
        local backup_file="$backup_dir/${backup_name}.tar.gz"
        tar -czf "$backup_file" -C "$(dirname "$source")" "$(basename "$source")" 2>/dev/null
        log_info "目录备份完成: $source -> $backup_file"
        echo "$backup_file"
    elif [[ -f "$source" ]]; then
        local backup_file="$backup_dir/${backup_name}.gz"
        gzip -c "$source" > "$backup_file"
        log_info "文件备份完成: $source -> $backup_file"
        echo "$backup_file"
    else
        log_error "备份源不存在: $source"
        return 1
    fi
}

# 恢复备份
restore_backup() {
    local backup_file="$1"
    local target_dir="${2:-.}"
    
    if [[ ! -f "$backup_file" ]]; then
        log_error "备份文件不存在: $backup_file"
        return 1
    fi
    
    ensure_dir "$target_dir"
    
    if [[ "$backup_file" == *.tar.gz ]]; then
        tar -xzf "$backup_file" -C "$target_dir"
        log_info "备份恢复完成: $backup_file -> $target_dir"
    elif [[ "$backup_file" == *.gz ]]; then
        local filename=$(basename "$backup_file" .gz)
        gzip -dc "$backup_file" > "$target_dir/$filename"
        log_info "文件恢复完成: $backup_file -> $target_dir/$filename"
    else
        log_error "不支持的备份文件格式: $backup_file"
        return 1
    fi
}

#==============================================================================
# 使用示例
#==============================================================================

# 显示使用示例
show_advanced_usage_example() {
    cat << EOF
高级函数库使用示例:

# 1. 引入函数库
source advanced_functions.sh

# 2. JSON处理
json_data='{"name": "John", "age": 30}'
if is_valid_json "$json_data"; then
    name=$(get_json_value "$json_data" "name")
    log_info "姓名: $name"
fi

# 3. 配置文件操作
write_ini_config "app.conf" "database" "host" "localhost"
db_host=$(read_ini_config "app.conf" "database" "host")
log_info "数据库主机: $db_host"

# 4. 数据验证
email="test@example.com"
if is_valid_email "$email"; then
    log_info "邮箱格式正确"
fi

# 5. 加密解密
password="secret123"
encoded=$(base64_encode "$password")
decoded=$(base64_decode "$encoded")
log_info "原始: $password, 编码: $encoded, 解码: $decoded"

# 6. 系统监控
load=$(get_system_load)
memory=$(get_memory_usage)
log_info "系统负载: $load, 内存使用率: ${memory}%"

# 7. 备份恢复
backup_file=$(create_backup "/important/data")
log_info "备份文件: $backup_file"

# 8. 进程管理
if is_process_running "nginx"; then
    log_info "Nginx正在运行"
fi

EOF
}

# 如果直接运行此脚本,显示使用示例
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    show_advanced_usage_example
fi

TIME-WAIT 状态监控脚本

#!/bin/bash

# TIME-WAIT 状态监控脚本

monitor_timewait() {
    echo "=== TIME-WAIT 连接统计 ==="
    ss -ant | awk '
    NR>1 {states[$1]++}
    END {
        printf "%-12s %-8s\n", "状态", "数量"
        printf "%-12s %-8s\n", "------", "------"
        for (state in states) {
            printf "%-12s %-8s\n", state, states[state]
        }
    }'
    
    echo -e "\n=== 详细的 TIME-WAIT 连接 ==="
    ss -ant state time-wait | head -20
    
    echo -e "\n=== 内核参数检查 ==="
    sysctl -a 2>/dev/null | grep -E "(tw_reuse|tw_recycle|fin_timeout|max_tw_buckets)" | grep -v "net.ipv6"
}

# 持续监控
continuous_monitor() {
    while true; do
        clear
        monitor_timewait
        echo -e "\n按 Ctrl+C 退出监控"
        sleep 5
    done
}

# 检查特定端口的 TIME-WAIT
check_port_timewait() {
    local port=${1:-80}
    echo "=== 端口 $port 的 TIME-WAIT 连接 ==="
    ss -ant sport = :$port state time-wait
    echo -e "\n总数: $(ss -ant sport = :$port state time-wait | wc -l)"
}

case "${1:-monitor}" in
    "monitor")
        monitor_timewait
        ;;
    "continuous")
        continuous_monitor
        ;;
    "port")
        check_port_timewait "$2"
        ;;
    *)
        echo "用法: $0 [monitor|continuous|port PORT]"
        ;;
esac

优化脚本

#!/bin/bash

# TIME-WAIT 自动优化脚本

apply_optimizations() {
    local level="${1:-medium}"
    
    case "$level" in
        "light")
            # 轻度优化
            sudo sysctl -w net.ipv4.tcp_tw_reuse=1
            sudo sysctl -w net.ipv4.tcp_fin_timeout=45
            ;;
        "medium")
            # 中度优化
            sudo sysctl -w net.ipv4.tcp_tw_reuse=1
            sudo sysctl -w net.ipv4.tcp_fin_timeout=30
            sudo sysctl -w net.ipv4.tcp_max_tw_buckets=180000
            sudo sysctl -w net.ipv4.ip_local_port_range="10000 65535"
            ;;
        "aggressive")
            # 激进优化
            sudo sysctl -w net.ipv4.tcp_tw_reuse=1
            sudo sysctl -w net.ipv4.tcp_tw_recycle=1
            sudo sysctl -w net.ipv4.tcp_fin_timeout=15
            sudo sysctl -w net.ipv4.tcp_max_tw_buckets=100000
            sudo sysctl -w net.ipv4.ip_local_port_range="15000 65535"
            ;;
    esac
    
    echo "已应用 $level 级别的优化"
}

# 备份当前配置
backup_config() {
    local backup_file="/tmp/sysctl_backup_$(date +%Y%m%d_%H%M%S).conf"
    sysctl -a 2>/dev/null | grep -E "(tw_reuse|tw_recycle|fin_timeout|max_tw_buckets|ip_local_port_range)" > "$backup_file"
    echo "配置已备份到: $backup_file"
}

# 恢复配置
restore_config() {
    local backup_file="$1"
    if [[ -f "$backup_file" ]]; then
        while IFS= read -r line; do
            if [[ "$line" =~ ^[a-z] ]]; then
                local key=$(echo "$line" | cut -d'=' -f1 | awk '{print $1}')
                local value=$(echo "$line" | cut -d'=' -f2 | awk '{print $1}')
                sudo sysctl -w "$key=$value"
            fi
        done < "$backup_file"
        echo "配置已从 $backup_file 恢复"
    else
        echo "备份文件不存在: $backup_file"
    fi
}

case "${1:-help}" in
    "apply")
        apply_optimizations "$2"
        ;;
    "backup")
        backup_config
        ;;
    "restore")
        restore_config "$2"
        ;;
    *)
        echo "用法: $0 [apply LEVEL|backup|restore FILE]"
        echo "LEVEL: light|medium|aggressive"
        ;;
esac

日期函数

#!/bin/bash
#===============================================================================
# Shell日期处理函数库
# 描述: 提供各种日期相关的实用函数和组合方法
# 版本: 1.0
#===============================================================================

# 设置错误处理
set -euo pipefail

#===============================================================================
# 基础配置和检查
#===============================================================================

# 检查系统类型和命令可用性
check_date_commands() {
    local commands=("date" "cal" "seq" "awk" "sed")
    local missing=()
    
    for cmd in "${commands[@]}"; do
        if ! command -v "$cmd" &> /dev/null; then
            missing+=("$cmd")
        fi
    done
    
    if [ ${#missing[@]} -ne 0 ]; then
        echo "警告: 缺少以下命令: ${missing[*]}"
        echo "某些功能可能无法使用"
    fi
}

#===============================================================================
# 基础日期获取函数
#===============================================================================

# 获取当前日期的各种格式
get_current_date_formats() {
    echo "=== 当前日期格式示例 ==="
    
    # ISO格式 (YYYY-MM-DD)
    echo "ISO格式: $(date '+%Y-%m-%d')"
    
    # 美式格式 (MM/DD/YYYY)
    echo "美式格式: $(date '+%m/%d/%Y')"
    
    # 欧式格式 (DD/MM/YYYY)
    echo "欧式格式: $(date '+%d/%m/%Y')"
    
    # 中文格式 (YYYY年MM月DD日)
    echo "中文格式: $(date '+%Y年%m月%d日')"
    
    # 时间戳 (秒)
    echo "Unix时间戳: $(date '+%s')"
    
    # 时间戳 (毫秒)
    echo "毫秒时间戳: $(date '+%s%3N')"
    
    # 带时间的完整格式
    echo "完整日期时间: $(date '+%Y-%m-%d %H:%M:%S')"
    
    # RFC 2822格式
    echo "RFC 2822格式: $(date '+%a, %d %b %Y %H:%M:%S %z')"
    
    # 自定义格式
    echo "自定义格式1: $(date '+%Y%m%d_%H%M%S')"
    echo "自定义格式2: $(date '+%d-%b-%Y')"
    echo "自定义格式3: $(date '+%A, %B %d, %Y')"
}

#===============================================================================
# 日期计算函数
#===============================================================================

# 日期加减计算
date_calculate() {
    local base_date="${1:-$(date '+%Y-%m-%d')}"
    local operation="${2:-+}"  # + 或 -
    local days="${3:-1}"
    
    if [[ "$operation" == "+" ]]; then
        date -d "$base_date + $days days" '+%Y-%m-%d'
    else
        date -d "$base_date - $days days" '+%Y-%m-%d'
    fi
}

# 月份加减计算
month_calculate() {
    local base_date="${1:-$(date '+%Y-%m-%d')}"
    local operation="${2:-+}"
    local months="${3:-1}"
    
    if [[ "$operation" == "+" ]]; then
        date -d "$base_date + $months months" '+%Y-%m-%d'
    else
        date -d "$base_date - $months months" '+%Y-%m-%d'
    fi
}

# 年份加减计算
year_calculate() {
    local base_date="${1:-$(date '+%Y-%m-%d')}"
    local operation="${2:-+}"
    local years="${3:-1}"
    
    if [[ "$operation" == "+" ]]; then
        date -d "$base_date + $years years" '+%Y-%m-%d'
    else
        date -d "$base_date - $years years" '+%Y-%m-%d'
    fi
}

#===============================================================================
# 日期比较函数
#===============================================================================

# 比较两个日期
compare_dates() {
    local date1="$1"
    local date2="$2"
    
    local timestamp1=$(date -d "$date1" '+%s')
    local timestamp2=$(date -d "$date2" '+%s')
    
    if [[ $timestamp1 -lt $timestamp2 ]]; then
        echo "-1"  # date1 < date2
    elif [[ $timestamp1 -gt $timestamp2 ]]; then
        echo "1"   # date1 > date2
    else
        echo "0"   # date1 = date2
    fi
}

# 检查日期是否在范围内
is_date_in_range() {
    local check_date="$1"
    local start_date="$2"
    local end_date="$3"
    
    local check_ts=$(date -d "$check_date" '+%s')
    local start_ts=$(date -d "$start_date" '+%s')
    local end_ts=$(date -d "$end_date" '+%s')
    
    if [[ $check_ts -ge $start_ts && $check_ts -le $end_ts ]]; then
        echo "true"
    else
        echo "false"
    fi
}

# 计算两个日期之间的天数
days_between() {
    local date1="$1"
    local date2="$2"
    
    local ts1=$(date -d "$date1" '+%s')
    local ts2=$(date -d "$date2" '+%s')
    
    local diff=$(( (ts2 - ts1) / 86400 ))
    echo ${diff#-}  # 返回绝对值
}

#===============================================================================
# 日期格式转换函数
#===============================================================================

# 时间戳转日期
timestamp_to_date() {
    local timestamp="$1"
    local format="${2:-%Y-%m-%d %H:%M:%S}"
    
    date -d "@$timestamp" "+$format"
}

# 日期转时间戳
date_to_timestamp() {
    local date_str="$1"
    date -d "$date_str" '+%s'
}

# 转换日期格式
convert_date_format() {
    local date_str="$1"
    local input_format="$2"
    local output_format="$3"
    
    # 先解析输入格式,再输出目标格式
    case "$input_format" in
        "iso"|"ISO")
            date -d "$date_str" "+$output_format"
            ;;
        "us"|"US")
            # MM/DD/YYYY to target format
            local month=$(echo "$date_str" | cut -d'/' -f1)
            local day=$(echo "$date_str" | cut -d'/' -f2)
            local year=$(echo "$date_str" | cut -d'/' -f3)
            date -d "$year-$month-$day" "+$output_format"
            ;;
        "eu"|"EU")
            # DD/MM/YYYY to target format
            local day=$(echo "$date_str" | cut -d'/' -f1)
            local month=$(echo "$date_str" | cut -d'/' -f2)
            local year=$(echo "$date_str" | cut -d'/' -f3)
            date -d "$year-$month-$day" "+$output_format"
            ;;
        *)
            echo "不支持的输入格式: $input_format"
            return 1
            ;;
    esac
}

#===============================================================================
# 工作日计算函数
#===============================================================================

# 获取星期几 (1-7, 1=Monday)
get_weekday() {
    local date_str="${1:-$(date '+%Y-%m-%d')}"
    date -d "$date_str" '+%u'
}

# 获取星期几名称
get_weekday_name() {
    local date_str="${1:-$(date '+%Y-%m-%d')}"
    local locale="${2:-zh_CN}"
    
    if [[ "$locale" == "en" ]]; then
        date -d "$date_str" '+%A'
    else
        # 中文环境
        local weekday_num=$(date -d "$date_str" '+%w')
        local weekdays=("星期日" "星期一" "星期二" "星期三" "星期四" "星期五" "星期六")
        echo "${weekdays[$weekday_num]}"
    fi
}

# 检查是否为工作日 (周一到周五)
is_workday() {
    local date_str="${1:-$(date '+%Y-%m-%d')}"
    local weekday=$(date -d "$date_str" '+%u')
    
    if [[ $weekday -le 5 ]]; then
        echo "true"
    else
        echo "false"
    fi
}

# 获取下一个工作日
next_workday() {
    local date_str="${1:-$(date '+%Y-%m-%d')}"
    local current_date="$date_str"
    
    while true; do
        current_date=$(date_calculate "$current_date" "+" 1)
        if [[ $(is_workday "$current_date") == "true" ]]; then
            echo "$current_date"
            break
        fi
    done
}

#===============================================================================
# 月份和年份处理函数
#===============================================================================

# 获取月份天数
days_in_month() {
    local year="$1"
    local month="$2"
    
    case "$month" in
        1|3|5|7|8|10|12) echo "31" ;;
        4|6|9|11) echo "30" ;;
        2)
            # 闰年判断
            if [[ $((year % 4)) -eq 0 && ($((year % 100)) -ne 0 || $((year % 400)) -eq 0) ]]; then
                echo "29"
            else
                echo "28"
            fi
            ;;
        *)
            echo "无效的月份: $month"
            return 1
            ;;
    esac
}

# 获取季度
get_quarter() {
    local month="${1:-$(date '+%m')}"
    echo $(((10#$month - 1) / 3 + 1))
}

# 获取月份开始和结束日期
get_month_range() {
    local year="$1"
    local month="$2"
    
    local start_date="${year}-${month}-01"
    local end_day=$(days_in_month "$year" "$month")
    local end_date="${year}-${month}-${end_day}"
    
    echo "$start_date 到 $end_date"
}

#===============================================================================
# 高级日期组合函数
#===============================================================================

# 生成日期序列
generate_date_sequence() {
    local start_date="$1"
    local end_date="$2"
    local step="${3:-1}"  # 步长(天)
    
    local current="$start_date"
    while [[ $(compare_dates "$current" "$end_date") -le 0 ]]; do
        echo "$current"
        current=$(date_calculate "$current" "+" "$step")
    done
}

# 获取指定月份的所有工作日
get_workdays_in_month() {
    local year="$1"
    local month="$2"
    
    local start_date="${year}-${month}-01"
    local end_day=$(days_in_month "$year" "$month")
    local end_date="${year}-${month}-${end_day}"
    
    generate_date_sequence "$start_date" "$end_date" | while read -r date; do
        if [[ $(is_workday "$date") == "true" ]]; then
            echo "$date"
        fi
    done
}

# 计算年龄
calculate_age() {
    local birth_date="$1"
    local current_date="${2:-$(date '+%Y-%m-%d')}"
    
    local birth_ts=$(date_to_timestamp "$birth_date")
    local current_ts=$(date_to_timestamp "$current_date")
    
    local birth_year=$(date -d "$birth_date" '+%Y')
    local current_year=$(date -d "$current_date" '+%Y')
    
    local age=$((current_year - birth_year))
    
    # 检查是否已经过了生日
    local birth_month_day=$(date -d "$birth_date" '+%m%d')
    local current_month_day=$(date -d "$current_date" '+%m%d')
    
    if [[ "$current_month_day" < "$birth_month_day" ]]; then
        age=$((age - 1))
    fi
    
    echo "$age"
}

#===============================================================================
# 实用工具函数
#===============================================================================

# 获取系统支持的日期格式
show_supported_formats() {
    echo "=== 系统支持的日期格式 ==="
    echo "标准格式: YYYY-MM-DD"
    echo "美式格式: MM/DD/YYYY"
    echo "欧式格式: DD/MM/YYYY"
    echo "中文格式: YYYY年MM月DD日"
    echo "紧凑格式: YYYYMMDD"
    echo "时间戳格式: @timestamp"
}

# 演示所有功能
demo_all_functions() {
    echo "=== 日期处理函数演示 ==="
    
    # 基础日期格式
    get_current_date_formats
    echo
    
    # 日期计算示例
    echo "=== 日期计算示例 ==="
    local today=$(date '+%Y-%m-%d')
    echo "今天: $today"
    echo "明天: $(date_calculate "$today" "+" 1)"
    echo "昨天: $(date_calculate "$today" "-" 1)"
    echo "一周后: $(date_calculate "$today" "+" 7)"
    echo "一月后: $(month_calculate "$today" "+" 1)"
    echo "一年后: $(year_calculate "$today" "+" 1)"
    echo
    
    # 日期比较示例
    echo "=== 日期比较示例 ==="
    local date1="2024-01-01"
    local date2="2024-12-31"
    echo "比较 $date1 和 $date2: $(compare_dates "$date1" "$date2")"
    echo "$date1 到 $date2 的天数: $(days_between "$date1" "$date2")"
    echo
    
    # 工作日相关
    echo "=== 工作日相关 ==="
    echo "今天是工作日: $(is_workday)"
    echo "今天是星期几: $(get_weekday_name)"
    echo "下一个工作日: $(next_workday)"
    echo
    
    # 月份信息
    echo "=== 月份信息 ==="
    local current_year=$(date '+%Y')
    local current_month=$(date '+%m')
    echo "$current_year年$current_month月有 $(days_in_month "$current_year" "$current_month") 天"
    echo "当前季度: 第$(get_quarter)季度"
    echo "本月工作日: $(get_workdays_in_month "$current_year" "$current_month" | wc -l) 天"
}

#===============================================================================
# 帮助函数
#===============================================================================

show_help() {
    cat << 'EOF'
日期处理函数库 - 使用帮助

基础函数:
  get_current_date_formats    - 显示各种日期格式
  date_calculate <date> <+/-> <days>     - 日期加减
  month_calculate <date> <+/-> <months>  - 月份加减
  year_calculate <date> <+/-> <years>    - 年份加减

比较函数:
  compare_dates <date1> <date2>          - 比较两个日期
  is_date_in_range <date> <start> <end>  - 检查日期是否在范围内
  days_between <date1> <date2>          - 计算日期间隔天数

转换函数:
  timestamp_to_date <timestamp> [format] - 时间戳转日期
  date_to_timestamp <date>              - 日期转时间戳
  convert_date_format <date> <input_fmt> <output_fmt> - 格式转换

工作日函数:
  get_weekday [date]                    - 获取星期几(1-7)
  get_weekday_name [date] [locale]      - 获取星期几名称
  is_workday [date]                     - 检查是否为工作日
  next_workday [date]                   - 获取下一个工作日

月份函数:
  days_in_month <year> <month>          - 获取月份天数
  get_quarter [month]                   - 获取季度
  get_month_range <year> <month>        - 获取月份开始结束日期

高级函数:
  generate_date_sequence <start> <end> [step] - 生成日期序列
  get_workdays_in_month <year> <month>  - 获取月份所有工作日
  calculate_age <birth_date> [current_date]   - 计算年龄

工具函数:
  show_supported_formats                - 显示支持的格式
  demo_all_functions                    - 演示所有功能
  show_help                            - 显示此帮助

示例:
  # 获取明天日期
  date_calculate "" "+" 1
  
  # 检查日期是否在工作范围内
  is_date_in_range "2024-12-25" "2024-12-01" "2024-12-31"
  
  # 计算年龄
  calculate_age "1990-01-01"
  
  # 获取工作日序列
  get_workdays_in_month 2024 12
EOF
}

#===============================================================================
# 脚本入口点
#===============================================================================

main() {
    case "${1:-help}" in
        "demo")
            demo_all_functions
            ;;
        "formats")
            show_supported_formats
            ;;
        "check")
            check_date_commands
            ;;
        "help"|*)
            show_help
            ;;
    esac
}

# 如果直接执行脚本,则运行主函数
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容