Skip to content

Commit be697bd

Browse files
authored
Merge pull request #232 from BassT23/beta
v4.5 release
2 parents 9f369b2 + 64c7f48 commit be697bd

File tree

11 files changed

+810
-345
lines changed

11 files changed

+810
-345
lines changed

.github/workflows/linting.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55
branches: [master, beta, develop]
66
pull_request:
77
branches: [master, beta, develop]
8-
schedule:
8+
# schedule:
99

1010
permissions: {}
1111

README.md

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,15 @@ I am no member of the Proxmox Server Solutions GmbH. This is not an official pro
3737

3838
### Features:
3939
- Update Proxmox VE (the host / all cluster nodes / all included LXCs and VMs)
40+
- LXC distriburion upgrade (deb12 -> deb13) with `update -dist-upgrade`
4041
- Snapshot / Backup support (for Snapshot, your system must prepared for it)
4142
- Normal run is "Interactive" / Headless Mode can be run with `update -s`
4243
- Logging - location can be change in config file
4344
- Exit tracking, so you can send additional commands for finish or failure (edit files in `/etc/ultimate-updater/exit`)
4445
- [Config file](https://github.com/BassT23/Proxmox/tree/master#config-file)
45-
- Trim filesystem on ext4 nodes -
46+
- [Use TAG/ID/Range](https://github.com/BassT23/Proxmox/tree/beta#new-onlyexclude-handling-in-config-file) for "Only" / "Exclude" LXC/VM
47+
- send email after update/check
48+
- Trim filesystem on ext4 nodes
4649

4750
Info can be found with `update -h`
4851

@@ -107,7 +110,35 @@ With this file, you can manage the updater. For example; if you don't want to up
107110
- Headless Mode
108111
- Extra updates
109112
- "stopped" or "running" LXC/VM
110-
- "only" or "exclude" LXC/VM by ID
113+
- "only" or "exclude" LXC/VM - see below
114+
115+
# New Only/Exclude handling in config file:
116+
Expands ONLY/EXCLUDE into a space-separated list of numeric VMIDs.
117+
Supports:
118+
- Plain VMIDs: 101 202
119+
- Delimiters: commas / semicolons / pipes / spaces intermixed (e.g. 101,202;203|204)
120+
- Ranges: 120-125 (inclusive)
121+
- Mixed IDs + ranges + tags: 110 testing 111 200-202
122+
- Uppercase user tag input (config tags assumed already lowercase)
123+
Tag tokens are any token not matching ^[0-9]+$ or ^[0-9]+-[0-9]+$.
124+
- OR matching across tag tokens.
125+
126+
Behavior summary:
127+
1. Tokenize ONLY if set/matched; else tokenized EXCLUDE.
128+
2. For each token:
129+
number -> add as VMID
130+
range a-b -> expand (a..b)
131+
tag -> collect tag for later resolution
132+
3. Resolve tags to IDs (any tag match) and append, de-duplicating while
133+
preserving first-seen order (input order then discovery order for tags).
134+
4. Assign final space-separated list back to ONLY / EXCLUDE variable.
135+
5. If ONLY provided, EXCLUDE is ignored.
136+
137+
Usage examples:
138+
- ONLY="backup,windows"
139+
- ONLY="101,102,105-107"
140+
- ONLY="110 testtag 111 120-121"
141+
- ONLY="" EXCLUDE="old 300-302"
111142

112143
# Extra Updates:
113144
If updater detects installation: (disable, if you want in `/etc/ultimate-updater/update.conf`)
@@ -117,7 +148,7 @@ If updater detects installation: (disable, if you want in `/etc/ultimate-updater
117148
- Octoprint
118149
- Docker Compose (v1 and v2)
119150

120-
# User scripts
151+
# User scripts:
121152
How to use user scripts:
122153

123154
In "/etc/ultimate-updater/scripts.d" create an folder for each LXC/VM who should use it like this:
@@ -136,7 +167,7 @@ The Welcome Screen is an extra for you. It's optional!
136167
- 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).
137168
- The update-checker also uses the config file!
138169
- To force the check, you can run `/etc/ultimate-updater/check-updates.sh` in Terminal.
139-
- You can choose, if neofetch will be show also (if neofetch is not installed, script will make it automatically)
170+
- You can choose, if screenfetch will be show also (if screenfetch is not installed, script will make it automatically)
140171

141172
# Beta Testing:
142173
If anybody wants to help with failure search, please test our beta (if available).

change.log

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
11
Changelog:
22
==========
33

4+
**v4.5** (22.08.2025)
5+
- add LXC debian trixie upgrade (`update -dist-upgrade`)
6+
- "only" or "exclude" LXC/VM by ID/TAG/range #thx to @AdamSutch
7+
- add debug mode (can be enabled in config file)
8+
- add check-updates command `update -check`
9+
- add email notification after update
10+
- add better email notification for update-check
11+
- add more symbolic
12+
- add LXC template detection
13+
- check "paused" VMs during update-check and bring them back in pause
14+
- fix #203 Error on apt clean
15+
- fix unsupported neofetch under trixie - change to screenfetch
16+
- fix #201 (abbort after template detection)
17+
- fix VM ID in error-log-file
18+
- fix shell check
19+
- fix typo
20+
- code cleaning
21+
422
**v4.4** (10.05.2025)
523
- add symbolic
624
- add user scripts folder
@@ -10,7 +28,7 @@ Changelog:
1028
- fix docker-compose v2 skipping
1129
- fix YUM Update - used now only for centos
1230
- fix VM shutdown errors
13-
- FreeBSD is disabled by default in config file
31+
- FreeBSD is disabled by default - in config file
1432
- modify "update <ID>" - disable skip output
1533
- code cleaning
1634

check-updates.sh

Lines changed: 93 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@
44
# Check Updates #
55
#################
66

7-
# shellcheck disable=SC1017
87
# shellcheck disable=SC2034
98

10-
VERSION="1.7"
9+
VERSION="1.7.7"
1110

1211
#Variable / Function
1312
LOCAL_FILES="/etc/ultimate-updater"
1413
CONFIG_FILE="$LOCAL_FILES/update.conf"
1514

15+
# Tag filter
16+
# shellcheck disable=SC1091
17+
. "$LOCAL_FILES/tag-filter.sh"
18+
1619
# Colors
1720
BL="\e[36m"
1821
OR="\e[1;33m"
@@ -21,7 +24,8 @@ GN="\e[1;92m"
2124
CL="\e[0m"
2225

2326
ARGUMENTS () {
24-
while test $# -gt -0; do
27+
local ARGUMENT
28+
while [ $# -gt 0 ]; do
2529
ARGUMENT="$1"
2630
case "$ARGUMENT" in
2731
-c)
@@ -80,13 +84,21 @@ USAGE () {
8084

8185
READ_WRITE_CONFIG () {
8286
SSH_PORT=$(awk -F'"' '/^SSH_PORT=/ {print $2}' $CONFIG_FILE)
87+
EMAIL_USER=$(awk -F'"' '/^EMAIL_USER=/ {print $2}' $CONFIG_FILE)
8388
WITH_HOST=$(awk -F'"' '/^CHECK_WITH_HOST=/ {print $2}' $CONFIG_FILE)
8489
WITH_LXC=$(awk -F'"' '/^CHECK_WITH_LXC=/ {print $2}' $CONFIG_FILE)
8590
WITH_VM=$(awk -F'"' '/^CHECK_WITH_VM=/ {print $2}' $CONFIG_FILE)
8691
RUNNING=$(awk -F'"' '/^CHECK_RUNNING_CONTAINER=/ {print $2}' $CONFIG_FILE)
8792
STOPPED=$(awk -F'"' '/^CHECK_STOPPED_CONTAINER=/ {print $2}' $CONFIG_FILE)
93+
RUNNING_VM=$(awk -F'"' '/^CHECK_RUNNING_VM=/ {print $2}' $CONFIG_FILE)
94+
STOPPED_VM=$(awk -F'"' '/^CHECK_STOPPED_VM=/ {print $2}' $CONFIG_FILE)
95+
PAUSED_VM=$(awk -F'"' '/^CHECK_PAUSED_VM=/ {print $2}' $CONFIG_FILE)
8896
EXCLUDED=$(awk -F'"' '/^EXCLUDE_UPDATE_CHECK=/ {print $2}' $CONFIG_FILE)
8997
ONLY=$(awk -F'"' '/^ONLY_UPDATE_CHECK=/ {print $2}' $CONFIG_FILE)
98+
CHECK_URL=$(awk -F '"' '/^URL_FOR_INTERNET_CHECK=/ {print $2}' $CONFIG_FILE)
99+
if declare -f apply_only_exclude_tags >/dev/null 2>&1; then
100+
apply_only_exclude_tags ONLY EXCLUDED
101+
fi
90102
}
91103

92104
## HOST ##
@@ -135,6 +147,8 @@ CONTAINER_CHECK_START () {
135147
continue
136148
elif [[ "$ONLY" != "" ]] && ! [[ "$ONLY" =~ $CONTAINER ]]; then
137149
continue
150+
elif (pct config "$CONTAINER" | grep template >/dev/null 2>&1); then
151+
continue
138152
else
139153
STATUS=$(pct status "$CONTAINER")
140154
if [[ "$STATUS" == "status: stopped" && "$STOPPED" == true ]]; then
@@ -164,9 +178,9 @@ CHECK_CONTAINER () {
164178
NAME=$(pct exec "$CONTAINER" hostname)
165179
if [[ "$OS" =~ ubuntu ]] || [[ "$OS" =~ debian ]] || [[ "$OS" =~ devuan ]]; then
166180
pct exec "$CONTAINER" -- bash -c "apt-get update" >/dev/null 2>&1
167-
SECURITY_APT_UPDATES=$(pct exec "$CONTAINER" -- bash -c "apt-get -s upgrade | grep -ci ^inst.*security | tr -d '\n'")
168-
NORMAL_APT_UPDATES=$(pct exec "$CONTAINER" -- bash -c "apt-get -s upgrade | grep -ci ^inst. | tr -d '\n'")
169-
# NOT_INSTALLED=$(apt-get -s upgrade | grep -ci "^inst.*not")
181+
APT_OUTPUT=$(pct exec "$CONTAINER" -- bash -c "apt-get -s upgrade")
182+
SECURITY_APT_UPDATES=$(echo "$APT_OUTPUT" | grep -ci '^inst.*security' || true)
183+
NORMAL_APT_UPDATES=$(echo "$APT_OUTPUT" | grep -ci '^inst.' || true)
170184
if [[ "$SECURITY_APT_UPDATES" -gt 0 || "$NORMAL_APT_UPDATES" != 0 ]]; then
171185
echo -e "${GN}LXC ${BL}$CONTAINER${CL} : ${GN}$NAME${CL}"
172186
fi
@@ -208,29 +222,44 @@ CHECK_CONTAINER () {
208222
VM_CHECK_START () {
209223
# Get the list of VMs
210224
VMS=$(qm list | tail -n +2 | cut -c -10)
211-
# Loop through the VMs
225+
# Loop through VMs
212226
for VM in $VMS; do
213-
PRE_OS=$(qm config "$VM" | grep 'ostype:' | sed 's/ostype:\s*//')
214-
if [[ "$ONLY" == "" && "$EXCLUDED" =~ $VM ]]; then
215-
continue
216-
elif [[ "$ONLY" != "" ]] && ! [[ "$ONLY" =~ $VM ]]; then
217-
continue
218-
elif [[ "$PRE_OS" =~ w ]]; then
219-
continue
220-
else
221-
STATUS=$(qm status "$VM")
222-
if [[ "$STATUS" == "status: stopped" && "$STOPPED" == true ]]; then
223-
# Check if connection is available
224-
if [[ $(qm config "$VM" | grep 'agent:' | sed 's/agent:\s*//') == 1 ]] || [[ -f $LOCAL_FILES/VMs/"$VM" ]]; then
225-
# Start the VM
227+
# Check if connection is available
228+
if [[ $(qm config "$VM" | grep 'agent:' | sed 's/agent:\s*//') == 1 ]] || [[ -f $LOCAL_FILES/VMs/"$VM" ]]; then
229+
# Check VM
230+
PRE_OS=$(qm config "$VM" | grep 'ostype:' | sed 's/ostype:\s*//')
231+
if [[ "$ONLY" == "" && "$EXCLUDED" =~ $VM ]]; then
232+
continue
233+
elif [[ "$ONLY" != "" ]] && ! [[ "$ONLY" =~ $VM ]]; then
234+
continue
235+
elif [[ "$PRE_OS" =~ w ]]; then
236+
continue
237+
else
238+
STATUS=$(qm status "$VM")
239+
if [[ "$STATUS" == "status: stopped" && "$STOPPED_VM" == true ]]; then
240+
# Check suspend mode
241+
if [[ $(qm config "$VM" | grep 'lock:' | sed 's/lock:\s*//') == "suspend" ]]; then
242+
SUSPEND=true
243+
echo -e "${OR}skip suspend VM${CL}"
244+
continue
245+
fi
246+
# Start VM
226247
qm start "$VM" >/dev/null 2>&1
227248
sleep 45
228249
CHECK_VM "$VM"
229-
# Stop the VM
250+
# Stop/Suspend VM
230251
qm stop "$VM"
252+
SUSPEND=
253+
elif [[ "$STATUS" == "status: paused" && "$PAUSED_VM" == true ]]; then
254+
# Start VM
255+
qm resume "$VM" >/dev/null 2>&1
256+
sleep 45
257+
CHECK_VM "$VM"
258+
# Suspend VM
259+
qm suspend "$VM"
260+
elif [[ "$STATUS" == "status: running" && "$RUNNING_VM" == true ]]; then
261+
CHECK_VM "$VM"
231262
fi
232-
elif [[ "$STATUS" == "status: running" && "$RUNNING" == true ]]; then
233-
CHECK_VM "$VM"
234263
fi
235264
fi
236265
done
@@ -259,8 +288,9 @@ CHECK_VM () {
259288
# fi
260289
if [[ "$OS" =~ Ubuntu ]] || [[ "$OS" =~ Debian ]] || [[ "$OS" =~ Devuan ]]; then
261290
ssh "$IP" "apt-get update" >/dev/null 2>&1
262-
SECURITY_APT_UPDATES=$(ssh "$IP" "apt-get -s upgrade | grep -ci ^inst.*security")
263-
NORMAL_APT_UPDATES=$(ssh "$IP" "apt-get -s upgrade | grep -ci ^inst.")
291+
APT_OUTPUT=$(ssh "$IP" "apt-get -s upgrade")
292+
SECURITY_APT_UPDATES=$(echo "$APT_OUTPUT" | grep -ci '^inst.*security')
293+
NORMAL_APT_UPDATES=$(echo "$APT_OUTPUT" | grep -ci '^inst.')
264294
if ssh "$IP" stat /var/run/reboot-required.pkgs \> /dev/null 2\>\&1; then REBOOT_REQUIRED=true; fi
265295
if [[ "$SECURITY_APT_UPDATES" -gt 0 || "$NORMAL_APT_UPDATES" -gt 0 || "$REBOOT_REQUIRED" == true ]]; then
266296
echo -e "${GN}VM ${BL}$VM${CL} : ${GN}$NAME${CL}"
@@ -356,9 +386,40 @@ OUTPUT_TO_FILE () {
356386
if [[ "$RDU" != true && "$RICM" != true ]]; then
357387
touch $LOCAL_FILES/check-output
358388
exec > >(tee $LOCAL_FILES/check-output)
389+
# create mail output file
390+
touch $LOCAL_FILES/mail-output
391+
echo -e "Available Updates:" > $LOCAL_FILES/mail-output
392+
echo -e "S = Security / N = Normal\n" >> $LOCAL_FILES/mail-output
393+
exec > >(tee -a $LOCAL_FILES/mail-output)
359394
fi
360395
}
361396

397+
# Exit
398+
# shellcheck disable=SC2329
399+
EXIT () {
400+
# clean email output file
401+
if [[ "$RDU" != true && "$RICM" != true ]]; then
402+
if [[ -f "$LOCAL_FILES/mail-output" ]]; then
403+
cat "$LOCAL_FILES/mail-output" | sed -r "s/\x1B\[([0-9]{1,3}(;[0-9]{1,3})*)?[mGK]//g" | tee "$LOCAL_FILES/mail-output" >/dev/null 2>&1
404+
chmod 640 "$LOCAL_FILES/mail-output"
405+
if [[ $(stat -c%s "$LOCAL_FILES/mail-output") -gt 46 ]]; then
406+
mail -s "Ultimate Updater summary" "$EMAIL_USER" < "$LOCAL_FILES"/mail-output
407+
else
408+
echo "No updates found during search" | mail -s "Ultimate Updater" root
409+
fi
410+
fi
411+
fi
412+
}
413+
trap EXIT EXIT
414+
415+
# Run
416+
417+
# Debug
418+
DEBUG=$(awk -F'"' '/^DEBUG=/ {print $2}' $CONFIG_FILE)
419+
if [[ "$DEBUG" == true ]]; then
420+
set -x
421+
fi
422+
362423
# Check Cluster Mode
363424
if [[ -f /etc/corosync/corosync.conf ]]; then
364425
HOSTS=$(awk '/ring0_addr/{print $2}' "/etc/corosync/corosync.conf")
@@ -367,10 +428,12 @@ else
367428
MODE="Host"
368429
fi
369430

370-
# Run
371-
if [[ "$(wget -q --spider http://google.com)" -eq 0 ]]; then
372-
READ_WRITE_CONFIG
431+
# Read config
432+
READ_WRITE_CONFIG
433+
if wget -q --spider "$CHECK_URL" >/dev/null 2>&1; then
373434
ARGUMENTS "$@"
435+
# Print any tag selection summary captured during config parse
436+
if [[ "$RDU" != true && "$RICM" != true && "$TAG_OUTPUT" != false ]]; then if declare -f print_tag_log >/dev/null 2>&1; then print_tag_log; fi; fi
374437
else
375438
echo -e "${OR} You are offline${CL}"
376439
exit 2
@@ -379,7 +442,6 @@ fi
379442
# Run without commands (Automatic Mode)
380443
if [[ "$COMMAND" != true && "$RDU" == true ]]; then
381444
OUTPUT_TO_FILE
382-
CHECK_RUNNUNG_MACHINE
383445
elif [[ "$COMMAND" != true ]]; then
384446
OUTPUT_TO_FILE
385447
if [[ "$MODE" =~ Cluster ]]; then HOST_CHECK_START; else
@@ -388,3 +450,5 @@ elif [[ "$COMMAND" != true ]]; then
388450
if [[ "$WITH_VM" == true ]]; then VM_CHECK_START; fi
389451
fi
390452
fi
453+
454+
exit 0

0 commit comments

Comments
 (0)