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

相关推荐
豆是浪个4 小时前
Linux(Centos 7.6)命令详解:usermod
linux·运维·centos
极地星光4 小时前
网络检测:Linux下实时获取WiFi与热点状态
linux·网络
还是奇怪8 小时前
Linux - 安全排查 3
android·linux·安全
NUZGNAW8 小时前
VMware安装Centos 7
linux·运维·centos
Another Iso8 小时前
CentOs 7 MySql8.0.23之前的版本主从复制
linux·mysql·centos
A7bert7778 小时前
【YOLOv8-obb部署至RK3588】模型训练→转换RKNN→开发板部署
linux·c++·人工智能·python·yolo
筑梦之路8 小时前
linux 系统找出磁盘IO占用元凶 —— 筑梦之路
linux·运维·服务器
LiQiang3310 小时前
Ubuntu2404修改国内镜像
linux
杰哥技术分享10 小时前
Ubuntu 22.04安装SQL Server指南
linux·运维·ubuntu·sqlserver
遇见火星10 小时前
ubuntu18.04 升级Ubuntu 20.04
linux·运维·ubuntu·系统升级