直接写清除目录命令可能会因为一时手抖导致删除重要目录
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
