326 lines
7.6 KiB
Bash
Executable File
326 lines
7.6 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
###############################################################################
|
||
# Script Name: system-update.sh
|
||
#
|
||
# Description:
|
||
# Performs automated system maintenance and package updates.
|
||
#
|
||
# Tasks:
|
||
# - apt update
|
||
# - apt upgrade
|
||
# - apt dist-upgrade
|
||
# - apt autoclean
|
||
# - apt autoremove
|
||
# - flatpak update
|
||
# - cleanup old log files
|
||
# - update Docker images
|
||
# - restart Docker service
|
||
# - maintain SpotDL Python virtual environment
|
||
# - install/update spotdl, yt-dlp and youtube-dl
|
||
# - optional email reporting
|
||
#
|
||
# Requirements:
|
||
# - apt
|
||
# - flatpak (optional)
|
||
# - python3-venv
|
||
# - docker (optional)
|
||
# - mail (optional, for -mail mode)
|
||
#
|
||
# Usage:
|
||
#
|
||
# Normal execution:
|
||
# ./system-update.sh
|
||
#
|
||
# Email report mode:
|
||
# ./system-update.sh -mail
|
||
#
|
||
# Logs:
|
||
# ~/.LOG/log_update_<timestamp>.log
|
||
#
|
||
###############################################################################
|
||
|
||
set -o pipefail
|
||
usage() {
|
||
cat <<EOF
|
||
Usage: ${0##*/} [OPTIONS]
|
||
|
||
Update apt pythoni flatpak and docker
|
||
|
||
Options:
|
||
-h, --help Show this help message and exit
|
||
--version Show script version
|
||
|
||
EOF
|
||
}
|
||
|
||
home_dir="/home/lucas"
|
||
|
||
green="\e[32m"
|
||
red="\e[31m"
|
||
norm="\e[0m"
|
||
|
||
MAIL=false
|
||
BUILD=false
|
||
die() {
|
||
echo "Error: $*" >&2
|
||
echo
|
||
usage >&2
|
||
exit 2
|
||
}
|
||
|
||
parse_args() {
|
||
while [[ $# -gt 0 ]]; do
|
||
case "$1" in
|
||
-h|--help)
|
||
usage
|
||
exit 0
|
||
;;
|
||
|
||
--version)
|
||
echo "${0##*/} 1.0"
|
||
exit 0
|
||
;;
|
||
--build)
|
||
BUILD=true
|
||
shift 1;
|
||
;;
|
||
--mail)
|
||
MAIL=true
|
||
shift 1;
|
||
;;
|
||
-*)
|
||
die "Unknown option: $1"
|
||
;;
|
||
|
||
*)
|
||
die "Unexpected argument: $1"
|
||
;;
|
||
esac
|
||
|
||
shift
|
||
done
|
||
}
|
||
|
||
write_out() {
|
||
if [[ "${MAIL}" == "true" ]]; then
|
||
printf "$@\n" >> /tmp/update.txt
|
||
else
|
||
printf "$@\n"
|
||
fi
|
||
}
|
||
|
||
echo "Start Update"
|
||
|
||
mkdir -p "${home_dir}/.LOG"
|
||
|
||
log_date="$(date +"%m%d%H")"
|
||
|
||
if [[ "$1" == "-mail" ]]; then
|
||
> /tmp/update.txt
|
||
|
||
exec 3>&1 4>&2 \
|
||
1>"${home_dir}/.LOG/log_update_${log_date}.log" \
|
||
2>&1
|
||
|
||
MAIL=true
|
||
green=""
|
||
red=""
|
||
norm=""
|
||
fi
|
||
|
||
write_out "Start: $(date)"
|
||
|
||
###############################################################################
|
||
# System Updates
|
||
###############################################################################
|
||
###############################################################################
|
||
# Standard updates
|
||
###############################################################################
|
||
|
||
CMD=(
|
||
"apt -y update"
|
||
"apt -y upgrade"
|
||
"apt -y dist-upgrade"
|
||
"apt -y autoclean"
|
||
"apt -y autoremove"
|
||
"find ${home_dir}/.LOG/ -name 'log_update_*' -mtime +6 -type f -delete"
|
||
)
|
||
|
||
MSG=(
|
||
"update"
|
||
"upgrade"
|
||
"dist-upgrade"
|
||
"autoclean"
|
||
"autoremove"
|
||
"log-cleanup"
|
||
)
|
||
|
||
for ((i=0; i<${#CMD[@]}; i++)); do
|
||
|
||
printf "Running: %s\n" "${CMD[$i]}"
|
||
|
||
if eval "sudo ${CMD[$i]}"; then
|
||
write_out "${MSG[$i]} [${green}OK${norm}]"
|
||
else
|
||
write_out "${MSG[$i]} [${red}FAIL${norm}]"
|
||
fi
|
||
|
||
done
|
||
|
||
###############################################################################
|
||
# Flatpak Update
|
||
###############################################################################
|
||
|
||
if command -v flatpak >/dev/null 2>&1; then
|
||
|
||
echo "Starting Flatpak Update..."
|
||
|
||
sudo flatpak update -y --noninteractive
|
||
|
||
ret=$?
|
||
|
||
echo "Flatpak returned: ${ret}"
|
||
|
||
if [[ $ret -eq 0 ]]; then
|
||
write_out "flatpak-update [${green}OK${norm}]"
|
||
else
|
||
write_out "flatpak-update [${red}FAIL${norm}]"
|
||
fi
|
||
fi
|
||
|
||
echo "Finished Package Update"
|
||
|
||
###############################################################################
|
||
# SpotDL Virtual Environment
|
||
###############################################################################
|
||
|
||
|
||
PACKAGES=(
|
||
yt-dlp
|
||
spotdl
|
||
)
|
||
|
||
# Install pipx if missing
|
||
if ! command -v pipx >/dev/null 2>&1; then
|
||
echo "Installing pipx..."
|
||
sudo apt update
|
||
sudo apt install -y pipx
|
||
pipx ensurepath
|
||
fi
|
||
|
||
# Check ffmpeg
|
||
if ! command -v ffmpeg >/dev/null 2>&1; then
|
||
echo "Installing ffmpeg..."
|
||
sudo apt install -y ffmpeg
|
||
fi
|
||
|
||
# Install or update packages
|
||
for pkg in "${PACKAGES[@]}"; do
|
||
if pipx list --short 2>/dev/null | grep -qx "$pkg"; then
|
||
echo "Updating $pkg..."
|
||
pipx upgrade "$pkg"
|
||
else
|
||
echo "Installing $pkg..."
|
||
pipx install "$pkg"
|
||
fi
|
||
done
|
||
|
||
# Install Deno for spotdl if missing
|
||
if ! command -v deno >/dev/null 2>&1; then
|
||
echo "Installing Deno..."
|
||
curl -fsSL https://deno.land/install.sh | sh
|
||
|
||
# Add to PATH for current shell
|
||
export PATH="$HOME/.deno/bin:$PATH"
|
||
fi
|
||
|
||
###############################################################################
|
||
# Docker Updates
|
||
###############################################################################
|
||
|
||
if command -v docker >/dev/null 2>&1; then
|
||
|
||
echo "Updating Docker images"
|
||
|
||
docker images --format "{{.Repository}}:{{.Tag}}" |
|
||
while read -r image; do
|
||
echo "####################################################"
|
||
echo "### $image"
|
||
echo "####################################################"
|
||
|
||
case "$image" in
|
||
qbittorrent-qbittorrent:*)
|
||
echo "Updating custom qBittorrent image..."
|
||
(
|
||
latest="$(curl -s https://api.github.com/repos/qbittorrent/qBittorrent/releases/latest | grep '"tag_name"' | cut -d '"' -f 4 | cut -d '-' -f2)"
|
||
current="$(docker exec -it qbittorrent /app/qbittorrent-nox -v | cut -d 'v' -f2)"
|
||
if [[ "$LATEST" != "$CURRENT" && "$BUILD" == "true" ]]; then
|
||
echo "New version available: $CURRENT -> $LATEST"
|
||
cd /docker/qbittorrent &&
|
||
docker compose build --pull &&
|
||
docker compose up -d
|
||
elif [[ "$LATEST" != "$CURRENT" ]]; then
|
||
echo "New version available: $CURRENT -> $LATEST"
|
||
echo "BUILD is turend off"
|
||
else
|
||
echo "No new version available: $CURRENT == $LATEST"
|
||
fi
|
||
)
|
||
;;
|
||
*"<none>"*)
|
||
;;
|
||
*)
|
||
docker pull "$image"
|
||
;;
|
||
esac
|
||
done
|
||
|
||
systemctl restart docker
|
||
|
||
if [[ $? -eq 0 ]]; then
|
||
write_out "docker [${green}OK${norm}]"
|
||
else
|
||
write_out "docker [${red}FAIL${norm}]"
|
||
fi
|
||
fi
|
||
|
||
if [ -f /docker/qbittorrent/docker-compose.yml ]; then
|
||
cd /docker/qbittorrent || exit 1
|
||
|
||
if docker compose config >/dev/null 2>&1; then
|
||
echo "Updating custom qBittorrent image..."
|
||
docker compose build --pull
|
||
docker compose up -d
|
||
fi
|
||
fi
|
||
|
||
for d in /docker/*; do
|
||
if [ -d $d ]; then
|
||
docker compose -f $d/docker-compose.yaml up -d
|
||
fi
|
||
done
|
||
|
||
|
||
docker container prune -f
|
||
docker network prune -f
|
||
docker image prune -a -f
|
||
docker builder prune -f
|
||
|
||
|
||
|
||
###############################################################################
|
||
# Mail Report
|
||
###############################################################################
|
||
|
||
if [[ "${MAIL}" == "true" ]]; then
|
||
|
||
mail_str="$(cat /tmp/update.txt)"
|
||
|
||
echo "$mail_str" | mail \
|
||
-s "Automated Server Message - Upgrade" \
|
||
lucas-f@live.at
|
||
fi
|
||
|
||
write_out "Finished: $(date)"
|