首页
友情链接
关于我们
Search
1
Docker安装Chromium浏览器 - Docker里的浏览器
388 阅读
2
Windows10添加共享网络打印机出现错误0x000004f8
264 阅读
3
CPU型号后缀带K、KF、F、KS、X、G、H、U、P的含义与区别
227 阅读
4
Docker安装FRPS、FRPC
189 阅读
5
Docker安装网心云
151 阅读
系统
Windows
Linux
Docker
编程
源码
代码
软件
电脑软件
手机软件
登录
Search
Kernel
累计撰写
100
篇文章
累计收到
0
条评论
本站共
43.14 W
字
首页
栏目
系统
Windows
Linux
Docker
编程
源码
代码
软件
电脑软件
手机软件
页面
友情链接
关于我们
用户中心
登录
搜索到
28
篇与
Linux
相关的结果
2025-08-08
Linux系统资源监控与优化工具箱
#!/bin/bash # ============================================ # 系统资源监控与优化工具箱 # 功能:实时监控CPU、内存、磁盘、网络,提供优化建议 # 使用方法:./sys-monitor.sh [选项] # ============================================ # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' PURPLE='\033[0;35m' NC='\033[0m' # No Color # 配置文件 CONFIG_DIR="$HOME/.sys-monitor" LOG_FILE="$CONFIG_DIR/sys-monitor.log" ALERT_LOG="$CONFIG_DIR/alerts.log" CONFIG_FILE="$CONFIG_DIR/config" REPORT_DIR="$CONFIG_DIR/reports" # 阈值配置(可在设置中修改) CPU_WARNING=70 CPU_CRITICAL=90 MEM_WARNING=70 MEM_CRITICAL=90 DISK_WARNING=80 DISK_CRITICAL=95 LOAD_WARNING=1 LOAD_CRITICAL=2 # 初始化函数 init_monitor() { mkdir -p "$CONFIG_DIR" mkdir -p "$REPORT_DIR" if [ ! -f "$CONFIG_FILE" ]; then save_config else load_config fi # 初始化日志 echo "========================================" >> "$LOG_FILE" echo "系统监控启动时间: $(date)" >> "$LOG_FILE" echo "主机名: $(hostname)" >> "$LOG_FILE" echo "========================================" >> "$LOG_FILE" } # 保存配置 save_config() { cat > "$CONFIG_FILE" << EOF # 系统监控配置 CPU_WARNING=$CPU_WARNING CPU_CRITICAL=$CPU_CRITICAL MEM_WARNING=$MEM_WARNING MEM_CRITICAL=$MEM_CRITICAL DISK_WARNING=$DISK_WARNING DISK_CRITICAL=$DISK_CRITICAL ALERT_ENABLED=true MONITOR_INTERVAL=2 KEEP_LOGS_DAYS=7 EOF } # 加载配置 load_config() { if [ -f "$CONFIG_FILE" ]; then source "$CONFIG_FILE" fi } # ============================================ # 内存信息获取函数(完全修复版) # ============================================ # 方法1: 使用/proc/meminfo(最可靠) get_memory_info_from_proc() { if [ -f /proc/meminfo ]; then # 读取内存信息 local mem_total_kb=$(grep "^MemTotal:" /proc/meminfo | awk '{print $2}') local mem_free_kb=$(grep "^MemFree:" /proc/meminfo | awk '{print $2}') local buffers_kb=$(grep "^Buffers:" /proc/meminfo | awk '{print $2}') local cached_kb=$(grep "^Cached:" /proc/meminfo | awk '{print $2}') local sreclaimable_kb=$(grep "^SReclaimable:" /proc/meminfo | awk '{print $2}') # 转换为MB local mem_total_mb=$((mem_total_kb / 1024)) # 计算已用内存 (更准确的方法) # 已用内存 = 总内存 - 可用内存 # 可用内存 = MemFree + Buffers + Cached + SReclaimable if [ -n "$mem_free_kb" ] && [ -n "$buffers_kb" ] && [ -n "$cached_kb" ]; then local mem_available_kb=$((mem_free_kb + buffers_kb + cached_kb)) if [ -n "$sreclaimable_kb" ]; then mem_available_kb=$((mem_available_kb + sreclaimable_kb)) fi local mem_used_mb=$(((mem_total_kb - mem_available_kb) / 1024)) echo "$mem_total_mb $mem_used_mb" return 0 fi # 如果上面的方法失败,使用简单方法 if [ -n "$mem_total_kb" ]; then local mem_used_kb=$((mem_total_kb - mem_free_kb)) local mem_used_mb=$((mem_used_kb / 1024)) echo "$mem_total_mb $mem_used_mb" return 0 fi fi return 1 } # 方法2: 使用free命令 get_memory_info_from_free() { if command -v free &> /dev/null; then local free_output=$(free -m 2>/dev/null) if [ $? -eq 0 ]; then local mem_total=$(echo "$free_output" | awk '/^Mem:/{print $2}') local mem_used=$(echo "$free_output" | awk '/^Mem:/{print $3}') local mem_available=$(echo "$free_output" | awk '/^Mem:/{print $7}') # 如果有available字段,使用更准确的计算 if [ -n "$mem_available" ] && [ "$mem_available" -gt 0 ]; then local mem_real_used=$((mem_total - mem_available)) echo "$mem_total $mem_real_used" elif [ -n "$mem_total" ] && [ -n "$mem_used" ]; then echo "$mem_total $mem_used" fi return 0 fi fi return 1 } # 方法3: 使用vmstat get_memory_info_from_vmstat() { if command -v vmstat &> /dev/null; then local vmstat_output=$(vmstat -s 2>/dev/null) if [ $? -eq 0 ]; then local mem_total_kb=$(echo "$vmstat_output" | grep -i "total memory" | awk '{print $1}') local mem_used_kb=$(echo "$vmstat_output" | grep -i "used memory" | awk '{print $1}') if [ -n "$mem_total_kb" ] && [ -n "$mem_used_kb" ]; then local mem_total_mb=$((mem_total_kb / 1024)) local mem_used_mb=$((mem_used_kb / 1024)) echo "$mem_total_mb $mem_used_mb" return 0 fi fi fi return 1 } # 主内存获取函数 get_memory_info() { # 尝试方法1: /proc/meminfo local mem_info=$(get_memory_info_from_proc) if [ $? -eq 0 ] && [ -n "$mem_info" ]; then echo "$mem_info" return 0 fi # 尝试方法2: free命令 mem_info=$(get_memory_info_from_free) if [ $? -eq 0 ] && [ -n "$mem_info" ]; then echo "$mem_info" return 0 fi # 尝试方法3: vmstat mem_info=$(get_memory_info_from_vmstat) if [ $? -eq 0 ] && [ -n "$mem_info" ]; then echo "$mem_info" return 0 fi # 所有方法都失败 echo "0 0" return 1 } # 安全地计算内存使用率 calculate_mem_percent() { local total_mem=$1 local used_mem=$2 # 检查参数是否有效 if [ -z "$total_mem" ] || [ "$total_mem" -le 0 ] || [ -z "$used_mem" ] || [ "$used_mem" -lt 0 ]; then echo "0" return fi # 计算百分比(使用整数运算) local percent=0 if [ "$total_mem" -gt 0 ]; then percent=$((used_mem * 100 / total_mem)) # 确保百分比在合理范围内 if [ "$percent" -lt 0 ]; then percent=0 elif [ "$percent" -gt 100 ]; then percent=100 fi fi echo "$percent" } # ============================================ # 其他信息获取函数 # ============================================ # 获取CPU使用率 get_cpu_usage() { # 方法1: 使用/proc/stat(最可靠) if [ -f /proc/stat ]; then # 获取第一次CPU统计 local cpu_line=$(grep '^cpu ' /proc/stat) read cpu user nice system idle iowait irq softirq steal guest guest_nice <<< "$cpu_line" local total1=$((user + nice + system + idle + iowait + irq + softirq + steal)) local idle1=$idle # 等待1秒 sleep 0.5 # 获取第二次CPU统计 cpu_line=$(grep '^cpu ' /proc/stat) read cpu user nice system idle iowait irq softirq steal guest guest_nice <<< "$cpu_line" local total2=$((user + nice + system + idle + iowait + irq + softirq + steal)) local idle2=$idle # 计算CPU使用率 local total_diff=$((total2 - total1)) local idle_diff=$((idle2 - idle1)) if [ $total_diff -gt 0 ]; then local cpu_usage=$((100 * (total_diff - idle_diff) / total_diff)) echo "$cpu_usage" return 0 fi fi # 方法2: 使用top命令 if command -v top &> /dev/null; then local cpu_usage=$(top -bn1 2>/dev/null | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1) if [ -n "$cpu_usage" ]; then echo "${cpu_usage%.*}" return 0 fi fi echo "0" } # 获取磁盘使用率 get_disk_usage() { # 方法1: 使用df命令 if command -v df &> /dev/null; then local disk_usage=$(df -h / 2>/dev/null | awk 'NR==2 {print $5}' | sed 's/%//') if [ -n "$disk_usage" ]; then echo "$disk_usage" return 0 fi fi # 方法2: 使用/proc/mounts if [ -f /proc/mounts ]; then local root_device=$(grep " / " /proc/mounts | awk '{print $1}') if [ -n "$root_device" ] && command -v df &> /dev/null; then local disk_usage=$(df -h "$root_device" 2>/dev/null | awk 'NR==2 {print $5}' | sed 's/%//') if [ -n "$disk_usage" ]; then echo "$disk_usage" return 0 fi fi fi echo "0" } # 获取系统负载 get_load_average() { if [ -f /proc/loadavg ]; then cat /proc/loadavg | awk '{print $1, $2, $3}' elif command -v uptime &> /dev/null; then uptime | sed -n 's/.*load average: //p' | tr -d ',' else echo "0 0 0" fi } # 获取系统信息 get_system_info() { # 获取操作系统信息 if [ -f /etc/os-release ]; then OS_INFO=$(grep PRETTY_NAME /etc/os-release 2>/dev/null | cut -d'"' -f2) elif [ -f /etc/redhat-release ]; then OS_INFO=$(cat /etc/redhat-release 2>/dev/null) elif [ -f /etc/debian_version ]; then OS_INFO="Debian $(cat /etc/debian_version 2>/dev/null)" elif [ -f /etc/lsb-release ]; then OS_INFO=$(grep DISTRIB_DESCRIPTION /etc/lsb-release 2>/dev/null | cut -d'=' -f2 | tr -d '"') else OS_INFO=$(uname -o 2>/dev/null) fi OS_INFO=${OS_INFO:-"Unknown Linux"} # 获取内核版本 KERNEL=$(uname -r 2>/dev/null) KERNEL=${KERNEL:-"Unknown"} # 获取系统架构 ARCH=$(uname -m 2>/dev/null) ARCH=${ARCH:-"Unknown"} # 获取主机名 HOSTNAME=$(hostname 2>/dev/null) HOSTNAME=${HOSTNAME:-"Unknown"} # 获取正常运行时间 if [ -f /proc/uptime ]; then local uptime_sec=$(awk '{print int($1)}' /proc/uptime 2>/dev/null) local uptime_days=$((uptime_sec / 86400)) local uptime_hours=$(( (uptime_sec % 86400) / 3600 )) local uptime_mins=$(( (uptime_sec % 3600) / 60 )) if [ $uptime_days -gt 0 ]; then UPTIME="${uptime_days}天 ${uptime_hours}小时" elif [ $uptime_hours -gt 0 ]; then UPTIME="${uptime_hours}小时 ${uptime_mins}分钟" else UPTIME="${uptime_mins}分钟" fi else UPTIME="unknown" fi # 获取CPU信息 if [ -f /proc/cpuinfo ]; then CPU_MODEL=$(grep "model name" /proc/cpuinfo 2>/dev/null | head -1 | cut -d':' -f2 | sed 's/^ *//') CPU_CORES=$(grep -c "^processor" /proc/cpuinfo 2>/dev/null) fi CPU_MODEL=${CPU_MODEL:-"Unknown CPU"} CPU_CORES=${CPU_CORES:-1} # 获取内存信息(使用新函数) mem_info=$(get_memory_info) TOTAL_MEM=$(echo $mem_info | awk '{print $1}') USED_MEM=$(echo $mem_info | awk '{print $2}') # 获取磁盘信息 if command -v df &> /dev/null; then TOTAL_DISK=$(df -h / 2>/dev/null | awk 'NR==2 {print $2}' || echo "unknown") else TOTAL_DISK="unknown" fi } # 显示标题 show_header() { clear echo -e "${PURPLE}" echo "╔══════════════════════════════════════════════════════════╗" echo "║ 系统资源监控与优化工具箱 v1.0 ║" echo "║ System Monitor & Optimizer Toolkit ║" echo "╚══════════════════════════════════════════════════════════╝" echo -e "${NC}" get_system_info # 计算内存使用率 local mem_percent=$(calculate_mem_percent "$TOTAL_MEM" "$USED_MEM") echo -e "${CYAN}系统概览:${NC}" echo -e "主机: ${GREEN}$HOSTNAME${NC} | 系统: ${YELLOW}$OS_INFO${NC}" echo -e "内核: ${BLUE}$KERNEL${NC} | 架构: ${BLUE}$ARCH${NC}" echo -e "运行: ${CYAN}$UPTIME${NC} | CPU: ${CPU_CORES}核 ${CPU_MODEL:0:30}" echo -e "内存: ${GREEN}${TOTAL_MEM}MB${NC} (使用率: ${mem_percent}%) | 磁盘: ${GREEN}$TOTAL_DISK${NC}" echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}" } # 显示菜单 show_menu() { echo -e "\n${YELLOW}主菜单:${NC}" echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}" echo -e "${GREEN}1. 实时系统监控${NC} - 监控CPU、内存、磁盘、网络" echo -e "${GREEN}2. 资源使用分析${NC} - 详细分析资源使用情况" echo -e "${GREEN}3. 进程管理${NC} - 查看和管理进程" echo -e "${GREEN}4. 服务状态检查${NC} - 检查系统服务状态" echo -e "${GREEN}5. 系统日志分析${NC} - 分析系统日志" echo -e "${GREEN}6. 磁盘空间管理${NC} - 磁盘使用分析和清理" echo -e "${GREEN}7. 网络连接监控${NC} - 监控网络连接和流量" echo -e "${GREEN}8. 系统优化建议${NC} - 获取系统优化建议" echo -e "${GREEN}9. 性能基准测试${NC} - 运行性能基准测试" echo -e "${GREEN}10. 生成系统报告${NC} - 生成详细系统报告" echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}" echo -e "${GREEN}0. 退出${NC}" echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}" } # 记录日志 log_message() { local message="$1" echo "[$(date '+%Y-%m-%d %H:%M:%S')] $message" >> "$LOG_FILE" } # 记录告警 log_alert() { local alert_type="$1" local message="$2" echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$alert_type] $message" >> "$ALERT_LOG" echo -e "${RED}[告警] $message${NC}" } # 1. 实时系统监控 real_time_monitor() { local refresh_rate=${MONITOR_INTERVAL:-2} local monitor_duration=0 show_header echo -e "\n${CYAN}实时系统监控 (按 q 退出)${NC}" echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}" echo -e "${YELLOW}刷新间隔: ${refresh_rate}秒 | 按 '+' 增加间隔 | 按 '-' 减少间隔${NC}" echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}" while true; do # 获取当前时间 local current_time=$(date '+%H:%M:%S') # 获取CPU使用率 local cpu_usage=$(get_cpu_usage) # 获取内存信息 local mem_info=$(get_memory_info) local total_mem=$(echo $mem_info | awk '{print $1}') local used_mem=$(echo $mem_info | awk '{print $2}') local mem_percent=$(calculate_mem_percent "$total_mem" "$used_mem") # 获取磁盘使用率 local disk_usage=$(get_disk_usage) # 获取系统负载 local load_avg=$(get_load_average) local load1=$(echo $load_avg | awk '{print $1}') local load5=$(echo $load_avg | awk '{print $2}') local load15=$(echo $load_avg | awk '{print $3}') # 获取运行时间 local uptime_sec=0 local uptime_days=0 local uptime_hours=0 local uptime_mins=0 if [ -f /proc/uptime ]; then uptime_sec=$(awk '{print int($1)}' /proc/uptime 2>/dev/null) uptime_days=$((uptime_sec / 86400)) uptime_hours=$(( (uptime_sec % 86400) / 3600 )) uptime_mins=$(( (uptime_sec % 3600) / 60 )) fi # 清屏并显示信息 clear # 显示简化标题 echo -e "${PURPLE}" echo "╔══════════════════════════════════════════════════════════╗" echo "║ 实时系统监控 (按q退出) ║" echo "╚══════════════════════════════════════════════════════════╝" echo -e "${NC}" echo -e "${CYAN}监控时间: $current_time | 刷新间隔: ${refresh_rate}秒${NC}" echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}" # CPU使用率 echo -e "\n${GREEN}CPU 使用率:${NC}" echo -n " [" local cpu_bar_length=50 local cpu_filled=0 # 安全地计算填充长度 if [ "$cpu_usage" -gt 0 ] 2>/dev/null && [ "$cpu_usage" -le 100 ]; then cpu_filled=$((cpu_usage * cpu_bar_length / 100)) fi if [ "$cpu_filled" -gt "$cpu_bar_length" ]; then cpu_filled=$cpu_bar_length fi local cpu_empty=$((cpu_bar_length - cpu_filled)) # 根据使用率显示不同颜色 if [ "$cpu_usage" -ge "$CPU_CRITICAL" ] 2>/dev/null; then echo -ne "${RED}" elif [ "$cpu_usage" -ge "$CPU_WARNING" ] 2>/dev/null; then echo -ne "${YELLOW}" else echo -ne "${GREEN}" fi printf "%${cpu_filled}s" | tr " " "█" echo -ne "${NC}" printf "%${cpu_empty}s" | tr " " "░" echo -e "] ${cpu_usage}%" # 内存使用率 echo -e "\n${GREEN}内存 使用率:${NC}" echo -n " [" local mem_bar_length=50 local mem_filled=0 if [ "$mem_percent" -gt 0 ] 2>/dev/null && [ "$mem_percent" -le 100 ]; then mem_filled=$((mem_percent * mem_bar_length / 100)) fi if [ "$mem_filled" -gt "$mem_bar_length" ]; then mem_filled=$mem_bar_length fi local mem_empty=$((mem_bar_length - mem_filled)) if [ "$mem_percent" -ge "$MEM_CRITICAL" ] 2>/dev/null; then echo -ne "${RED}" elif [ "$mem_percent" -ge "$MEM_WARNING" ] 2>/dev/null; then echo -ne "${YELLOW}" else echo -ne "${GREEN}" fi printf "%${mem_filled}s" | tr " " "█" echo -ne "${NC}" printf "%${mem_empty}s" | tr " " "░" echo -e "] ${mem_percent}% (${used_mem}MB/${total_mem}MB)" # 磁盘使用率 echo -e "\n${GREEN}磁盘 使用率(/):${NC}" echo -n " [" local disk_bar_length=50 local disk_filled=0 if [ "$disk_usage" -gt 0 ] 2>/dev/null && [ "$disk_usage" -le 100 ]; then disk_filled=$((disk_usage * disk_bar_length / 100)) fi if [ "$disk_filled" -gt "$disk_bar_length" ]; then disk_filled=$disk_bar_length fi local disk_empty=$((disk_bar_length - disk_filled)) if [ "$disk_usage" -ge "$DISK_CRITICAL" ] 2>/dev/null; then echo -ne "${RED}" elif [ "$disk_usage" -ge "$DISK_WARNING" ] 2>/dev/null; then echo -ne "${YELLOW}" else echo -ne "${GREEN}" fi printf "%${disk_filled}s" | tr " " "█" echo -ne "${NC}" printf "%${disk_empty}s" | tr " " "░" echo -e "] ${disk_usage}%" # 系统负载 echo -e "\n${GREEN}系统负载:${NC}" echo -e " 1分钟: ${load1:-0} | 5分钟: ${load5:-0} | 15分钟: ${load15:-0}" # 获取CPU核心数 local cpu_cores=1 if [ -f /proc/cpuinfo ]; then cpu_cores=$(grep -c "^processor" /proc/cpuinfo 2>/dev/null || echo 1) fi echo -e " CPU核心数: ${cpu_cores}" # 其他信息 echo -e "\n${GREEN}其他信息:${NC}" # 获取进程数 local process_count=0 if [ -f /proc/stat ]; then process_count=$(grep -c "^procs_running" /proc/stat) fi echo -e " 运行进程数: ${process_count}" echo -e " 系统运行: ${uptime_days}天 ${uptime_hours}小时 ${uptime_mins}分钟" # 检查告警条件 if [ "$ALERT_ENABLED" = "true" ]; then echo -e "\n${YELLOW}告警检查:${NC}" # 检查CPU if [ "$cpu_usage" -ge "$CPU_CRITICAL" ] 2>/dev/null; then echo -e " ${RED}⚠ CPU使用率过高: ${cpu_usage}%${NC}" elif [ "$cpu_usage" -ge "$CPU_WARNING" ] 2>/dev/null; then echo -e " ${YELLOW}⚠ CPU使用率警告: ${cpu_usage}%${NC}" else echo -e " ${GREEN}✓ CPU使用率正常${NC}" fi # 检查内存 if [ "$mem_percent" -ge "$MEM_CRITICAL" ] 2>/dev/null; then echo -e " ${RED}⚠ 内存使用率过高: ${mem_percent}%${NC}" elif [ "$mem_percent" -ge "$MEM_WARNING" ] 2>/dev/null; then echo -e " ${YELLOW}⚠ 内存使用率警告: ${mem_percent}%${NC}" else echo -e " ${GREEN}✓ 内存使用率正常${NC}" fi # 检查磁盘 if [ "$disk_usage" -ge "$DISK_CRITICAL" ] 2>/dev/null; then echo -e " ${RED}⚠ 磁盘使用率过高: ${disk_usage}%${NC}" elif [ "$disk_usage" -ge "$DISK_WARNING" ] 2>/dev/null; then echo -e " ${YELLOW}⚠ 磁盘使用率警告: ${disk_usage}%${NC}" else echo -e " ${GREEN}✓ 磁盘使用率正常${NC}" fi fi echo -e "\n${BLUE}══════════════════════════════════════════════════════════${NC}" echo -e "${YELLOW}按 q 退出 | 按 + 增加间隔 | 按 - 减少间隔${NC}" # 非阻塞读取键盘输入 if read -t "$refresh_rate" -n 1 key; then case $key in q|Q) echo -e "\n${GREEN}退出监控模式${NC}" break ;; +) refresh_rate=$((refresh_rate + 1)) echo -e "\n${YELLOW}刷新间隔增加至 ${refresh_rate}秒${NC}" sleep 1 ;; -) if [ "$refresh_rate" -gt 1 ]; then refresh_rate=$((refresh_rate - 1)) echo -e "\n${YELLOW}刷新间隔减少至 ${refresh_rate}秒${NC}" sleep 1 fi ;; esac fi monitor_duration=$((monitor_duration + refresh_rate)) done log_message "实时监控运行 ${monitor_duration}秒" } # 2. 资源使用分析 resource_analysis() { show_header echo -e "\n${CYAN}资源使用详细分析${NC}" echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}" # CPU详细分析 echo -e "\n${YELLOW}1. CPU使用分析:${NC}" echo -e "${GREEN}══════════════════════════════════════════════════════════${NC}" echo -e "CPU型号: ${CPU_MODEL}" echo -e "CPU核心数: ${CPU_CORES}" # 显示CPU架构 if [ -f /proc/cpuinfo ]; then echo -e "CPU架构: $(grep -m1 "model name" /proc/cpuinfo | cut -d: -f2 | sed 's/^ *//')" fi # 显示CPU频率 if [ -f /proc/cpuinfo ]; then echo -e "CPU频率: $(grep -m1 "cpu MHz" /proc/cpuinfo | cut -d: -f2 | sed 's/^ *//') MHz" fi # 按进程统计CPU使用 echo -e "\n${CYAN}CPU使用最高的进程 (前5):${NC}" if command -v ps &> /dev/null; then echo -e "${YELLOW}USER PID CPU% COMMAND${NC}" ps aux --sort=-%cpu 2>/dev/null | head -6 | tail -5 | awk '{printf "%-10s %-8s %-6s %-50s\n", $1, $2, $3, $11}' else echo -e "${YELLOW}无法获取进程信息${NC}" fi # 内存详细分析 echo -e "\n${YELLOW}2. 内存使用分析:${NC}" echo -e "${GREEN}══════════════════════════════════════════════════════════${NC}" # 使用多种方法显示内存信息 echo -e "${CYAN}方法1: 使用free命令${NC}" if command -v free &> /dev/null; then free -h 2>/dev/null || echo -e "${YELLOW}无法获取内存信息${NC}" fi echo -e "\n${CYAN}方法2: 使用/proc/meminfo${NC}" if [ -f /proc/meminfo ]; then echo -e "总内存: $(grep "^MemTotal:" /proc/meminfo | awk '{print $2/1024 " MB"}')" echo -e "空闲内存: $(grep "^MemFree:" /proc/meminfo | awk '{print $2/1024 " MB"}')" echo -e "可用内存: $(grep "^MemAvailable:" /proc/meminfo 2>/dev/null | awk '{print $2/1024 " MB"}' || echo "未知")" echo -e "缓存: $(grep "^Cached:" /proc/meminfo | awk '{print $2/1024 " MB"}')" echo -e "缓冲: $(grep "^Buffers:" /proc/meminfo | awk '{print $2/1024 " MB"}')" fi # 按进程统计内存使用 echo -e "\n${CYAN}内存使用最高的进程 (前5):${NC}" if command -v ps &> /dev/null; then echo -e "${YELLOW}USER PID MEM% COMMAND${NC}" ps aux --sort=-%mem 2>/dev/null | head -6 | tail -5 | awk '{printf "%-10s %-8s %-6s %-50s\n", $1, $2, $4, $11}' fi # 磁盘详细分析 echo -e "\n${YELLOW}3. 磁盘使用分析:${NC}" echo -e "${GREEN}══════════════════════════════════════════════════════════${NC}" if command -v df &> /dev/null; then echo -e "${CYAN}磁盘使用情况:${NC}" df -h 2>/dev/null | head -10 || echo -e "${YELLOW}无法获取磁盘信息${NC}" fi # 显示inode使用情况 echo -e "\n${CYAN}Inode使用情况:${NC}" if command -v df &> /dev/null; then df -i 2>/dev/null | head -5 fi # 总结和建议 echo -e "\n${YELLOW}4. 分析总结:${NC}" echo -e "${GREEN}══════════════════════════════════════════════════════════${NC}" # 获取当前资源使用 local cpu_usage=$(get_cpu_usage) local mem_info=$(get_memory_info) local total_mem=$(echo $mem_info | awk '{print $1}') local used_mem=$(echo $mem_info | awk '{print $2}') local mem_percent=$(calculate_mem_percent "$total_mem" "$used_mem") local disk_usage=$(get_disk_usage) echo -e "${CYAN}当前资源使用情况:${NC}" echo -e " CPU使用率: ${cpu_usage}%" echo -e " 内存使用率: ${mem_percent}% (${used_mem}MB/${total_mem}MB)" echo -e " 磁盘使用率: ${disk_usage}%" # 提供建议 echo -e "\n${CYAN}优化建议:${NC}" if [ "$cpu_usage" -gt 80 ] 2>/dev/null; then echo -e " ${RED}⚠ CPU使用率较高,建议:${NC}" echo -e " 1. 检查并优化高CPU进程" echo -e " 2. 考虑升级CPU" echo -e " 3. 优化应用程序配置" else echo -e " ${GREEN}✓ CPU使用率正常${NC}" fi if [ "$mem_percent" -gt 80 ] 2>/dev/null; then echo -e " ${RED}⚠ 内存使用率较高,建议:${NC}" echo -e " 1. 关闭不必要的应用程序" echo -e " 2. 增加交换空间" echo -e " 3. 考虑增加物理内存" echo -e " 4. 优化应用程序内存使用" else echo -e " ${GREEN}✓ 内存使用率正常${NC}" fi if [ "$disk_usage" -gt 80 ] 2>/dev/null; then echo -e " ${RED}⚠ 磁盘使用率较高,建议:${NC}" echo -e " 1. 清理临时文件" echo -e " 2. 删除不需要的软件包" echo -e " 3. 清理日志文件" echo -e " 4. 考虑增加磁盘空间" else echo -e " ${GREEN}✓ 磁盘使用率正常${NC}" fi log_message "资源使用分析" read -p "按回车键继续..." } # 3. 进程管理 process_management() { while true; do show_header echo -e "\n${CYAN}进程管理${NC}" echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}" echo -e "\n${YELLOW}进程管理选项:${NC}" echo "1. 查看所有进程" echo "2. 查看高CPU进程" echo "3. 查看高内存进程" echo "4. 查找特定进程" echo "5. 结束进程" echo "0. 返回主菜单" echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}" read -p "请选择 [0-5]: " choice case $choice in 1) echo -e "\n${CYAN}所有进程 (前20个):${NC}" if command -v ps &> /dev/null; then ps aux | head -20 else echo -e "${RED}无法获取进程信息${NC}" fi ;; 2) echo -e "\n${CYAN}高CPU进程 (前10个):${NC}" if command -v ps &> /dev/null; then echo -e "${YELLOW}USER PID CPU% COMMAND${NC}" ps aux --sort=-%cpu | head -11 | tail -10 | awk '{printf "%-10s %-8s %-6s %-50s\n", $1, $2, $3, $11}' fi ;; 3) echo -e "\n${CYAN}高内存进程 (前10个):${NC}" if command -v ps &> /dev/null; then echo -e "${YELLOW}USER PID MEM% COMMAND${NC}" ps aux --sort=-%mem | head -11 | tail -10 | awk '{printf "%-10s %-8s %-6s %-50s\n", $1, $2, $4, $11}' fi ;; 4) read -p "输入要查找的进程名: " proc_name if [ -n "$proc_name" ]; then echo -e "\n${CYAN}查找进程: $proc_name${NC}" if command -v ps &> /dev/null; then ps aux | grep -i "$proc_name" | grep -v grep fi fi ;; 5) read -p "输入要结束的进程PID: " pid if [ -n "$pid" ]; then echo -e "${YELLOW}结束进程 $pid ...${NC}" if kill "$pid" 2>/dev/null; then echo -e "${GREEN}✓ 进程 $pid 已结束${NC}" else echo -e "${RED}✗ 无法结束进程 $pid${NC}" fi fi ;; 0) break ;; *) echo -e "${RED}无效选择${NC}" ;; esac if [ "$choice" -ne 0 ]; then read -p "按回车键继续..." fi done } # 4. 服务状态检查 service_check() { show_header echo -e "\n${CYAN}服务状态检查${NC}" echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}" echo -e "\n${YELLOW}关键服务状态:${NC}" # 检查系统是使用systemd还是init if command -v systemctl &> /dev/null; then echo -e "${GREEN}使用systemd管理系统${NC}" # 检查常见服务 services=("ssh" "cron" "nginx" "apache2" "mysql" "docker" "network" "systemd-logind") for service in "${services[@]}"; do if systemctl list-unit-files "$service.service" &>/dev/null 2>&1; then status=$(systemctl is-active "$service.service" 2>/dev/null) if [ "$status" = "active" ]; then echo -e " ${GREEN}✓ $service: 运行中${NC}" elif [ "$status" = "inactive" ]; then echo -e " ${YELLOW}○ $service: 已停止${NC}" elif [ "$status" = "failed" ]; then echo -e " ${RED}✗ $service: 失败${NC}" else echo -e " ${BLUE}? $service: 未知状态${NC}" fi fi done # 显示失败的服务 echo -e "\n${YELLOW}失败的服务:${NC}" systemctl --failed 2>/dev/null | grep -v "0 loaded units listed" || echo -e " ${GREEN}✓ 没有失败的服务${NC}" elif [ -d /etc/init.d ]; then echo -e "${GREEN}使用init.d管理系统${NC}" echo -e "\n${YELLOW}服务状态:${NC}" service --status-all 2>/dev/null | head -10 else echo -e "${YELLOW}无法确定服务管理系统${NC}" fi # 检查网络服务 echo -e "\n${YELLOW}网络服务端口:${NC}" if command -v ss &> /dev/null; then ss -tulpn 2>/dev/null | head -10 elif command -v netstat &> /dev/null; then netstat -tulpn 2>/dev/null | head -10 else echo -e "${YELLOW}无法检查网络端口${NC}" fi read -p "按回车键继续..." } # 主程序 main() { # 初始化 init_monitor # 显示欢迎信息 show_header # 检查是否以root运行 if [ "$EUID" -ne 0 ]; then echo -e "${YELLOW}注意: 部分功能需要root权限${NC}" echo -e "${CYAN}可以使用sudo运行脚本: sudo $0${NC}" echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}" fi while true; do show_header show_menu read -p "请选择操作 [0-10]: " main_choice case $main_choice in 1) real_time_monitor ;; 2) resource_analysis ;; 3) process_management ;; 4) service_check ;; 5) show_header echo -e "\n${CYAN}系统日志分析${NC}" echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}" echo -e "${YELLOW}功能开发中...${NC}" read -p "按回车键继续..." ;; 6) show_header echo -e "\n${CYAN}磁盘空间管理${NC}" echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}" echo -e "${YELLOW}功能开发中...${NC}" read -p "按回车键继续..." ;; 7) show_header echo -e "\n${CYAN}网络连接监控${NC}" echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}" echo -e "${YELLOW}功能开发中...${NC}" read -p "按回车键继续..." ;; 8) show_header echo -e "\n${CYAN}系统优化建议${NC}" echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}" echo -e "${YELLOW}功能开发中...${NC}" read -p "按回车键继续..." ;; 9) show_header echo -e "\n${CYAN}性能基准测试${NC}" echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}" echo -e "${YELLOW}功能开发中...${NC}" read -p "按回车键继续..." ;; 10) show_header echo -e "\n${CYAN}生成系统报告${NC}" echo -e "${BLUE}══════════════════════════════════════════════════════════${NC}" echo -e "${YELLOW}功能开发中...${NC}" read -p "按回车键继续..." ;; 0) echo -e "\n${GREEN}感谢使用系统监控工具!${NC}" echo -e "${CYAN}日志文件: $LOG_FILE${NC}" echo -e "${CYAN}告警日志: $ALERT_LOG${NC}" echo -e "${CYAN}报告目录: $REPORT_DIR${NC}" exit 0 ;; *) echo -e "${RED}无效选择,请重新输入${NC}" sleep 1 ;; esac done } # 运行主程序 main
2025年08月08日
5 阅读
0 评论
0 点赞
2025-07-07
Linux系统安全加固与审计脚本
#!/bin/bash # ============================================ # Linux系统安全加固与审计脚本 # 功能:自动化安全检查和系统加固 # 使用方法:sudo ./security-audit.sh [选项] ## 保存脚本 ## sudo nano /usr/local/bin/security-audit.sh ## 赋予执行权限 ## sudo chmod +x /usr/local/bin/security-audit.sh ## 运行交互式菜单 ## sudo security-audit.sh ## 或直接运行完整审计 ## sudo security-audit.sh --audit # ============================================ # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' PURPLE='\033[0;35m' NC='\033[0m' # No Color # 配置 REPORT_FILE="/var/log/security-audit-$(date +%Y%m%d).report" LOG_FILE="/var/log/security-audit.log" BACKUP_DIR="/root/security-backup-$(date +%Y%m%d)" AUDIT_SCORE=0 MAX_SCORE=100 CHECK_COUNT=0 PASS_COUNT=0 FAIL_COUNT=0 WARN_COUNT=0 # 函数:打印带颜色的消息 print_color() { local color=$1 local msg=$2 echo -e "${color}${msg}${NC}" } # 函数:记录日志 log_message() { local message=$1 echo "[$(date '+%Y-%m-%d %H:%M:%S')] $message" >> "$LOG_FILE" } # 函数:打印检查结果 print_result() { local level=$1 local check_name=$2 local status=$3 local message=$4 CHECK_COUNT=$((CHECK_COUNT + 1)) case $status in "PASS") PASS_COUNT=$((PASS_COUNT + 1)) AUDIT_SCORE=$((AUDIT_SCORE + 2)) printf "[${GREEN}✓${NC}] %-50s ${GREEN}通过${NC}\n" "$check_name" log_message "PASS - $check_name: $message" ;; "FAIL") FAIL_COUNT=$((FAIL_COUNT + 1)) printf "[${RED}✗${NC}] %-50s ${RED}失败${NC}\n" "$check_name" printf " ${YELLOW}建议: $message${NC}" log_message "FAIL - $check_name: $message" ;; "WARN") WARN_COUNT=$((WARN_COUNT + 1)) AUDIT_SCORE=$((AUDIT_SCORE + 1)) printf "[${YELLOW}!${NC}] %-50s ${YELLOW}警告${NC}\n" "$check_name" printf " ${CYAN}信息: $message${NC}" log_message "WARN - $check_name: $message" ;; "INFO") printf "[${BLUE}i${NC}] %-50s ${BLUE}信息${NC}\n" "$check_name" printf " ${CYAN}详情: $message${NC}" log_message "INFO - $check_name: $message" ;; esac } # 函数:生成报告头部 report_header() { cat > "$REPORT_FILE" << EOF ============================================ Linux系统安全审计报告 生成时间: $(date) 主机名: $(hostname) 操作系统: $(cat /etc/os-release | grep PRETTY_NAME | cut -d'"' -f2 2>/dev/null || uname -o) 内核版本: $(uname -r) ============================================ EOF log_message "生成审计报告头部" } # 函数:添加报告内容 add_report() { local section=$1 local content=$2 echo -e "\n=== $section ===" >> "$REPORT_FILE" echo "$content" >> "$REPORT_FILE" } # 函数:显示进度条 show_progress() { local current=$1 local total=$2 local width=50 local percent=$((current * 100 / total)) local filled=$((current * width / total)) local empty=$((width - filled)) printf "\r[" printf "%${filled}s" | tr " " "=" printf "%${empty}s" | tr " " " " printf "] %3d%%" "$percent" } # 函数:显示标题 show_section() { local title=$1 echo "" print_color "$PURPLE" "┌──────────────────────────────────────────────────────┐" print_color "$PURPLE" "│ $(printf "%-52s" "$title") │" print_color "$PURPLE" "└──────────────────────────────────────────────────────┘" } # 函数:检查是否为root用户 check_root() { if [ "$EUID" -ne 0 ]; then print_color "$RED" "错误:此脚本需要root权限运行!" print_color "$CYAN" "请使用: sudo $0" exit 1 fi } # 函数:备份配置文件 backup_config() { local file=$1 if [ -f "$file" ]; then mkdir -p "$BACKUP_DIR" cp "$file" "$BACKUP_DIR/" 2>/dev/null if [ $? -eq 0 ]; then print_color "$CYAN" "已备份: $file -> $BACKUP_DIR/" else print_color "$YELLOW" "备份失败: $file (可能权限不足)" fi fi } # 函数:暂停等待 pause() { echo "" print_color "$CYAN" "按回车键继续..." read -n 1 } # ==================== 安全检查模块 ==================== # 1. 检查SSH安全配置 check_ssh_security() { show_section "SSH服务安全检查" local ssh_config="/etc/ssh/sshd_config" if [ -f "$ssh_config" ]; then backup_config "$ssh_config" # 检查PermitRootLogin if grep -q "^PermitRootLogin no" "$ssh_config" || grep -q "^#PermitRootLogin no" "$ssh_config"; then print_result "HIGH" "SSH禁止root登录" "PASS" "已禁止root通过SSH登录" else print_result "HIGH" "SSH禁止root登录" "FAIL" "建议设置 PermitRootLogin no" fi # 检查密码认证 if grep -q "^PasswordAuthentication no" "$ssh_config"; then print_result "MEDIUM" "SSH密码认证" "PASS" "已禁用密码认证" elif grep -q "^#PasswordAuthentication no" "$ssh_config"; then print_result "MEDIUM" "SSH密码认证" "WARN" "考虑禁用密码认证,使用密钥" else print_result "MEDIUM" "SSH密码认证" "FAIL" "建议禁用密码认证" fi # 检查空闲超时 if grep -q "^ClientAliveInterval 300" "$ssh_config" && grep -q "^ClientAliveCountMax 3" "$ssh_config"; then print_result "LOW" "SSH连接超时" "PASS" "已设置连接超时" else print_result "LOW" "SSH连接超时" "WARN" "建议设置 ClientAliveInterval 300 和 ClientAliveCountMax 3" fi # 检查端口 local ssh_port=$(grep "^Port" "$ssh_config" | awk '{print $2}' | head -1) if [ "$ssh_port" = "22" ] || [ -z "$ssh_port" ]; then print_result "MEDIUM" "SSH默认端口" "WARN" "考虑修改默认SSH端口" else print_result "MEDIUM" "SSH默认端口" "PASS" "已修改默认端口: $ssh_port" fi # 检查协议版本 if grep -q "^Protocol 2" "$ssh_config"; then print_result "HIGH" "SSH协议版本" "PASS" "已使用SSH协议版本2" else print_result "HIGH" "SSH协议版本" "FAIL" "必须使用SSH协议版本2" fi # 检查失败登录限制 if grep -q "^MaxAuthTries 3" "$ssh_config"; then print_result "MEDIUM" "SSH登录尝试次数" "PASS" "已限制登录尝试次数" else print_result "MEDIUM" "SSH登录尝试次数" "WARN" "建议设置 MaxAuthTries 3" fi else print_result "HIGH" "SSH配置文件" "WARN" "SSH配置文件不存在" fi } # 2. 检查防火墙配置 check_firewall() { show_section "防火墙安全检查" # 检查iptables if command -v iptables &> /dev/null; then local iptables_rules=$(iptables -L -n 2>/dev/null | grep -c "^ACCEPT") if [ $iptables_rules -gt 0 ]; then print_result "HIGH" "iptables防火墙" "PASS" "iptables规则已配置" # 检查默认策略 local input_policy=$(iptables -L INPUT -n 2>/dev/null | grep "policy" | awk '{print $4}') local forward_policy=$(iptables -L FORWARD -n 2>/dev/null | grep "policy" | awk '{print $4}') if [ "$input_policy" = "DROP" ] || [ "$input_policy" = "REJECT" ]; then print_result "HIGH" "INPUT链默认策略" "PASS" "INPUT策略: $input_policy" else print_result "HIGH" "INPUT链默认策略" "FAIL" "建议设置INPUT链为DROP" fi else print_result "HIGH" "iptables防火墙" "FAIL" "未配置iptables规则" fi fi # 检查firewalld if command -v systemctl &> /dev/null && systemctl is-active firewalld &> /dev/null; then print_result "MEDIUM" "firewalld防火墙" "PASS" "firewalld正在运行" if command -v firewall-cmd &> /dev/null; then local firewalld_zones=$(firewall-cmd --get-active-zones 2>/dev/null | wc -l) if [ $firewalld_zones -gt 0 ]; then print_result "MEDIUM" "firewalld区域" "PASS" "已配置防火墙区域" fi fi fi # 检查UFW if command -v ufw &> /dev/null; then local ufw_status=$(ufw status 2>/dev/null | grep -i "active") if [ -n "$ufw_status" ]; then print_result "MEDIUM" "UFW防火墙" "PASS" "UFW已启用" else print_result "MEDIUM" "UFW防火墙" "WARN" "UFW已安装但未启用" fi fi } # 3. 检查密码策略 check_password_policy() { show_section "密码策略检查" local login_defs="/etc/login.defs" local common_auth="/etc/pam.d/common-auth" local common_password="/etc/pam.d/common-password" if [ -f "$login_defs" ]; then # 检查密码最大天数 local pass_max_days=$(grep "^PASS_MAX_DAYS" "$login_defs" | awk '{print $2}') if [ -n "$pass_max_days" ] && [ "$pass_max_days" -le 90 ]; then print_result "MEDIUM" "密码最大有效期" "PASS" "密码有效期: $pass_max_days 天" else print_result "MEDIUM" "密码最大有效期" "FAIL" "建议设置密码有效期不超过90天" fi # 检查密码最小天数 local pass_min_days=$(grep "^PASS_MIN_DAYS" "$login_defs" | awk '{print $2}') if [ -n "$pass_min_days" ] && [ "$pass_min_days" -ge 1 ]; then print_result "LOW" "密码最小修改间隔" "PASS" "最小修改间隔: $pass_min_days 天" else print_result "LOW" "密码最小修改间隔" "WARN" "建议设置密码最小修改间隔为1天" fi # 检查密码警告天数 local pass_warn_age=$(grep "^PASS_WARN_AGE" "$login_defs" | awk '{print $2}') if [ -n "$pass_warn_age" ] && [ "$pass_warn_age" -ge 7 ]; then print_result "LOW" "密码过期警告" "PASS" "过期前警告: $pass_warn_age 天" else print_result "LOW" "密码过期警告" "WARN" "建议设置密码过期前7天警告" fi fi # 检查PAM密码复杂度 if [ -f "$common_password" ]; then if grep -q "pam_pwquality.so" "$common_password"; then print_result "HIGH" "密码复杂度检查" "PASS" "已启用密码复杂度检查" # 检查具体复杂度设置 if grep -q "minlen=12" "$common_password" || grep -q "minlen=14" "$common_password"; then print_result "HIGH" "密码最小长度" "PASS" "密码最小长度12+字符" else print_result "HIGH" "密码最小长度" "WARN" "建议密码最小长度12字符" fi else print_result "HIGH" "密码复杂度检查" "FAIL" "未启用密码复杂度检查" fi fi # 检查失败登录锁定 if [ -f "$common_auth" ]; then if grep -q "pam_tally2.so" "$common_auth" || grep -q "pam_faillock.so" "$common_auth"; then print_result "HIGH" "失败登录锁定" "PASS" "已启用失败登录锁定" else print_result "HIGH" "失败登录锁定" "WARN" "建议启用失败登录锁定机制" fi fi } # 4. 检查用户和权限 check_users_permissions() { show_section "用户和权限检查" # 检查空密码账户 local empty_passwords=$(awk -F: '($2 == "" ) {print $1}' /etc/shadow 2>/dev/null) if [ -z "$empty_passwords" ]; then print_result "CRITICAL" "空密码账户" "PASS" "没有空密码账户" else print_result "CRITICAL" "空密码账户" "FAIL" "发现空密码账户: $empty_passwords" fi # 检查UID为0的用户 local uid0_users=$(awk -F: '($3 == 0) {print $1}' /etc/passwd) local uid0_count=$(echo "$uid0_users" | wc -l) if [ "$uid0_count" -eq 1 ] && echo "$uid0_users" | grep -q "^root$"; then print_result "CRITICAL" "UID 0用户检查" "PASS" "只有root用户UID为0" else print_result "CRITICAL" "UID 0用户检查" "FAIL" "多个用户UID为0: $uid0_users" fi # 检查sudo权限 local sudo_users=$(grep -E "^[^#].*ALL.*NOPASSWD" /etc/sudoers /etc/sudoers.d/* 2>/dev/null | wc -l) if [ "$sudo_users" -eq 0 ]; then print_result "HIGH" "无密码sudo" "PASS" "没有配置无密码sudo" else print_result "HIGH" "无密码sudo" "WARN" "发现无密码sudo配置,建议审查" fi # 检查登录shell local valid_shells="/bin/bash|/bin/sh|/bin/zsh|/bin/tcsh|/bin/csh" local invalid_shell_users=$(awk -F: -v shells="$valid_shells" '$7 !~ shells && $7 != "/usr/sbin/nologin" && $7 != "/bin/false" && $7 != "/sbin/nologin" {print $1":"$7}' /etc/passwd 2>/dev/null) if [ -z "$invalid_shell_users" ]; then print_result "MEDIUM" "无效登录shell" "PASS" "没有无效的登录shell" else print_result "MEDIUM" "无效登录shell" "WARN" "发现无效登录shell: $invalid_shell_users" fi # 检查umask设置 local umask_global=$(grep -r "^umask" /etc/profile /etc/bash.bashrc /etc/profile.d/* 2>/dev/null | head -1) if echo "$umask_global" | grep -q "022\|027"; then print_result "MEDIUM" "全局umask设置" "PASS" "全局umask设置正确" else print_result "MEDIUM" "全局umask设置" "WARN" "建议设置全局umask为022或027" fi } # 5. 检查文件系统安全 check_filesystem_security() { show_section "文件系统安全检查" # 检查关键目录权限 local critical_dirs=( "/etc/passwd:644:root:root" "/etc/shadow:640:root:shadow" "/etc/group:644:root:root" "/etc/sudoers:440:root:root" "/etc/ssh/sshd_config:600:root:root" "/root:700:root:root" "/etc/crontab:644:root:root" ) for dir_info in "${critical_dirs[@]}"; do IFS=':' read -r file expected_mode expected_owner expected_group <<< "$dir_info" if [ -e "$file" ]; then local actual_mode=$(stat -c "%a" "$file" 2>/dev/null) local actual_owner=$(stat -c "%U" "$file" 2>/dev/null) local actual_group=$(stat -c "%G" "$file" 2>/dev/null) if [ "$actual_mode" = "$expected_mode" ] && [ "$actual_owner" = "$expected_owner" ] && [ "$actual_group" = "$expected_group" ]; then print_result "HIGH" "文件权限: $file" "PASS" "权限正确" else print_result "HIGH" "文件权限: $file" "FAIL" "当前: $actual_mode $actual_owner:$actual_group, 期望: $expected_mode $expected_owner:$expected_group" fi fi done # 检查SUID/SGID文件 local suid_files=$(find / -xdev -type f \( -perm -4000 -o -perm -2000 \) 2>/dev/null | head -20) local suid_count=$(echo "$suid_files" | wc -l) if [ "$suid_count" -lt 50 ]; then print_result "MEDIUM" "SUID/SGID文件检查" "PASS" "发现 $suid_count 个SUID/SGID文件" else print_result "MEDIUM" "SUID/SGID文件检查" "WARN" "发现较多SUID/SGID文件 ($suid_count),建议审查" fi # 检查world-writable文件 local world_writable=$(find / -xdev -type f -perm -0002 ! -path "/proc/*" ! -path "/sys/*" 2>/dev/null | head -20) local ww_count=$(echo "$world_writable" | wc -l) if [ "$ww_count" -eq 0 ]; then print_result "HIGH" "全局可写文件" "PASS" "未发现全局可写文件" else print_result "HIGH" "全局可写文件" "FAIL" "发现 $ww_count 个全局可写文件,建议审查" fi # 检查未授权文件 local no_owner_files=$(find / -xdev -nouser -o -nogroup 2>/dev/null | head -10) if [ -z "$no_owner_files" ]; then print_result "MEDIUM" "无属主文件" "PASS" "未发现无属主文件" else print_result "MEDIUM" "无属主文件" "WARN" "发现无属主文件,建议清理" fi } # 6. 检查服务安全 check_services_security() { show_section "服务安全检查" # 检查不必要的服务 local dangerous_services=( "telnet" "rsh" "rlogin" "rexec" "ypbind" "ypserv" "tftp" "chargen" "daytime" "echo" "discard" "vsftpd" "proftpd" "pure-ftpd" ) for service in "${dangerous_services[@]}"; do if systemctl is-enabled "$service" 2>/dev/null | grep -q "enabled"; then print_result "HIGH" "危险服务: $service" "FAIL" "发现危险服务启用" elif netstat -tulpn 2>/dev/null | grep -q "$service"; then print_result "HIGH" "危险服务: $service" "WARN" "发现危险服务运行" fi done # 检查网络服务 local listening_services=$(netstat -tulpn 2>/dev/null | grep "LISTEN" | awk '{print $4, $7}' | head -15) if [ -n "$listening_services" ]; then print_result "MEDIUM" "网络监听服务" "INFO" "当前监听服务:\n$listening_services" fi # 检查自动启动服务 if command -v systemctl &> /dev/null; then local enabled_services=$(systemctl list-unit-files --state=enabled 2>/dev/null | grep -E "\.service" | wc -l) if [ "$enabled_services" -lt 50 ]; then print_result "LOW" "自动启动服务数量" "PASS" "启用服务数量: $enabled_services" else print_result "LOW" "自动启动服务数量" "WARN" "启用服务较多 ($enabled_services),建议优化" fi fi } # 7. 检查日志配置 check_logging_config() { show_section "日志配置检查" # 检查rsyslog if systemctl is-active rsyslog &> /dev/null; then print_result "MEDIUM" "rsyslog服务" "PASS" "rsyslog正在运行" # 检查日志转发 if grep -q "@" /etc/rsyslog.conf 2>/dev/null || grep -r "@" /etc/rsyslog.d/ 2>/dev/null; then print_result "MEDIUM" "日志远程存储" "PASS" "已配置远程日志" else print_result "MEDIUM" "日志远程存储" "WARN" "建议配置远程日志存储" fi else print_result "MEDIUM" "rsyslog服务" "WARN" "rsyslog未运行" fi # 检查journald if command -v journalctl &> /dev/null; then local journal_size=$(grep "^SystemMaxUse=" /etc/systemd/journald.conf 2>/dev/null | cut -d= -f2) if [ -n "$journal_size" ]; then print_result "LOW" "journald日志大小" "PASS" "日志大小限制: $journal_size" else print_result "LOW" "journald日志大小" "WARN" "建议设置journald日志大小限制" fi fi # 检查日志轮转 if [ -f "/etc/logrotate.conf" ]; then print_result "LOW" "日志轮转配置" "PASS" "已配置日志轮转" fi # 检查auditd if command -v auditctl &> /dev/null; then if systemctl is-active auditd &> /dev/null; then print_result "HIGH" "auditd审计服务" "PASS" "auditd正在运行" # 检查审计规则 local audit_rules=$(auditctl -l 2>/dev/null | wc -l) if [ "$audit_rules" -gt 5 ]; then print_result "HIGH" "审计规则数量" "PASS" "配置了 $audit_rules 条审计规则" else print_result "HIGH" "审计规则数量" "WARN" "审计规则较少,建议增加" fi else print_result "HIGH" "auditd审计服务" "WARN" "auditd未运行" fi fi } # 8. 检查内核安全参数 check_kernel_security() { show_section "内核安全参数检查" local sysctl_conf="/etc/sysctl.conf" local sysctl_files=("/etc/sysctl.d/*.conf") backup_config "$sysctl_conf" # 重要内核参数检查 local kernel_params=( "net.ipv4.ip_forward:0:IP转发" "net.ipv4.conf.all.accept_redirects:0:接受重定向" "net.ipv4.conf.all.send_redirects:0:发送重定向" "net.ipv4.conf.all.accept_source_route:0:源路由" "net.ipv4.conf.all.rp_filter:1:反向路径过滤" "net.ipv4.icmp_echo_ignore_broadcasts:1:忽略广播ping" "net.ipv4.icmp_ignore_bogus_error_responses:1:忽略错误响应" "net.ipv4.tcp_syncookies:1:SYN cookies" "net.ipv4.tcp_max_syn_backlog:4096:SYN队列大小" "kernel.randomize_va_space:2:地址空间随机化" ) for param_info in "${kernel_params[@]}"; do IFS=':' read -r param expected_value description <<< "$param_info" local current_value=$(sysctl -n "$param" 2>/dev/null) if [ -n "$current_value" ]; then if [ "$current_value" = "$expected_value" ]; then print_result "HIGH" "内核参数: $description" "PASS" "$param = $current_value" else print_result "HIGH" "内核参数: $description" "FAIL" "当前: $current_value, 期望: $expected_value" fi else print_result "MEDIUM" "内核参数: $description" "WARN" "参数未设置" fi done # 检查YAMA配置(ptrace限制) if [ -f "/proc/sys/kernel/yama/ptrace_scope" ]; then local ptrace_scope=$(cat /proc/sys/kernel/yama/ptrace_scope 2>/dev/null) if [ "$ptrace_scope" -ge 1 ]; then print_result "MEDIUM" "ptrace限制" "PASS" "ptrace_scope = $ptrace_scope" else print_result "MEDIUM" "ptrace限制" "WARN" "建议设置ptrace_scope为1或更高" fi fi } # 9. 检查网络安全 check_network_security() { show_section "网络安全检查" # 检查IPv6配置 if ip -6 addr show &> /dev/null; then local ipv6_enabled=$(sysctl -n net.ipv6.conf.all.disable_ipv6 2>/dev/null) if [ "$ipv6_enabled" = "1" ]; then print_result "MEDIUM" "IPv6支持" "PASS" "IPv6已禁用" else print_result "MEDIUM" "IPv6支持" "WARN" "IPv6已启用,如不需要建议禁用" fi fi # 检查TCP时间戳 local tcp_timestamps=$(sysctl -n net.ipv4.tcp_timestamps 2>/dev/null) if [ "$tcp_timestamps" = "0" ]; then print_result "LOW" "TCP时间戳" "PASS" "TCP时间戳已禁用" else print_result "LOW" "TCP时间戳" "INFO" "TCP时间戳已启用" fi # 检查SYN flood防护 local tcp_syncookies=$(sysctl -n net.ipv4.tcp_syncookies 2>/dev/null) if [ "$tcp_syncookies" = "1" ]; then print_result "MEDIUM" "SYN flood防护" "PASS" "已启用SYN cookies" fi # 检查ICMP响应 local icmp_echo=$(sysctl -n net.ipv4.icmp_echo_ignore_all 2>/dev/null) if [ "$icmp_echo" = "1" ]; then print_result "LOW" "ICMP响应" "PASS" "已禁用ICMP响应" fi } # 10. 检查恶意软件和Rootkit check_malware_rootkit() { show_section "恶意软件和Rootkit检查" # 检查常见rootkit检测工具 local rootkit_tools=("rkhunter" "chkrootkit" "lynis") local installed_tools=() for tool in "${rootkit_tools[@]}"; do if command -v "$tool" &> /dev/null; then installed_tools+=("$tool") fi done if [ ${#installed_tools[@]} -gt 0 ]; then print_result "HIGH" "Rootkit检测工具" "PASS" "已安装: ${installed_tools[*]}" # 建议运行检测 for tool in "${installed_tools[@]}"; do case $tool in "rkhunter") print_result "INFO" "安全扫描建议" "INFO" "运行: sudo rkhunter --check --skip-keypress" ;; "chkrootkit") print_result "INFO" "安全扫描建议" "INFO" "运行: sudo chkrootkit" ;; "lynis") print_result "INFO" "安全扫描建议" "INFO" "运行: sudo lynis audit system" ;; esac done else print_result "HIGH" "Rootkit检测工具" "FAIL" "未安装Rootkit检测工具" print_result "INFO" "安全工具安装" "INFO" "建议安装: sudo apt install rkhunter chkrootkit lynis" fi # 检查可疑进程 local suspicious_procs=$(ps aux 2>/dev/null | grep -E "(nc |telnet |nmap |nessus|metasploit|john |hashcat)" | grep -v grep) if [ -z "$suspicious_procs" ]; then print_result "HIGH" "可疑进程检查" "PASS" "未发现可疑进程" else print_result "HIGH" "可疑进程检查" "FAIL" "发现可疑进程: $suspicious_procs" fi # 检查隐藏文件 local hidden_files=$(find / -name ".*" -type f 2>/dev/null | grep -E "\.(bash_history|ssh|mysql_history)$" | head -10) if [ -n "$hidden_files" ]; then print_result "MEDIUM" "敏感隐藏文件" "INFO" "发现敏感隐藏文件" fi } # 11. 检查Docker安全(如果安装) check_docker_security() { if command -v docker &> /dev/null; then show_section "Docker安全配置检查" # 检查Docker守护进程配置 local docker_config="/etc/docker/daemon.json" if [ -f "$docker_config" ]; then print_result "MEDIUM" "Docker配置文件" "PASS" "已配置Docker守护进程" # 检查是否启用用户命名空间 if grep -q "userns-remap" "$docker_config"; then print_result "HIGH" "Docker用户命名空间" "PASS" "已启用用户命名空间" else print_result "HIGH" "Docker用户命名空间" "WARN" "建议启用用户命名空间" fi # 检查是否启用seccomp if grep -q "seccomp" "$docker_config" && ! grep -q '"seccomp": "unconfined"' "$docker_config"; then print_result "HIGH" "Docker seccomp配置" "PASS" "已启用seccomp" else print_result "HIGH" "Docker seccomp配置" "WARN" "建议启用seccomp" fi else print_result "MEDIUM" "Docker配置文件" "WARN" "未找到Docker配置文件" fi # 检查容器运行状态 local running_containers=$(docker ps -q 2>/dev/null | wc -l) if [ "$running_containers" -gt 0 ]; then print_result "MEDIUM" "运行中的容器" "INFO" "有 $running_containers 个容器正在运行" fi # 检查特权容器 local privileged_containers=$(docker ps --filter "ancestor=privileged" -q 2>/dev/null | wc -l) if [ "$privileged_containers" -eq 0 ]; then print_result "HIGH" "特权容器检查" "PASS" "未发现特权容器" else print_result "HIGH" "特权容器检查" "FAIL" "发现特权容器,建议审查" fi fi } # 12. 检查Cron作业和定时任务 check_cron_jobs() { show_section "Cron作业检查" # 检查系统cron local cron_files=("/etc/crontab" "/etc/cron.d/*" "/etc/cron.hourly/*" "/etc/cron.daily/*" "/etc/cron.weekly/*" "/etc/cron.monthly/*") local suspicious_cron=() for file in ${cron_files[@]}; do if [ -f "$file" ]; then local file_perm=$(stat -c "%a" "$file" 2>/dev/null) local file_owner=$(stat -c "%U" "$file" 2>/dev/null) if [ "$file_owner" != "root" ] || [ "$file_perm" -gt "644" ]; then suspicious_cron+=("$file (权限: $file_perm, 属主: $file_owner)") fi fi done if [ ${#suspicious_cron[@]} -eq 0 ]; then print_result "HIGH" "系统cron作业" "PASS" "系统cron配置正常" else print_result "HIGH" "系统cron作业" "FAIL" "发现可疑cron配置: ${suspicious_cron[*]}" fi # 检查用户cron local users_with_cron=$(cut -d: -f1 /etc/passwd) for user in $users_with_cron; do local user_cron=$(crontab -l -u "$user" 2>/dev/null) if [ -n "$user_cron" ]; then print_result "MEDIUM" "用户cron作业: $user" "INFO" "用户 $user 有cron作业" fi done } # 13. 生成安全加固建议 generate_hardening_suggestions() { show_section "安全加固建议" local suggestions=() # 收集失败和建议项 if [ $FAIL_COUNT -gt 0 ]; then suggestions+=("发现 $FAIL_COUNT 个严重问题,建议立即修复") fi if [ $WARN_COUNT -gt 0 ]; then suggestions+=("发现 $WARN_COUNT 个警告项,建议尽快处理") fi # 具体建议 if ! command -v fail2ban &> /dev/null; then suggestions+=("安装fail2ban防止暴力破解: sudo apt install fail2ban") fi if ! grep -q "pam_tally2.so" /etc/pam.d/common-auth 2>/dev/null; then suggestions+=("配置登录失败锁定: 在/etc/pam.d/common-auth添加 pam_tally2.so") fi if ! sysctl -n net.ipv4.tcp_syncookies 2>/dev/null | grep -q "1"; then suggestions+=("启用SYN cookies防护: echo 'net.ipv4.tcp_syncookies = 1' >> /etc/sysctl.conf") fi if [ ! -f "/etc/ssh/sshd_config.d/99-hardening.conf" ]; then suggestions+=("创建SSH加固配置: /etc/ssh/sshd_config.d/99-hardening.conf") fi # 显示建议 if [ ${#suggestions[@]} -eq 0 ]; then print_result "INFO" "安全状况" "PASS" "系统安全状况良好" else for ((i=0; i<${#suggestions[@]}; i++)); do print_result "INFO" "建议 $((i+1))" "INFO" "${suggestions[$i]}" done fi } # 14. 生成审计报告 generate_audit_report() { show_section "审计报告生成" # 计算安全评分 local total_possible=$((CHECK_COUNT * 2)) local security_score=0 if [ $total_possible -gt 0 ]; then security_score=$((AUDIT_SCORE * 100 / total_possible)) fi print_color "$CYAN" "正在生成详细审计报告..." # 报告摘要 { echo "安全审计报告摘要" echo "==================" echo "审计时间: $(date)" echo "主机名: $(hostname)" echo "总检查项: $CHECK_COUNT" echo "通过: $PASS_COUNT" echo "失败: $FAIL_COUNT" echo "警告: $WARN_COUNT" echo "安全评分: ${security_score}/100" echo "" if [ "$security_score" -ge 80 ]; then echo "安全评级: 优秀" elif [ "$security_score" -ge 60 ]; then echo "安全评级: 良好" elif [ "$security_score" -ge 40 ]; then echo "安全评级: 一般" else echo "安全评级: 危险" fi echo "" echo "关键问题汇总:" echo "-------------" grep "FAIL" "$LOG_FILE" | tail -10 echo "" echo "加固建议:" echo "---------" echo "1. 立即修复所有FAIL级别的问题" echo "2. 审查并处理WARN级别的问题" echo "3. 定期运行此审计脚本" echo "4. 启用系统自动更新" echo "5. 配置定期安全扫描" } > "$REPORT_FILE" print_result "INFO" "报告生成" "PASS" "审计报告已保存到: $REPORT_FILE" print_result "INFO" "备份文件" "INFO" "配置文件备份在: $BACKUP_DIR" # 显示报告位置 echo "" print_color "$PURPLE" "================================================" print_color "$GREEN" "✅ 安全审计完成!" print_color "$CYAN" "📋 详细报告: $REPORT_FILE" print_color "$CYAN" "📝 操作日志: $LOG_FILE" print_color "$CYAN" "💾 配置备份: $BACKUP_DIR" print_color "$CYAN" "📊 安全评分: $security_score/100" if [ "$security_score" -lt 60 ]; then print_color "$RED" "⚠️ 警告:系统存在严重安全问题,建议立即修复!" fi print_color "$PURPLE" "================================================" } # 主函数:运行所有安全检查 run_security_audit() { print_color "$BLUE" "🔒 Linux系统安全审计与加固脚本" print_color "$CYAN" "开始时间: $(date)" print_color "$PURPLE" "================================================" # 检查root权限 check_root # 创建日志和报告文件 touch "$LOG_FILE" report_header # 备份重要配置文件 mkdir -p "$BACKUP_DIR" # 执行所有安全检查 local checks=( check_ssh_security check_firewall check_password_policy check_users_permissions check_filesystem_security check_services_security check_logging_config check_kernel_security check_network_security check_malware_rootkit check_docker_security check_cron_jobs ) local total_checks=${#checks[@]} local current_check=0 for check_func in "${checks[@]}"; do current_check=$((current_check + 1)) show_progress $current_check $total_checks $check_func sleep 0.5 # 短暂延迟,让用户看到进度 done echo "" # 换行 # 生成建议和报告 generate_hardening_suggestions generate_audit_report log_message "审计完成 - 总检查: $CHECK_COUNT, 通过: $PASS_COUNT, 失败: $FAIL_COUNT, 警告: $WARN_COUNT" } # 交互式菜单 show_menu() { while true; do clear print_color "$PURPLE" "┌──────────────────────────────────────────────────────┐" print_color "$PURPLE" "│ Linux安全审计与加固工具 │" print_color "$PURPLE" "└──────────────────────────────────────────────────────┘" echo "" print_color "$CYAN" "1. 运行完整安全审计" print_color "$CYAN" "2. 仅运行SSH安全配置检查" print_color "$CYAN" "3. 仅运行防火墙配置检查" print_color "$CYAN" "4. 仅运行密码策略检查" print_color "$CYAN" "5. 仅运行文件权限检查" print_color "$CYAN" "6. 查看最近审计报告" print_color "$CYAN" "7. 应用基本安全加固" print_color "$CYAN" "8. 查看系统安全状态" print_color "$CYAN" "9. 退出" echo "" print_color "$YELLOW" "选择操作 [1-9]: " read -n 1 choice echo "" case $choice in 1) run_security_audit pause ;; 2) show_section "SSH安全配置检查" check_ssh_security pause ;; 3) show_section "防火墙配置检查" check_firewall pause ;; 4) show_section "密码策略检查" check_password_policy pause ;; 5) show_section "文件权限检查" check_filesystem_security pause ;; 6) if [ -f "$REPORT_FILE" ]; then less "$REPORT_FILE" else print_color "$RED" "未找到审计报告" sleep 2 fi ;; 7) apply_basic_hardening ;; 8) show_system_security_status ;; 9) print_color "$GREEN" "感谢使用安全审计工具!" exit 0 ;; *) print_color "$RED" "无效选择" sleep 1 ;; esac done } # 应用基本安全加固 apply_basic_hardening() { show_section "应用基本安全加固" print_color "$RED" "警告:此操作将修改系统配置!" read -p "确定要继续吗?(y/N): " confirm if [[ ! $confirm =~ ^[Yy]$ ]]; then print_color "$YELLOW" "操作已取消" return fi # 备份当前配置 mkdir -p "$BACKUP_DIR" # 1. 加固SSH print_color "$CYAN" "加固SSH配置..." backup_config "/etc/ssh/sshd_config" # 禁用root登录 sed -i 's/^#*PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config 2>/dev/null # 禁用密码认证 sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config 2>/dev/null # 使用SSH协议2 sed -i 's/^#*Protocol.*/Protocol 2/' /etc/ssh/sshd_config 2>/dev/null # 2. 配置防火墙基本规则 print_color "$CYAN" "配置防火墙..." if command -v ufw &> /dev/null; then ufw --force enable ufw default deny incoming ufw default allow outgoing ufw allow ssh ufw reload fi # 3. 配置密码策略 print_color "$CYAN" "配置密码策略..." backup_config "/etc/login.defs" sed -i 's/^PASS_MAX_DAYS.*/PASS_MAX_DAYS 90/' /etc/login.defs 2>/dev/null sed -i 's/^PASS_MIN_DAYS.*/PASS_MIN_DAYS 1/' /etc/login.defs 2>/dev/null sed -i 's/^PASS_WARN_AGE.*/PASS_WARN_AGE 7/' /etc/login.defs 2>/dev/null # 4. 配置内核参数 print_color "$CYAN" "配置内核安全参数..." backup_config "/etc/sysctl.conf" cat >> /etc/sysctl.conf << EOF # 安全加固配置 net.ipv4.ip_forward = 0 net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.all.send_redirects = 0 net.ipv4.conf.all.accept_source_route = 0 net.ipv4.conf.all.rp_filter = 1 net.ipv4.icmp_echo_ignore_broadcasts = 1 net.ipv4.icmp_ignore_bogus_error_responses = 1 net.ipv4.tcp_syncookies = 1 kernel.randomize_va_space = 2 fs.suid_dumpable = 0 EOF sysctl -p print_color "$GREEN" "✅ 基本安全加固完成!" print_color "$CYAN" "建议重启系统以使所有更改生效" log_message "应用基本安全加固" } # 显示系统安全状态 show_system_security_status() { clear print_color "$PURPLE" "系统安全状态概览" echo "========================================" echo "" print_color "$CYAN" "🔐 认证安全:" echo " - 空密码用户: $(awk -F: '($2 == "" ) {print $1}' /etc/shadow 2>/dev/null | wc -l)" echo " - UID 0用户: $(awk -F: '($3 == 0) {print $1}' /etc/passwd | wc -l)" echo "" print_color "$CYAN" "🛡️ 网络安全:" echo " - 开放端口: $(netstat -tulpn 2>/dev/null | grep LISTEN | wc -l)" echo " - SSH连接: $(ss -tun 2>/dev/null | grep :22 | wc -l)" echo "" print_color "$CYAN" "📁 文件安全:" echo " - SUID文件: $(find / -type f -perm -4000 2>/dev/null | wc -l)" echo " - 全局可写文件: $(find / -type f -perm -0002 ! -path "/proc/*" ! -path "/sys/*" 2>/dev/null | wc -l)" echo "" print_color "$CYAN" "⚙️ 服务安全:" echo " - 运行中服务: $(systemctl list-units --state=running 2>/dev/null | grep service | wc -l)" echo " - 失败的服务: $(systemctl list-units --state=failed 2>/dev/null | wc -l)" echo "" print_color "$CYAN" "📊 资源监控:" echo " - 内存使用: $(free -h | awk '/^Mem:/ {print $3 "/" $2}')" echo " - 磁盘使用: $(df -h / | awk 'NR==2 {print $5}')" echo "========================================" print_color "$CYAN" "按回车键继续..." read -n 1 } # 启动脚本 if [ "$#" -eq 0 ]; then show_menu else case $1 in "--audit"|"-a") run_security_audit ;; "--harden"|"-h") apply_basic_hardening ;; "--status"|"-s") show_system_security_status ;; "--help"|"-?") print_color "$CYAN" "使用说明:" echo " $0 显示交互式菜单" echo " $0 --audit | -a 运行完整安全审计" echo " $0 --harden | -h 应用基本安全加固" echo " $0 --status | -s 显示系统安全状态" echo " $0 --help | -? 显示帮助信息" ;; *) print_color "$RED" "未知选项: $1" print_color "$CYAN" "使用 $0 --help 查看帮助" ;; esac fi
2025年07月07日
2 阅读
0 评论
0 点赞
2025-06-25
Linux系统信息与健康检查脚本
#!/bin/bash # ============================================ # 系统健康检查脚本 # 功能:收集系统信息并检查关键健康指标 # 使用方法:sudo ./system-check.sh # ============================================ # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # 日志文件 LOG_FILE="/var/log/system-check-$(date +%Y%m%d-%H%M%S).log" # 函数:打印带颜色的消息 print_msg() { local color=$1 local msg=$2 echo -e "${color}${msg}${NC}" } # 函数:检查命令是否成功执行 check_status() { if [ $? -eq 0 ]; then print_msg "$GREEN" "[✓] 成功" else print_msg "$RED" "[✗] 失败" fi } # 函数:记录日志 log_message() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE" } # 函数:显示分隔线 print_separator() { echo "========================================" } # 函数:检查命令是否存在 check_command() { if ! command -v $1 &> /dev/null; then print_msg "$YELLOW" "注意:$1 命令未安装,跳过相关检查" return 1 fi return 0 } # 检查是否以root权限运行 check_root() { if [ "$EUID" -ne 0 ]; then print_msg "$YELLOW" "警告:建议使用root权限运行此脚本以获取完整信息" read -p "是否继续?(y/n): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1 fi fi } # 系统基本信息 system_info() { print_msg "$BLUE" "\n1. 系统基本信息" print_separator echo "主机名: $(hostname)" if [ -f /etc/os-release ]; then echo "操作系统: $(grep PRETTY_NAME /etc/os-release | cut -d'"' -f2)" else echo "操作系统: $(uname -o)" fi echo "内核版本: $(uname -r)" echo "系统架构: $(uname -m)" echo "启动时间: $(who -b 2>/dev/null | awk '{print $3, $4}' || uptime -s 2>/dev/null || echo '无法获取')" echo "运行时间: $(uptime -p 2>/dev/null || echo '无法获取')" log_message "系统基本信息收集完成" } # CPU检查 cpu_check() { print_msg "$BLUE" "\n2. CPU信息" print_separator if check_command "lscpu"; then echo "CPU型号: $(lscpu | grep "Model name" | cut -d':' -f2 | sed 's/^ *//' 2>/dev/null || echo '无法获取')" echo "CPU核心数: $(nproc)" else echo "CPU核心数: $(grep -c '^processor' /proc/cpuinfo)" fi echo -n "CPU使用率: " if check_command "mpstat"; then mpstat 1 1 2>/dev/null | tail -2 || echo "无法获取" else echo "请安装 sysstat 包以获取详细CPU使用率" fi # 检查CPU负载 load_avg=$(uptime | awk -F'load average:' '{print $2}' 2>/dev/null) cpu_cores=$(grep -c '^processor' /proc/cpuinfo 2>/dev/null || echo 1) if [ -n "$load_avg" ]; then load1=$(echo $load_avg | awk -F, '{print $1}' | tr -d ' ' | sed 's/,/./') echo "1分钟负载: $load1 (核心数: $cpu_cores)" if command -v bc &> /dev/null; then if (( $(echo "$load1 > $cpu_cores" | bc -l 2>/dev/null) )); then print_msg "$YELLOW" "警告:CPU负载较高" fi fi fi log_message "CPU检查完成" } # 内存检查 memory_check() { print_msg "$BLUE" "\n3. 内存信息" print_separator echo "内存使用情况:" free -h # 安全地计算内存使用率 total_mem=$(free -m 2>/dev/null | awk '/^Mem:/{print $2}') used_mem=$(free -m 2>/dev/null | awk '/^Mem:/{print $3}') if [ -n "$total_mem" ] && [ "$total_mem" -gt 0 ]; then mem_percent=$((used_mem * 100 / total_mem)) echo -e "\n内存使用率: ${mem_percent}%" if [ $mem_percent -gt 90 ]; then print_msg "$RED" "警告:内存使用率超过90%" elif [ $mem_percent -gt 70 ]; then print_msg "$YELLOW" "注意:内存使用率超过70%" fi else echo -e "\n内存使用率: 无法计算" fi # 显示交换空间 echo -e "\n交换空间:" swapon --show 2>/dev/null || free -h | grep -i swap log_message "内存检查完成" } # 磁盘检查 disk_check() { print_msg "$BLUE" "\n4. 磁盘信息" print_separator echo "磁盘空间使用情况:" df -h 2>/dev/null | head -20 echo "" echo "磁盘I/O统计:" if check_command "iostat"; then iostat -d 1 1 2>/dev/null | tail -n +4 || echo "无法获取I/O统计" else echo "请安装 sysstat 包以获取磁盘I/O统计: sudo apt-get install sysstat" fi # 检查根分区使用率 root_usage=$(df / 2>/dev/null | tail -1 | awk '{print $5}' | sed 's/%//') if [ -n "$root_usage" ] && [ "$root_usage" -eq "$root_usage" ] 2>/dev/null; then if [ $root_usage -gt 90 ]; then print_msg "$RED" "警告:根分区使用率超过90%" elif [ $root_usage -gt 80 ]; then print_msg "$YELLOW" "注意:根分区使用率超过80%" fi ROOT_USAGE=$root_usage else ROOT_USAGE=0 print_msg "$YELLOW" "注意:无法获取根分区使用率" fi # 显示磁盘inode使用情况 echo -e "\nInode使用情况:" df -i 2>/dev/null | head -10 log_message "磁盘检查完成" } # 网络检查 network_check() { print_msg "$BLUE" "\n5. 网络信息" print_separator echo "网络接口:" ip addr show 2>/dev/null | grep -E "^[0-9]+:" | head -10 || ifconfig 2>/dev/null | head -20 echo "" echo "IP地址信息:" # 获取内网IP ip addr show 2>/dev/null | grep -E "inet (192\.168|10\.|172\.(1[6-9]|2[0-9]|3[0-1]))" | grep -v "127.0.0.1" || \ ifconfig 2>/dev/null | grep -E "inet (addr:)?(192\.168|10\.|172\.)" || \ echo "未找到内网IP或需要root权限" echo "" echo "网络连接状态(前10个):" if check_command "ss"; then ss -tun 2>/dev/null | head -11 elif check_command "netstat"; then netstat -tun 2>/dev/null | head -11 else echo "请安装 iproute2 或 net-tools 包" fi echo "" echo "路由表:" ip route 2>/dev/null | head -5 || route -n 2>/dev/null | head -5 # 测试网络连通性 echo "" echo -n "外网连通性测试: " if ping -c 1 -W 1 8.8.8.8 &> /dev/null; then print_msg "$GREEN" "正常" else print_msg "$YELLOW" "失败" fi log_message "网络检查完成" } # 服务检查 service_check() { print_msg "$BLUE" "\n6. 关键服务状态" print_separator # 检查系统是使用systemd还是sysvinit if [ -d /run/systemd/system ]; then echo "使用systemd管理系统服务" # 检查常见服务 services=("sshd" "ssh" "nginx" "apache2" "httpd" "mysql" "mariadb" "postgresql" "docker" "crond" "cron") for service in "${services[@]}"; do if systemctl list-unit-files 2>/dev/null | grep -q "^${service}\."; then status=$(systemctl is-active $service 2>/dev/null || echo "unknown") if [ "$status" = "active" ]; then echo -e "${service}: ${GREEN}运行中${NC}" elif [ "$status" = "inactive" ]; then echo -e "${service}: ${YELLOW}未运行${NC}" else echo -e "${service}: 状态未知" fi fi done elif [ -d /etc/init.d ]; then echo "使用sysvinit管理系统服务" echo "运行中的服务:" service --status-all 2>/dev/null | grep -E "\[ \+ \]" | head -10 else echo "无法确定服务管理系统" fi log_message "服务检查完成" } # 安全检查 security_check() { print_msg "$BLUE" "\n7. 安全检查" print_separator echo "当前登录用户:" who echo "" echo "最近登录记录(前5条):" last -5 2>/dev/null || echo "需要root权限查看" # 检查失败的登录尝试 echo "" echo "失败的登录尝试:" if [ -f /var/log/auth.log ]; then grep "Failed password" /var/log/auth.log 2>/dev/null | tail -3 || echo "无记录或需要root权限" elif [ -f /var/log/secure ]; then grep "Failed password" /var/log/secure 2>/dev/null | tail -3 || echo "无记录或需要root权限" else echo "认证日志文件未找到" fi # 检查sudo使用 echo "" echo "sudo使用记录(最近3条):" if [ -f /var/log/auth.log ]; then grep "sudo:" /var/log/auth.log 2>/dev/null | tail -3 || echo "无记录" else echo "日志文件不可访问" fi log_message "安全检查完成" } # 软件包更新检查(仅限基于APT或YUM的系统) package_check() { print_msg "$BLUE" "\n8. 软件包更新检查" print_separator if check_command "apt-get"; then echo "APT系统检测到 (Debian/Ubuntu)" apt-get update > /dev/null 2>&1 updates=$(apt-get -s upgrade 2>/dev/null | grep -c "^Inst") if [ "$updates" -gt 0 ]; then print_msg "$YELLOW" "有 $updates 个可用更新" apt-get -s upgrade 2>/dev/null | grep "^Inst" | head -5 else print_msg "$GREEN" "系统已是最新" fi elif check_command "yum"; then echo "YUM系统检测到 (RHEL/CentOS/Fedora)" updates=$(yum check-update --quiet 2>/dev/null | grep -vc "^$") if [ "$updates" -gt 0 ]; then print_msg "$YELLOW" "有 $updates 个可用更新" yum check-update 2>/dev/null | head -10 else print_msg "$GREEN" "系统已是最新" fi else echo "不支持的包管理器" fi log_message "软件包检查完成" } # 主函数 main() { clear print_msg "$GREEN" "开始系统健康检查..." echo "检查时间: $(date)" echo "日志文件: $LOG_FILE" print_separator # 创建日志文件 touch "$LOG_FILE" 2>/dev/null || { LOG_FILE="$HOME/system-check-$(date +%Y%m%d-%H%M%S).log" touch "$LOG_FILE" print_msg "$YELLOW" "无法写入/var/log,日志将保存到: $LOG_FILE" } log_message "开始系统健康检查" # 执行检查 check_root system_info cpu_check memory_check disk_check network_check service_check security_check package_check print_msg "$GREEN" "\n✓ 系统检查完成" echo "详细日志已保存至: $LOG_FILE" # 生成摘要报告 print_msg "$BLUE" "\n📊 检查摘要" print_separator echo "系统: $(hostname)" echo "运行时间: $(uptime -p 2>/dev/null || echo '未知')" # 获取内存使用率(如果可用) total_mem=$(free -m 2>/dev/null | awk '/^Mem:/{print $2}') used_mem=$(free -m 2>/dev/null | awk '/^Mem:/{print $3}') if [ -n "$total_mem" ] && [ "$total_mem" -gt 0 ]; then mem_percent=$((used_mem * 100 / total_mem)) echo "内存使用率: ${mem_percent}%" else echo "内存使用率: 未知" fi # 获取根分区使用率(如果可用) root_usage=$(df / 2>/dev/null | tail -1 | awk '{print $5}' | sed 's/%//') if [ -n "$root_usage" ] && [ "$root_usage" -eq "$root_usage" ] 2>/dev/null; then echo "根分区使用率: ${root_usage}%" else echo "根分区使用率: 未知" fi echo "检查时间: $(date '+%Y-%m-%d %H:%M:%S')" log_message "系统检查完成" } # 执行主函数 main安装缺失的命令:如果缺少某些命令,可以安装:# Debian/Ubuntu sudo apt-get update sudo apt-get install sysstat iproute2 net-tools # RHEL/CentOS/Fedora sudo yum install sysstat iproute net-tools # 通用依赖 sudo apt-get install bc # 或 sudo yum install bc点击复制
2025年06月25日
4 阅读
0 评论
0 点赞
2025-05-16
Linux获取系统基本信息脚本
#!/bin/bash # 获取系统基本信息 echo "系统信息收集脚本" echo "操作系统: $(uname -o)" echo "内核版本: $(uname -r)" echo "CPU型号: $(lscpu | grep 'Model name')" echo "CPU使用率: $(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1"%"}')" echo "内存总量: $(free -h | awk '/^Mem:/{print $2}')" echo "磁盘空间: $(df -h / | awk '/^\/dev/{print $5 " 已使用 " $4 " 总空间 " $2}')"
2025年05月16日
2 阅读
0 评论
0 点赞
2025-05-04
Linux挂载FTP、WEBDAV、SMB为本地目录交互式脚本(可挂载多个相同协议)
此版本可挂载多个相同协议使用方法1.保存文件为multi_mount_manager.sh2.切换root用户执行脚本3.运行bash multi_mount_manager.sh#!/bin/bash # multi_mount_manager.sh - 多协议挂载管理工具(支持多个相同协议远端) # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' ORANGE='\033[0;33m' WHITE='\033[1;37m' NC='\033[0m' # No Color # 配置文件目录 CONFIG_DIR="$HOME/.mount_manager" CONFIGS_DIR="$CONFIG_DIR/configs" MOUNT_HISTORY="$CONFIG_DIR/mount_history" ACTIVE_MOUNTS="$CONFIG_DIR/active_mounts" CURRENT_PROFILE="$CONFIG_DIR/current_profile" # 默认配置 DEFAULT_MOUNT_BASE="$HOME/mnt" # 当前选中的配置 CURRENT_FTP_CONFIG="" CURRENT_WEBDAV_CONFIG="" CURRENT_SMB_CONFIG="" # 加载所有配置 load_all_configs() { mkdir -p "$CONFIGS_DIR" # 如果配置文件目录为空,创建默认配置 if [ ! -f "$CONFIGS_DIR/default_ftp.cfg" ]; then create_default_configs fi # 加载当前配置文件 if [ -f "$CURRENT_PROFILE" ]; then source "$CURRENT_PROFILE" else echo "default" > "$CURRENT_PROFILE" CURRENT_PROFILE_NAME="default" fi } # 创建默认配置文件 create_default_configs() { # 创建默认FTP配置 cat > "$CONFIGS_DIR/default_ftp.cfg" << EOF CONFIG_NAME="default_ftp" PROTOCOL="ftp" FTP_HOST="" FTP_USER="" FTP_PASS="" FTP_PORT="21" FTP_REMOTE_PATH="/" FTP_MOUNT_POINT="$DEFAULT_MOUNT_BASE/ftp" ENABLED="true" DESCRIPTION="默认FTP配置" EOF # 创建默认WebDAV配置 cat > "$CONFIGS_DIR/default_webdav.cfg" << EOF CONFIG_NAME="default_webdav" PROTOCOL="webdav" WEBDAV_URL="" WEBDAV_USER="" WEBDAV_PASS="" WEBDAV_REMOTE_PATH="/" WEBDAV_MOUNT_POINT="$DEFAULT_MOUNT_BASE/webdav" ENABLED="true" DESCRIPTION="默认WebDAV配置" EOF # 创建默认SMB配置 cat > "$CONFIGS_DIR/default_smb.cfg" << EOF CONFIG_NAME="default_smb" PROTOCOL="smb" SMB_SERVER="" SMB_SHARE="" SMB_USER="" SMB_PASS="" SMB_DOMAIN="WORKGROUP" SMB_REMOTE_PATH="/" SMB_MOUNT_POINT="$DEFAULT_MOUNT_BASE/smb" ENABLED="true" DESCRIPTION="默认SMB配置" EOF } # 加载配置 load_config() { local config_name="$1" local config_file="$CONFIGS_DIR/$config_name.cfg" if [ -f "$config_file" ]; then source "$config_file" return 0 else echo -e "${RED}配置不存在: $config_name${NC}" return 1 fi } # 保存配置 save_config() { local config_name="$1" local config_file="$CONFIGS_DIR/$config_name.cfg" case $PROTOCOL in ftp) cat > "$config_file" << EOF CONFIG_NAME="$CONFIG_NAME" PROTOCOL="ftp" FTP_HOST="$FTP_HOST" FTP_USER="$FTP_USER" FTP_PASS="$FTP_PASS" FTP_PORT="$FTP_PORT" FTP_REMOTE_PATH="$FTP_REMOTE_PATH" FTP_MOUNT_POINT="$FTP_MOUNT_POINT" ENABLED="$ENABLED" DESCRIPTION="$DESCRIPTION" EOF ;; webdav) cat > "$config_file" << EOF CONFIG_NAME="$CONFIG_NAME" PROTOCOL="webdav" WEBDAV_URL="$WEBDAV_URL" WEBDAV_USER="$WEBDAV_USER" WEBDAV_PASS="$WEBDAV_PASS" WEBDAV_REMOTE_PATH="$WEBDAV_REMOTE_PATH" WEBDAV_MOUNT_POINT="$WEBDAV_MOUNT_POINT" ENABLED="$ENABLED" DESCRIPTION="$DESCRIPTION" EOF ;; smb) cat > "$config_file" << EOF CONFIG_NAME="$CONFIG_NAME" PROTOCOL="smb" SMB_SERVER="$SMB_SERVER" SMB_SHARE="$SMB_SHARE" SMB_USER="$SMB_USER" SMB_PASS="$SMB_PASS" SMB_DOMAIN="$SMB_DOMAIN" SMB_REMOTE_PATH="$SMB_REMOTE_PATH" SMB_MOUNT_POINT="$SMB_MOUNT_POINT" ENABLED="$ENABLED" DESCRIPTION="$DESCRIPTION" EOF ;; esac chmod 600 "$config_file" echo -e "${GREEN}配置已保存: $config_name${NC}" } # 列出所有配置 list_configs() { local protocol="$1" echo -e "${CYAN}可用的${protocol^^}配置:${NC}" echo local count=0 for config_file in "$CONFIGS_DIR"/*.cfg; do if [ -f "$config_file" ]; then source "$config_file" 2>/dev/null if [ "$PROTOCOL" = "$protocol" ]; then count=$((count + 1)) local status="" if [ "$ENABLED" = "true" ]; then status="${GREEN}✓${NC}" else status="${RED}✗${NC}" fi # 检查是否已挂载 local mounted="" if mount | grep -q "$FTP_MOUNT_POINT" 2>/dev/null || \ mount | grep -q "$WEBDAV_MOUNT_POINT" 2>/dev/null || \ mount | grep -q "$SMB_MOUNT_POINT" 2>/dev/null; then mounted="${GREEN}[已挂载]${NC}" fi echo -e " $count. $status ${WHITE}$CONFIG_NAME${NC} $mounted" echo -e " 描述: $DESCRIPTION" case $protocol in ftp) echo -e " 服务器: $FTP_HOST:$FTP_PORT$FTP_REMOTE_PATH" echo -e " 挂载点: $FTP_MOUNT_POINT" ;; webdav) echo -e " URL: $WEBDAV_URL$WEBDAV_REMOTE_PATH" echo -e " 挂载点: $WEBDAV_MOUNT_POINT" ;; smb) echo -e " 共享: //$SMB_SERVER/$SMB_SHARE$SMB_REMOTE_PATH" echo -e " 挂载点: $SMB_MOUNT_POINT" ;; esac echo fi fi done if [ $count -eq 0 ]; then echo -e "${YELLOW}没有找到$protocol配置${NC}" return 1 fi return 0 } # 选择配置 select_config() { local protocol="$1" if ! list_configs "$protocol"; then return 1 fi echo -e "${CYAN}[操作选项]${NC}" echo "1. 选择配置" echo "2. 创建新配置" echo "3. 编辑配置" echo "4. 删除配置" echo "5. 复制配置" echo "0. 返回" echo read -p "请选择: " choice case $choice in 1) read -p "输入配置编号或名称: " selection select_config_by_input "$protocol" "$selection" ;; 2) create_new_config "$protocol" ;; 3) edit_config "$protocol" ;; 4) delete_config "$protocol" ;; 5) clone_config "$protocol" ;; 0) return 1 ;; *) echo -e "${RED}无效选择${NC}" return 1 ;; esac return 0 } # 通过输入选择配置 select_config_by_input() { local protocol="$1" local input="$2" local configs=() local index=1 # 收集所有配置 for config_file in "$CONFIGS_DIR"/*.cfg; do if [ -f "$config_file" ]; then source "$config_file" 2>/dev/null if [ "$PROTOCOL" = "$protocol" ]; then if [ "$index" = "$input" ] || [ "$CONFIG_NAME" = "$input" ]; then echo -e "${GREEN}已选择配置: $CONFIG_NAME${NC}" # 设置当前配置 case $protocol in ftp) CURRENT_FTP_CONFIG="$CONFIG_NAME" ;; webdav) CURRENT_WEBDAV_CONFIG="$CONFIG_NAME" ;; smb) CURRENT_SMB_CONFIG="$CONFIG_NAME" ;; esac return 0 fi index=$((index + 1)) fi fi done echo -e "${RED}未找到配置: $input${NC}" return 1 } # 创建新配置 create_new_config() { local protocol="$1" echo -e "${GREEN}=== 创建新的${protocol^^}配置 ===${NC}" read -p "配置名称 (英文,不带空格): " config_name if [ -z "$config_name" ]; then echo -e "${RED}配置名称不能为空${NC}" return 1 fi # 检查是否已存在 if [ -f "$CONFIGS_DIR/$config_name.cfg" ]; then echo -e "${RED}配置已存在: $config_name${NC}" read -p "是否覆盖?(y/N): " overwrite if [[ ! "$overwrite" =~ ^[Yy]$ ]]; then return 1 fi fi read -p "配置描述: " description # 设置默认值 CONFIG_NAME="$config_name" PROTOCOL="$protocol" DESCRIPTION="$description" ENABLED="true" case $protocol in ftp) configure_ftp_new ;; webdav) configure_webdav_new ;; smb) configure_smb_new ;; esac save_config "$config_name" # 设置为当前配置 case $protocol in ftp) CURRENT_FTP_CONFIG="$config_name" ;; webdav) CURRENT_WEBDAV_CONFIG="$config_name" ;; smb) CURRENT_SMB_CONFIG="$config_name" ;; esac } # 编辑配置 edit_config() { local protocol="$1" if ! list_configs "$protocol"; then return fi read -p "输入要编辑的配置编号或名称: " selection local config_name="" local index=1 # 查找配置 for config_file in "$CONFIGS_DIR"/*.cfg; do if [ -f "$config_file" ]; then source "$config_file" 2>/dev/null if [ "$PROTOCOL" = "$protocol" ]; then if [ "$index" = "$selection" ] || [ "$CONFIG_NAME" = "$selection" ]; then config_name="$CONFIG_NAME" break fi index=$((index + 1)) fi fi done if [ -z "$config_name" ]; then echo -e "${RED}未找到配置${NC}" return fi load_config "$config_name" echo -e "${GREEN}=== 编辑配置: $config_name ===${NC}" read -p "新描述 [当前: $DESCRIPTION]: " new_desc [ -n "$new_desc" ] && DESCRIPTION="$new_desc" read -p "是否启用 (true/false) [当前: $ENABLED]: " new_enabled [ -n "$new_enabled" ] && ENABLED="$new_enabled" case $protocol in ftp) configure_ftp_edit ;; webdav) configure_webdav_edit ;; smb) configure_smb_edit ;; esac save_config "$config_name" echo -e "${GREEN}配置已更新: $config_name${NC}" } # 删除配置 delete_config() { local protocol="$1" if ! list_configs "$protocol"; then return fi read -p "输入要删除的配置编号或名称: " selection local config_name="" local config_file="" local index=1 # 查找配置 for cfg_file in "$CONFIGS_DIR"/*.cfg; do if [ -f "$cfg_file" ]; then source "$cfg_file" 2>/dev/null if [ "$PROTOCOL" = "$protocol" ]; then if [ "$index" = "$selection" ] || [ "$CONFIG_NAME" = "$selection" ]; then config_name="$CONFIG_NAME" config_file="$cfg_file" break fi index=$((index + 1)) fi fi done if [ -z "$config_name" ]; then echo -e "${RED}未找到配置${NC}" return fi echo -e "${RED}警告:这将删除配置 '$config_name'${NC}" read -p "确认删除?(y/N): " confirm if [[ "$confirm" =~ ^[Yy]$ ]]; then rm -f "$config_file" # 如果删除的是当前配置,清空当前配置 case $protocol in ftp) if [ "$CURRENT_FTP_CONFIG" = "$config_name" ]; then CURRENT_FTP_CONFIG="" fi ;; webdav) if [ "$CURRENT_WEBDAV_CONFIG" = "$config_name" ]; then CURRENT_WEBDAV_CONFIG="" fi ;; smb) if [ "$CURRENT_SMB_CONFIG" = "$config_name" ]; then CURRENT_SMB_CONFIG="" fi ;; esac echo -e "${GREEN}配置已删除: $config_name${NC}" else echo -e "${YELLOW}删除已取消${NC}" fi } # 复制配置 clone_config() { local protocol="$1" if ! list_configs "$protocol"; then return fi read -p "输入要复制的配置编号或名称: " selection local source_config="" local index=1 # 查找配置 for config_file in "$CONFIGS_DIR"/*.cfg; do if [ -f "$config_file" ]; then source "$config_file" 2>/dev/null if [ "$PROTOCOL" = "$protocol" ]; then if [ "$index" = "$selection" ] || [ "$CONFIG_NAME" = "$selection" ]; then source_config="$CONFIG_NAME" break fi index=$((index + 1)) fi fi done if [ -z "$source_config" ]; then echo -e "${RED}未找到配置${NC}" return fi load_config "$source_config" read -p "新配置名称 (英文,不带空格): " new_name if [ -z "$new_name" ]; then echo -e "${RED}配置名称不能为空${NC}" return fi if [ -f "$CONFIGS_DIR/$new_name.cfg" ]; then echo -e "${RED}配置已存在: $new_name${NC}" return fi CONFIG_NAME="$new_name" DESCRIPTION="$DESCRIPTION (副本)" save_config "$new_name" echo -e "${GREEN}配置已复制为: $new_name${NC}" } # FTP配置(新建) configure_ftp_new() { read -p "FTP服务器地址: " FTP_HOST read -p "端口 [默认: 21]: " FTP_PORT FTP_PORT=${FTP_PORT:-21} read -p "用户名: " FTP_USER read -s -p "密码: " FTP_PASS echo read -p "远端路径 [默认: /]: " FTP_REMOTE_PATH FTP_REMOTE_PATH=${FTP_REMOTE_PATH:-/} read -p "本地挂载点目录 [默认: $DEFAULT_MOUNT_BASE/ftp_${CONFIG_NAME}]: " mount_point FTP_MOUNT_POINT="${mount_point:-$DEFAULT_MOUNT_BASE/ftp_${CONFIG_NAME}}" # 创建挂载点目录 mkdir -p "$FTP_MOUNT_POINT" } # FTP配置(编辑) configure_ftp_edit() { read -p "FTP服务器地址 [当前: $FTP_HOST]: " input [ -n "$input" ] && FTP_HOST="$input" read -p "端口 [当前: $FTP_PORT]: " input [ -n "$input" ] && FTP_PORT="$input" read -p "用户名 [当前: $FTP_USER]: " input [ -n "$input" ] && FTP_USER="$input" read -s -p "密码 [输入新密码或回车保持]: " input echo [ -n "$input" ] && FTP_PASS="$input" read -p "远端路径 [当前: $FTP_REMOTE_PATH]: " input [ -n "$input" ] && FTP_REMOTE_PATH="$input" read -p "本地挂载点目录 [当前: $FTP_MOUNT_POINT]: " input [ -n "$input" ] && FTP_MOUNT_POINT="$input" # 创建挂载点目录 mkdir -p "$FTP_MOUNT_POINT" } # WebDAV配置(新建) configure_webdav_new() { read -p "WebDAV基础URL (如: http://example.com): " WEBDAV_URL read -p "用户名: " WEBDAV_USER read -s -p "密码: " WEBDAV_PASS echo read -p "远端路径 [默认: /]: " WEBDAV_REMOTE_PATH WEBDAV_REMOTE_PATH=${WEBDAV_REMOTE_PATH:-/} read -p "本地挂载点目录 [默认: $DEFAULT_MOUNT_BASE/webdav_${CONFIG_NAME}]: " mount_point WEBDAV_MOUNT_POINT="${mount_point:-$DEFAULT_MOUNT_BASE/webdav_${CONFIG_NAME}}" # 创建挂载点目录 mkdir -p "$WEBDAV_MOUNT_POINT" } # WebDAV配置(编辑) configure_webdav_edit() { read -p "WebDAV基础URL [当前: $WEBDAV_URL]: " input [ -n "$input" ] && WEBDAV_URL="$input" read -p "用户名 [当前: $WEBDAV_USER]: " input [ -n "$input" ] && WEBDAV_USER="$input" read -s -p "密码 [输入新密码或回车保持]: " input echo [ -n "$input" ] && WEBDAV_PASS="$input" read -p "远端路径 [当前: $WEBDAV_REMOTE_PATH]: " input [ -n "$input" ] && WEBDAV_REMOTE_PATH="$input" read -p "本地挂载点目录 [当前: $WEBDAV_MOUNT_POINT]: " input [ -n "$input" ] && WEBDAV_MOUNT_POINT="$input" # 创建挂载点目录 mkdir -p "$WEBDAV_MOUNT_POINT" } # SMB配置(新建) configure_smb_new() { read -p "SMB服务器地址: " SMB_SERVER read -p "共享名称: " SMB_SHARE read -p "域名 [默认: WORKGROUP]: " SMB_DOMAIN SMB_DOMAIN=${SMB_DOMAIN:-WORKGROUP} read -p "用户名: " SMB_USER read -s -p "密码: " SMB_PASS echo read -p "远端路径 [默认: /]: " SMB_REMOTE_PATH SMB_REMOTE_PATH=${SMB_REMOTE_PATH:-/} read -p "本地挂载点目录 [默认: $DEFAULT_MOUNT_BASE/smb_${CONFIG_NAME}]: " mount_point SMB_MOUNT_POINT="${mount_point:-$DEFAULT_MOUNT_BASE/smb_${CONFIG_NAME}}" # 创建挂载点目录 mkdir -p "$SMB_MOUNT_POINT" } # SMB配置(编辑) configure_smb_edit() { read -p "SMB服务器地址 [当前: $SMB_SERVER]: " input [ -n "$input" ] && SMB_SERVER="$input" read -p "共享名称 [当前: $SMB_SHARE]: " input [ -n "$input" ] && SMB_SHARE="$input" read -p "域名 [当前: $SMB_DOMAIN]: " input [ -n "$input" ] && SMB_DOMAIN="$input" read -p "用户名 [当前: $SMB_USER]: " input [ -n "$input" ] && SMB_USER="$input" read -s -p "密码 [输入新密码或回车保持]: " input echo [ -n "$input" ] && SMB_PASS="$input" read -p "远端路径 [当前: $SMB_REMOTE_PATH]: " input [ -n "$input" ] && SMB_REMOTE_PATH="$input" read -p "本地挂载点目录 [当前: $SMB_MOUNT_POINT]: " input [ -n "$input" ] && SMB_MOUNT_POINT="$input" # 创建挂载点目录 mkdir -p "$SMB_MOUNT_POINT" } # 记录挂载历史 record_mount() { local protocol="$1" local config_name="$2" local server="$3" local remote_path="$4" local mount_point="$5" local timestamp=$(date '+%Y-%m-%d %H:%M:%S') echo "$timestamp|$protocol|$config_name|$server|$remote_path|$mount_point" >> "$MOUNT_HISTORY" } # 记录活动挂载 record_active_mount() { local config_name="$1" local mount_point="$2" # 删除旧的记录 grep -v "^$config_name|" "$ACTIVE_MOUNTS" > "$ACTIVE_MOUNTS.tmp" 2>/dev/null || true mv "$ACTIVE_MOUNTS.tmp" "$ACTIVE_MOUNTS" 2>/dev/null || true # 添加新记录 echo "$config_name|$mount_point|$(date '+%Y-%m-%d %H:%M:%S')" >> "$ACTIVE_MOUNTS" } # 移除活动挂载记录 remove_active_mount() { local config_name="$1" grep -v "^$config_name|" "$ACTIVE_MOUNTS" > "$ACTIVE_MOUNTS.tmp" 2>/dev/null || true mv "$ACTIVE_MOUNTS.tmp" "$ACTIVE_MOUNTS" 2>/dev/null || true } # 检查依赖 check_dependencies() { local missing_pkgs="" # 检查FTP依赖 if ! command -v curlftpfs &> /dev/null; then missing_pkgs+=" curlftpfs" fi # 检查WebDAV依赖 if ! command -v mount.davfs &> /dev/null; then missing_pkgs+=" davfs2" fi # 检查SMB依赖 if ! command -v mount.cifs &> /dev/null; then missing_pkgs+=" cifs-utils" fi # 检查curl(用于目录浏览) if ! command -v curl &> /dev/null; then missing_pkgs+=" curl" fi if [ -n "$missing_pkgs" ]; then echo -e "${YELLOW}缺少必要软件包:$missing_pkgs${NC}" echo -e "${BLUE}是否安装?(y/N): ${NC}" read -n 1 install_choice echo if [[ "$install_choice" =~ ^[Yy]$ ]]; then install_dependencies "$missing_pkgs" else echo -e "${RED}部分功能可能无法使用${NC}" fi fi } # 安装依赖 install_dependencies() { local pkgs="$1" echo -e "${BLUE}正在安装依赖包...${NC}" if [ -f /etc/debian_version ]; then sudo apt update sudo apt install -y $pkgs elif [ -f /etc/redhat-release ]; then sudo yum install -y $pkgs elif [ -f /etc/arch-release ]; then sudo pacman -S --noconfirm $pkgs elif [ -f /etc/fedora-release ]; then sudo dnf install -y $pkgs else echo -e "${RED}无法识别发行版,请手动安装: $pkgs${NC}" return 1 fi if [ $? -eq 0 ]; then echo -e "${GREEN}依赖安装完成${NC}" else echo -e "${RED}依赖安装失败${NC}" fi } # 显示主菜单 show_main_menu() { clear echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}" echo -e "${BLUE} 多协议挂载管理工具 v3.0 (支持多个相同协议远端)${NC}" echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}" echo # 显示当前活动挂载 echo -e "${YELLOW}[当前活动挂载]${NC}" show_active_mounts echo echo -e "${GREEN}[主菜单选项]${NC}" echo -e " 1. 挂载管理 (选择协议和配置)" echo -e " 2. 配置管理 (创建/编辑/删除配置)" echo -e " 3. 批量操作" echo -e " 4. 测试连接" echo -e " 5. 查看挂载历史" echo -e " 6. 设置开机自动挂载" echo -e " 7. 创建快捷命令" echo -e " 8. 配置文件管理" echo -e " 0. 退出" echo echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}" } # 显示活动挂载 show_active_mounts() { if [ -f "$ACTIVE_MOUNTS" ] && [ -s "$ACTIVE_MOUNTS" ]; then echo -e "${CYAN}配置名称 挂载点 挂载时间${NC}" echo "────────────────────────────────────────────────────────────────────" while IFS='|' read -r config_name mount_point mount_time; do # 检查是否真的已挂载 if mount | grep -q "$mount_point"; then status="${GREEN}✓${NC}" else status="${RED}✗${NC}" fi # 获取协议和描述 if [ -f "$CONFIGS_DIR/$config_name.cfg" ]; then source "$CONFIGS_DIR/$config_name.cfg" 2>/dev/null printf "%-25s %-30s %s %s\n" "$config_name" "$mount_point" "$mount_time" "$status" fi done < "$ACTIVE_MOUNTS" else echo -e " ${YELLOW}没有活动挂载${NC}" fi } # 挂载管理菜单 show_mount_menu() { clear echo -e "${BLUE}══════════════════════════════════════════════════${NC}" echo -e "${BLUE} 挂载管理${NC}" echo -e "${BLUE}══════════════════════════════════════════════════${NC}" echo echo -e "${CYAN}[选择协议]${NC}" echo -e " 1. ${GREEN}FTP${NC} - 文件传输协议" echo -e " 2. ${YELLOW}WebDAV${NC} - Web分布式创作和版本控制" echo -e " 3. ${PURPLE}SMB/CIFS${NC} - Windows文件共享" echo -e " 4. ${BLUE}查看所有活动挂载${NC}" echo -e " 5. ${RED}批量卸载所有${NC}" echo -e " 0. 返回主菜单" echo echo -e "${BLUE}══════════════════════════════════════════════════${NC}" } # 配置管理菜单 show_config_menu() { clear echo -e "${BLUE}══════════════════════════════════════════════════${NC}" echo -e "${BLUE} 配置管理${NC}" echo -e "${BLUE}══════════════════════════════════════════════════${NC}" echo echo -e "${CYAN}[选择协议]${NC}" echo -e " 1. ${GREEN}FTP配置管理${NC}" echo -e " 2. ${YELLOW}WebDAV配置管理${NC}" echo -e " 3. ${PURPLE}SMB配置管理${NC}" echo -e " 4. ${BLUE}查看所有配置${NC}" echo -e " 5. ${ORANGE}配置导入/导出${NC}" echo -e " 0. 返回主菜单" echo echo -e "${BLUE}══════════════════════════════════════════════════${NC}" } # FTP挂载功能 mount_ftp_config() { local config_name="$1" if ! load_config "$config_name"; then return 1 fi if [ "$ENABLED" != "true" ]; then echo -e "${RED}配置已被禁用: $config_name${NC}" return 1 fi echo -e "${GREEN}[挂载FTP: $config_name]${NC}" # 检查是否已挂载 if mount | grep -q "$FTP_MOUNT_POINT"; then echo -e "${YELLOW}FTP已经挂载到 $FTP_MOUNT_POINT${NC}" read -p "是否重新挂载?(y/N): " choice if [[ ! "$choice" =~ ^[Yy]$ ]]; then return fi umount_ftp_config "$config_name" fi # 创建挂载点 mkdir -p "$FTP_MOUNT_POINT" echo -e "${BLUE}正在挂载FTP...${NC}" echo -e "服务器: ${FTP_HOST}:${FTP_PORT}" echo -e "远端路径: $FTP_REMOTE_PATH" echo -e "挂载点: $FTP_MOUNT_POINT" local mount_cmd local full_url if [ -z "$FTP_PASS" ]; then # 匿名访问 full_url="ftp://$FTP_HOST:$FTP_PORT$FTP_REMOTE_PATH" mount_cmd="curlftpfs -o allow_other,uid=$(id -u),gid=$(id -g) \"$full_url\" \"$FTP_MOUNT_POINT\"" else # 认证访问 full_url="ftp://$FTP_USER:$FTP_PASS@$FTP_HOST:$FTP_PORT$FTP_REMOTE_PATH" mount_cmd="curlftpfs -o allow_other,uid=$(id -u),gid=$(id -g) \"$full_url\" \"$FTP_MOUNT_POINT\"" fi echo -e "${YELLOW}执行命令: $mount_cmd${NC}" if eval "$mount_cmd"; then echo -e "${GREEN}✓ FTP挂载成功${NC}" record_mount "FTP" "$config_name" "$FTP_HOST:$FTP_PORT" "$FTP_REMOTE_PATH" "$FTP_MOUNT_POINT" record_active_mount "$config_name" "$FTP_MOUNT_POINT" else echo -e "${RED}✗ FTP挂载失败${NC}" fi } # FTP卸载功能 umount_ftp_config() { local config_name="$1" if ! load_config "$config_name"; then return 1 fi if mount | grep -q "$FTP_MOUNT_POINT"; then echo -e "${BLUE}正在卸载FTP: $config_name...${NC}" fusermount -u "$FTP_MOUNT_POINT" 2>/dev/null || sudo fusermount -u "$FTP_MOUNT_POINT" echo -e "${GREEN}✓ FTP卸载完成: $config_name${NC}" remove_active_mount "$config_name" else echo -e "${YELLOW}FTP未挂载: $config_name${NC}" fi } # WebDAV挂载功能 mount_webdav_config() { local config_name="$1" if ! load_config "$config_name"; then return 1 fi if [ "$ENABLED" != "true" ]; then echo -e "${RED}配置已被禁用: $config_name${NC}" return 1 fi echo -e "${YELLOW}[挂载WebDAV: $config_name]${NC}" # 检查是否已挂载 if mount | grep -q "$WEBDAV_MOUNT_POINT"; then echo -e "${YELLOW}WebDAV已经挂载到 $WEBDAV_MOUNT_POINT${NC}" read -p "是否重新挂载?(y/N): " choice if [[ ! "$choice" =~ ^[Yy]$ ]]; then return fi umount_webdav_config "$config_name" fi # 创建挂载点 mkdir -p "$WEBDAV_MOUNT_POINT" local full_url="${WEBDAV_URL%/}${WEBDAV_REMOTE_PATH}" echo -e "${BLUE}正在挂载WebDAV...${NC}" echo -e "URL: $full_url" echo -e "挂载点: $WEBDAV_MOUNT_POINT" local mount_cmd if [ -z "$WEBDAV_PASS" ]; then # 匿名访问 mount_cmd="sudo mount -t davfs \"$full_url\" \"$WEBDAV_MOUNT_POINT\" -o uid=$(id -u),gid=$(id -g),noexec" else # 认证访问 mount_cmd="sudo mount -t davfs \"$full_url\" \"$WEBDAV_MOUNT_POINT\" -o uid=$(id -u),gid=$(id -g),noexec,username=$WEBDAV_USER,password=$WEBDAV_PASS" fi echo -e "${YELLOW}执行命令: $mount_cmd${NC}" if eval "$mount_cmd"; then echo -e "${GREEN}✓ WebDAV挂载成功${NC}" record_mount "WebDAV" "$config_name" "$WEBDAV_URL" "$WEBDAV_REMOTE_PATH" "$WEBDAV_MOUNT_POINT" record_active_mount "$config_name" "$WEBDAV_MOUNT_POINT" else echo -e "${RED}✗ WebDAV挂载失败${NC}" fi } # WebDAV卸载功能 umount_webdav_config() { local config_name="$1" if ! load_config "$config_name"; then return 1 fi if mount | grep -q "$WEBDAV_MOUNT_POINT"; then echo -e "${BLUE}正在卸载WebDAV: $config_name...${NC}" sudo umount "$WEBDAV_MOUNT_POINT" echo -e "${GREEN}✓ WebDAV卸载完成: $config_name${NC}" remove_active_mount "$config_name" else echo -e "${YELLOW}WebDAV未挂载: $config_name${NC}" fi } # SMB挂载功能 mount_smb_config() { local config_name="$1" if ! load_config "$config_name"; then return 1 fi if [ "$ENABLED" != "true" ]; then echo -e "${RED}配置已被禁用: $config_name${NC}" return 1 fi echo -e "${PURPLE}[挂载SMB/CIFS: $config_name]${NC}" # 检查是否已挂载 if mount | grep -q "$SMB_MOUNT_POINT"; then echo -e "${YELLOW}SMB已经挂载到 $SMB_MOUNT_POINT${NC}" read -p "是否重新挂载?(y/N): " choice if [[ ! "$choice" =~ ^[Yy]$ ]]; then return fi umount_smb_config "$config_name" fi # 创建挂载点 mkdir -p "$SMB_MOUNT_POINT" local full_path="//$SMB_SERVER/$SMB_SHARE$SMB_REMOTE_PATH" echo -e "${BLUE}正在挂载SMB...${NC}" echo -e "共享: $full_path" echo -e "挂载点: $SMB_MOUNT_POINT" local mount_cmd if [ -z "$SMB_PASS" ]; then # 访客访问 mount_cmd="sudo mount -t cifs \"$full_path\" \"$SMB_MOUNT_POINT\" -o guest,uid=$(id -u),gid=$(id -g),iocharset=utf8,file_mode=0777,dir_mode=0777" else # 认证访问 mount_cmd="sudo mount -t cifs \"$full_path\" \"$SMB_MOUNT_POINT\" -o username=$SMB_USER,password=$SMB_PASS,domain=$SMB_DOMAIN,uid=$(id -u),gid=$(id -g),iocharset=utf8,file_mode=0777,dir_mode=0777" fi echo -e "${YELLOW}执行命令: $mount_cmd${NC}" if eval "$mount_cmd"; then echo -e "${GREEN}✓ SMB挂载成功${NC}" record_mount "SMB" "$config_name" "//$SMB_SERVER/$SMB_SHARE" "$SMB_REMOTE_PATH" "$SMB_MOUNT_POINT" record_active_mount "$config_name" "$SMB_MOUNT_POINT" else echo -e "${RED}✗ SMB挂载失败${NC}" fi } # SMB卸载功能 umount_smb_config() { local config_name="$1" if ! load_config "$config_name"; then return 1 fi if mount | grep -q "$SMB_MOUNT_POINT"; then echo -e "${BLUE}正在卸载SMB: $config_name...${NC}" sudo umount "$SMB_MOUNT_POINT" echo -e "${GREEN}✓ SMB卸载完成: $config_name${NC}" remove_active_mount "$config_name" else echo -e "${YELLOW}SMB未挂载: $config_name${NC}" fi } # 批量操作菜单 show_batch_menu() { clear echo -e "${BLUE}══════════════════════════════════════════════════${NC}" echo -e "${BLUE} 批量操作${NC}" echo -e "${BLUE}══════════════════════════════════════════════════${NC}" echo echo -e "${CYAN}[选择批量操作]${NC}" echo -e " 1. ${GREEN}挂载所有FTP配置${NC}" echo -e " 2. ${GREEN}卸载所有FTP配置${NC}" echo -e " 3. ${YELLOW}挂载所有WebDAV配置${NC}" echo -e " 4. ${YELLOW}卸载所有WebDAV配置${NC}" echo -e " 5. ${PURPLE}挂载所有SMB配置${NC}" echo -e " 6. ${PURPLE}卸载所有SMB配置${NC}" echo -e " 7. ${BLUE}挂载所有启用的配置${NC}" echo -e " 8. ${RED}卸载所有配置${NC}" echo -e " 0. 返回主菜单" echo echo -e "${BLUE}══════════════════════════════════════════════════${NC}" } # 挂载所有FTP配置 mount_all_ftp() { echo -e "${GREEN}[挂载所有FTP配置]${NC}" local count=0 for config_file in "$CONFIGS_DIR"/*.cfg; do if [ -f "$config_file" ]; then source "$config_file" 2>/dev/null if [ "$PROTOCOL" = "ftp" ] && [ "$ENABLED" = "true" ]; then mount_ftp_config "$CONFIG_NAME" count=$((count + 1)) fi fi done if [ $count -eq 0 ]; then echo -e "${YELLOW}没有启用的FTP配置${NC}" else echo -e "${GREEN}已尝试挂载 $count 个FTP配置${NC}" fi } # 卸载所有FTP配置 umount_all_ftp() { echo -e "${RED}[卸载所有FTP配置]${NC}" local count=0 for config_file in "$CONFIGS_DIR"/*.cfg; do if [ -f "$config_file" ]; then source "$config_file" 2>/dev/null if [ "$PROTOCOL" = "ftp" ]; then umount_ftp_config "$CONFIG_NAME" count=$((count + 1)) fi fi done echo -e "${GREEN}已尝试卸载 $count 个FTP配置${NC}" } # 挂载所有WebDAV配置 mount_all_webdav() { echo -e "${YELLOW}[挂载所有WebDAV配置]${NC}" local count=0 for config_file in "$CONFIGS_DIR"/*.cfg; do if [ -f "$config_file" ]; then source "$config_file" 2>/dev/null if [ "$PROTOCOL" = "webdav" ] && [ "$ENABLED" = "true" ]; then mount_webdav_config "$CONFIG_NAME" count=$((count + 1)) fi fi done if [ $count -eq 0 ]; then echo -e "${YELLOW}没有启用的WebDAV配置${NC}" else echo -e "${GREEN}已尝试挂载 $count 个WebDAV配置${NC}" fi } # 卸载所有WebDAV配置 umount_all_webdav() { echo -e "${RED}[卸载所有WebDAV配置]${NC}" local count=0 for config_file in "$CONFIGS_DIR"/*.cfg; do if [ -f "$config_file" ]; then source "$config_file" 2>/dev/null if [ "$PROTOCOL" = "webdav" ]; then umount_webdav_config "$CONFIG_NAME" count=$((count + 1)) fi fi done echo -e "${GREEN}已尝试卸载 $count 个WebDAV配置${NC}" } # 挂载所有SMB配置 mount_all_smb() { echo -e "${PURPLE}[挂载所有SMB配置]${NC}" local count=0 for config_file in "$CONFIGS_DIR"/*.cfg; do if [ -f "$config_file" ]; then source "$config_file" 2>/dev/null if [ "$PROTOCOL" = "smb" ] && [ "$ENABLED" = "true" ]; then mount_smb_config "$CONFIG_NAME" count=$((count + 1)) fi fi done if [ $count -eq 0 ]; then echo -e "${YELLOW}没有启用的SMB配置${NC}" else echo -e "${GREEN}已尝试挂载 $count 个SMB配置${NC}" fi } # 卸载所有SMB配置 umount_all_smb() { echo -e "${RED}[卸载所有SMB配置]${NC}" local count=0 for config_file in "$CONFIGS_DIR"/*.cfg; do if [ -f "$config_file" ]; then source "$config_file" 2>/dev/null if [ "$PROTOCOL" = "smb" ]; then umount_smb_config "$CONFIG_NAME" count=$((count + 1)) fi fi done echo -e "${GREEN}已尝试卸载 $count 个SMB配置${NC}" } # 挂载所有启用的配置 mount_all_enabled() { echo -e "${BLUE}[挂载所有启用的配置]${NC}" local ftp_count=0 local webdav_count=0 local smb_count=0 for config_file in "$CONFIGS_DIR"/*.cfg; do if [ -f "$config_file" ]; then source "$config_file" 2>/dev/null if [ "$ENABLED" = "true" ]; then case $PROTOCOL in ftp) mount_ftp_config "$CONFIG_NAME" ftp_count=$((ftp_count + 1)) ;; webdav) mount_webdav_config "$CONFIG_NAME" webdav_count=$((webdav_count + 1)) ;; smb) mount_smb_config "$CONFIG_NAME" smb_count=$((smb_count + 1)) ;; esac fi fi done echo -e "${GREEN}挂载完成: FTP($ftp_count) WebDAV($webdav_count) SMB($smb_count)${NC}" } # 卸载所有配置 umount_all_configs() { echo -e "${RED}[卸载所有配置]${NC}" local total_count=0 # 从活动挂载记录卸载 if [ -f "$ACTIVE_MOUNTS" ]; then while IFS='|' read -r config_name mount_point mount_time; do if [ -f "$CONFIGS_DIR/$config_name.cfg" ]; then source "$CONFIGS_DIR/$config_name.cfg" 2>/dev/null case $PROTOCOL in ftp) umount_ftp_config "$config_name" ;; webdav) umount_webdav_config "$config_name" ;; smb) umount_smb_config "$config_name" ;; esac total_count=$((total_count + 1)) fi done < "$ACTIVE_MOUNTS" fi echo -e "${GREEN}已卸载 $total_count 个配置${NC}" } # 配置文件管理菜单 show_profile_menu() { clear echo -e "${BLUE}══════════════════════════════════════════════════${NC}" echo -e "${BLUE} 配置文件管理${NC}" echo -e "${BLUE}══════════════════════════════════════════════════${NC}" echo echo -e "${CYAN}[选择操作]${NC}" echo -e " 1. ${GREEN}导出所有配置${NC}" echo -e " 2. ${GREEN}导入配置${NC}" echo -e " 3. ${YELLOW}备份配置${NC}" echo -e " 4. ${YELLOW}恢复配置${NC}" echo -e " 5. ${RED}重置所有配置${NC}" echo -e " 6. ${BLUE}查看配置统计${NC}" echo -e " 0. 返回主菜单" echo echo -e "${BLUE}══════════════════════════════════════════════════${NC}" } # 导出所有配置 export_configs() { local export_dir="$CONFIG_DIR/exports" mkdir -p "$export_dir" local timestamp=$(date '+%Y%m%d_%H%M%S') local export_file="$export_dir/configs_backup_$timestamp.tar.gz" tar -czf "$export_file" -C "$CONFIG_DIR" configs if [ $? -eq 0 ]; then echo -e "${GREEN}配置已导出到: $export_file${NC}" echo -e "包含 $(ls "$CONFIGS_DIR"/*.cfg 2>/dev/null | wc -l) 个配置文件" else echo -e "${RED}导出失败${NC}" fi } # 导入配置 import_configs() { echo -e "${YELLOW}将配置文件 (.cfg) 放入目录: $CONFIGS_DIR/${NC}" echo -e "或者输入备份文件路径:" read -p "备份文件路径 (或回车跳过): " backup_file if [ -n "$backup_file" ] && [ -f "$backup_file" ]; then echo -e "${BLUE}正在从备份恢复...${NC}" tar -xzf "$backup_file" -C "$CONFIG_DIR" if [ $? -eq 0 ]; then echo -e "${GREEN}配置已从备份恢复${NC}" else echo -e "${RED}恢复失败${NC}" fi else echo -e "${YELLOW}请手动将.cfg文件复制到 $CONFIGS_DIR/${NC}" echo -e "按回车键继续..." read fi } # 备份配置 backup_configs() { local backup_dir="$HOME/backups/mount_manager" mkdir -p "$backup_dir" local timestamp=$(date '+%Y%m%d_%H%M%S') local backup_file="$backup_dir/full_backup_$timestamp.tar.gz" tar -czf "$backup_file" -C "$CONFIG_DIR" . if [ $? -eq 0 ]; then echo -e "${GREEN}完整备份已创建: $backup_file${NC}" echo -e "备份大小: $(du -h "$backup_file" | cut -f1)" else echo -e "${RED}备份失败${NC}" fi } # 恢复配置 restore_configs() { echo -e "${RED}警告:这将覆盖现有配置${NC}" read -p "确认恢复配置?(y/N): " confirm if [[ ! "$confirm" =~ ^[Yy]$ ]]; then return fi echo -e "可用的备份文件:" local backup_dir="$HOME/backups/mount_manager" if [ -d "$backup_dir" ]; then ls -lh "$backup_dir"/*.tar.gz 2>/dev/null | nl else echo -e "${YELLOW}没有找到备份目录${NC}" return fi read -p "输入备份文件编号: " backup_num local backup_file=$(ls "$backup_dir"/*.tar.gz 2>/dev/null | sed -n "${backup_num}p") if [ -f "$backup_file" ]; then echo -e "${BLUE}正在从 $backup_file 恢复...${NC}" # 备份当前配置 local temp_backup="$CONFIG_DIR/backup_before_restore.tar.gz" tar -czf "$temp_backup" -C "$CONFIG_DIR" . # 清空配置目录 rm -rf "$CONFIG_DIR"/* # 恢复备份 tar -xzf "$backup_file" -C "$CONFIG_DIR" if [ $? -eq 0 ]; then echo -e "${GREEN}配置已成功恢复${NC}" else echo -e "${RED}恢复失败,尝试回滚${NC}" tar -xzf "$temp_backup" -C "$CONFIG_DIR" fi rm -f "$temp_backup" else echo -e "${RED}无效的备份文件${NC}" fi } # 重置所有配置 reset_configs() { echo -e "${RED}警告:这将删除所有配置!${NC}" read -p "确认重置所有配置?(输入'RESET'确认): " confirm if [ "$confirm" = "RESET" ]; then rm -rf "$CONFIG_DIR" echo -e "${GREEN}所有配置已重置${NC}" echo -e "请重新启动脚本" exit 0 else echo -e "${YELLOW}重置已取消${NC}" fi } # 查看配置统计 show_config_stats() { echo -e "${CYAN}[配置统计]${NC}" echo local ftp_count=0 local webdav_count=0 local smb_count=0 local enabled_count=0 for config_file in "$CONFIGS_DIR"/*.cfg; do if [ -f "$config_file" ]; then source "$config_file" 2>/dev/null case $PROTOCOL in ftp) ftp_count=$((ftp_count + 1)) ;; webdav) webdav_count=$((webdav_count + 1)) ;; smb) smb_count=$((smb_count + 1)) ;; esac [ "$ENABLED" = "true" ] && enabled_count=$((enabled_count + 1)) fi done local total=$((ftp_count + webdav_count + smb_count)) echo -e "总配置数: $total" echo -e " FTP配置: $ftp_count" echo -e " WebDAV配置: $webdav_count" echo -e " SMB配置: $smb_count" echo -e "启用配置: $enabled_count" echo -e "禁用配置: $((total - enabled_count))" echo # 显示挂载点使用情况 echo -e "${YELLOW}[挂载点使用情况]${NC}" for config_file in "$CONFIGS_DIR"/*.cfg; do if [ -f "$config_file" ]; then source "$config_file" 2>/dev/null local mount_var="${PROTOCOL^^}_MOUNT_POINT" local mount_point="${!mount_var}" if mount | grep -q "$mount_point"; then echo -e " ${GREEN}✓${NC} $CONFIG_NAME: $mount_point" fi fi done } # 测试连接 test_connections() { echo -e "${CYAN}=== 测试连接 ===${NC}" echo echo "1. 测试所有FTP连接" echo "2. 测试所有WebDAV连接" echo "3. 测试所有SMB连接" echo "4. 测试特定配置" echo "0. 返回" echo read -p "请选择: " choice case $choice in 1) test_all_ftp ;; 2) test_all_webdav ;; 3) test_all_smb ;; 4) test_specific_config ;; 0) return ;; *) echo -e "${RED}无效选择${NC}" ;; esac } # 测试所有FTP连接 test_all_ftp() { echo -e "${GREEN}[测试所有FTP连接]${NC}" local success=0 local total=0 for config_file in "$CONFIGS_DIR"/*.cfg; do if [ -f "$config_file" ]; then source "$config_file" 2>/dev/null if [ "$PROTOCOL" = "ftp" ] && [ "$ENABLED" = "true" ]; then total=$((total + 1)) echo -n "测试 $CONFIG_NAME ($FTP_HOST:$FTP_PORT)... " if [ -z "$FTP_PASS" ]; then timeout 10 curl -s --list-only "ftp://$FTP_HOST:$FTP_PORT$FTP_REMOTE_PATH" > /dev/null 2>&1 else timeout 10 curl -s --list-only --user "$FTP_USER:$FTP_PASS" "ftp://$FTP_HOST:$FTP_PORT$FTP_REMOTE_PATH" > /dev/null 2>&1 fi if [ $? -eq 0 ]; then echo -e "${GREEN}✓${NC}" success=$((success + 1)) else echo -e "${RED}✗${NC}" fi fi fi done echo -e "\n${BLUE}测试完成: $success/$total 成功${NC}" } # 主程序 main() { # 初始化 mkdir -p "$CONFIGS_DIR" load_all_configs check_dependencies while true; do show_main_menu read -p "请选择操作 [0-8]: " choice case $choice in 1) # 挂载管理 while true; do show_mount_menu read -p "请选择 [0-5]: " mount_choice case $mount_choice in 1) # FTP挂载 if select_config "ftp"; then mount_ftp_config "$CURRENT_FTP_CONFIG" fi ;; 2) # WebDAV挂载 if select_config "webdav"; then mount_webdav_config "$CURRENT_WEBDAV_CONFIG" fi ;; 3) # SMB挂载 if select_config "smb"; then mount_smb_config "$CURRENT_SMB_CONFIG" fi ;; 4) # 查看所有活动挂载 show_active_mounts echo echo -e "${YELLOW}[操作]${NC}" echo "1. 卸载特定配置" echo "2. 刷新状态" echo "0. 返回" read -p "请选择: " action case $action in 1) read -p "输入要卸载的配置名称: " config_name if [ -f "$CONFIGS_DIR/$config_name.cfg" ]; then source "$CONFIGS_DIR/$config_name.cfg" case $PROTOCOL in ftp) umount_ftp_config "$config_name" ;; webdav) umount_webdav_config "$config_name" ;; smb) umount_smb_config "$config_name" ;; esac else echo -e "${RED}配置不存在${NC}" fi ;; 2) continue ;; esac ;; 5) # 批量卸载所有 umount_all_configs ;; 0) break ;; *) echo -e "${RED}无效选择${NC}" ;; esac echo read -p "按回车键继续..." done ;; 2) # 配置管理 while true; do show_config_menu read -p "请选择 [0-5]: " config_choice case $config_choice in 1) # FTP配置管理 select_config "ftp" ;; 2) # WebDAV配置管理 select_config "webdav" ;; 3) # SMB配置管理 select_config "smb" ;; 4) # 查看所有配置 echo -e "${CYAN}[所有配置]${NC}" echo list_configs "ftp" list_configs "webdav" list_configs "smb" ;; 5) # 配置导入/导出 show_profile_menu read -p "请选择 [0-6]: " profile_choice case $profile_choice in 1) export_configs ;; 2) import_configs ;; 3) backup_configs ;; 4) restore_configs ;; 5) reset_configs ;; 6) show_config_stats ;; 0) continue ;; *) echo -e "${RED}无效选择${NC}" ;; esac ;; 0) break ;; *) echo -e "${RED}无效选择${NC}" ;; esac echo read -p "按回车键继续..." done ;; 3) # 批量操作 while true; do show_batch_menu read -p "请选择 [0-8]: " batch_choice case $batch_choice in 1) mount_all_ftp ;; 2) umount_all_ftp ;; 3) mount_all_webdav ;; 4) umount_all_webdav ;; 5) mount_all_smb ;; 6) umount_all_smb ;; 7) mount_all_enabled ;; 8) umount_all_configs ;; 0) break ;; *) echo -e "${RED}无效选择${NC}" ;; esac echo read -p "按回车键继续..." done ;; 4) test_connections ;; 5) show_mount_history ;; 6) setup_autostart ;; 7) create_shortcuts ;; 8) show_profile_menu read -p "请选择 [0-6]: " profile_choice case $profile_choice in 1) export_configs ;; 2) import_configs ;; 3) backup_configs ;; 4) restore_configs ;; 5) reset_configs ;; 6) show_config_stats ;; 0) continue ;; *) echo -e "${RED}无效选择${NC}" ;; esac ;; 0) echo -e "${GREEN}感谢使用,再见!${NC}" exit 0 ;; *) echo -e "${RED}无效选择,请重新输入${NC}" ;; esac echo read -p "按回车键继续..." done } # 运行主程序 if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then main "$@" fi
2025年05月04日
5 阅读
0 评论
0 点赞
1
2
3
...
6
网站公告
×
欢迎访问本站
如果你有教程想要分享,请
联系我们