Linux安全清理删除目录bash脚本

直接写清除目录命令可能会因为一时手抖导致删除重要目录
rm -rf是个危险的命令,我写了bash脚本,放在环境变量目录下可以当系统命令来用

这里是单线程的,如果需要更高的性能,需要加入多线程的支持。

1.实现功能

清理目录的子内容

可选删除目录本身,默认不删除目录

人工二次确认

清理删除白名单(允许操作的目录前缀,我这里默认是/,即不限制,如果要限制,则修改bash脚本)

清理删除黑名单(禁止清理的目录,比如系统目录)

模拟删除,可以仅浏览删除内容,而不真删除

保留一定天数之内的文件

删除时增加日志,清理日志依照时间命名,保存在具体目录(/var/log/clear_path_logs,可在bash脚本修改)

防止清理软连接

带颜色的输出:删除文件高亮绿色输出,删除目录高亮蓝色输出,出错或提示警告高亮红色/黄色输出

没有删除权限的也记录

2.bash脚本内容

bash 复制代码
vi ./safedel.sh

注意下面的配置区域可以调整

bash 复制代码
#!/bin/bash

# ===================
# 配置区(可根据需要调整)
# ===================
LOG_DIR="/var/log/clear_path_logs"    # 日志集中保存目录
KEEP_LOG_DAYS=7                      # 日志保留天数
DEFAULT_OLD_DAYS=0                   # 默认清理所有
# 清理白名单前缀
ALLOWED_PREFIXES=(
  "/"
)

# ===================
# 颜色定义
# ===================
COLOR_RESET="\033[0m"
COLOR_GREEN="\033[32m"
COLOR_BLUE="\033[34m"
COLOR_RED="\033[31m"
COLOR_YELLOW="\033[33m"

# ===================
# 开始执行
# ===================

# 检查参数
if [ $# -lt 1 ]; then
  echo "用法: $0 [--dry-run] [--days=N] [--remove-dir] <要清空的目录>"
  echo "示例: $0 /var/img/tmp"
  echo "示例: $0 --dry-run /home/youruser/tmp"
  echo "示例: $0 --days=30 /var/img/tmp"
  echo "示例: $0 --remove-dir /var/img/tmp"
  exit 1
fi

# 解析参数
DRY_RUN=0
OLD_DAYS=$DEFAULT_OLD_DAYS
REMOVE_DIR=0

while [[ "$1" == --* ]]; do
  case "$1" in
    --dry-run)
      DRY_RUN=1
      shift
      ;;
    --days=*)
      OLD_DAYS="${1#--days=}"
      shift
      ;;
    --remove-dir)
      REMOVE_DIR=1
      shift
      ;;
    *)
      echo -e "${COLOR_RED}未知参数: $1${COLOR_RESET}"
      exit 1
      ;;
  esac
done

# 目录参数只能放在最后
TARGET_DIR="$1"

# 检查目录
if [ -z "$TARGET_DIR" ] || [ ! -d "$TARGET_DIR" ]; then
  echo -e "${COLOR_RED}错误: 目录不存在或不是目录: $TARGET_DIR${COLOR_RESET}"
  exit 1
fi

# 防止软链接
if [ -L "$TARGET_DIR" ]; then
  echo -e "${COLOR_RED}错误: 目标是软链接,禁止清空软链接指向的内容: $TARGET_DIR${COLOR_RESET}"
  exit 1
fi

# 防止系统目录误删
PROTECTED_DIRS=(
  "/"
  "/boot"
  "/dev"
  "/etc"
  "/home"
  "/lib"
  "/lib64"
  "/proc"
  "/root"
  "/run"
  "/sbin"
  "/sys"
  "/tmp"
  "/usr"
  "/var"
  "/bin"
  "/opt"
)

for protected in "${PROTECTED_DIRS[@]}"; do
  if [ "$TARGET_DIR" = "$protected" ]; then
    echo -e "${COLOR_RED}危险: 不允许对关键系统目录执行清空操作: $TARGET_DIR${COLOR_RESET}"
    exit 1
  fi
done

# 白名单检测
ALLOWED=0
for prefix in "${ALLOWED_PREFIXES[@]}"; do
  case "$TARGET_DIR" in
    "$prefix"|"${prefix}/"*)
      ALLOWED=1
      break
      ;;
  esac
done

if [ "$ALLOWED" -ne 1 ]; then
  echo -e "${COLOR_RED}错误: 仅允许清理以下目录前缀:${COLOR_RESET}"
  for prefix in "${ALLOWED_PREFIXES[@]}"; do
    echo "  - $prefix"
  done
  echo "当前目录: $TARGET_DIR"
  exit 1
fi

# 确保日志目录存在
mkdir -p "$LOG_DIR"

# 日志文件
timestamp=$(date +"%Y%m%d_%H%M%S")
log_file="$LOG_DIR/clear_tmp_log_${timestamp}.txt"

echo "清理日志 - $(date)" | tee "$log_file"
echo "清理目录: $TARGET_DIR" | tee -a "$log_file"
echo "模拟删除模式: $([ "$DRY_RUN" -eq 1 ] && echo "是" || echo "否")" | tee -a "$log_file"
echo "清理修改时间超过 $OLD_DAYS 天的内容" | tee -a "$log_file"
echo "清理完成后是否删除目录自身: $([ "$REMOVE_DIR" -eq 1 ] && echo "是" || echo "否")" | tee -a "$log_file"
echo "" | tee -a "$log_file"

# 确认
echo -e "${COLOR_YELLOW}即将开始清理: $TARGET_DIR${COLOR_RESET}"
read -p "确认要继续吗?(y/n): " confirm
if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
  echo "已取消操作。"
  exit 0
fi

# 执行清理
if [ "$OLD_DAYS" -gt 0 ]; then
  FIND_CMD=(find "$TARGET_DIR" -mindepth 1 -mtime +"$OLD_DAYS")
else
  FIND_CMD=(find "$TARGET_DIR" -mindepth 1)
fi

"${FIND_CMD[@]}" | while read -r item; do
  if [ -d "$item" ]; then
    echo -e "${COLOR_BLUE}目录: $item${COLOR_RESET}" | tee -a "$log_file"
    [ "$DRY_RUN" -eq 0 ] && rm -rf "$item" 2>>"$log_file" || true
  elif [ -f "$item" ]; then
    echo -e "${COLOR_GREEN}文件: $item${COLOR_RESET}" | tee -a "$log_file"
    [ "$DRY_RUN" -eq 0 ] && rm -f "$item" 2>>"$log_file" || true
  else
    echo -e "${COLOR_RED}其他: $item${COLOR_RESET}" | tee -a "$log_file"
    [ "$DRY_RUN" -eq 0 ] && rm -rf "$item" 2>>"$log_file" || true
  fi
done

# 如果 --remove-dir 参数开启
if [ "$REMOVE_DIR" -eq 1 ]; then
  if [ "$DRY_RUN" -eq 0 ]; then
    echo -e "${COLOR_RED}删除目标目录本身: $TARGET_DIR${COLOR_RESET}" | tee -a "$log_file"
    rm -rf "$TARGET_DIR" 2>>"$log_file"
  else
    echo -e "${COLOR_RED}[dry-run] 将删除目录本身: $TARGET_DIR${COLOR_RESET}" | tee -a "$log_file"
  fi
fi

echo "" | tee -a "$log_file"
echo "$([ "$DRY_RUN" -eq 1 ] && echo "模拟")清理完成。" | tee -a "$log_file"
echo "日志保存在: $log_file"

# 自动清理老旧日志
find "$LOG_DIR" -type f -name "clear_tmp_log_*.txt" -mtime +"$KEEP_LOG_DAYS" -delete

将其作为一个自定义的系统命令,这样后面可以直接使用safedel命令

bash 复制代码
mv safedel.sh /usr/local/bin/safedel
chmod +x /usr/local/bin/safedel

3.使用

正常清理目录内内容,不删自身 safedel /var/img/tmp

模拟清理,不删内容 safedel --dry-run /var/img/tmp

只清30天前的内容 safedel --days=30 /var/img/tmp

清完后把目录也删掉 safedel --remove-dir /var/img/tmp

模拟清除+删目录 safedel --dry-run --remove-dir /var/img/tmp

相关推荐
虾..2 小时前
Linux 软硬链接和动静态库
linux·运维·服务器
Evan芙3 小时前
Linux常见的日志服务管理的常见日志服务
linux·运维·服务器
hkhkhkhkh1234 小时前
Linux设备节点基础知识
linux·服务器·驱动开发
HZero.chen6 小时前
Linux字符串处理
linux·string
张童瑶6 小时前
Linux SSH隧道代理转发及多层转发
linux·运维·ssh
汪汪队立大功1236 小时前
什么是SELinux
linux
石小千6 小时前
Linux安装OpenProject
linux·运维
柏木乃一6 小时前
进程(2)进程概念与基本操作
linux·服务器·开发语言·性能优化·shell·进程
Lime-30906 小时前
制作Ubuntu 24.04-GPU服务器测试系统盘
linux·运维·ubuntu
百年渔翁_肯肯6 小时前
Linux 与 Unix 的核心区别(清晰对比版)
linux·运维·unix