kubelet清理脚本

#!/usr/bin/env bash
set -Eeuo pipefail
IFS=$'\n\t'

# Production-safe kubelet cleanup utility.
# Default behavior is dry-run. Destructive execution requires:
#   sudo ./cleanup-kubelet.sh --execute --confirm-host "$(hostname)"

readonly PROGRAM="${0##*/}"
readonly LOG_FILE="/var/log/cleanup-kubelet.log"
readonly -a TARGETS=(
  "/export/kubelet"
  "/var/lib/kubelet"
  "/etc/systemd/system/kubelet.service"
  "/etc/kubernetes"
  "/etc/ssl/etcd/ssl"
)

MODE="dry-run"
CONFIRM_HOST=""

usage() {
  cat <<EOF
Usage:
  sudo $PROGRAM                         # preview only
  sudo $PROGRAM --execute --confirm-host HOSTNAME

Options:
  --execute                Perform the cleanup.
  --confirm-host HOSTNAME  Must exactly match this machine's hostname.
  -h, --help               Show this help.
EOF
}

log() {
  local message="$*"
  printf '%s [%s] %s\n' "$(date '+%Y-%m-%dT%H:%M:%S%z')" "$MODE" "$message" | tee -a "$LOG_FILE"
}

die() {
  log "ERROR: $*"
  exit 1
}

while (($#)); do
  case "$1" in
    --execute)
      MODE="execute"
      shift
      ;;
    --confirm-host)
      (($# >= 2)) || { usage >&2; exit 2; }
      CONFIRM_HOST="$2"
      shift 2
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      printf 'Unknown argument: %s\n' "$1" >&2
      usage >&2
      exit 2
      ;;
  esac
done

((EUID == 0)) || { printf 'Run as root (sudo).\n' >&2; exit 1; }
touch "$LOG_FILE"
chmod 0600 "$LOG_FILE"

current_host="$(hostname)"
if [[ "$MODE" == "execute" ]]; then
  [[ -n "$CONFIRM_HOST" ]] || die "--confirm-host is required with --execute"
  [[ "$CONFIRM_HOST" == "$current_host" ]] || die "hostname mismatch (expected: $current_host)"
fi

validate_target() {
  local target="$1"
  [[ "$target" == /* ]] || die "non-absolute target rejected: $target"
  [[ "$target" != "/" ]] || die "root path rejected"
  [[ "$target" != *'..'* ]] || die "parent traversal rejected: $target"
  case "$target" in
    /export/kubelet|/var/lib/kubelet|/etc/systemd/system/kubelet.service|/etc/kubernetes|/etc/ssl/etcd/ssl) ;;
    *) die "target outside allowlist: $target" ;;
  esac
}

for target in "${TARGETS[@]}"; do
  validate_target "$target"
done

log "Host: $current_host"
log "Requested targets:"
for target in "${TARGETS[@]}"; do
  if [[ -e "$target" || -L "$target" ]]; then
    log "  present: $target"
  else
    log "  absent:  $target"
  fi
done

if [[ "$MODE" == "dry-run" ]]; then
  log "Preview complete; nothing was changed."
  log "To execute: sudo ./$PROGRAM --execute --confirm-host '$current_host'"
  exit 0
fi

log "Stopping kubelet service"
if command -v systemctl >/dev/null 2>&1; then
  systemctl stop kubelet.service || log "WARN: kubelet stop returned a non-zero status"
  systemctl disable kubelet.service || log "WARN: kubelet disable returned a non-zero status"
fi

# Refuse to recursively delete through any active mount under a target.
if command -v findmnt >/dev/null 2>&1; then
  for target in "${TARGETS[@]}"; do
    while IFS= read -r mountpoint; do
      [[ -z "$mountpoint" ]] && continue
      die "active mount detected under $target: $mountpoint; unmount it explicitly first"
    done < <(findmnt -rn -o TARGET -R "$target" 2>/dev/null || true)
  done
fi

for target in "${TARGETS[@]}"; do
  if [[ -e "$target" || -L "$target" ]]; then
    log "Removing: $target"
    rm -rf --one-file-system -- "$target"
  else
    log "Skipping absent target: $target"
  fi
done

if command -v systemctl >/dev/null 2>&1; then
  systemctl daemon-reload
fi

log "Cleanup completed successfully"

#!/usr/bin/env bash
set -Eeuo pipefail
IFS=$'\n\t'

readonly SCRIPT_NAME="${0##*/}"
readonly START_SECONDS="$SECONDS"

LOG_LEVEL="${LOG_LEVEL:-INFO}"
LOG_FILE="${LOG_FILE:-/var/log/${SCRIPT_NAME%.sh}.log}"

declare -Ar LEVEL_VALUE=(
    [DEBUG]=10
    [INFO]=20
    [WARN]=30
    [ERROR]=40
    [FATAL]=50
)

init_log() {
    local log_dir
    log_dir="$(dirname -- "$LOG_FILE")"

    mkdir -p -- "$log_dir"

    if [[ -L "$LOG_FILE" ]]; then
        printf 'Refusing symlink log file: %s\n' "$LOG_FILE" >&2
        exit 1
    fi

    touch -- "$LOG_FILE"
    chmod 0640 "$LOG_FILE"

    exec 200>>"$LOG_FILE"
}

should_log() {
    local level="$1"

    [[ -n "${LEVEL_VALUE[$level]+x}" ]] || return 1
    [[ -n "${LEVEL_VALUE[$LOG_LEVEL]+x}" ]] || return 1

    ((LEVEL_VALUE[$level] >= LEVEL_VALUE[$LOG_LEVEL]))
}

sanitize_message() {
    local message="${1-}"

    message="${message//$'\r'/\\r}"
    message="${message//$'\n'/\\n}"
    message="${message//$'\t'/\\t}"

    printf '%s' "$message"
}

_log() {
    local level="$1"
    local file="$2"
    local line_number="$3"
    local function_name="$4"
    shift 4

    should_log "$level" || return 0

    local message
    local record

    message="$(sanitize_message "$*")"

    printf -v record \
        '%s [%s] [%s] [pid=%d] [%s:%s:%s] %s' \
        "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \
        "$level" \
        "$SCRIPT_NAME" \
        "$$" \
        "$file" \
        "$line_number" \
        "$function_name" \
        "$message"

    if command -v flock >/dev/null 2>&1; then
        flock -x 200
        printf '%s\n' "$record" >&200
        flock -u 200
    else
        printf '%s\n' "$record" >&200
    fi

    printf '%s\n' "$record" >&2
}

log_debug() {
    _log DEBUG "${BASH_SOURCE[1]##*/}" "${BASH_LINENO[0]}" "${FUNCNAME[1]:-main}" "$@"
}

log_info() {
    _log INFO "${BASH_SOURCE[1]##*/}" "${BASH_LINENO[0]}" "${FUNCNAME[1]:-main}" "$@"
}

log_warn() {
    _log WARN "${BASH_SOURCE[1]##*/}" "${BASH_LINENO[0]}" "${FUNCNAME[1]:-main}" "$@"
}

log_error() {
    _log ERROR "${BASH_SOURCE[1]##*/}" "${BASH_LINENO[0]}" "${FUNCNAME[1]:-main}" "$@"
}

log_fatal() {
    local rc="${1:?exit code is required}"
    shift

    _log FATAL "${BASH_SOURCE[1]##*/}" "${BASH_LINENO[0]}" "${FUNCNAME[1]:-main}" "$@"
    exit "$rc"
}

on_error() {
    local rc=$?
    local line="${1:-unknown}"

    log_error "unexpected failure: rc=$rc line=$line"
    return "$rc"
}

on_exit() {
    local rc=$?
    local elapsed=$((SECONDS - START_SECONDS))

    trap - ERR EXIT

    if ((rc == 0)); then
        log_info "script completed: rc=0 elapsed=${elapsed}s"
    else
        log_error "script terminated: rc=$rc elapsed=${elapsed}s"
    fi

    exit "$rc"
}

main() {
    init_log
    trap 'on_error "$LINENO"' ERR
    trap on_exit EXIT

    log_info "script started: host=$(hostname)"
    log_debug "effective_user=$(id -un) effective_uid=$EUID"

    # 在这里编写业务逻辑。
    if [[ ! -r /etc/hosts ]]; then
        log_fatal 1 "required file is not readable: /etc/hosts"
    fi

    log_info "business operation completed"
}

main "$@"

拉取镜像

#!/usr/bin/env bash

set -u

IMAGE_FILE="${1:-images.txt}"

if command -v docker >/dev/null 2>&1; then
    CONTAINER_CLI="docker"
elif command -v nerdctl >/dev/null 2>&1; then
    CONTAINER_CLI="nerdctl"
else
    echo "错误:系统中未找到 docker 或 nerdctl" >&2
    exit 1
fi

if [[ ! -f "$IMAGE_FILE" ]]; then
    echo "错误:镜像列表文件不存在:$IMAGE_FILE" >&2
    exit 1
fi

echo "使用命令:$CONTAINER_CLI"
echo "读取文件:$IMAGE_FILE"

success=0
failed=0

while IFS= read -r image || [[ -n "$image" ]]; do
    # 去除 Windows 文本的回车符和首尾空白
    image="${image//$'\r'/}"
    image="${image#"${image%%[![:space:]]*}"}"
    image="${image%"${image##*[![:space:]]}"}"

    # 跳过空行和注释行
    [[ -z "$image" || "$image" == \#* ]] && continue

    echo "正在拉取:$image"

    if "$CONTAINER_CLI" pull "$image"; then
        ((success += 1))
    else
        echo "拉取失败:$image" >&2
        ((failed += 1))
    fi
done < "$IMAGE_FILE"

echo "完成:成功 $success 个,失败 $failed 个"

[[ "$failed" -eq 0 ]]
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容