Skip to main content

Heute mal ein Blogpost in Form einer Linux-Manpage 🙂 Mama sagt: „Ist halt scheiße fürs SEO, du Spacken.“ – aber was solls. Leben geht irgendwie weiter.

Blockpost

OS-CLEANUP-DEBIAN-SERVER(1)         Beschmutzerhandbuch         OS-CLEANUP-DEBIAN-SERVER(1)

NAME
    os-cleanup-debian-server.sh - Wartungsskript zum Popoputzen von Debian-basierten Servern

ÜBERSICHT
    os-cleanup-debian-server.sh

BESCHREIBUNG
    Dieses einfach gestrickte Bash-Skript führt eine Systembereinigung auf Debian-basierten Servern durch. Es räumt veraltete Paketdaten
    ab wie ein dickes Kind nachts mit tödlicher Präzision den Inhalt des Kühlschranks, löscht temporäre Dateien, begrenzt Systemd-Logs,
    säubert - wie Léon der Profi seine Gegner - Container-Ressourcen und schreibt strukturierte Protokolle in eine Logdatei.

    Ursprünglich aus einem altgedienten Script hervorgegangen, wurde es liebevoll generalüberholt, CO2-neutral durchgelüftet und auf Hochglanz poliert.
    Das Script läuft auf meinen Servern als Cronjob und dient auch als Vorlage/Bestandteil eines Automatisierungs-Tasks.

    PS: Da das Script neu aufgelegt wurde, ist es noch nicht ganz battle-tested. Vor allem der Task "System - Cleanup Temp Files" hat noch nicht
    so viele Testdurchläufe.

FUNKTIONEN
    cleanup_apt_packages
        - Leert das APT-Cache-Verzeichnis (/var/cache/apt/archives) fast so schnell wie Behörden dein Konto.
        - Entfernt (autoremove) nicht mehr benötigte Pakete – fast so flink wie Haustürdiebe eure Amazon-Pakete.
        - Entfernt verwaiste Konfigurationspakete und schickt sie dahin, wo auch deine heroisch geplanten Neujahrsvorsätze immer landen > /dev/null.
        - Frischt die Apt-Paketlisten fast so professionell und unauffällig auf wie manch Lobbyisten die Kaffeekasse der EU-Politiker im Hinterzimmer.

    cleanup_journal_log_files
        - Löscht bis auf die letzten 3 Tage die Systemd-Journal-Logfiles, damit wenigstens einige deiner IT-Sünden von letzter Woche gekonnt
          unter den Tisch gekehrt werden :)

    cleanup_tmp_files
        - Entfernt Dateien und leere Verzeichnisse in /tmp und /var/tmp, sofern sie älter als 3 Tage und nicht in Benutzung sind (lsof-Prüfung).

    cleanup_old_script_log_files
        - Entfernt unter /var/log die von diesem hässlichen Skript erstellten Logdateien, die älter als ein 3 Tage Bart sind.

    cleanup_container_resources
        - Führt bei podman, docker und crictl ohne kulturelle Aneignung eine leichte und eine seichte Image-Bereinigung durch.

LOGGING
    Die Ausgabe erfolgt actiongeladen sowohl im Terminal als auch in /var/log/os-cleanup-debian-server.sh.log.
    Log-Level werden mit [INFO], [WARNING], [ERROR] (wie ein Hund den Baum) markiert. Farbige Ausgaben werden aus Respekt vor Diskriminierung und in Solidarität
    mit monochromen Terminals nicht erstellt.

VORAUSSETZUNGEN
    - Root[lichtviertel]-Rechte.
    - Mindestens Volljährig oder im Beisein eines Erziehungsberechtigten :)
    - Programme: bash, tee (am besten Schwarztee), find, lsof, apt-get, dpkg.
    - Optional: podman, docker, crictl.

AUTOR
    Hackspoiler - https://hackspoiler.de

VERSION
    0.9.0 (erstellt am 30.01.2023, letzte Änderung 21.03.2025)

DATEIPFAD
    /root/server-scripts/os-cleanup-debian-server.sh

INSTALLATION
    curl -sSL https://codeberg.org/hackspoiler/root/src/branch/main/server-scripts/os-cleanup-debian-server.sh -o /root/server-scripts/os-cleanup-debian-server.sh
    chmod +x /root/server-scripts/os-cleanup-debian-server.sh

NUTZUNG
    ./os-cleanup-debian-server.sh

    Für automatische Ausführung via Cron z.B. jeden Montag um 03:00 Uhr Nackts (Serverzeit):
    00 03 * * 1 root /root/server-scripts/os-cleanup-debian-server.sh

LIZENZ
    Gerührt, nicht geschüttelt.

SIEHE AUCH
    bash(1), apt-get(8), journalctl(1), find(1), lsof(8)

Debian-basiertes Server-Cleanup-Bash-Skript

#!/usr/bin/env bash
#==========================================================
# Author:             Hackspoiler
# URL:                https://hackspoiler.de
# Scriptname:         os-cleanup-debian-server.sh
# Scriptpath:         /root/server-scripts/
# Usage:              ./os-cleanup-debian-server.sh
# Version:            0.9.0
# Date Creation:      30.01.2023
# Date Modification:  13.04.2025
# Used Packages:      tee awk find lsof xargs
# Description:        Cleanup a debian based server
#==========================================================

#==========================================================
# Check for root permissions
#==========================================================
if [[ "$EUID" -ne 0 ]]; then
  echo "Script requires root permissions" >&2
  exit 1
fi

#==========================================================
# Set Bash-Defaults
#==========================================================
set -o pipefail
set -o nounset

#==========================================================
# Les Variables
#==========================================================
SCRIPT_NAME=$(basename "$0" .sh)
LOG_FILE="/var/log/${SCRIPT_NAME}.log"
LOG_RETENTION_DAYS=3

#==========================================================
# Logging Setup
#==========================================================
exec > >(tee --append --ignore-interrupts "${LOG_FILE}") 2>&1

log() {
  local LEVEL="$1"
  local MESSAGE="$2"
  local TIMESTAMP
  TIMESTAMP=$(date +'%Y-%m-%d--%H-%M-%S')

  if [[ "$LEVEL" == "ERROR" ]]; then
    echo "${TIMESTAMP} [${LEVEL}] ${MESSAGE}" >&2
  else
    echo "${TIMESTAMP} [${LEVEL}] ${MESSAGE}"
  fi
}

log_info()    { log "INFO" "$1"; }
log_error()   { log "ERROR" "$1"; }
log_warning() { log "WARNING" "$1"; }

#==========================================================
# Error handling
#==========================================================
tryrun() {
  "$@"
  local EXIT_CODE=$?
  if [[ $EXIT_CODE -ne 0 ]]; then
    log_warning "Command \"$*\" failed with exit code ${EXIT_CODE}, continuing..."
  fi
}

#==========================================================
# Main
#==========================================================
# System - Cleanup Apt Packages
cleanup_apt_packages() {
  local TASK_NAME="<===== Cleanup APT Packages.... =====>"
  log_info "Start: ${TASK_NAME}"

  export DEBIAN_FRONTEND=noninteractive
  tryrun apt-get clean
  tryrun apt-get autoclean
  tryrun apt-get autoremove --purge --yes
  tryrun dpkg --list | awk '/^rc/ {print $2}' | xargs --no-run-if-empty dpkg --purge
  tryrun rm --force --verbose /var/lib/apt/lists/*
  tryrun apt-get update -qq
}

# System - Cleanup Temp Files
cleanup_tmp_files() {
  local TASK_NAME="<===== Cleanup Temp Files...... =====>"
  log_info "Start: ${TASK_NAME}"

  for TMPDIR in /tmp /var/tmp; do
    # Delete files (only if not in use)
    LC_ALL=C find "${TMPDIR}" -type f -mtime +${LOG_RETENTION_DAYS} -print0 | while IFS= read -r -d '' FILE; do
      if ! lsof -- "${FILE}" &>/dev/null; then
        rm --force --verbose -- "${FILE}" || log_warning "Could not delete ${FILE}"
      else
        log_info "File ${FILE} is dirty in use, skipping"
      fi
    done

    # Delete directories (only if not in use)
    LC_ALL=C find "${TMPDIR}" -type d -empty -mtime +${LOG_RETENTION_DAYS} -print0 | while IFS= read -r -d '' DIR; do
      if ! lsof +d -- "${DIR}" &>/dev/null; then
        rm --recursive --force --verbose -- "${DIR}" || log_warning "Could not delete ${DIR}"
      else
        log_info "Directory ${DIR} is dirty in use, skipping"
      fi
    done
  done
}

# System - Cleanup Journal Logfiles
cleanup_journal_log_files() {
  local TASK_NAME="<===== Cleanup Systemd Logfiles =====>"
  log_info "Start: ${TASK_NAME}"

  tryrun journalctl --vacuum-time="${LOG_RETENTION_DAYS}d" --vacuum-size=500M
}

# System - Cleanup Logs from this Script
cleanup_old_script_log_files() {
  local TASK_NAME="<===== Cleanup Log Files....... =====>"
  log_info "Start: ${TASK_NAME}"

  tryrun find /var/log -type f -name "${SCRIPT_NAME}.log" -mtime +${LOG_RETENTION_DAYS} -delete
}

# App - Cleanup unused Podman/Docker/Kubernetes Images
cleanup_container_resources() {
  local TASK_NAME="<===== Cleanup Container Shit =====>"
  log_info "Start: ${TASK_NAME}"

  if command -v podman &> /dev/null; then
    tryrun podman image prune --force
  fi

  if command -v docker &> /dev/null; then
    tryrun docker image prune --force
  fi

  if command -v crictl &> /dev/null; then
    tryrun crictl rmi --prune
  fi
}

# L'exécution
main() {
  local INITIAL_SPACE=$(df -h / | awk 'NR==2 {print $4}')
  log_info "Script gestartet: ${SCRIPT_NAME}"

  cleanup_apt_packages
  cleanup_journal_log_files
  cleanup_tmp_files
  cleanup_old_script_log_files
  cleanup_container_resources

  local FINAL_SPACE=$(df -h / | awk 'NR==2 {print $4}')
  log_info "Initial Free Space: ${INITIAL_SPACE} - Final Free Space: ${FINAL_SPACE}"
}
main "$@"

Bash Cleanup-Skript-Repository

os-cleanup-debian-server.sh