1. 问题背景与解决思路
当服务器磁盘空间告急时,系统性能会急剧下降,甚至可能导致服务不可用。本教程将详细介绍如何快速定位占用磁盘空间的大文件,并进行安全清理。
1.1 整体解决流程
graph TB
A[磁盘空间告急] --> B[检查磁盘使用情况]
B --> C[定位大文件目录]
C --> D[分析文件类型和大小]
D --> E[安全清理策略]
E --> F[验证清理效果]
F --> G[建立监控预防]
style A fill:#ff6b6b,stroke:#fff,stroke-width:2px,color:#fff
style B fill:#4ecdc4,stroke:#fff,stroke-width:2px,color:#fff
style C fill:#45b7d1,stroke:#fff,stroke-width:2px,color:#fff
style D fill:#96ceb4,stroke:#fff,stroke-width:2px,color:#fff
style E fill:#feca57,stroke:#fff,stroke-width:2px,color:#fff
style F fill:#ff9ff3,stroke:#fff,stroke-width:2px,color:#fff
style G fill:#54a0ff,stroke:#fff,stroke-width:2px,color:#fff
classDef default fill:#333,stroke:#fff,stroke-width:2px,color:#fff;
2. 环境准备和基础检查
2.1 创建检查脚本文件
文件名: disk_cleanup_helper.sh
bash
#!/bin/bash
# 磁盘清理助手脚本
# 功能:自动化磁盘空间检查和清理
set -e # 遇到错误立即退出
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 日志函数
log_info() {
echo -e "${BLUE}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
# 检查是否以root用户运行
check_root() {
if [[ $EUID -eq 0 ]]; then
log_info "以root用户运行"
else
log_warn "建议使用root用户运行以获得完整权限"
fi
}
# 主函数
main() {
log_info "开始磁盘空间检查"
check_root
echo "=================================================="
echo " 磁盘清理助手 v1.0"
echo "=================================================="
echo "1. 检查磁盘使用情况"
echo "2. 查找大文件"
echo "3. 查找大目录"
echo "4. 清理临时文件"
echo "5. 清理日志文件"
echo "6. 退出"
echo "=================================================="
read -p "请选择操作 [1-6]: " choice
case $choice in
1) check_disk_usage ;;
2) find_large_files ;;
3) find_large_directories ;;
4) cleanup_temp_files ;;
5) cleanup_log_files ;;
6) exit 0 ;;
*) log_error "无效选择" && main ;;
esac
}
# 后续函数定义将在这里添加
3. 磁盘使用情况检查
3.1 检查磁盘使用情况函数
将以下函数添加到 disk_cleanup_helper.sh 中:
bash
# 检查磁盘使用情况
check_disk_usage() {
log_info "开始检查磁盘使用情况..."
echo -e "\n${YELLOW}=== 磁盘空间使用情况 ===${NC}"
df -h | grep -v tmpfs
echo -e "\n${YELLOW}=== inode使用情况 ===${NC}"
df -i | grep -v tmpfs
echo -e "\n${YELLOW}=== 根目录使用情况详情 ===${NC}"
du -sh /* 2>/dev/null | sort -hr | head -20
# 检查磁盘使用率超过80%的分区
local high_usage=$(df -h | awk '0+$5 >= 80 {print $1 " : " $5}')
if [[ -n "$high_usage" ]]; then
log_warn "以下分区使用率超过80%:"
echo "$high_usage"
else
log_success "所有分区使用率正常"
fi
read -p "按回车键继续..."
main
}
3.2 创建专门的磁盘检查脚本
文件名: disk_analyzer.sh
bash
#!/bin/bash
# 磁盘分析脚本 - 详细分析磁盘使用情况
# 颜色设置
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m'
# 阈值设置
DISK_WARNING=80
DISK_CRITICAL=90
LARGE_FILE_SIZE="500M" # 大文件阈值
# 生成报告
generate_report() {
local report_file="/tmp/disk_analysis_report_$(date +%Y%m%d_%H%M%S).txt"
echo "磁盘分析报告 - 生成时间: $(date)" > $report_file
echo "==========================================" >> $report_file
# 磁盘使用情况
echo -e "\n1. 磁盘空间使用情况:" >> $report_file
df -h >> $report_file
# 大文件查找
echo -e "\n2. 根目录下大于${LARGE_FILE_SIZE}的文件:" >> $report_file
find / -type f -size +${LARGE_FILE_SIZE} 2>/dev/null | xargs du -h 2>/dev/null | sort -hr >> $report_file
# 目录大小
echo -e "\n3. 根目录下各目录大小:" >> $report_file
du -sh /* 2>/dev/null | sort -hr >> $report_file
echo -e "\n报告已保存至: $report_file"
echo -e "使用命令查看: ${YELLOW}less $report_file${NC}"
}
# 详细磁盘检查
detailed_disk_check() {
echo -e "${CYAN}=== 详细磁盘分析 ===${NC}"
# 1. 基本磁盘信息
echo -e "\n${YELLOW}1. 磁盘分区信息:${NC}"
lsblk
# 2. 挂载点详细信息
echo -e "\n${YELLOW}2. 挂载点详细信息:${NC}"
mount | grep -E "^/dev"
# 3. 检查磁盘健康(如果有smartctl)
if command -v smartctl &> /dev/null; then
echo -e "\n${YELLOW}3. 磁盘健康检查:${NC}"
for disk in $(lsblk -d -o NAME | grep -v NAME); do
if [[ -e "/dev/$disk" ]]; then
echo "检查 /dev/$disk ..."
smartctl -H "/dev/$disk" 2>/dev/null | grep -E "(SMART|result)" || true
fi
done
fi
# 4. 生成详细报告
generate_report
}
# 监控模式
monitor_mode() {
echo -e "${GREEN}启动磁盘监控模式,每60秒刷新一次...${NC}"
echo -e "按 Ctrl+C 退出监控\n"
while true; do
clear
echo -e "${CYAN}=== 磁盘监控 - $(date) ===${NC}"
echo -e "${YELLOW}磁盘使用情况:${NC}"
df -h | grep -v tmpfs
# 高亮显示使用率高的分区
echo -e "\n${YELLOW}警告级别:${NC}"
df -h | awk -v warn=$DISK_WARNING -v crit=$DISK_CRITICAL '
NR>1 {
usage = substr($5, 1, length($5)-1)
if (usage >= crit)
printf "'${RED}'CRITICAL: %s 使用率 %s'${NC}'\n", $1, $5
else if (usage >= warn)
printf "'${YELLOW}'WARNING: %s 使用率 %s'${NC}'\n", $1, $5
}'
sleep 60
done
}
main() {
echo -e "${PURPLE}================================${NC}"
echo -e "${PURPLE} 磁盘分析工具 v1.0 ${NC}"
echo -e "${PURPLE}================================${NC}"
echo "1. 快速磁盘检查"
echo "2. 详细磁盘分析"
echo "3. 实时监控模式"
echo "4. 生成分析报告"
echo "5. 退出"
echo -e "${PURPLE}================================${NC}"
read -p "请选择操作 [1-5]: " choice
case $choice in
1)
echo -e "${CYAN}=== 快速磁盘检查 ===${NC}"
df -h
;;
2) detailed_disk_check ;;
3) monitor_mode ;;
4) generate_report ;;
5) exit 0 ;;
*) echo -e "${RED}无效选择${NC}" && main ;;
esac
read -p "按回车键返回主菜单..."
main
}
# 脚本入口
if [[ "$1" == "monitor" ]]; then
monitor_mode
else
main
fi
4. 定位大文件和大目录
4.1 大文件查找函数
将以下函数添加到 disk_cleanup_helper.sh 中:
bash
# 查找大文件
find_large_files() {
log_info "开始查找大文件..."
local size_threshold="100M"
read -p "设置文件大小阈值 (默认: 100M): " custom_size
if [[ -n "$custom_size" ]]; then
size_threshold=$custom_size
fi
echo -e "\n${YELLOW}=== 查找大于 ${size_threshold} 的文件 ===${NC}"
# 创建临时文件保存结果
local temp_file=$(mktemp)
log_info "正在扫描,这可能需要几分钟..."
# 查找大文件并排序
find / -type f -size +${size_threshold} 2>/dev/null | \
xargs du -h 2>/dev/null | \
sort -hr > "$temp_file"
if [[ -s "$temp_file" ]]; then
echo -e "\n${GREEN}找到的大文件列表:${NC}"
head -50 "$temp_file" | awk '{printf "%-10s %s\n", $1, $2}'
local total_count=$(wc -l < "$temp_file")
echo -e "\n${BLUE}总共找到 ${total_count} 个大于 ${size_threshold} 的文件${NC}"
# 保存完整结果
local result_file="/tmp/large_files_$(date +%Y%m%d_%H%M%S).txt"
cp "$temp_file" "$result_file"
log_info "完整结果已保存至: $result_file"
else
log_warn "未找到大于 ${size_threshold} 的文件"
fi
# 清理临时文件
rm -f "$temp_file"
read -p "按回车键继续..."
main
}
# 查找大目录
find_large_directories() {
log_info "开始查找大目录..."
local depth=3
read -p "设置扫描深度 (默认: 3): " custom_depth
if [[ -n "$custom_depth" ]]; then
depth=$custom_depth
fi
echo -e "\n${YELLOW}=== 查找前20个大目录 (深度: ${depth}) ===${NC}"
# 扫描指定深度的目录
for i in $(seq 1 $depth); do
echo -e "\n${CYAN}=== 深度 $i ===${NC}"
du -h --max-depth=$i / 2>/dev/null | sort -hr | head -20
done
# 详细扫描home目录
echo -e "\n${YELLOW}=== /home 目录详细分析 ===${NC}"
if [[ -d "/home" ]]; then
du -sh /home/* 2>/dev/null | sort -hr | head -10
fi
# 详细扫描var目录
echo -e "\n${YELLOW}=== /var 目录详细分析 ===${NC}"
if [[ -d "/var" ]]; then
du -sh /var/* 2>/dev/null | sort -hr | head -10
fi
read -p "按回车键继续..."
main
}
4.2 创建高级文件分析工具
文件名: file_analyzer.sh
bash
#!/bin/bash
# 高级文件分析工具
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m'
# 文件类型分析
analyze_file_types() {
local target_dir="${1:-/}"
local depth="${2:-2}"
echo -e "${CYAN}分析目录: $target_dir (深度: $depth)${NC}"
# 按文件类型统计
echo -e "\n${YELLOW}=== 按文件类型统计 ===${NC}"
find "$target_dir" -maxdepth $depth -type f 2>/dev/null | \
awk -F. '{
if (NF>1) {
ext = tolower($NF)
if (length(ext) < 10) types[ext]++
} else {
types["no_extension"]++
}
total++
}
END {
for (ext in types) {
printf "%-15s: %8d files (%5.1f%%)\n", ext, types[ext], (types[ext]/total)*100
}
printf "%-15s: %8d files\n", "TOTAL", total
}' | sort -k2 -nr
# 按文件大小区间统计
echo -e "\n${YELLOW}=== 按文件大小区间统计 ===${NC}"
find "$target_dir" -maxdepth $depth -type f 2>/dev/null | \
xargs du -k 2>/dev/null | \
awk '
{
size = $1
if (size < 100) small++
else if (size < 1024) medium++ # < 1MB
else if (size < 10240) large++ # < 10MB
else if (size < 102400) very_large++ # < 100MB
else huge++
total_files++
}
END {
printf "%-15s: %8d files (%5.1f%%)\n", "< 100KB", small, (small/total_files)*100
printf "%-15s: %8d files (%5.1f%%)\n", "100KB-1MB", medium, (medium/total_files)*100
printf "%-15s: %8d files (%5.1f%%)\n", "1MB-10MB", large, (large/total_files)*100
printf "%-15s: %8d files (%5.1f%%)\n", "10MB-100MB", very_large, (very_large/total_files)*100
printf "%-15s: %8d files (%5.1f%%)\n", "> 100MB", huge, (huge/total_files)*100
printf "%-15s: %8d files\n", "TOTAL", total_files
}'
}
# 查找重复文件
find_duplicate_files() {
local target_dir="${1:-/}"
echo -e "${CYAN}查找重复文件: $target_dir${NC}"
echo -e "${YELLOW}这可能需要较长时间...${NC}"
find "$target_dir" -type f 2>/dev/null | \
xargs md5sum 2>/dev/null | \
sort | \
uniq -w32 -d --all-repeated=separate | \
awk '{
if ($1 != prev_md5) {
if (count > 1) {
printf "\n%s - %d duplicates\n", prev_md5, count
for (i=0; i<count; i++) printf " %s\n", files[i]
}
count = 0
prev_md5 = $1
}
files[count] = $2
count++
}
END {
if (count > 1) {
printf "\n%s - %d duplicates\n", prev_md5, count
for (i=0; i<count; i++) printf " %s\n", files[i]
}
}'
}
# 文件时间分析
analyze_file_ages() {
local target_dir="${1:-/}"
echo -e "${CYAN}分析文件修改时间: $target_dir${NC}"
find "$target_dir" -type f 2>/dev/null | \
xargs stat -c %Y 2>/dev/null | \
awk -v now=$(date +%s) '
{
age = now - $1
if (age < 86400) today++ # < 1天
else if (age < 604800) week++ # < 1周
else if (age < 2592000) month++ # < 1月
else if (age < 31536000) year++ # < 1年
else old++ # > 1年
total++
}
END {
printf "%-15s: %8d files (%5.1f%%)\n", "< 1天", today, (today/total)*100
printf "%-15s: %8d files (%5.1f%%)\n", "1天-1周", week, (week/total)*100
printf "%-15s: %8d files (%5.1f%%)\n", "1周-1月", month, (month/total)*100
printf "%-15s: %8d files (%5.1f%%)\n", "1月-1年", year, (year/total)*100
printf "%-15s: %8d files (%5.1f%%)\n", "> 1年", old, (old/total)*100
printf "%-15s: %8d files\n", "TOTAL", total
}'
}
# 大文件详细分析
detailed_large_file_analysis() {
local min_size="${1:-100M}"
echo -e "${CYAN}详细大文件分析 (大于 $min_size)${NC}"
# 查找并分析大文件
find / -type f -size +$min_size 2>/dev/null | \
while read file; do
if [[ -f "$file" ]]; then
size=$(du -h "$file" 2>/dev/null | cut -f1)
mtime=$(stat -c %y "$file" 2>/dev/null | cut -d' ' -f1)
file_type=$(file -b "$file" 2>/dev/null | cut -c1-50)
owner=$(stat -c %U "$file" 2>/dev/null)
printf "%-10s %-12s %-15s %-50s %s\n" \
"$size" "$mtime" "$owner" "${file_type:-unknown}" "$file"
fi
done | sort -hr | head -30
}
main() {
echo -e "${PURPLE}================================${NC}"
echo -e "${PURPLE} 高级文件分析工具 ${NC}"
echo -e "${PURPLE}================================${NC}"
echo "1. 文件类型分析"
echo "2. 查找重复文件"
echo "3. 文件时间分析"
echo "4. 大文件详细分析"
echo "5. 退出"
echo -e "${PURPLE}================================${NC}"
read -p "请选择操作 [1-5]: " choice
case $choice in
1)
read -p "请输入要分析的目录 (默认: /): " dir
analyze_file_types "${dir:-/}"
;;
2)
read -p "请输入要查找的目录 (默认: /): " dir
find_duplicate_files "${dir:-/}"
;;
3)
read -p "请输入要分析的目录 (默认: /): " dir
analyze_file_ages "${dir:-/}"
;;
4)
read -p "请输入最小文件大小 (默认: 100M): " size
detailed_large_file_analysis "${size:-100M}"
;;
5) exit 0 ;;
*) echo -e "${RED}无效选择${NC}" && main ;;
esac
read -p "按回车键返回主菜单..."
main
}
main
5. 安全清理操作
5.1 临时文件清理函数
将以下函数添加到 disk_cleanup_helper.sh 中:
bash
# 清理临时文件
cleanup_temp_files() {
log_info "开始清理临时文件..."
local total_before=$(df / | awk 'NR==2 {print $4}')
echo -e "${YELLOW}=== 清理系统临时文件 ===${NC}"
# 清理 /tmp 目录
if [[ -d "/tmp" ]]; then
local tmp_size=$(du -sh /tmp 2>/dev/null | cut -f1)
log_info "清理 /tmp 目录 (当前大小: ${tmp_size})"
find /tmp -type f -atime +7 -delete 2>/dev/null || true
fi
# 清理缓存文件
echo -e "\n${YELLOW}=== 清理缓存文件 ===${NC}"
# 安全清理yum缓存
if command -v yum &> /dev/null; then
log_info "清理 yum 缓存"
yum clean all 2>/dev/null || true
fi
# 清理apt缓存
if command -v apt-get &> /dev/null; then
log_info "清理 apt 缓存"
apt-get clean 2>/dev/null || true
fi
# 清理pip缓存
if command -v pip &> /dev/null; then
log_info "清理 pip 缓存"
pip cache purge 2>/dev/null || true
fi
# 清理日志轮转文件
echo -e "\n${YELLOW}=== 清理旧日志文件 ===${NC}"
find /var/log -name "*.log.*" -type f -mtime +30 -delete 2>/dev/null || true
find /var/log -name "*.gz" -type f -mtime +30 -delete 2>/dev/null || true
# 清理系统缓存(需要root权限)
if [[ $EUID -eq 0 ]]; then
echo -e "\n${YELLOW}=== 清理系统缓存 ===${NC}"
sync
echo 3 > /proc/sys/vm/drop_caches 2>/dev/null || true
fi
local total_after=$(df / | awk 'NR==2 {print $4}')
local freed_space=$((total_after - total_before))
if [[ $freed_space -gt 0 ]]; then
log_success "清理完成,释放空间: ${freed_space}KB"
else
log_info "清理完成,但未释放额外空间"
fi
read -p "按回车键继续..."
main
}
# 清理日志文件
cleanup_log_files() {
log_info "开始清理日志文件..."
echo -e "${YELLOW}=== 日志文件分析 ===${NC}"
# 检查日志目录大小
if [[ -d "/var/log" ]]; then
local log_size=$(du -sh /var/log 2>/dev/null | cut -f1)
echo -e "当前 /var/log 目录大小: ${RED}${log_size}${NC}"
fi
# 显示大日志文件
echo -e "\n${YELLOW}=== 大日志文件列表 ===${NC}"
find /var/log -type f -name "*.log" -size +100M 2>/dev/null | \
xargs du -h 2>/dev/null | sort -hr | head -10
# 安全清理选项
echo -e "\n${CYAN}=== 安全清理选项 ===${NC}"
echo "1. 清空特定日志文件(保留文件)"
echo "2. 删除旧日志文件(30天前)"
echo "3. 压缩旧日志文件"
echo "4. 返回主菜单"
read -p "请选择操作 [1-4]: " log_choice
case $log_choice in
1)
read -p "请输入要清空的日志文件路径: " log_file
if [[ -f "$log_file" && -w "$log_file" ]]; then
log_info "清空日志文件: $log_file"
: > "$log_file"
log_success "日志文件已清空"
else
log_error "无法访问或写入文件: $log_file"
fi
;;
2)
log_info "删除30天前的日志文件"
find /var/log -name "*.log.*" -type f -mtime +30 -delete 2>/dev/null
find /var/log -name "*.gz" -type f -mtime +30 -delete 2>/dev/null
log_success "旧日志文件已删除"
;;
3)
log_info "压缩7天前的日志文件"
find /var/log -name "*.log" -type f -mtime +7 -exec gzip {} \; 2>/dev/null
log_success "日志文件已压缩"
;;
4)
main
return
;;
*)
log_error "无效选择"
;;
esac
# 显示清理后的大小
if [[ -d "/var/log" ]]; then
local new_log_size=$(du -sh /var/log 2>/dev/null | cut -f1)
echo -e "\n清理后 /var/log 目录大小: ${GREEN}${new_log_size}${NC}"
fi
read -p "按回车键继续..."
main
}
5.2 创建安全清理脚本
文件名: safe_cleanup.sh
bash
#!/bin/bash
# 安全清理脚本 - 提供安全的文件清理功能
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m'
# 备份目录
BACKUP_DIR="/tmp/cleanup_backup_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"
# 日志函数
log() {
echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1" | tee -a "$BACKUP_DIR/cleanup.log"
}
warn() {
echo -e "${YELLOW}[WARNING]${NC} $1" | tee -a "$BACKUP_DIR/cleanup.log"
}
error() {
echo -e "${RED}[ERROR]${NC} $1" | tee -a "$BACKUP_DIR/cleanup.log"
}
success() {
echo -e "${GREEN}[SUCCESS]${NC} $1" | tee -a "$BACKUP_DIR/cleanup.log"
}
# 创建备份
backup_file() {
local file="$1"
local reason="$2"
if [[ -e "$file" ]]; then
local backup_path="$BACKUP_DIR/$(echo "$file" | tr '/' '_')"
log "备份文件: $file -> $backup_path (原因: $reason)"
cp -r "$file" "$backup_path" 2>/dev/null || true
fi
}
# 交互式删除
interactive_delete() {
local target="$1"
local reason="$2"
if [[ ! -e "$target" ]]; then
warn "文件不存在: $target"
return
fi
local size=$(du -sh "$target" 2>/dev/null | cut -f1)
echo -e "\n${YELLOW}=== 删除确认 ===${NC}"
echo "文件: $target"
echo "大小: $size"
echo "原因: $reason"
echo -e "${RED}此操作不可逆!${NC}"
read -p "确认删除?(y/N): " confirm
if [[ "$confirm" == "y" || "$confirm" == "Y" ]]; then
backup_file "$target" "$reason"
if rm -rf "$target"; then
success "已删除: $target (释放空间: $size)"
else
error "删除失败: $target"
fi
else
log "取消删除: $target"
fi
}
# 清理Docker相关文件
cleanup_docker() {
if ! command -v docker &> /dev/null; then
log "Docker 未安装,跳过清理"
return
fi
echo -e "\n${CYAN}=== Docker 清理 ===${NC}"
# 检查Docker磁盘使用
local docker_size=$(docker system df 2>/dev/null | grep -v "RECLAIMABLE" | awk 'NR>1 {print $1}' | head -1)
log "Docker 当前使用: $docker_size"
echo -e "\n${YELLOW}Docker 清理选项:${NC}"
echo "1. 清理所有停止的容器"
echo "2. 清理所有未使用的镜像"
echo "3. 清理所有未使用的网络"
echo "4. 清理构建缓存"
echo "5. 全部清理"
read -p "请选择 [1-5]: " docker_choice
case $docker_choice in
1) docker container prune -f ;;
2) docker image prune -a -f ;;
3) docker network prune -f ;;
4) docker builder prune -f ;;
5) docker system prune -a -f ;;
*) log "跳过 Docker 清理" ;;
esac
local new_docker_size=$(docker system df 2>/dev/null | grep -v "RECLAIMABLE" | awk 'NR>1 {print $1}' | head -1)
success "Docker 清理完成,当前使用: $new_docker_size"
}
# 清理软件包缓存
cleanup_package_cache() {
echo -e "\n${CYAN}=== 软件包缓存清理 ===${NC}"
if command -v apt-get &> /dev/null; then
log "清理 APT 缓存"
local apt_before=$(du -sh /var/cache/apt 2>/dev/null | cut -f1)
apt-get autoremove -y
apt-get autoclean
apt-get clean
local apt_after=$(du -sh /var/cache/apt 2>/dev/null | cut -f1)
success "APT 缓存清理完成: $apt_before -> $apt_after"
fi
if command -v yum &> /dev/null; then
log "清理 YUM 缓存"
local yum_before=$(du -sh /var/cache/yum 2>/dev/null | cut -f1)
yum clean all
local yum_after=$(du -sh /var/cache/yum 2>/dev/null | cut -f1)
success "YUM 缓存清理完成: $yum_before -> $yum_after"
fi
}
# 清理用户缓存
cleanup_user_cache() {
echo -e "\n${CYAN}=== 用户缓存清理 ===${NC}"
# 清理浏览器缓存(如果有)
for user_home in /home/*; do
if [[ -d "$user_home" ]]; then
local user=$(basename "$user_home")
log "清理用户 $user 的缓存"
# Chrome缓存
local chrome_cache="$user_home/.cache/google-chrome"
if [[ -d "$chrome_cache" ]]; then
local chrome_size=$(du -sh "$chrome_cache" 2>/dev/null | cut -f1)
rm -rf "$chrome_cache"/Default/Cache/*
success "清理 Chrome 缓存: 释放 $chrome_size"
fi
# 通用缓存
local cache_dir="$user_home/.cache"
if [[ -d "$cache_dir" ]]; then
find "$cache_dir" -type f -atime +30 -delete 2>/dev/null || true
fi
fi
done
}
# 核心文件保护检查
check_protected_files() {
local file="$1"
# 系统关键文件保护
local protected_patterns=(
"/bin/" "/sbin/" "/usr/bin/" "/usr/sbin/"
"/lib/" "/lib64/" "/usr/lib/" "/usr/lib64/"
"/etc/passwd" "/etc/shadow" "/etc/group"
"/boot/" "/root/" "/home/"
)
for pattern in "${protected_patterns[@]}"; do
if [[ "$file" == "$pattern"* ]]; then
return 0 # 受保护文件
fi
done
return 1 # 非保护文件
}
# 主清理函数
main_cleanup() {
log "开始安全清理操作"
log "备份目录: $BACKUP_DIR"
# 显示当前磁盘空间
echo -e "\n${CYAN}=== 当前磁盘空间 ===${NC}"
df -h /
# 执行各种清理
cleanup_package_cache
cleanup_docker
cleanup_user_cache
# 清理系统临时文件
echo -e "\n${CYAN}=== 系统临时文件清理 ===${NC}"
find /tmp -type f -atime +7 -delete 2>/dev/null || true
find /var/tmp -type f -atime +30 -delete 2>/dev/null || true
# 清理旧日志
echo -e "\n${CYAN}=== 旧日志文件清理 ===${NC}"
find /var/log -name "*.log.*" -type f -mtime +30 -delete 2>/dev/null || true
find /var/log -name "*.gz" -type f -mtime +30 -delete 2>/dev/null || true
# 显示清理结果
echo -e "\n${GREEN}=== 清理完成 ===${NC}"
df -h /
log "清理操作完成"
log "备份文件保存在: $BACKUP_DIR"
echo -e "${YELLOW}重要: 请检查备份目录确认无误后,可手动删除备份文件${NC}"
}
# 脚本入口
if [[ "$1" == "--auto" ]]; then
main_cleanup
else
echo -e "${PURPLE}=== 安全清理脚本 ===${NC}"
echo "此脚本将执行安全的磁盘清理操作"
echo "所有删除的文件都会备份到: $BACKUP_DIR"
echo -e "${YELLOW}建议先备份重要数据!${NC}"
read -p "是否继续?(y/N): " confirm
if [[ "$confirm" == "y" || "$confirm" == "Y" ]]; then
main_cleanup
else
echo "操作已取消"
exit 0
fi
fi
6. 自动化监控和预防
6.1 创建磁盘监控脚本
文件名: disk_monitor.sh
bash
#!/bin/bash
# 磁盘监控和自动清理脚本
set -e
# 配置
CONFIG_FILE="/etc/disk_monitor.conf"
LOG_FILE="/var/log/disk_monitor.log"
ALERT_THRESHOLD=80
CRITICAL_THRESHOLD=90
CHECK_INTERVAL=300 # 5分钟
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# 日志函数
log() {
echo -e "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
echo -e "${BLUE}[$(date '+%H:%M:%S')]${NC} $1"
}
# 发送告警
send_alert() {
local partition="$1"
local usage="$2"
local level="$3"
local message="磁盘告警: 分区 $partition 使用率 ${usage}% (${level})"
log "$message"
# 尝试发送邮件告警(如果有邮件配置)
if command -v mail &> /dev/null; then
echo "$message" | mail -s "磁盘空间告警 - $(hostname)" root
fi
# 写入系统日志
logger "磁盘监控: $message"
}
# 检查磁盘使用率
check_disk_usage() {
df -h | awk 'NR>1 {print $1 "," $5 "," $6}' | while IFS=',' read -r device usage mount; do
# 移除百分比符号
usage=${usage%\%}
# 跳过特定文件系统
if [[ "$mount" == "/boot" ]] || [[ "$device" == tmpfs* ]] || [[ "$device" == devtmpfs* ]]; then
continue
fi
if [[ "$usage" -ge "$CRITICAL_THRESHOLD" ]]; then
send_alert "$device" "$usage" "CRITICAL"
emergency_cleanup "$mount"
elif [[ "$usage" -ge "$ALERT_THRESHOLD" ]]; then
send_alert "$device" "$usage" "WARNING"
auto_cleanup "$mount"
fi
done
}
# 自动清理
auto_cleanup() {
local mount_point="$1"
log "执行自动清理: $mount_point"
# 清理临时文件
find "$mount_point/tmp" -type f -atime +1 -delete 2>/dev/null || true
# 清理缓存
if [[ -d "$mount_point/var/cache" ]]; then
find "$mount_point/var/cache" -type f -atime +7 -delete 2>/dev/null || true
fi
# 清理日志文件(保留最近7天)
if [[ -d "$mount_point/var/log" ]]; then
find "$mount_point/var/log" -name "*.log.*" -type f -mtime +7 -delete 2>/dev/null || true
fi
}
# 紧急清理
emergency_cleanup() {
local mount_point="$1"
log "执行紧急清理: $mount_point"
# 更激进的清理策略
auto_cleanup "$mount_point"
# 清理Docker(如果使用)
if command -v docker &> /dev/null; then
docker system prune -a -f 2>/dev/null || true
fi
# 清理软件包缓存
if command -v apt-get &> /dev/null; then
apt-get clean 2>/dev/null || true
fi
if command -v yum &> /dev/null; then
yum clean all 2>/dev/null || true
fi
}
# 生成报告
generate_report() {
local report_file="/tmp/disk_report_$(date +%Y%m%d).txt"
echo "磁盘监控报告 - $(date)" > "$report_file"
echo "==========================================" >> "$report_file"
# 磁盘使用情况
echo -e "\n磁盘使用情况:" >> "$report_file"
df -h >> "$report_file"
# 大文件列表
echo -e "\n前20个大文件:" >> "$report_file"
find / -type f -size +100M 2>/dev/null | xargs du -h 2>/dev/null | sort -hr | head -20 >> "$report_file"
# 目录大小
echo -e "\n目录大小统计:" >> "$report_file"
du -sh /* 2>/dev/null | sort -hr >> "$report_file"
log "报告已生成: $report_file"
}
# 监控模式
monitor_mode() {
log "启动磁盘监控模式 (检查间隔: ${CHECK_INTERVAL}秒)"
log "告警阈值: ${ALERT_THRESHOLD}%, 紧急阈值: ${CRITICAL_THRESHOLD}%"
while true; do
check_disk_usage
sleep "$CHECK_INTERVAL"
done
}
# 安装服务
install_service() {
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}需要root权限安装服务${NC}"
exit 1
fi
local service_file="/etc/systemd/system/disk-monitor.service"
cat > "$service_file" << EOF
[Unit]
Description=Disk Space Monitor
After=network.target
[Service]
Type=simple
ExecStart=$PWD/disk_monitor.sh --daemon
Restart=always
RestartSec=60
User=root
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable disk-monitor.service
echo -e "${GREEN}服务安装完成${NC}"
echo "启动服务: systemctl start disk-monitor"
echo "查看状态: systemctl status disk-monitor"
}
# 显示帮助
show_help() {
echo "磁盘监控脚本"
echo
echo "用法: $0 [选项]"
echo
echo "选项:"
echo " --monitor 启动监控模式"
echo " --report 生成磁盘报告"
echo " --install 安装为系统服务"
echo " --daemon 守护进程模式(内部使用)"
echo " --help 显示此帮助信息"
}
# 主函数
main() {
case "$1" in
--monitor)
monitor_mode
;;
--report)
generate_report
;;
--install)
install_service
;;
--daemon)
# 守护进程模式
exec > /dev/null 2>&1
monitor_mode
;;
--help)
show_help
;;
*)
echo -e "${GREEN}磁盘监控脚本${NC}"
echo "请使用 --help 查看可用选项"
;;
esac
}
# 脚本入口
if [[ $# -eq 0 ]]; then
show_help
else
main "$1"
fi
6.2 创建配置文件
文件名: disk_monitor.conf
bash
# 磁盘监控配置文件
# 监控设置
ALERT_THRESHOLD=80
CRITICAL_THRESHOLD=90
CHECK_INTERVAL=300
# 排除的文件系统(逗号分隔)
EXCLUDE_FILESYSTEMS="tmpfs,devtmpfs,overlay"
# 排除的挂载点(逗号分隔)
EXCLUDE_MOUNTS="/boot,/proc,/sys"
# 清理设置
CLEANUP_TEMP_DAYS=1
CLEANUP_CACHE_DAYS=7
CLEANUP_LOG_DAYS=7
# 邮件告警设置
MAIL_ENABLED=true
MAIL_RECIPIENTS="admin@company.com"
MAIL_SUBJECT_PREFIX="[Disk Alert]"
# 日志设置
LOG_LEVEL="INFO" # DEBUG, INFO, WARN, ERROR
LOG_RETENTION_DAYS=30
# 自动清理设置
AUTO_CLEANUP_ENABLED=true
EMERGENCY_CLEANUP_ENABLED=true
# 监控的分区(为空则监控所有分区)
# MONITOR_PARTITIONS="/,/home,/var"
# 大文件阈值(用于报告)
LARGE_FILE_THRESHOLD="100M"
7. 完整的使用流程
7.1 执行步骤
graph TD
A[开始磁盘清理] --> B[运行基础检查]
B --> C[分析磁盘使用情况]
C --> D{是否发现大文件?}
D -->|是| E[定位具体大文件]
D -->|否| F[检查其他问题]
E --> G[分析文件安全性]
G --> H[执行安全清理]
H --> I[验证清理效果]
I --> J[建立监控预防]
F --> J
J --> K[完成]
style A fill:#ff6b6b,stroke:#fff,stroke-width:2px,color:#fff
style B fill:#4ecdc4,stroke:#fff,stroke-width:2px,color:#fff
style C fill:#45b7d1,stroke:#fff,stroke-width:2px,color:#fff
style E fill:#feca57,stroke:#fff,stroke-width:2px,color:#fff
style H fill:#ff9ff3,stroke:#fff,stroke-width:2px,color:#fff
style J fill:#54a0ff,stroke:#fff,stroke-width:2px,color:#fff
style K fill:#1dd1a1,stroke:#fff,stroke-width:2px,color:#fff
classDef default fill:#333,stroke:#fff,stroke-width:2px,color:#fff;
7.2 使用示例
第一步:赋予执行权限并运行基础检查
bash
# 赋予所有脚本执行权限
chmod +x disk_cleanup_helper.sh disk_analyzer.sh file_analyzer.sh safe_cleanup.sh disk_monitor.sh
# 运行基础检查
./disk_cleanup_helper.sh
第二步:使用详细分析工具
bash
# 运行磁盘分析
./disk_analyzer.sh
# 运行文件分析
./file_analyzer.sh
第三步:执行安全清理
bash
# 交互式安全清理
./safe_cleanup.sh
# 或者自动清理
./safe_cleanup.sh --auto
第四步:设置监控
bash
# 安装监控服务(需要root)
sudo ./disk_monitor.sh --install
# 或者直接运行监控
./disk_monitor.sh --monitor
8. 总结
本教程提供了完整的服务器磁盘空间清理解决方案,包括:
- 基础检查工具 - 快速了解磁盘使用情况
- 详细分析工具 - 深入分析文件和目录
- 安全清理工具 - 避免误删重要文件
- 自动监控系统 - 预防磁盘空间问题
所有脚本都设计为可以直接使用,适合零基础用户按照步骤操作。建议在生产环境使用前,先在测试环境验证,确保理解每个步骤的影响。
通过这套工具,您可以快速定位磁盘空间问题,安全地清理不必要的文件,并建立长期的监控机制,确保服务器稳定运行。