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

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

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

1.实现功能

清理目录的子内容
可选删除目录本身,默认不删除目录
人工二次确认
清理删除白名单(允许操作的目录前缀,我这里默认是/,即不限制,如果要限制,则修改bash脚本)
清理删除黑名单(禁止清理的目录,比如系统目录)
模拟删除,可以仅浏览删除内容,而不真删除
保留一定天数之内的文件
删除时增加日志,清理日志依照时间命名,保存在具体目录(/var/log/clear_path_logs,可在bash脚本修改)
防止清理软连接
带颜色的输出:删除文件高亮绿色输出,删除目录高亮蓝色输出,出错或提示警告高亮红色/黄色输出
没有删除权限的也记录

2.bash脚本内容

vi ./safedel.sh

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

#!/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命令

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

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ziqibit

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值