dlc — Docker Log Cleaner(支持名称、ID前缀、交互序号清理,模糊匹配交互确认)
安装脚本:
curl -L -o /usr/local/bin/dlc https://files-cdn.cnblogs.com/files/nihaorz/dlc.sh && chmod +x /usr/local/bin/dlc && dlc -h
脚本源码:
#!/bin/bash stty erase ^H 2>/dev/null # dlc — Docker Log Cleaner(支持名称、ID前缀、交互序号清理,模糊匹配交互确认) docker_root=$(docker info --format '{{.DockerRootDir}}' 2>/dev/null) interactive_mode_flag=0 resolved_matches=() # 清理指定容器日志 clean_logs() { local cid="$1" local silent="${2:-0}" local cname cname=$(docker ps -a --filter id="$cid" --format '{{.Names}}' 2>/dev/null) local log_dir="$docker_root/containers/$cid" local log_file="$log_dir/${cid}-json.log" if [ -d "$log_dir" ]; then if [ -f "$log_file" ]; then truncate -s 0 "$log_file" 2>/dev/null || echo -n > "$log_file" fi find "$log_dir" -type f -name "${cid}-json.log*" ! -name "${cid}-json.log" -exec rm -f {} + [ "$silent" -ne 1 ] && echo "✅ 容器 $cname (${cid:0:12}) 日志已清理" fi } # 解析容器标识 resolve_container_ids() { local input="$1" resolved_matches=() local -a ids=() declare -A name_map=() while read -r id name; do ids+=("$id") name_map["$name"]="$id" done < <(docker ps -a --format '{{.ID}} {{.Names}}' --no-trunc) if [[ "$input" =~ ^[0-9]+$ && "$interactive_mode_flag" -eq 1 ]]; then local sorted=($(docker ps -a --format '{{.ID}} {{.Names}}' --no-trunc | sort -k2 | awk '{print $1}')) local index=$((10#$input - 1)) if [ "${sorted[$index]}" ]; then resolved_matches+=("${sorted[$index]}") return 0 else return 1 fi fi if [ "${name_map[$input]}" ]; then resolved_matches+=("${name_map[$input]}") return 0 fi for id in "${ids[@]}"; do [[ "$id" == "$input"* ]] && resolved_matches+=("$id") done [ ${#resolved_matches[@]} -gt 0 ] && return 0 || return 1 } # 批量清理容器日志 clean_multiple() { declare -A cleaned=() for arg in "$@"; do resolved_matches=() resolve_container_ids "$arg" status=$? if [ $status -ne 0 ]; then echo "❌ 未找到容器标识 '$arg'" >&2 continue fi for cid in "${resolved_matches[@]}"; do [ -z "${cleaned[$cid]}" ] && cleaned[$cid]=1 && clean_logs "$cid" done done [ ${#cleaned[@]} -gt 0 ] && echo "🧹 所有指定容器日志已清理" } # 交互选择容器 interactive_mode() { interactive_mode_flag=1 echo "📋 当前容器列表(按名称升序):" printf "%-4s | %-14s | %s\n" "序号" "容器ID" "容器名称" printf -- "------------------------------\n" local -a sorted_ids=() while read -r id name; do sorted_ids+=("$id") printf "%-4d | %-12s | %s\n" "${#sorted_ids[@]}" "${id:0:12}" "$name" done < <(docker ps -a --format '{{.ID}} {{.Names}}' --no-trunc | sort -k2) echo -n "请输入要清理的 序号/名称/ID前缀(空格分隔多个): " read -r -a inputs [ ${#inputs[@]} -eq 0 ] && echo "⚠️ 未输入任何标识" && exit 1 declare -a resolved=() for input in "${inputs[@]}"; do if [[ "$input" =~ ^[0-9]+$ ]]; then index=$((10#$input - 1)) [ "${sorted_ids[$index]}" ] && resolved+=("${sorted_ids[$index]}") || echo "❌ 无效序号 '$input'" >&2 else resolved+=("$input") fi done declare -A preview=() for arg in "${resolved[@]}"; do resolved_matches=() resolve_container_ids "$arg" for cid in "${resolved_matches[@]}"; do [ -z "${preview[$cid]}" ] && preview[$cid]=1 done done if [ ${#preview[@]} -eq 0 ]; then echo "⚠️ 未匹配到任何容器" && exit 1 fi echo "🧾 即将清理以下容器日志:" for cid in "${!preview[@]}"; do cname=$(docker ps -a --filter id="$cid" --format '{{.Names}}') echo " - $cname (${cid:0:12})" done echo -n "⚠️ 是否确认清理这些容器日志?(y/N): " read -r -n1 confirm && echo [[ "$confirm" =~ ^[Yy]$ ]] || { echo "❌ 已取消"; exit 0; } clean_multiple "${resolved[@]}" } # 清理所有容器日志 clean_all() { local force="${1:-0}" local -a all_ids=($(docker ps -a --no-trunc -q)) [ ${#all_ids[@]} -eq 0 ] && echo "📭 没有容器可清理" && exit 0 if [ "$force" -ne 1 ]; then echo -n "⚠️ 即将清理 ${#all_ids[@]} 个容器日志,确认?(y/N): " read -r -n1 confirm && echo [[ "$confirm" =~ ^[Yy]$ ]] || { echo "❌ 已取消"; exit 0; } fi for cid in "${all_ids[@]}"; do clean_logs "$cid" 1; done echo "✅ 所有容器日志已清理" } # 帮助信息 show_help() { cat <<EOF dlc — Docker Log Cleaner(支持名称、ID前缀、交互序号清理,模糊匹配交互确认) 用法: dlc [选项] [容器标识]... 选项: -l, --list 交互选择容器(支持多个) -a, --all 清理所有容器日志(默认需确认) -f, --force 跳过确认直接清理(需与 -a 组合使用) -h, --help 显示帮助信息 组合参数支持: -af, -fa 等同于 -a -f,清理所有容器日志并跳过确认 容器标识支持: - 名称(如 nginx) - ID前缀(如 fc82) - 序号(仅在交互模式下,如 1 2 3) 示例: dlc nginx fc82 # 按名称或 ID 前缀清理 dlc -l # 交互选择容器 dlc -a # 清理所有容器日志(需确认) dlc -af # 清理所有容器日志(跳过确认) 清理规则说明: - 主日志文件(container-id-json.log)将被清空内容,文件保留 - 滚动日志文件(如 container-id-json.log.1、.log.2.gz 等)将被直接删除 - 不影响容器运行状态或其他数据 - 若日志文件不存在则跳过,不报错 - 支持模糊匹配(ID前缀、名称),交互模式下支持序号选择 EOF } # 主入口 main() { local force=0 local all=0 local list=0 local help=0 local args=() local positional=() for raw in "$@"; do if [[ "$raw" =~ ^-([a-zA-Z]{2,})$ ]]; then for ((i=1; i<${#raw}; i++)); do args+=("-${raw:$i:1}") done else args+=("$raw") fi done for arg in "${args[@]}"; do case "$arg" in -f|--force) force=1 ;; -a|--all) all=1 ;; -l|--list) list=1 ;; -h|--help) help=1 ;; *) positional+=("$arg") ;; esac done if [ "$help" -eq 1 ] || [ "$all$list" == "00" ] && [ ${#positional[@]} -eq 0 ]; then show_help elif [ "$list" -eq 1 ]; then interactive_mode elif [ "$all" -eq 1 ]; then clean_all "$force" else clean_multiple "${positional[@]}" fi } main "$@"

浙公网安备 33010602011771号