Last active
November 13, 2024 19:16
-
-
Save pythoninthegrass/b2802cd8220d3053ede12bb85942e9e7 to your computer and use it in GitHub Desktop.
Cleanup ubuntu servers (non)interactively (cf. no disk space left)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
set -euo pipefail | |
# $USER | |
[[ -n $(logname >/dev/null 2>&1) ]] && logged_in_user=$(logname) || logged_in_user=$(whoami) | |
# $UID | |
# logged_in_uid=$(id -u "${logged_in_user}") | |
# $HOME | |
logged_in_home=$(eval echo "~${logged_in_user}") | |
get_current_kernel() { | |
uname -r | |
} | |
get_installed_kernels() { | |
dpkg-query -f '${Package}\n' -W 'linux-image-*' | grep -v meta | |
} | |
cleanup_kernels() { | |
local current_kernel=$(get_current_kernel) | |
echo "Current kernel: $current_kernel" | |
echo "Keeping current kernel and two previous versions..." | |
# Keep the last three kernels including the current one | |
kernels_to_keep=$(dpkg-query -f '${Package}\n' -W 'linux-image-*' | | |
grep -v meta | | |
grep -v "linux-image-${current_kernel}" | | |
sort -V | | |
tail -n 2) | |
# Add current kernel to keep list | |
kernels_to_keep="linux-image-${current_kernel} ${kernels_to_keep}" | |
echo "Keeping kernels: ${kernels_to_keep}" | |
# Remove other kernels, explicitly excluding the ones we want to keep | |
dpkg-query -f '${Package}\n' -W 'linux-image-*' \ | |
| grep -v meta \ | |
| grep -v -E "$(echo $kernels_to_keep | tr ' ' '|')" \ | |
| xargs -r apt-get -y purge | |
# Cleanup any remaining configs | |
dpkg -l | grep '^rc' | awk '{print $2}' | grep linux-image | xargs -r dpkg --purge | |
} | |
# Package management cleanup | |
cleanup_packages() { | |
echo "Cleaning package cache..." | |
apt-get clean | |
apt-get autoremove --purge -y | |
echo "Removing old package lists..." | |
rm -rf /var/lib/apt/lists/* | |
apt-get update | |
} | |
# Log cleanup | |
cleanup_logs() { | |
echo "Cleaning system logs..." | |
# Cleanup journal | |
journalctl --vacuum-time=1d | |
# Clean old logs | |
find /var/log -type f -name "*.gz" -delete | |
find /var/log -type f -name "*.log.*" -delete | |
# Truncate active logs | |
find /var/log -type f -name "*.log" -exec tee {} \; < /dev/null | |
find /var/log -type f -name "messages" -exec tee {} \; < /dev/null | |
find /var/log -type f -name "syslog" -exec tee {} \; < /dev/null | |
} | |
# Docker cleanup | |
cleanup_docker() { | |
if command -v docker &> /dev/null; then | |
echo "Cleaning Docker resources..." | |
docker images -f "dangling=true" -q | xargs -r docker rmi || true | |
fi | |
} | |
# Temporary files cleanup | |
cleanup_temp() { | |
echo "Cleaning temporary files..." | |
rm -rf /tmp/* | |
rm -rf /var/tmp/* | |
# Clean user cache dirs over 7 days old | |
find ${logged_in_user}/*/.cache -type f -atime +7 -delete 2>/dev/null || true | |
} | |
# User specific cleanup | |
cleanup_user() { | |
echo "Cleaning user files..." | |
# Clean bash history | |
truncate -s 0 ${logged_in_home}/.bash_history | |
# Clean thumbnails | |
rm -rf ${logged_in_home}/.cache/thumbnails/* | |
# Clean trash | |
rm -rf ${logged_in_home}/.local/share/Trash/* | |
} | |
# Find large files | |
find_large_files() { | |
local min_size=${1:-"100M"} | |
echo "Finding files larger than $min_size..." | |
find / -type f -size +$min_size -exec ls -lh {} \; 2>/dev/null | |
} | |
# Show disk usage | |
show_disk_usage() { | |
echo "Current disk usage by directory:" | |
du -hax / 2>/dev/null | sort -rh | head -n 20 | |
} | |
# Full cleanup function | |
full_cleanup() { | |
local show_large_files=${1:-false} | |
echo "Starting full system cleanup..." | |
# Show initial disk usage | |
df -h / | |
cleanup_kernels | |
cleanup_packages | |
cleanup_logs | |
cleanup_docker | |
cleanup_temp | |
cleanup_user | |
echo -e "\nCleanup completed. Current disk usage:" | |
df -h / | |
if [[ "$show_large_files" == true ]]; then | |
find_large_files | |
show_disk_usage | |
fi | |
} | |
# Print usage | |
print_usage() { | |
echo "Usage: $0 [-n] {kernels|packages|logs|docker|temp|user|large-files|usage|all} [size]" | |
echo | |
echo "Options:" | |
echo " -n Non-interactive mode" | |
echo " -l Show large files after cleanup (only with 'all' command)" | |
echo | |
echo "Commands:" | |
echo " kernels Clean old kernel packages" | |
echo " packages Clean package cache and remove unused packages" | |
echo " logs Clean system logs" | |
echo " docker Clean Docker resources" | |
echo " temp Clean temporary files" | |
echo " user Clean user-specific files" | |
echo " large-files Find large files (optional size parameter, default 100M)" | |
echo " usage Show disk usage" | |
echo " all Perform full system cleanup" | |
} | |
# Main function | |
main() { | |
# Check if running as root | |
if [[ $EUID -ne 0 ]]; then | |
echo "This script must be run as root" | |
exit 1 | |
fi | |
local NONINTERACTIVE=false | |
local SHOW_LARGE_FILES=false | |
# Parse options | |
while getopts ":nl" opt; do | |
case ${opt} in | |
n) | |
NONINTERACTIVE=true | |
;; | |
l) | |
SHOW_LARGE_FILES=true | |
;; | |
\?) | |
echo "Invalid option: -$OPTARG" | |
print_usage | |
exit 1 | |
;; | |
esac | |
done | |
shift $((OPTIND -1)) | |
# Check if command is provided | |
if [[ $# -lt 1 ]]; then | |
print_usage | |
exit 0 | |
fi | |
local command=$1 | |
shift | |
if [[ "$NONINTERACTIVE" = false && "$command" = "all" ]]; then | |
echo -e "\nWould you like to perform a full system cleanup? (y/n)" | |
read -r response | |
if [[ ! "$response" =~ ^[Yy]$ ]]; then | |
echo "Operation cancelled." | |
exit 0 | |
fi | |
fi | |
case "$command" in | |
kernels) | |
cleanup_kernels | |
;; | |
packages) | |
cleanup_packages | |
;; | |
logs) | |
cleanup_logs | |
;; | |
docker) | |
cleanup_docker | |
;; | |
temp) | |
cleanup_temp | |
;; | |
user) | |
cleanup_user | |
;; | |
large-files) | |
find_large_files "${1:-100M}" | |
;; | |
usage) | |
show_disk_usage | |
;; | |
all) | |
full_cleanup "$SHOW_LARGE_FILES" | |
;; | |
*) | |
echo "Invalid command: $command" | |
print_usage | |
exit 1 | |
;; | |
esac | |
} | |
main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment