diff --git a/README.md b/README.md index 599cb7d..f99a2b1 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,9 @@ [![GitHub stars](https://img.shields.io/github/stars/BassT23/Proxmox.svg)](https://github.com/BassT23/Proxmox/stargazers) - + +![screenshot](https://user-images.githubusercontent.com/30832786/222421730-873ea121-bffd-4bab-a52a-e2beb3cca783.png) + # Proxmox-Updater Features: @@ -26,7 +28,7 @@ Features: - Normal run is "Interactive" / Headless Mode can be run with `update -s` - Logging - Exit tracking, so you can send additional commands for finish or failure (edit files in `/root/Proxmox-Updater/exit`) -- Extra updates for specific container +- Config file Info can be found with `update -h` @@ -59,7 +61,7 @@ If updater detects Installation: (disable, if you wand in `/root/Proxmox-Updater - ioBroker - Pterodactyl - Octoprint -- Docker Container Images (disabled by default - need some fixing) +- Docker Container Images ## Config File: @@ -67,8 +69,27 @@ If updater detects Installation: (disable, if you wand in `/root/Proxmox-Updater The config file is stored under `/root/Proxmox-Updater/update.conf` With this file, you can manage the updater. For example; if you don't want to update PiHole, comment the line out with #, or change `true` to `false`. -You can also exclude machines from updating, by put the ID in the `EXCLUDE` line. +- Host / LXC / VM +- Headless Mode +- Extra updates +- "stopped" or "running" LXC/VM +- "only" or "exclude" LXC/VM by ID + + +## Welcome Screen + +The Welcome Screen is an extra for you. Its optional! + +Can be installed or uninstalled with: +``` +bash <(curl -s https://raw.githubusercontent.com/BassT23/Proxmox/master/install.sh) welcome +``` + +- The Welcome-Screen brings an update-checker with it. It check on 07am and 07pm for updates via crontab. The result will show up in Welcome-Screen (Only if updates are available). +- The update-checker also use the config file! +- To force the check, you can run `/root/Proxmox-Updater/check-updates.sh` in Terminal. +- Need neofetch to be installed (if not installed, script will make it automatically) ## Beta Testing: diff --git a/change.log b/change.log index 29450b0..ab9842f 100644 --- a/change.log +++ b/change.log @@ -1,28 +1,37 @@ Changelog: ========== +**v3.7** (09.03.2023) + +- Fixing code +- Support "only" LXC/VM +- Fix docker-compose update +- VM-Update show errors +- Add Welcome Screen with periodic update check +- Need neofetch (will install automatic) + **v3.6** (22.02.2023) -- add config file -- cleaning code -- more colorful -- fixing logging +- Add config file +- Cleaning code +- More colorful +- Fixing logging **v3.4** (not released) -- add VM Update -- cleaning code -- fixed Docker Update +- Add VM Update +- Cleaning code +- Fixed Docker Update **v3.3** (15.02.2023) -- add Update Info -- add extra Updates -- add version check by user +- Add Update Info +- Add extra Updates +- Add version check by user **v3.1.1** (13.02.2023) -- fixed update failure with CentOS +- Fixed update failure with CentOS **v3.1** (12.02.2023) @@ -39,11 +48,11 @@ Changelog: **v2.7.1** (06.02.2023) -- small fixes +- Small fixes **v2.7** (31.01.2023) -- add root check +- Add root check - Cleanup overall code **v2.6** (30.01.2023) @@ -54,7 +63,7 @@ Changelog: **v2.5** (30.01.2023) -- added "Headless Mode" as option with `update -3` otherwise runs in "Interactive Mode" +- Added "Headless Mode" as option with `update -3` otherwise runs in "Interactive Mode" **v2.4** (29.01.2023) diff --git a/check-updates.sh b/check-updates.sh new file mode 100644 index 0000000..febc43d --- /dev/null +++ b/check-updates.sh @@ -0,0 +1,283 @@ +#!/bin/bash + +################# +# Check Updates # +################# + +VERSION="1.3" + +#Variable / Function +CONFIG_FILE="/root/Proxmox-Updater/update.conf" + +# Colors +BL="\e[36m" +OR="\e[1;33m" +RD="\e[1;91m" +GN="\e[1;92m" +CL="\e[0m" + +# Usage +function USAGE { + echo -e "\nUsage: $0 {COMMAND}\n" + echo -e "{COMMAND}:" + echo -e "=========" + echo -e " host Host-Mode" + echo -e " cluster Cluster-Mode\n" + echo -e "Report issues at: \n" +} + +function READ_WRITE_CONFIG { + WITH_HOST=$(awk -F'"' '/^WITH_HOST=/ {print $2}' $CONFIG_FILE) + WITH_LXC=$(awk -F'"' '/^WITH_LXC=/ {print $2}' $CONFIG_FILE) + WITH_VM=$(awk -F'"' '/^WITH_VM=/ {print $2}' $CONFIG_FILE) + RUNNING=$(awk -F'"' '/^RUNNING_CONTAINER=/ {print $2}' $CONFIG_FILE) + STOPPED=$(awk -F'"' '/^STOPPED_CONTAINER=/ {print $2}' $CONFIG_FILE) + EXCLUDED=$(awk -F'"' '/^EXCLUDE=/ {print $2}' $CONFIG_FILE) + ONLY=$(awk -F'"' '/^ONLY=/ {print $2}' $CONFIG_FILE) +} + +## HOST ## +# Host Check Start +function HOST_CHECK_START { + for HOST in $HOSTS; do + CHECK_HOST "$HOST" + done +} + +# Host Check +function CHECK_HOST { + HOST=$1 + ssh "$HOST" mkdir -p /root/Proxmox-Updater + scp /root/Proxmox-Updater/update.conf "$HOST":/root/Proxmox-Updater/update.conf >/dev/null 2>&1 + ssh "$HOST" 'bash -s' < "$0" -- "-c host" +} + +function CHECK_HOST_ITSELF { + apt-get update >/dev/null 2>&1 + SECURITY_APT_UPDATES=$(apt-get -s upgrade | grep -ci "^inst.*security" | tr -d '\n') + NORMAL_APT_UPDATES=$(apt-get -s upgrade | grep -ci "^inst." | tr -d '\n') + if [[ -f /var/run/reboot-required.pkgs ]]; then REBOOT_REQUIRED=true; fi + if [[ $SECURITY_APT_UPDATES != 0 || $NORMAL_APT_UPDATES != 0 || $REBOOT_REQUIRED == true ]]; then + echo -e "${GN}Host${CL} : ${GN}$HOSTNAME${CL}" + fi + if [[ $REBOOT_REQUIRED == true ]]; then echo -e "${OR} Reboot required${CL}"; fi + if [[ $SECURITY_APT_UPDATES != 0 && $NORMAL_APT_UPDATES != 0 ]]; then + echo -e "S: $SECURITY_APT_UPDATES / N: $NORMAL_APT_UPDATES" + elif [[ $SECURITY_APT_UPDATES != 0 ]]; then + echo -e "S: $SECURITY_APT_UPDATES / " + elif [[ $NORMAL_APT_UPDATES != 0 ]]; then + echo -e "N: $NORMAL_APT_UPDATES" + fi +} + +## Container ## +# Container Check Start +function CONTAINER_CHECK_START { + # Get the list of containers + CONTAINERS=$(pct list | tail -n +2 | cut -f1 -d' ') + # Loop through the containers + for CONTAINER in $CONTAINERS; do + if [[ $ONLY == "" ]] && [[ $EXCLUDED =~ $CONTAINER ]]; then + continue + elif [[ $ONLY != "" ]] && ! [[ $ONLY =~ $CONTAINER ]]; then + continue + else + STATUS=$(pct status "$CONTAINER") + if [[ $STATUS == "status: stopped" && $STOPPED == true ]]; then + # Start the container + pct start "$CONTAINER" + sleep 5 + CHECK_CONTAINER "$CONTAINER" + # Stop the container + pct shutdown "$CONTAINER" & + elif [[ $STATUS == "status: running" && $RUNNING == true ]]; then + CHECK_CONTAINER "$CONTAINER" + fi + fi + done + rm -rf temp +} + +# Container Check +function CHECK_CONTAINER { + CONTAINER=$1 + pct config "$CONTAINER" > temp + OS=$(awk '/^ostype/' temp | cut -d' ' -f2) + if [[ $OS =~ centos ]]; then + NAME=$(pct exec "$CONTAINER" hostnamectl | grep 'hostname' | tail -n +2 | rev |cut -c -11 | rev) + else + NAME=$(pct exec "$CONTAINER" hostname) + fi + if [[ $OS =~ ubuntu ]] || [[ $OS =~ debian ]] || [[ $OS =~ devuan ]]; then + pct exec "$CONTAINER" -- bash -c "apt-get update" >/dev/null 2>&1 + SECURITY_APT_UPDATES=$(pct exec "$CONTAINER" -- bash -c "apt-get -s upgrade | grep -ci ^inst.*security | tr -d '\n'") + NORMAL_APT_UPDATES=$(pct exec "$CONTAINER" -- bash -c "apt-get -s upgrade | grep -ci ^inst. | tr -d '\n'") + if [[ $SECURITY_APT_UPDATES -gt 0 || $NORMAL_APT_UPDATES != 0 ]]; then + echo -e "${GN}LXC ${BL}$CONTAINER${CL} : ${GN}$NAME${CL}" + fi + if [[ $SECURITY_APT_UPDATES -gt 0 && $NORMAL_APT_UPDATES != 0 ]]; then + echo -e "S: $SECURITY_APT_UPDATES / N: $NORMAL_APT_UPDATES" + elif [[ $SECURITY_APT_UPDATES -gt 0 ]]; then + echo -e "S: $SECURITY_APT_UPDATES / " + elif [[ $NORMAL_APT_UPDATES -gt 0 ]]; then + echo -e "N: $NORMAL_APT_UPDATES" + fi + elif [[ $OS =~ fedora ]]; then + pct exec "$CONTAINER" -- bash -c "dnf -y update" >/dev/null 2>&1 + UPDATES=$(pct exec "$CONTAINER" -- bash -c "dnf check-update| grep -Ec ' updates$'") + if [[ $UPDATES -gt 0 ]]; then + echo -e "${GN}LXC ${BL}$CONTAINER${CL} : ${GN}$NAME${CL}" + echo -e "$UPDATES" + fi + elif [[ $OS =~ archlinux ]]; then + pct exec "$CONTAINER" -- bash -c "pacman -Syyu" >/dev/null 2>&1 + UPDATES=$(pct exec "$CONTAINER" -- bash -c "pacman -Qu | wc -l") + if [[ $UPDATES -gt 0 ]]; then + echo -e "${GN}LXC ${BL}$CONTAINER${CL} : ${GN}$NAME${CL}" + echo -e "$UPDATES" + fi + elif [[ $OS =~ alpine ]]; then + pct exec "$CONTAINER" -- ash -c "apk update" >/dev/null 2>&1 + else + pct exec "$CONTAINER" -- bash -c "yum update" >/dev/null 2>&1 + UPDATES=$(pct exec "$CONTAINER" -- bash -c "yum -q check-update | wc -l") + if [[ $UPDATES -gt 0 ]]; then + echo -e "${GN}LXC ${BL}$CONTAINER${CL} : ${GN}$NAME${CL}" + echo -e "$UPDATES" + fi + fi +} + +## VM ## +# VM Check Start +function VM_CHECK_START { + # Get the list of VMs + VMS=$(qm list | tail -n +2 | cut -c -10) + # Loop through the VMs + for VM in $VMS; do + PRE_OS=$(qm config "$VM" | grep 'ostype:' | sed 's/ostype:\s*//') + if [[ $ONLY == "" && $EXCLUDED =~ $VM ]]; then + continue + elif [[ $ONLY != "" ]] && ! [[ $ONLY =~ $VM ]]; then + continue + elif [[ $PRE_OS =~ w ]]; then + continue + else + STATUS=$(qm status "$VM") + if [[ $STATUS == "status: stopped" && $STOPPED == true ]]; then + # Start the VM + qm set "$VM" --agent 1 >/dev/null 2>&1 + qm start "$VM" >/dev/null 2>&1 + sleep 30 + CHECK_VM "$VM" + # Stop the VM + qm shutdown "$VM" + elif [[ $STATUS == "status: running" && $RUNNING == true ]]; then + CHECK_VM "$VM" + fi + fi + done +} + +# VM Check +function CHECK_VM { + VM=$1 + if qm guest exec "$VM" test >/dev/null 2>&1; then +# REBOOT_REQUIRED=$(qm guest cmd "$VM" -- bash -c "-f /var/run/reboot-required.pkgs") + NAME=$(qm config "$VM" | grep 'name:' | sed 's/name:\s*//') + OS=$(qm guest cmd "$VM" get-osinfo | grep name) + if [[ $OS =~ Ubuntu ]] || [[ $OS =~ Debian ]] || [[ $OS =~ Devuan ]]; then + qm guest exec "$VM" -- bash -c "apt-get update" >/dev/null 2>&1 + SECURITY_APT_UPDATES=$(qm guest exec "$VM" -- bash -c "apt-get -s upgrade | grep -ci ^inst.*security | tr -d '\n'" | tail -n +4 | head -n -1 | cut -c 18- | rev | cut -c 2- | rev) + NORMAL_APT_UPDATES=$(qm guest exec "$VM" -- bash -c "apt-get -s upgrade | grep -ci ^inst. | tr -d '\n'" | tail -n +4 | head -n -1 | cut -c 18- | rev | cut -c 2- | rev) + if [[ $SECURITY_APT_UPDATES -gt 0 || $NORMAL_APT_UPDATES -gt 0 ]]; then + echo -e "${GN}VM ${BL}$VM${CL} : ${GN}$NAME${CL}" + fi + if [[ $SECURITY_APT_UPDATES -gt 0 && $NORMAL_APT_UPDATES -gt 0 ]]; then + echo -e "S: $SECURITY_APT_UPDATES / N: $NORMAL_APT_UPDATES" + elif [[ $SECURITY_APT_UPDATES -gt 0 ]]; then + echo -e "S: $SECURITY_APT_UPDATES / " + elif [[ $NORMAL_APT_UPDATES -gt 0 ]]; then + echo -e "N: $NORMAL_APT_UPDATES" + fi + elif [[ $OS =~ Fedora ]]; then + qm guest exec "$VM" -- bash -c "dnf -y update" >/dev/null 2>&1 + UPDATES=$(qm guest exec "$VM" -- bash -c "dnf check-update| grep -Ec ' updates$'" | tail -n +4 | head -n -1 | cut -c 18- | rev | cut -c 2- | rev) + if [[ $UPDATES -gt 0 ]]; then + echo -e "${GN}VM ${BL}$VM${CL} : ${GN}$NAME${CL}" + echo -e "$UPDATES" + fi + elif [[ $OS =~ Arch ]]; then + UPDATES=$(qm guest exec "$VM" -- bash -c "pacman -Qu | wc -l" | tail -n +4 | head -n -1 | cut -c 18- | rev | cut -c 2- | rev) + if [[ $UPDATES -gt 0 ]]; then + echo -e "${GN}VM ${BL}$VM${CL} : ${GN}$NAME${CL}" + echo -e "$UPDATES" + fi + elif [[ $OS =~ Alpine ]]; then + return + elif [[ $OS =~ CentOS ]]; then + UPDATES=$(qm guest exec "$VM" -- bash -c "yum -q check-update | wc -l" | tail -n +4 | head -n -1 | cut -c 18- | rev | cut -c 2- | rev) + if [[ $UPDATES -gt 0 ]]; then + echo -e "${GN}VM ${BL}$VM${CL} : ${GN}$NAME${CL}" + echo -e "$UPDATES" + fi + fi + fi +} + +# Output to file +#if [[ $RICM != true ]]; then + touch /root/Proxmox-Updater/check-output + exec > >(tee /root/Proxmox-Updater/check-output) +#fi + +# Check Cluster Mode +if [[ -f /etc/corosync/corosync.conf ]]; then + HOSTS=$(awk '/ring0_addr/{print $2}' "/etc/corosync/corosync.conf") + MODE="Cluster" +else + MODE="Host" +fi + +# Run +READ_WRITE_CONFIG +parse_cli() +{ + while test $# -gt -0 + do + argument="$1" + case "$argument" in + -c) + RICM=true + ;; + host) + COMMAND=true + if [[ $WITH_HOST == true ]]; then CHECK_HOST_ITSELF; fi + if [[ $WITH_LXC == true ]]; then CONTAINER_CHECK_START; fi + if [[ $WITH_VM == true ]]; then VM_CHECK_START; fi + ;; + cluster) + COMMAND=true + HOST_CHECK_START + ;; + *) + echo -e "\n${RD} Error: Got an unexpected argument \"$argument\"${CL}"; + USAGE; + exit 2; + ;; + esac + shift + done +} +parse_cli "$@" + +# Run without commands (Automatic Mode) +if [[ $COMMAND != true ]]; then + if [[ $MODE =~ Cluster ]]; then HOST_CHECK_START; else + if [[ $WITH_HOST == true ]]; then CHECK_HOST_ITSELF; fi + if [[ $WITH_LXC == true ]]; then CONTAINER_CHECK_START; fi + if [[ $WITH_VM == true ]]; then VM_CHECK_START; fi + fi +fi + +exit 0 diff --git a/install.sh b/install.sh index e7a949f..e28a695 100644 --- a/install.sh +++ b/install.sh @@ -1,11 +1,14 @@ #!/bin/bash -#Variable / Function -VERSION="1.4" +########### +# Install # +########### -SERVER_URL="https://raw.githubusercontent.com/BassT23/Proxmox/master" +VERSION="1.5" +#Variable / Function LOCAL_FILES="/root/Proxmox-Updater" +SERVER_URL="https://raw.githubusercontent.com/BassT23/Proxmox/master" #Colors BL="\e[36m" @@ -48,15 +51,13 @@ function CHECK_ROOT { function USAGE { if [[ $SILENT != true ]]; then - echo -e "Usage: $0 [OPTIONS...] {COMMAND}\n" - echo -e "[OPTIONS] Manages the Proxmox-Updater:" - echo -e "======================================" + echo -e "Usage: $0 {COMMAND}\n" + echo -e "{COMMAND}:" + echo -e "==========" echo -e " -h --help Show this help" - echo -e " -s --silent Silent mode\n" - echo -e "Commands:" - echo -e "=========" echo -e " status Check current installation status" echo -e " install Install Proxmox-Updater" + echo -e " welcome Install or Uninstall Welcome Screen" echo -e " uninstall Uninstall Proxmox-Updater" echo -e " update Update Proxmox-Updater\n" echo -e "Report issues at: \n" @@ -87,7 +88,7 @@ function INSTALL { echo -e "\n${BL}[Info]${GN} Installing Proxmox-Updater${CL}\n" if [ -f "/usr/local/bin/update" ]; then echo -e "${OR}Proxmox-Updater is already installed.${CL}" - read -p "${OR}Should I update for you? Type [Y/y] or Enter for yes - enything else will exit${CL}" -n 1 -r -s + read -p "Should I update for you? Type [Y/y] or Enter for yes - enything else will exit" -n 1 -r -s if [[ $REPLY =~ ^[Yy]$ || $REPLY = "" ]]; then bash <(curl -s $SERVER_URL/install.sh) update else @@ -123,6 +124,13 @@ ${OR}Is it OK for you, or want to backup first your files?${CL}\n" else echo -e "\n${BL}[Info]${GN} Updating script ...${CL}\n" curl -s $SERVER_URL/update.sh > /usr/local/bin/update + curl -s $SERVER_URL/welcome-screen.sh > /etc/update-motd.d/01-welcome-screen + chmod +x /etc/update-motd.d/01-welcome-screen + curl -s $SERVER_URL/check-updates.sh > /root/Proxmox-Updater/check-updates.sh + chmod +x /root/Proxmox-Updater/check-updates.sh + # Delete old files + if [[ -f /etc/update-motd.d/01-updater ]];then rm -r /etc/update-motd.d/01-updater; fi + if [[ -f /etc/update-motd.d/01-updater.bak ]];then rm -r /etc/update-motd.d/01-updater.bak; fi # Check if files are different mkdir -p /root/Proxmox-Updater-Temp/exit curl -s $SERVER_URL/exit/error.sh > /root/Proxmox-Updater-Temp/exit/error.sh @@ -134,7 +142,7 @@ ${OR}Is it OK for you, or want to backup first your files?${CL}\n" FILES="*.* **/*.*" for f in $FILES do - CHECK_DIFF + CHECK_DIFF done rm -r /root/Proxmox-Updater-Temp echo -e "${GN}Proxmox-Updater updated successfully.${CL}\n" @@ -156,7 +164,7 @@ function CHECK_DIFF { echo -e "The file $f\n \ ==> Modified (by you or by a script) since installation.\n \ What would you like to do about it ? Your options are:\n \ - Y or y : install the package maintainer's version (old file will be save as 'file.bak')\n \ + Y or y : install the package maintainer's version (old file will be save as '$f.bak')\n \ N or n : keep your currently-installed version\n \ S or s : show the differences between the versions\n \ The default action is to keep your current version.\n \ @@ -177,6 +185,48 @@ function CHECK_DIFF { fi } +function WELCOME_SCREEN { + if [[ $COMMAND != true ]]; then + echo -e "\n${BL}[Info]${GN} Installing Proxmox-Updater Welcome-Screen${CL}\n" + if ! [[ -d /root/Proxmox-Updater-Temp ]];then mkdir /root/Proxmox-Updater-Temp; fi + curl -s $SERVER_URL/welcome-screen.sh > /root/Proxmox-Updater-Temp/welcome-screen.sh + curl -s $SERVER_URL/check-updates.sh > /root/Proxmox-Updater-Temp/check-updates.sh + if ! [[ -f "/etc/update-motd.d/01-welcome-screen" && -x "/etc/update-motd.d/01-welcome-screen" ]]; then + echo -e "${OR} Welcome-Screen is not installed${CL}\n" + read -p "Would you like to install it also? Type [Y/y] or Enter for yes - enything else will skip" -n 1 -r -s && echo + if [[ $REPLY =~ ^[Yy]$ || $REPLY = "" ]]; then + if [[ -f /etc/motd ]];then mv /etc/motd /etc/motd.bak; fi + cp /etc/crontab /etc/crontab.bak + touch /etc/motd + if ! [ -f /usr/bin/neofetch ]; then apt-get install neofetch -y; fi + cp /root/Proxmox-Updater-Temp/welcome-screen.sh /etc/update-motd.d/01-welcome-screen + cp /root/Proxmox-Updater-Temp/check-updates.sh /root/Proxmox-Updater/check-updates.sh + chmod +x /etc/update-motd.d/01-welcome-screen + chmod +x /root/Proxmox-Updater/check-updates.sh + if ! grep -q "check-updates.sh" /etc/crontab; then + echo "00 07,19 * * * root /root/Proxmox-Updater/check-updates.sh" >> /etc/crontab + fi + echo -e "\n${GN} Welcome-Screen installed${CL}\n" + fi + else + echo -e "${OR} Welcome-Screen is already installed${CL}\n" + read -p "Would you like to uninstall it? Type [Y/y] for yes - enything else will skip" -n 1 -r -s && echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + rm -rf /etc/update-motd.d/01-welcome-screen + rm -rf /etc/motd + if [[ -f /etc/motd.bak ]]; then mv /etc/motd.bak /etc/motd; fi + #restore old crontab with info output + mv /etc/crontab /etc/crontab.bak2 + mv /etc/crontab.bak /etc/crontab + mv /etc/crontab.bak2 /etc/crontab.bak + echo -e "\n${BL} Welcome-Screen uninstalled${CL}\n\ + crontab file restored (old one backed up as crontab.bak)\n" + fi + fi + rm -r /root/Proxmox-Updater-Temp + fi +} + function UNINSTALL { if [ -f "/usr/local/bin/update" ]; then echo -e "\n${BL}[Info]${GN} Uninstall Proxmox-Updater${CL}\n" @@ -185,6 +235,11 @@ function UNINSTALL { if [[ $REPLY =~ ^[Yy]$ ]]; then rm /usr/local/bin/update rm -r /root/Proxmox-Updater + if [[ -f "/etc/update-motd.d/01-welcome-screen" ]]; then + chmod -x /etc/update-motd.d/01-welcome-screen + rm -rf /etc/motd + mv /etc/motd.bak /etc/motd + fi echo -e "\n\n${BL}Proxmox-Updater removed${CL}\n" fi else @@ -219,9 +274,6 @@ parse_cli() USAGE exit 0 ;; - -s|--silent) - SILENT=true - ;; status) STATUS exit 0 @@ -229,6 +281,13 @@ parse_cli() install) COMMAND=true INSTALL + WELCOME_SCREEN + exit 0 + ;; + update) + COMMAND=true + UPDATE + WELCOME_SCREEN exit 0 ;; uninstall) @@ -236,9 +295,8 @@ parse_cli() UNINSTALL exit 0 ;; - update) - COMMAND=true - UPDATE + welcome) + WELCOME_SCREEN exit 0 ;; *) diff --git a/update-extras.sh b/update-extras.sh index 26c3564..751f775 100644 --- a/update-extras.sh +++ b/update-extras.sh @@ -1,9 +1,10 @@ #!/bin/bash -# This work only for LXC-Container NOT for HOST or VM -VERSION="1.7.1" +################# +# Update-Extras # +################# -CONFIG_FILE="/root/Proxmox-Updater/update.conf" +VERSION="1.7.5" # Variables CONFIG_FILE="/root/Proxmox-Updater/update.conf" @@ -77,17 +78,29 @@ fi # Docker-Compose if [[ -f "/usr/local/bin/docker-compose" && $DOCKER_COMPOSE == true ]]; then - echo -e "\n*** Updating Docker-Compose ***\n" - # Update - echo "*** Update/Upgrade ***" - systemctl restart docker.service - COMPOSE=$(find / -name docker-compose.yaml 2> /dev/null | rev | cut -c 21- | rev) + COMPOSE=$(find /home -name "docker-compose.*" 2> /dev/null | rev | cut -c 20- | rev) cd "$COMPOSE" || exit - /usr/local/bin/docker-compose up --force-recreate --build -d + echo -e "\n*** Updating Docker-Compose ***\n" + # Get the containers from first argument, else get all containers + CONTAINER_LIST="${1:-$(docker ps -q)}" + for CONTAINER in ${CONTAINER_LIST}; do + # Get requirements + CONTAINER_IMAGE=$(docker inspect --format "{{.Config.Image}}" --type container "${CONTAINER}") + RUNNING_IMAGE=$(docker inspect --format "{{.Image}}" --type container "${CONTAINER}") + NAME=$(docker inspect --format "{{.Name}}" --type container "${CONTAINER}" | cut -c 2-) + # Pull in latest version of the container and get the hash + docker pull "${CONTAINER_IMAGE}" 2> /dev/null + LATEST_IMAGE=$(docker inspect --format "{{.Id}}" --type image "${CONTAINER_IMAGE}") + # Restart the container if the image is different by name + if [[ ${RUNNING_IMAGE} != "${LATEST_IMAGE}" ]]; then + echo "Updating ${CONTAINER} image ${CONTAINER_IMAGE}" + /usr/local/bin/docker-compose up -d --no-deps --build "$NAME" + fi + done # Cleaning - echo -e "*** Cleaning *** (disabled during beta)" -# docker container prune -f -# docker system prune -a -f -# docker image prune -f -# docker system prune --volumes -f + echo -e "\n*** Cleaning ***" + docker container prune -f + docker system prune -a -f + docker image prune -f + docker system prune --volumes -f fi diff --git a/update.conf b/update.conf index 4ed670d..54b21bd 100644 --- a/update.conf +++ b/update.conf @@ -33,9 +33,10 @@ DOCKER_COMPOSE="true" ################################################ # Only/Exclude LXC and/or VM # -# Example: ONLY="100 110 120" # +# Example: ONLY/EXCLUDE="100 110 120" # +################################################ +# ! If 'ONLY' is set, 'EXCLUDE' don't work ! # ################################################ -ONLY="" <--- Not working for now -# 'EXCLUDE' don't work, if 'ONLY' is set +ONLY="" EXCLUDE="" diff --git a/update.sh b/update.sh index 9f1aa4f..18238e8 100644 --- a/update.sh +++ b/update.sh @@ -1,13 +1,15 @@ #!/bin/bash -# https://github.com/BassT23/Proxmox -# Variable / Function -LOG_FILE=/var/log/update-$HOSTNAME.log # <- change location for logfile if you want -VERSION="3.6" +########## +# Update # +########## -SERVER_URL="https://raw.githubusercontent.com/BassT23/Proxmox/master" +VERSION="3.7" +# Variable / Function +LOG_FILE=/var/log/update-$HOSTNAME.log # <- change location for logfile if you want CONFIG_FILE="/root/Proxmox-Updater/update.conf" +SERVER_URL="https://raw.githubusercontent.com/BassT23/Proxmox/master" # Colors BL="\e[36m" @@ -56,19 +58,19 @@ function CHECK_ROOT { # Usage function USAGE { if [[ $HEADLESS != true ]]; then - echo -e "\nUsage: $0 [OPTIONS...] {COMMAND}\n" - echo -e "[OPTIONS] Manages the Proxmox-Updater:" - echo -e "======================================" - echo -e " -s --silent Silent / Headless Mode\n" - echo -e "{COMMAND}:" - echo -e "=========" - echo -e " -h --help Show this help" - echo -e " -v --version Show Proxmox-Updater Version" - echo -e " -up Update Proxmox-Updater" - echo -e " uninstall Uninstall Proxmox-Updater\n" - echo -e " host Host-Mode" - echo -e " cluster Cluster-Mode\n" - echo -e "Report issues at: \n" + echo -e "\nUsage: $0 [OPTIONS...] {COMMAND}\n" + echo -e "[OPTIONS] Manages the Proxmox-Updater:" + echo -e "======================================" + echo -e " -s --silent Silent / Headless Mode\n" + echo -e "{COMMAND}:" + echo -e "=========" + echo -e " -h --help Show this help" + echo -e " -v --version Show Proxmox-Updater Version" + echo -e " -up Update Proxmox-Updater" + echo -e " uninstall Uninstall Proxmox-Updater\n" + echo -e " host Host-Mode" + echo -e " cluster Cluster-Mode\n" + echo -e "Report issues at: \n" fi } @@ -121,7 +123,7 @@ function READ_WRITE_CONFIG { STOPPED=$(awk -F'"' '/^STOPPED_CONTAINER=/ {print $2}' $CONFIG_FILE) EXTRA_IN_HEADLESS=$(awk -F'"' '/^IN_HEADLESS_MODE=/ {print $2}' $CONFIG_FILE) EXCLUDED=$(awk -F'"' '/^EXCLUDE=/ {print $2}' $CONFIG_FILE) - ONLY=$(awk -F'"' '/^Only=/ {print $2}' $CONFIG_FILE) + ONLY=$(awk -F'"' '/^ONLY=/ {print $2}' $CONFIG_FILE) } # Extras @@ -134,7 +136,7 @@ function EXTRAS { pct exec "$CONTAINER" -- bash -c "chmod +x /root/Proxmox-Updater/update-extras.sh && \ /root/Proxmox-Updater/update-extras.sh && \ rm -rf /root/Proxmox-Updater" - echo -e "${GN}--- Finished extra updates ---${CL}\n" + echo -e "${GN}--- Finished extra updates ---${CL}\n" if [[ $WILL_STOP != true ]]; then echo; fi else echo -e "${OR}--- Skip Extra Updates because of Headless Mode or user settings ---${CL}\n\n" @@ -183,7 +185,9 @@ function CONTAINER_UPDATE_START { CONTAINERS=$(pct list | tail -n +2 | cut -f1 -d' ') # Loop through the containers for CONTAINER in $CONTAINERS; do - if [[ $EXCLUDED =~ $CONTAINER ]]; then + if [[ $ONLY == "" && $EXCLUDED =~ $CONTAINER ]]; then + echo -e "${BL}[Info] Skipped LXC $CONTAINER by user${CL}\n\n" + elif [[ $ONLY != "" ]] && ! [[ $ONLY =~ $CONTAINER ]]; then echo -e "${BL}[Info] Skipped LXC $CONTAINER by user${CL}\n\n" else STATUS=$(pct status "$CONTAINER") @@ -210,10 +214,14 @@ function CONTAINER_UPDATE_START { # Container Update function UPDATE_CONTAINER { CONTAINER=$1 - NAME=$(pct exec "$CONTAINER" hostname) - echo -e "${BL}[Info]${GN} Updating LXC ${BL}$CONTAINER${CL} : ${GN}$NAME${CL}\n" pct config "$CONTAINER" > temp OS=$(awk '/^ostype/' temp | cut -d' ' -f2) + if [[ $OS =~ centos ]]; then + NAME=$(pct exec "$CONTAINER" hostnamectl | grep 'hostname' | tail -n +2 | rev |cut -c -11 | rev) + else + NAME=$(pct exec "$CONTAINER" hostname) + fi + echo -e "${BL}[Info]${GN} Updating LXC ${BL}$CONTAINER${CL} : ${GN}$NAME${CL}\n" if [[ $OS =~ ubuntu ]] || [[ $OS =~ debian ]] || [[ $OS =~ devuan ]]; then echo -e "${OR}--- APT UPDATE ---${CL}" pct exec "$CONTAINER" -- bash -c "apt-get update" @@ -228,25 +236,26 @@ function UPDATE_CONTAINER { pct exec "$CONTAINER" -- bash -c "apt-get --purge autoremove -y" EXTRAS elif [[ $OS =~ fedora ]]; then - echo -e "${OR}--- DNF UPDATE ---${CL}" - pct exec "$CONTAINER" -- bash -c "dnf -y update" - echo -e "\n${OR}--- DNF UPGRATE ---${CL}" - pct exec "$CONTAINER" -- bash -c "dnf -y upgrade" - echo -e "\n${OR}--- DNF CLEANING ---${CL}" - pct exec "$CONTAINER" -- bash -c "dnf -y --purge autoremove" - EXTRAS + echo -e "${OR}--- DNF UPDATE ---${CL}" + pct exec "$CONTAINER" -- bash -c "dnf -y update" + echo -e "\n${OR}--- DNF UPGRATE ---${CL}" + pct exec "$CONTAINER" -- bash -c "dnf -y upgrade" + echo -e "\n${OR}--- DNF CLEANING ---${CL}" + pct exec "$CONTAINER" -- bash -c "dnf -y autoremove" + EXTRAS elif [[ $OS =~ archlinux ]]; then - echo -e "${OR}--- PACMAN UPDATE ---${CL}" - pct exec "$CONTAINER" -- bash -c "pacman -Syyu --noconfirm" - EXTRAS + echo -e "${OR}--- PACMAN UPDATE ---${CL}" + pct exec "$CONTAINER" -- bash -c "pacman -Syyu --noconfirm" + EXTRAS elif [[ $OS =~ alpine ]]; then - echo -e "${OR}--- APK UPDATE ---${CL}" - pct exec "$CONTAINER" -- ash -c "apk -U upgrade" - EXTRAS + echo -e "${OR}--- APK UPDATE ---${CL}" + pct exec "$CONTAINER" -- ash -c "apk -U upgrade" + if [[ $WILL_STOP != true ]]; then echo; fi + echo else - echo -e "\n${OR}--- YUM UPDATE ---${CL}" - pct exec "$CONTAINER" -- bash -c "yum -y update" - EXTRAS + echo -e "${OR}--- YUM UPDATE ---${CL}" + pct exec "$CONTAINER" -- bash -c "yum -y update" + EXTRAS fi } @@ -258,10 +267,13 @@ function VM_UPDATE_START { # Loop through the VMs for VM in $VMS; do PRE_OS=$(qm config "$VM" | grep 'ostype:' | sed 's/ostype:\s*//') - if [[ $EXCLUDED =~ $VM ]]; then + if [[ $ONLY == "" && $EXCLUDED =~ $VM ]]; then + echo -e "${BL}[Info] Skipped VM $VM by user${CL}\n\n" + elif [[ $ONLY != "" ]] && ! [[ $ONLY =~ $VM ]]; then echo -e "${BL}[Info] Skipped VM $VM by user${CL}\n\n" elif [[ $PRE_OS =~ w ]]; then echo -e "${RD} Windows is not supported for now.\n Maybe with later version ;)${CL}\n\n" + # Install-WindowsUpdate -MicrosoftUpdate -AcceptAll -AutoReboot else STATUS=$(qm status "$VM") if [[ $STATUS == "status: stopped" && $STOPPED == true ]]; then @@ -271,8 +283,8 @@ function VM_UPDATE_START { qm set "$VM" --agent 1 >/dev/null 2>&1 qm start "$VM" >/dev/null 2>&1 echo -e "${BL}[Info]${GN} Waiting for VM${BL} $VM${CL}${GN} to start${CL}" - echo -e "${OR}This will take some time, ... 30 secounds is set!${CL}" - sleep 30 + echo -e "${OR}This will take some time, ... 45 secounds is set!${CL}" + sleep 45 UPDATE_VM "$VM" # Stop the VM echo -e "${BL}[Info]${GN} Shutting down VM${BL} $VM ${CL}\n\n" @@ -289,34 +301,35 @@ function VM_UPDATE_START { function UPDATE_VM { VM=$1 if qm guest exec "$VM" test >/dev/null 2>&1; then - VM_NAME=$(qm config "$VM" | grep 'name:' | sed 's/name:\s*//') - echo -e "${BL}[Info]${GN} Updating VM ${BL}$VM${CL} : ${GN}$VM_NAME${CL}\n" + NAME=$(qm config "$VM" | grep 'name:' | sed 's/name:\s*//') + echo -e "${BL}[Info]${GN} Updating VM ${BL}$VM${CL} : ${GN}$NAME${CL}\n" OS=$(qm guest cmd "$VM" get-osinfo | grep name) if [[ $OS =~ Ubuntu ]] || [[ $OS =~ Debian ]] || [[ $OS =~ Devuan ]]; then echo -e "${OR}--- APT UPDATE ---${CL}" - qm guest exec "$VM" --timeout 60 -- bash -c "apt-get update" | tail -n +4 | head -n -1 | cut -c 17- + qm guest exec "$VM" -- bash -c "apt-get update" | tail -n +4 | head -n -1 | cut -c 17- echo -e "\n${OR}--- APT UPGRADE ---${CL}" - qm guest exec "$VM" --timeout 600 -- bash -c "apt-get -o APT::Get::Always-Include-Phased-Updates=true upgrade -y" | tail -n +4 | head -n -1 | cut -c 17- + qm guest exec "$VM" --timeout 120 -- bash -c "apt-get -o APT::Get::Always-Include-Phased-Updates=true upgrade -y" | tail -n +2 | head -n -1 echo -e "\n${OR}--- APT CLEANING ---${CL}" - qm guest exec "$VM" --timeout 60 -- bash -c "apt-get --purge autoremove -y" | tail -n +4 | head -n -1 | cut -c 17- + qm guest exec "$VM" -- bash -c "apt-get --purge autoremove -y" | tail -n +4 | head -n -1 | cut -c 17- elif [[ $OS =~ Fedora ]]; then echo -e "${OR}--- DNF UPDATE ---${CL}" - qm guest exec "$VM" --timeout 60 -- bash -c "dnf -y update && echo" | tail -n +4 | head -n -1 | cut -c 17- + qm guest exec "$VM" -- bash -c "dnf -y update && echo" | tail -n +4 | head -n -1 | cut -c 17- echo -e "\n${OR}--- DNF UPGRATE ---${CL}" - qm guest exec "$VM" --timeout 600 -- bash -c "dnf -y upgrade && echo" | tail -n +4 | head -n -1 | cut -c 17- + qm guest exec "$VM" -- bash -c "dnf -y upgrade && echo" | tail -n +2 | head -n -1 echo -e "\n${OR}--- DNF CLEANING ---${CL}" - qm guest exec "$VM" --timeout 60 -- bash -c "dnf -y --purge autoremove && echo" | tail -n +4 | head -n -1 | cut -c 17- + qm guest exec "$VM" -- bash -c "dnf -y --purge autoremove && echo" | tail -n +4 | head -n -1 | cut -c 17- elif [[ $OS =~ Arch ]]; then echo -e "${OR}--- PACMAN UPDATE ---${CL}" - qm guest exec "$VM" --timeout 360 -- bash -c "pacman -Syyu --noconfirm" | tail -n +4 | head -n -1 | cut -c 17- + qm guest exec "$VM" -- bash -c "pacman -Syyu --noconfirm" | tail -n +2 | head -n -1 elif [[ $OS =~ Alpine ]]; then echo -e "${OR}--- APK UPDATE ---${CL}" - qm guest exec "$VM" --timeout 360 -- ash -c "apk -U upgrade" | tail -n +4 | head -n -1 | cut -c 17- + qm guest exec "$VM" -- ash -c "apk -U upgrade" | tail -n +2 | head -n -1 elif [[ $OS =~ CentOS ]]; then echo -e "${OR}--- YUM UPDATE ---${CL}" - qm guest exec "$VM" --timeout 360 -- bash -c "yum -y update" | tail -n +4 | head -n -1 | cut -c 17- + qm guest exec "$VM" -- bash -c "yum -y update" | tail -n +2 | head -n -1 else echo -e "${RD} System is not supported.\n Maybe with later version ;)\n${CL}" + echo -e " If you want, make a request here: \n" fi echo if [[ $WILL_STOP != true ]]; then echo; fi @@ -353,9 +366,14 @@ function EXIT { # Update Finish elif [[ $EXIT_CODE == 0 ]]; then if [[ $RICM != true ]]; then - echo -e "${GN}Finished, All Containers Updated.${CL}\n" + echo -e "${GN}Finished, All Updates Done.${CL}\n" /root/Proxmox-Updater/exit/passed.sh CLEAN_LOGFILE + if [[ -f /etc/update-motd.d/01-welcome-screen ]]; then + echo -e "${OR}Check Updates for Welcome-Screen${CL}\n\ +This will take some time. Please wait.\n" + /root/Proxmox-Updater/check-updates.sh + fi fi # Update Error else @@ -375,6 +393,9 @@ trap EXIT EXIT # Check Cluster Mode if [[ -f /etc/corosync/corosync.conf ]]; then HOSTS=$(awk '/ring0_addr/{print $2}' "/etc/corosync/corosync.conf") + MODE=" Cluster" +else + MODE=" Host " fi # Update Start @@ -439,7 +460,6 @@ parse_cli() parse_cli "$@" # Run without commands (Automatic Mode) -if [[ -f /etc/corosync/corosync.conf ]]; then MODE=" Cluster"; else MODE=" Host "; fi if [[ $COMMAND != true ]]; then HEADER_INFO if [[ $MODE =~ Cluster ]]; then HOST_UPDATE_START; else diff --git a/welcome-screen.sh b/welcome-screen.sh new file mode 100644 index 0000000..e13a66a --- /dev/null +++ b/welcome-screen.sh @@ -0,0 +1,85 @@ +#!/bin/bash + +################## +# Welcome-Screen # +################## + +VERSION="1.2.1" + +# Variable / Function +CONFIG_FILE="/root/Proxmox-Updater/update.conf" +CHECK_OUTPUT=$(stat -c%s /root/Proxmox-Updater/check-output) +SERVER_URL="https://raw.githubusercontent.com/BassT23/Proxmox/master" + +# Colors +# BL="\e[36m" +OR="\e[1;33m" +RD="\e[1;91m" +GN="\e[1;92m" +CL="\e[0m" + +# Version Check +function VERSION_CHECK { + curl -s $SERVER_URL/update.sh > /root/update.sh + SERVER_VERSION=$(awk -F'"' '/^VERSION=/ {print $2}' /root/update.sh) + LOCAL_VERSION=$(awk -F'"' '/^VERSION=/ {print $2}' /usr/local/bin/update) + if [[ $LOCAL_VERSION != "$SERVER_VERSION" ]]; then + echo -e "${RD} *** A newer version of Proxmox-Updater is available ***${CL}\n \ + Installed: $LOCAL_VERSION / Server: $SERVER_VERSION\n \ + ${OR}Update with ${CL}\n" + else + echo -e " ${GN}Proxmox-Updater is UpToDate${CL}\n \ + Version: $LOCAL_VERSION\n" + fi + rm -rf /root/update.sh +} + +function READ_WRITE_CONFIG { +# CHECK_VERSION=$(awk -F'"' '/^VERSION_CHECK=/ {print $2}' $CONFIG_FILE) + WITH_HOST=$(awk -F'"' '/^WITH_HOST=/ {print $2}' $CONFIG_FILE) + WITH_LXC=$(awk -F'"' '/^WITH_LXC=/ {print $2}' $CONFIG_FILE) + WITH_VM=$(awk -F'"' '/^WITH_VM=/ {print $2}' $CONFIG_FILE) + RUNNING=$(awk -F'"' '/^RUNNING_CONTAINER=/ {print $2}' $CONFIG_FILE) + STOPPED=$(awk -F'"' '/^STOPPED_CONTAINER=/ {print $2}' $CONFIG_FILE) + EXCLUDED=$(awk -F'"' '/^EXCLUDE=/ {print $2}' $CONFIG_FILE) + ONLY=$(awk -F'"' '/^ONLY=/ {print $2}' $CONFIG_FILE) + if [[ $ONLY == "" && $EXCLUDED != "" ]]; then + echo -e "${OR}Exclude is set. Not all machines were checked.${CL}\n" + elif [[ $ONLY != "" ]]; then + echo -e "${OR}Only is set. Not all machines were checked.${CL}\n" + elif [[ $WITH_HOST != true || $WITH_LXC != true || $WITH_VM != true ||$RUNNING != true || $STOPPED != true ]]; then + echo -e "${OR}Variable is set in config file. One or more machines will not be checked!${CL}\n" + fi +} + +function TIME_CALCULTION { +MOD=$(date -r "/root/Proxmox-Updater/check-output" +%s) +# convert seconds to Days, Hours, Minutes +NOW=$(date +%s) +DAYS=$(expr \( "$NOW" - "$MOD" \) / 86400) +HOURS=$(expr \( "$NOW" - "$MOD" \) / 1440) +MINUTES=$(expr \( "$NOW" - "$MOD" \) / 60) +} + +# Welcome +echo +neofetch +VERSION_CHECK +READ_WRITE_CONFIG +TIME_CALCULTION +if [[ $DAYS -gt 1 ]]; then + echo -e " Last Update Check: $DAYS day(s) ago\n" +elif [[ $HOURS -gt 1 ]]; then + echo -e " Last Update Check: $HOURS hour(s) ago\n" +else + echo -e " Last Update Check: $MINUTES minute(s) ago\n" +fi +#echo -e "Time since last update check (D:H:M): $DAYS:$HOURS:$MINUTES\n" +if [[ -f /root/Proxmox-Updater/check-output ]] && [[ $CHECK_OUTPUT -gt 0 ]]; then + echo -e "${OR}Available Updates:${CL}" + echo -e "S = Security / N = Normal" + cat /root/Proxmox-Updater/check-output + echo +fi + +exit 0