add update.sh: OS detection + package list update
All checks were successful
Check scripts syntax / check-scripts-syntax (push) Successful in 41s
All checks were successful
Check scripts syntax / check-scripts-syntax (push) Successful in 41s
- New update.sh: detects Alpine, Arch, Debian/Ubuntu, RHEL/Fedora/CentOS,
openSUSE, Void, Gentoo and updates the package index only (no upgrades)
- clean.sh fixes:
- Fix ((cleaned_count++)) exiting under set -e on first successful rm
- Stop recursively deleting /var/cache and /root/.cache wholesale
- Add CACHE_RETENTION_DAYS (7d) — clean_directory now only deletes
files older than retention period instead of wiping everything
- Remove dangerous rm -rf fallback in clean_directory
- Narrow CACHE_DIRS to /var/cache/apt instead of /var/cache
- Fix /home/*/.cache pattern to only target pip/npm caches
This commit is contained in:
12
README.md
12
README.md
@@ -1,6 +1,6 @@
|
|||||||
# server-scripts
|
# server-scripts
|
||||||
|
|
||||||
Useful scripts for managing servers written in Bash. Supported OS includes only Ubuntu/Debian and Alpine.
|
Useful scripts for managing servers written in Bash. Supported OS includes Debian/Ubuntu, Alpine, Arch, RHEL/Fedora/CentOS, openSUSE, Void, and Gentoo.
|
||||||
|
|
||||||
In the past I was using it more for maintaining my home servers, bare metal with Docker, however when I changed to k3s, I started using it less. Now I'm using this as a collection of useful scripts that I can use when needed. Also `clean.sh` is still useful.
|
In the past I was using it more for maintaining my home servers, bare metal with Docker, however when I changed to k3s, I started using it less. Now I'm using this as a collection of useful scripts that I can use when needed. Also `clean.sh` is still useful.
|
||||||
|
|
||||||
@@ -8,6 +8,16 @@ In the past I was using it more for maintaining my home servers, bare metal with
|
|||||||
|
|
||||||
This script is used to clean some of the files, docker dangling images, and docker stopped/unused containers.
|
This script is used to clean some of the files, docker dangling images, and docker stopped/unused containers.
|
||||||
|
|
||||||
|
### `update.sh`
|
||||||
|
|
||||||
|
Detects the running OS (Alpine, Arch, Debian/Ubuntu, RHEL/Fedora/CentOS, openSUSE, Void, Gentoo) and updates the **package list** only — it does not upgrade or install any packages. Useful for keeping package indexes fresh so that `upgrade` commands run faster later.
|
||||||
|
|
||||||
|
Run with `curl | bash`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -sSL https://git.ivanch.me/ivanch/server-scripts/raw/branch/main/update.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
### `windows-backup.ps1`
|
### `windows-backup.ps1`
|
||||||
|
|
||||||
This PowerShell script is used to backup files from a Windows machine to a remote Samba server. It uses `7zip` to create the zip file, and then sends over the network using SMB protocol.
|
This PowerShell script is used to backup files from a Windows machine to a remote Samba server. It uses `7zip` to create the zip file, and then sends over the network using SMB protocol.
|
||||||
|
|||||||
52
clean.sh
52
clean.sh
@@ -20,8 +20,9 @@ readonly YELLOW='\033[1;33m'
|
|||||||
# Cleanup configuration
|
# Cleanup configuration
|
||||||
readonly LOG_RETENTION_DAYS=30
|
readonly LOG_RETENTION_DAYS=30
|
||||||
readonly JOURNAL_RETENTION_DAYS=7
|
readonly JOURNAL_RETENTION_DAYS=7
|
||||||
|
readonly CACHE_RETENTION_DAYS=7
|
||||||
readonly TEMP_DIRS=("/tmp" "/var/tmp")
|
readonly TEMP_DIRS=("/tmp" "/var/tmp")
|
||||||
readonly CACHE_DIRS=("/var/cache" "/root/.cache")
|
readonly CACHE_DIRS=("/var/cache/apt" "/root/.cache")
|
||||||
|
|
||||||
#==============================================================================
|
#==============================================================================
|
||||||
# UTILITY FUNCTIONS
|
# UTILITY FUNCTIONS
|
||||||
@@ -56,6 +57,7 @@ get_dir_size() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Safe directory cleanup with size reporting
|
# Safe directory cleanup with size reporting
|
||||||
|
# Deletes files older than CACHE_RETENTION_DAYS instead of wiping everything
|
||||||
clean_directory() {
|
clean_directory() {
|
||||||
local dir="$1"
|
local dir="$1"
|
||||||
local description="$2"
|
local description="$2"
|
||||||
@@ -74,16 +76,26 @@ clean_directory() {
|
|||||||
|
|
||||||
log_step "$description (was $size_before)..."
|
log_step "$description (was $size_before)..."
|
||||||
|
|
||||||
# Use find with -delete for safer cleanup
|
# Use find to delete files older than retention period
|
||||||
if find "$dir" -mindepth 1 -delete 2>/dev/null; then
|
# -type f -mtime +N: only files older than N days (not directories)
|
||||||
log_success "$description: freed $size_before"
|
local deleted=false
|
||||||
else
|
if find "$dir" -type f -mtime +"${CACHE_RETENTION_DAYS:-7}" -delete 2>/dev/null; then
|
||||||
# Fallback to rm if find fails
|
deleted=true
|
||||||
if rm -rf "$dir"/* 2>/dev/null; then
|
fi
|
||||||
log_success "$description: freed $size_before"
|
|
||||||
|
# Clean up empty directories left behind (but don't remove the dir itself)
|
||||||
|
find "$dir" -mindepth 1 -type d -empty -delete 2>/dev/null || true
|
||||||
|
|
||||||
|
if $deleted; then
|
||||||
|
local size_after
|
||||||
|
size_after=$(get_dir_size "$dir")
|
||||||
|
if [[ "$size_after" == "$size_before" ]]; then
|
||||||
|
log_info "$description: nothing old enough to clean (retention: ${CACHE_RETENTION_DAYS:-7}d)"
|
||||||
else
|
else
|
||||||
log_warning "$description: partial cleanup completed"
|
log_success "$description: freed (was $size_before, now $size_after)"
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
log_warning "$description: partial cleanup completed"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,13 +281,19 @@ cleanup_cache_dirs() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# Clean additional cache locations
|
# Clean safe cache locations only
|
||||||
|
# NOTE: We do NOT recursively delete /var/cache or /root/.cache as a whole,
|
||||||
|
# as that can break package managers and remove important data.
|
||||||
local additional_caches=(
|
local additional_caches=(
|
||||||
"/var/lib/apt/lists"
|
"/var/cache/apt/archives"
|
||||||
|
"/var/cache/apt/archives/partial"
|
||||||
"/var/cache/debconf"
|
"/var/cache/debconf"
|
||||||
|
"/var/lib/apt/lists"
|
||||||
"/root/.npm"
|
"/root/.npm"
|
||||||
"/root/.pip"
|
"/root/.cache/pip"
|
||||||
"/home/*/.cache"
|
"/root/.cache/npm"
|
||||||
|
"/home/*/.cache/pip"
|
||||||
|
"/home/*/.cache/npm"
|
||||||
"/home/*/.npm"
|
"/home/*/.npm"
|
||||||
"/home/*/.pip"
|
"/home/*/.pip"
|
||||||
)
|
)
|
||||||
@@ -300,12 +318,16 @@ cleanup_logs() {
|
|||||||
|
|
||||||
# Find and remove old log files
|
# Find and remove old log files
|
||||||
while IFS= read -r -d '' logfile; do
|
while IFS= read -r -d '' logfile; do
|
||||||
rm -f "$logfile" 2>/dev/null && ((cleaned_count++))
|
if rm -f "$logfile" 2>/dev/null; then
|
||||||
|
((++cleaned_count)) || true
|
||||||
|
fi
|
||||||
done < <(find /var/log -type f -name "*.log" -mtime +"$LOG_RETENTION_DAYS" -print0 2>/dev/null || true)
|
done < <(find /var/log -type f -name "*.log" -mtime +"$LOG_RETENTION_DAYS" -print0 2>/dev/null || true)
|
||||||
|
|
||||||
# Clean compressed logs
|
# Clean compressed logs
|
||||||
while IFS= read -r -d '' logfile; do
|
while IFS= read -r -d '' logfile; do
|
||||||
rm -f "$logfile" 2>/dev/null && ((cleaned_count++))
|
if rm -f "$logfile" 2>/dev/null; then
|
||||||
|
((++cleaned_count)) || true
|
||||||
|
fi
|
||||||
done < <(find /var/log -type f \( -name "*.log.gz" -o -name "*.log.bz2" -o -name "*.log.xz" \) -mtime +"$LOG_RETENTION_DAYS" -print0 2>/dev/null || true)
|
done < <(find /var/log -type f \( -name "*.log.gz" -o -name "*.log.bz2" -o -name "*.log.xz" \) -mtime +"$LOG_RETENTION_DAYS" -print0 2>/dev/null || true)
|
||||||
|
|
||||||
if [[ $cleaned_count -gt 0 ]]; then
|
if [[ $cleaned_count -gt 0 ]]; then
|
||||||
|
|||||||
269
update.sh
Normal file
269
update.sh
Normal file
@@ -0,0 +1,269 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Package List Update Script
|
||||||
|
# Detects the running OS and updates the package index only (no upgrades).
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
#==============================================================================
|
||||||
|
# CONFIGURATION
|
||||||
|
#==============================================================================
|
||||||
|
|
||||||
|
readonly NC='\033[0m'
|
||||||
|
readonly RED='\033[1;31m'
|
||||||
|
readonly GREEN='\033[1;32m'
|
||||||
|
readonly LIGHT_GREEN='\033[1;32m'
|
||||||
|
readonly LIGHT_BLUE='\033[1;34m'
|
||||||
|
readonly LIGHT_GREY='\033[0;37m'
|
||||||
|
readonly YELLOW='\033[1;33m'
|
||||||
|
|
||||||
|
readonly SCRIPT_NAME="$(basename "$0")"
|
||||||
|
|
||||||
|
#==============================================================================
|
||||||
|
# UTILITY FUNCTIONS
|
||||||
|
#==============================================================================
|
||||||
|
|
||||||
|
log_info() { echo -e "${LIGHT_GREY}[i] $1${NC}"; }
|
||||||
|
log_success() { echo -e "${LIGHT_GREEN}[✓] $1${NC}"; }
|
||||||
|
log_warning() { echo -e "${YELLOW}[!] $1${NC}"; }
|
||||||
|
log_error() { echo -e "${RED}[x] $1${NC}" >&2; }
|
||||||
|
log_step() { echo -e "${LIGHT_BLUE}[i] $1${NC}"; }
|
||||||
|
|
||||||
|
die() {
|
||||||
|
log_error "$1"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
command_exists() {
|
||||||
|
command -v "$1" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Detect the running OS and its ID string.
|
||||||
|
# Prints two values: the distro id (lowercase) and the family id (lowercase).
|
||||||
|
detect_os() {
|
||||||
|
local id=""
|
||||||
|
local family=""
|
||||||
|
|
||||||
|
if [[ -f /etc/os-release ]]; then
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
. /etc/os-release
|
||||||
|
id="${ID:-unknown}"
|
||||||
|
family="${ID_LIKE:-}"
|
||||||
|
elif [[ -f /etc/alpine-release ]]; then
|
||||||
|
id="alpine"
|
||||||
|
family="alpine"
|
||||||
|
else
|
||||||
|
# Fall back to package manager detection
|
||||||
|
if command_exists apk; then
|
||||||
|
id="alpine"; family="alpine"
|
||||||
|
elif command_exists pacman; then
|
||||||
|
id="arch"; family="arch"
|
||||||
|
elif command_exists apt-get; then
|
||||||
|
id="debian"; family="debian"
|
||||||
|
elif command_exists dnf; then
|
||||||
|
id="fedora"; family="rhel"
|
||||||
|
elif command_exists yum; then
|
||||||
|
id="centos"; family="rhel"
|
||||||
|
elif command_exists zypper; then
|
||||||
|
id="opensuse"; family="suse"
|
||||||
|
elif command_exists xbps-install; then
|
||||||
|
id="void"; family="void"
|
||||||
|
elif command_exists emerge; then
|
||||||
|
id="gentoo"; family="gentoo"
|
||||||
|
else
|
||||||
|
id="unknown"; family="unknown"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "${id} ${family}"
|
||||||
|
}
|
||||||
|
|
||||||
|
#==============================================================================
|
||||||
|
# OS-SPECIFIC UPDATE FUNCTIONS
|
||||||
|
#==============================================================================
|
||||||
|
|
||||||
|
update_alpine() {
|
||||||
|
if ! command_exists apk; then
|
||||||
|
log_warning "apk not found on Alpine-type system"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Running apk update..."
|
||||||
|
if apk update 2>&1; then
|
||||||
|
log_success "Alpine package index updated"
|
||||||
|
else
|
||||||
|
log_warning "apk update failed"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
update_arch() {
|
||||||
|
if ! command_exists pacman; then
|
||||||
|
log_warning "pacman not found on Arch-type system"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Refreshing pacman database (pacman -Sy)..."
|
||||||
|
# -S = sync, -y = refresh local database only (no package installation)
|
||||||
|
if pacman -Sy --noconfirm 2>&1; then
|
||||||
|
log_success "Arch package database refreshed"
|
||||||
|
else
|
||||||
|
log_warning "pacman -Sy failed"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
update_debian() {
|
||||||
|
if ! command_exists apt-get; then
|
||||||
|
log_warning "apt-get not found on Debian-type system"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Running apt-get update..."
|
||||||
|
if apt-get update 2>&1; then
|
||||||
|
log_success "Debian/Ubuntu package index updated"
|
||||||
|
else
|
||||||
|
log_warning "apt-get update failed"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
update_rhel() {
|
||||||
|
if command_exists dnf; then
|
||||||
|
log_info "Running dnf makecache..."
|
||||||
|
if dnf makecache 2>&1; then
|
||||||
|
log_success "RHEL/Fedora metadata cache refreshed (dnf)"
|
||||||
|
else
|
||||||
|
log_warning "dnf makecache failed"
|
||||||
|
fi
|
||||||
|
elif command_exists yum; then
|
||||||
|
log_info "Running yum makecache..."
|
||||||
|
if yum makecache fast 2>&1; then
|
||||||
|
log_success "CentOS/RHEL metadata cache refreshed (yum)"
|
||||||
|
else
|
||||||
|
log_warning "yum makecache failed"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log_warning "No DNF or YUM found on RHEL-type system"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
update_suse() {
|
||||||
|
if ! command_exists zypper; then
|
||||||
|
log_warning "zypper not found on openSUSE-type system"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Running zypper refresh..."
|
||||||
|
if zypper --non-interactive refresh 2>&1; then
|
||||||
|
log_success "openSUSE repositories refreshed"
|
||||||
|
else
|
||||||
|
log_warning "zypper refresh failed"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
update_void() {
|
||||||
|
if ! command_exists xbps-install; then
|
||||||
|
log_warning "xbps-install not found on Void system"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Running xbps-install -S (sync repository index)..."
|
||||||
|
if xbps-install -S 2>&1; then
|
||||||
|
log_success "Void package index synced"
|
||||||
|
else
|
||||||
|
log_warning "xbps-install -S failed"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
update_gentoo() {
|
||||||
|
if ! command_exists emerge; then
|
||||||
|
log_warning "emerge not found on Gentoo system"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Running emaint sync -a..."
|
||||||
|
if emaint sync -a 2>&1; then
|
||||||
|
log_success "Gentoo Portage tree synced"
|
||||||
|
else
|
||||||
|
log_warning "emaint sync failed"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#==============================================================================
|
||||||
|
# MAIN EXECUTION
|
||||||
|
#==============================================================================
|
||||||
|
|
||||||
|
main() {
|
||||||
|
log_step "Starting package list update (${SCRIPT_NAME})"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Detect the OS
|
||||||
|
local distro_info distro_id family_id
|
||||||
|
distro_info="$(detect_os)"
|
||||||
|
distro_id="${distro_info%% *}"
|
||||||
|
family_id="${distro_info##* }"
|
||||||
|
|
||||||
|
log_info "Detected OS: ${distro_id}"
|
||||||
|
if [[ -n "${family_id}" && "${family_id}" != "${distro_id}" ]]; then
|
||||||
|
log_info "OS family: ${family_id}"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Dispatch to the correct handler based on distro family
|
||||||
|
# Check distro_id first, then fall back to family_id for aliases
|
||||||
|
case "${distro_id}" in
|
||||||
|
alpine)
|
||||||
|
update_alpine
|
||||||
|
;;
|
||||||
|
arch|artix|manjaro|garuda)
|
||||||
|
update_arch
|
||||||
|
;;
|
||||||
|
debian|ubuntu|linuxmint|kali|raspbian|pop)
|
||||||
|
update_debian
|
||||||
|
;;
|
||||||
|
fedora|rhel|centos|rocky|almalinux|amazon|oracle|clear-linux-os)
|
||||||
|
update_rhel
|
||||||
|
;;
|
||||||
|
opensuse*|suse|sles)
|
||||||
|
update_suse
|
||||||
|
;;
|
||||||
|
void)
|
||||||
|
update_void
|
||||||
|
;;
|
||||||
|
gentoo|funtoo)
|
||||||
|
update_gentoo
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# Try matching on family ID as fallback
|
||||||
|
case "${family_id}" in
|
||||||
|
*alpine*)
|
||||||
|
update_alpine
|
||||||
|
;;
|
||||||
|
*arch*)
|
||||||
|
update_arch
|
||||||
|
;;
|
||||||
|
*debian*|*ubuntu*)
|
||||||
|
update_debian
|
||||||
|
;;
|
||||||
|
*rhel*|*fedora*|*centos*)
|
||||||
|
update_rhel
|
||||||
|
;;
|
||||||
|
*suse*|*opensuse*)
|
||||||
|
update_suse
|
||||||
|
;;
|
||||||
|
*void*)
|
||||||
|
update_void
|
||||||
|
;;
|
||||||
|
*gentoo*)
|
||||||
|
update_gentoo
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
die "Unsupported OS: ${distro_id} (${family_id}). Cannot update package index."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo
|
||||||
|
log_success "Package list update completed!"
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
Reference in New Issue
Block a user