mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-03-27 20:32:59 +01:00
Compare commits
1 Commits
add-script
...
pr-update-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0db9ad689 |
11
CHANGELOG.md
11
CHANGELOG.md
@@ -428,10 +428,6 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
||||
|
||||
## 2026-03-27
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
- GeoPulse ([#13320](https://github.com/community-scripts/ProxmoxVE/pull/13320))
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
@@ -440,15 +436,8 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- Dispatcharr add custom Postgres port support for upgrade [@MickLesk](https://github.com/MickLesk) ([#13347](https://github.com/community-scripts/ProxmoxVE/pull/13347))
|
||||
- Immich: bump to v2.6.3 [@MickLesk](https://github.com/MickLesk) ([#13324](https://github.com/community-scripts/ProxmoxVE/pull/13324))
|
||||
|
||||
### 🧰 Tools
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- Refactor/Feature-Bump/Security: Update-Cron-LXCs (Now Local Mode!) [@MickLesk](https://github.com/MickLesk) ([#13339](https://github.com/community-scripts/ProxmoxVE/pull/13339))
|
||||
|
||||
## 2026-03-26
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
@@ -70,7 +70,7 @@ function update_script() {
|
||||
source /opt/dispatcharr/.env
|
||||
set +o allexport
|
||||
if [[ -n "$POSTGRES_DB" ]] && [[ -n "$POSTGRES_USER" ]] && [[ -n "$POSTGRES_PASSWORD" ]]; then
|
||||
PGPASSWORD=$POSTGRES_PASSWORD pg_dump -U "$POSTGRES_USER" -h "${POSTGRES_HOST:-localhost}" -p "${POSTGRES_PORT:-5432}" "$POSTGRES_DB" >/tmp/dispatcharr_db_$(date +%F).sql
|
||||
PGPASSWORD=$POSTGRES_PASSWORD pg_dump -U $POSTGRES_USER -h ${POSTGRES_HOST:-localhost} $POSTGRES_DB >/tmp/dispatcharr_db_$(date +%F).sql
|
||||
msg_info "Database backup created"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
|
||||
# Copyright (c) 2021-2026 community-scripts ORG
|
||||
# Author: MickLesk (CanbiZ)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/matter-js/python-matter-server
|
||||
|
||||
APP="Matter-Server"
|
||||
var_tags="${var_tags:-matter;iot;smart-home}"
|
||||
var_cpu="${var_cpu:-2}"
|
||||
var_ram="${var_ram:-2048}"
|
||||
var_disk="${var_disk:-4}"
|
||||
var_os="${var_os:-debian}"
|
||||
var_version="${var_version:-13}"
|
||||
var_unprivileged="${var_unprivileged:-1}"
|
||||
|
||||
header_info "$APP"
|
||||
variables
|
||||
color
|
||||
catch_errors
|
||||
|
||||
function update_script() {
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
|
||||
if [[ ! -d /opt/matter-server ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
if check_for_gh_release "matter-server" "matter-js/python-matter-server"; then
|
||||
msg_info "Stopping Service"
|
||||
systemctl stop matter-server
|
||||
msg_ok "Stopped Service"
|
||||
|
||||
msg_info "Updating Matter Server"
|
||||
MATTER_VERSION=$(get_latest_github_release "matter-js/python-matter-server")
|
||||
$STD uv pip install --python /opt/matter-server/.venv/bin/python --upgrade "python-matter-server[server]==${MATTER_VERSION}"
|
||||
echo "${MATTER_VERSION}" >~/.matter-server
|
||||
msg_ok "Updated Matter Server"
|
||||
|
||||
fetch_and_deploy_gh_release "chip-ota-provider-app" "home-assistant-libs/matter-linux-ota-provider" "singlefile" "latest" "/usr/local/bin" "chip-ota-provider-app-x86-64"
|
||||
|
||||
msg_info "Starting Service"
|
||||
systemctl start matter-server
|
||||
msg_ok "Started Service"
|
||||
msg_ok "Updated successfully!"
|
||||
fi
|
||||
exit
|
||||
}
|
||||
|
||||
start
|
||||
build_container
|
||||
description
|
||||
|
||||
msg_ok "Completed Successfully!\n"
|
||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||
echo -e "${INFO}${YW} Matter Server WebSocket API is running on port 5580.${CL}"
|
||||
echo -e "${TAB}${GATEWAY}${BGN}ws://${IP}:5580/ws${CL}"
|
||||
@@ -28,6 +28,11 @@ function update_script() {
|
||||
exit
|
||||
fi
|
||||
|
||||
if [[ $(grep -E '^VERSION_ID=' /etc/os-release) == *"12"* ]]; then
|
||||
msg_error "Wrong Debian version detected!"
|
||||
msg_error "Please create a snapshot first. You must upgrade your LXC to Debian Trixie before updating. Visit: https://github.com/community-scripts/ProxmoxVE/discussions/7489"
|
||||
exit
|
||||
fi
|
||||
|
||||
if command -v node &>/dev/null; then
|
||||
CURRENT_NODE_VERSION=$(node --version | cut -d'v' -f2 | cut -d'.' -f1)
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2026 community-scripts ORG
|
||||
# Author: MickLesk (CanbiZ)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# Source: https://github.com/matter-js/python-matter-server
|
||||
|
||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
|
||||
color
|
||||
verb_ip6
|
||||
catch_errors
|
||||
setting_up_container
|
||||
network_check
|
||||
update_os
|
||||
|
||||
msg_info "Installing Dependencies"
|
||||
$STD apt install -y \
|
||||
libuv1 \
|
||||
libjson-c5 \
|
||||
libnl-3-200 \
|
||||
libnl-route-3-200 \
|
||||
iputils-ping \
|
||||
iproute2
|
||||
msg_ok "Installed Dependencies"
|
||||
|
||||
UV_PYTHON="3.12" setup_uv
|
||||
|
||||
msg_info "Setting up Matter Server"
|
||||
mkdir -p /opt/matter-server/data/credentials
|
||||
if [ -L /data ]; then
|
||||
rm -f /data
|
||||
fi
|
||||
if [ ! -e /data ]; then
|
||||
ln -s /opt/matter-server/data /data
|
||||
fi
|
||||
$STD uv venv /opt/matter-server/.venv
|
||||
MATTER_VERSION=$(get_latest_github_release "matter-js/python-matter-server")
|
||||
$STD uv pip install --python /opt/matter-server/.venv/bin/python "python-matter-server[server]==${MATTER_VERSION}"
|
||||
echo "${MATTER_VERSION}" >~/.matter-server
|
||||
msg_ok "Set up Matter Server"
|
||||
|
||||
fetch_and_deploy_gh_release "chip-ota-provider-app" "home-assistant-libs/matter-linux-ota-provider" "singlefile" "latest" "/usr/local/bin" "chip-ota-provider-app-x86-64"
|
||||
|
||||
msg_info "Configuring Network"
|
||||
cat <<EOF >/etc/sysctl.d/99-matter.conf
|
||||
net.ipv4.igmp_max_memberships=1024
|
||||
EOF
|
||||
$STD sysctl -p /etc/sysctl.d/99-matter.conf
|
||||
msg_ok "Configured Network"
|
||||
|
||||
msg_info "Creating Service"
|
||||
cat <<EOF >/etc/systemd/system/matter-server.service
|
||||
[Unit]
|
||||
Description=Matter Server
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
ExecStart=/opt/matter-server/.venv/bin/matter-server --storage-path /data --paa-root-cert-dir /data/credentials
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable -q --now matter-server
|
||||
msg_ok "Created Service"
|
||||
|
||||
motd_ssh
|
||||
customize
|
||||
cleanup_lxc
|
||||
@@ -1,24 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2026 community-scripts ORG
|
||||
# Author: MickLesk (CanbiZ)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
#
|
||||
# This script manages a local cron job for automatic LXC container OS updates.
|
||||
# The update script is downloaded once, displayed for review, and installed
|
||||
# locally. Cron runs the local copy — no remote code execution at runtime.
|
||||
#
|
||||
# Copyright (c) 2021-2026 tteck
|
||||
# Author: tteck (tteckster)
|
||||
# License: MIT
|
||||
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
# bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/pve/cron-update-lxcs.sh)"
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main"
|
||||
SCRIPT_URL="${REPO_URL}/tools/pve/update-lxcs-cron.sh"
|
||||
LOCAL_SCRIPT="/usr/local/bin/update-lxcs.sh"
|
||||
CONF_FILE="/etc/update-lxcs.conf"
|
||||
LOG_FILE="/var/log/update-lxcs-cron.log"
|
||||
CRON_ENTRY="0 0 * * 0 ${LOCAL_SCRIPT} >>${LOG_FILE} 2>&1"
|
||||
|
||||
clear
|
||||
cat <<"EOF"
|
||||
______ __ __ __ __ __ _ ________
|
||||
@@ -29,322 +16,41 @@ cat <<"EOF"
|
||||
/_/
|
||||
EOF
|
||||
|
||||
info() { echo -e "\n \e[36m[Info]\e[0m $1"; }
|
||||
ok() { echo -e " \e[32m[OK]\e[0m $1"; }
|
||||
err() { echo -e " \e[31m[Error]\e[0m $1" >&2; }
|
||||
|
||||
confirm() {
|
||||
local prompt="${1:-Proceed?}"
|
||||
add() {
|
||||
while true; do
|
||||
read -rp " ${prompt} (y/n): " yn
|
||||
read -p "This script will add a crontab schedule that updates all LXCs every Sunday at midnight. Proceed(y/n)?" yn
|
||||
case $yn in
|
||||
[Yy]*) return 0 ;;
|
||||
[Nn]*) return 1 ;;
|
||||
*) echo " Please answer yes or no." ;;
|
||||
[Yy]*) break ;;
|
||||
[Nn]*) exit ;;
|
||||
*) echo "Please answer yes or no." ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
download_script() {
|
||||
local tmp
|
||||
tmp=$(mktemp)
|
||||
if ! curl -fsSL -o "$tmp" "$SCRIPT_URL"; then
|
||||
err "Failed to download script from:\n ${SCRIPT_URL}"
|
||||
rm -f "$tmp"
|
||||
return 1
|
||||
fi
|
||||
echo "$tmp"
|
||||
}
|
||||
|
||||
review_script() {
|
||||
local file="$1"
|
||||
local hash
|
||||
hash=$(sha256sum "$file" | awk '{print $1}')
|
||||
echo ""
|
||||
echo -e " \e[1;33m─── Script Content ───────────────────────────────────────────\e[0m"
|
||||
cat "$file"
|
||||
echo -e " \e[1;33m──────────────────────────────────────────────────────────────\e[0m"
|
||||
echo -e " \e[36mSHA256:\e[0m ${hash}"
|
||||
echo -e " \e[36mSource:\e[0m ${SCRIPT_URL}"
|
||||
echo ""
|
||||
}
|
||||
|
||||
remove_legacy_cron() {
|
||||
if crontab -l -u root 2>/dev/null | grep -q "update-lxcs-cron.sh"; then
|
||||
(crontab -l -u root 2>/dev/null | grep -v "update-lxcs-cron.sh") | crontab -u root -
|
||||
ok "Removed legacy curl-based cron entry"
|
||||
fi
|
||||
}
|
||||
|
||||
add() {
|
||||
info "Downloading update script..."
|
||||
local tmp
|
||||
tmp=$(download_script) || exit 1
|
||||
|
||||
local hash
|
||||
hash=$(sha256sum "$tmp" | awk '{print $1}')
|
||||
echo ""
|
||||
echo -e " \e[1;33m─── Installation Summary ─────────────────────────────────────\e[0m"
|
||||
echo -e " \e[36mSource:\e[0m ${SCRIPT_URL}"
|
||||
echo -e " \e[36mSHA256:\e[0m ${hash}"
|
||||
echo -e " \e[36mInstall to:\e[0m ${LOCAL_SCRIPT}"
|
||||
echo -e " \e[36mConfig:\e[0m ${CONF_FILE}"
|
||||
echo -e " \e[36mLog file:\e[0m ${LOG_FILE}"
|
||||
echo -e " \e[36mCron schedule:\e[0m Every Sunday at midnight (0 0 * * 0)"
|
||||
echo -e " \e[1;33m──────────────────────────────────────────────────────────────\e[0m"
|
||||
echo ""
|
||||
|
||||
if confirm "Review script content before installing?"; then
|
||||
review_script "$tmp"
|
||||
fi
|
||||
|
||||
if ! confirm "Install this script and activate cron schedule?"; then
|
||||
rm -f "$tmp"
|
||||
echo " Aborted."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
remove_legacy_cron
|
||||
|
||||
install -m 0755 "$tmp" "$LOCAL_SCRIPT"
|
||||
rm -f "$tmp"
|
||||
ok "Installed script to ${LOCAL_SCRIPT}"
|
||||
|
||||
if [[ ! -f "$CONF_FILE" ]]; then
|
||||
cat >"$CONF_FILE" <<'CONF'
|
||||
# Configuration for automatic LXC container OS updates.
|
||||
# Add container IDs to exclude from updates (comma-separated):
|
||||
# EXCLUDE=100,101,102
|
||||
EXCLUDE=
|
||||
CONF
|
||||
ok "Created config ${CONF_FILE}"
|
||||
fi
|
||||
|
||||
(
|
||||
crontab -l -u root 2>/dev/null | grep -v "${LOCAL_SCRIPT}" || true
|
||||
echo "${CRON_ENTRY}"
|
||||
) | crontab -u root -
|
||||
ok "Added cron schedule: Every Sunday at midnight"
|
||||
echo ""
|
||||
echo -e " \e[36mLocal script:\e[0m ${LOCAL_SCRIPT}"
|
||||
echo -e " \e[36mConfig:\e[0m ${CONF_FILE}"
|
||||
echo -e " \e[36mLog file:\e[0m ${LOG_FILE}"
|
||||
echo ""
|
||||
sh -c '(crontab -l -u root 2>/dev/null; echo "0 0 * * 0 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/pve/update-lxcs-cron.sh)\" >>/var/log/update-lxcs-cron.log 2>/dev/null") | crontab -u root -'
|
||||
clear
|
||||
echo -e "\n To view Cron Update LXCs logs: cat /var/log/update-lxcs-cron.log"
|
||||
}
|
||||
|
||||
remove() {
|
||||
if crontab -l -u root 2>/dev/null | grep -q "${LOCAL_SCRIPT}"; then
|
||||
(crontab -l -u root 2>/dev/null | grep -v "${LOCAL_SCRIPT}") | crontab -u root -
|
||||
ok "Removed cron schedule"
|
||||
fi
|
||||
remove_legacy_cron
|
||||
[[ -f "$LOCAL_SCRIPT" ]] && rm -f "$LOCAL_SCRIPT" && ok "Removed ${LOCAL_SCRIPT}"
|
||||
[[ -f "$LOG_FILE" ]] && rm -f "$LOG_FILE" && ok "Removed ${LOG_FILE}"
|
||||
echo -e "\n Cron Update LXCs has been fully removed."
|
||||
echo -e " \e[90mNote: ${CONF_FILE} was kept (remove manually if desired).\e[0m"
|
||||
(crontab -l | grep -v "update-lxcs-cron.sh") | crontab -
|
||||
rm -rf /var/log/update-lxcs-cron.log
|
||||
echo "Removed Crontab Schedule from Proxmox VE"
|
||||
}
|
||||
|
||||
update_script() {
|
||||
if [[ ! -f "$LOCAL_SCRIPT" ]]; then
|
||||
err "No local script found at ${LOCAL_SCRIPT}. Use 'Add' first."
|
||||
exit 1
|
||||
fi
|
||||
OPTIONS=(Add "Add Crontab Schedule"
|
||||
Remove "Remove Crontab Schedule")
|
||||
|
||||
info "Downloading latest version..."
|
||||
local tmp
|
||||
tmp=$(download_script) || exit 1
|
||||
|
||||
if command -v diff &>/dev/null; then
|
||||
local changes
|
||||
changes=$(diff --color=auto "$LOCAL_SCRIPT" "$tmp" 2>/dev/null || true)
|
||||
if [[ -z "$changes" ]]; then
|
||||
ok "Script is already up-to-date (no changes)."
|
||||
rm -f "$tmp"
|
||||
return
|
||||
fi
|
||||
echo ""
|
||||
echo -e " \e[1;33m─── Changes ──────────────────────────────────────────────────\e[0m"
|
||||
echo "$changes"
|
||||
echo -e " \e[1;33m──────────────────────────────────────────────────────────────\e[0m"
|
||||
else
|
||||
review_script "$tmp"
|
||||
fi
|
||||
|
||||
local new_hash old_hash
|
||||
new_hash=$(sha256sum "$tmp" | awk '{print $1}')
|
||||
old_hash=$(sha256sum "$LOCAL_SCRIPT" | awk '{print $1}')
|
||||
echo -e " \e[36mCurrent SHA256:\e[0m ${old_hash}"
|
||||
echo -e " \e[36mNew SHA256:\e[0m ${new_hash}"
|
||||
echo ""
|
||||
|
||||
if ! confirm "Apply update?"; then
|
||||
rm -f "$tmp"
|
||||
echo " Aborted."
|
||||
return
|
||||
fi
|
||||
|
||||
install -m 0755 "$tmp" "$LOCAL_SCRIPT"
|
||||
rm -f "$tmp"
|
||||
ok "Updated ${LOCAL_SCRIPT}"
|
||||
}
|
||||
|
||||
view_script() {
|
||||
if [[ ! -f "$LOCAL_SCRIPT" ]]; then
|
||||
err "No local script found at ${LOCAL_SCRIPT}. Use 'Add' first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local view_choice
|
||||
view_choice=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "View Script" --menu "What do you want to view?" 12 60 3 \
|
||||
"Worker" "Installed update script (${LOCAL_SCRIPT##*/})" \
|
||||
"Cron" "Cron schedule & configuration" \
|
||||
"Both" "Show everything" \
|
||||
3>&1 1>&2 2>&3) || return 0
|
||||
|
||||
case "$view_choice" in
|
||||
"Worker") view_worker_script ;;
|
||||
"Cron") view_cron_config ;;
|
||||
"Both") view_cron_config && echo "" && view_worker_script ;;
|
||||
esac
|
||||
}
|
||||
|
||||
view_worker_script() {
|
||||
local hash
|
||||
hash=$(sha256sum "$LOCAL_SCRIPT" | awk '{print $1}')
|
||||
echo ""
|
||||
echo -e " \e[1;33m─── ${LOCAL_SCRIPT} ───\e[0m"
|
||||
cat "$LOCAL_SCRIPT"
|
||||
echo -e " \e[1;33m──────────────────────────────────────────────────────────────\e[0m"
|
||||
echo -e " \e[36mSHA256:\e[0m ${hash}"
|
||||
echo -e " \e[36mInstalled:\e[0m $(stat -c '%y' "$LOCAL_SCRIPT" 2>/dev/null | cut -d. -f1)"
|
||||
echo ""
|
||||
}
|
||||
|
||||
view_cron_config() {
|
||||
echo ""
|
||||
echo -e " \e[1;33m─── Cron Configuration ───────────────────────────────────────\e[0m"
|
||||
if crontab -l -u root 2>/dev/null | grep -q "${LOCAL_SCRIPT}"; then
|
||||
local entry
|
||||
entry=$(crontab -l -u root 2>/dev/null | grep "${LOCAL_SCRIPT}")
|
||||
echo -e " \e[36mCron entry:\e[0m ${entry}"
|
||||
local schedule
|
||||
schedule=$(echo "$entry" | awk '{print $1,$2,$3,$4,$5}')
|
||||
echo -e " \e[36mSchedule:\e[0m ${schedule} ($(cron_to_human "$schedule"))"
|
||||
else
|
||||
echo -e " \e[31mCron:\e[0m Not configured"
|
||||
fi
|
||||
if [[ -f "$CONF_FILE" ]]; then
|
||||
echo -e " \e[36mConfig file:\e[0m ${CONF_FILE}"
|
||||
local excludes
|
||||
excludes=$(grep -oP '^\s*EXCLUDE\s*=\s*\K.*' "$CONF_FILE" 2>/dev/null || true)
|
||||
echo -e " \e[36mExcluded:\e[0m ${excludes:-(none)}"
|
||||
echo ""
|
||||
echo -e " \e[90m--- ${CONF_FILE} ---\e[0m"
|
||||
cat "$CONF_FILE"
|
||||
else
|
||||
echo -e " \e[36mConfig file:\e[0m (not created yet)"
|
||||
fi
|
||||
if [[ -f "$LOG_FILE" ]]; then
|
||||
local log_size
|
||||
log_size=$(du -h "$LOG_FILE" | awk '{print $1}')
|
||||
echo -e " \e[36mLog file:\e[0m ${LOG_FILE} (${log_size})"
|
||||
fi
|
||||
echo -e " \e[1;33m──────────────────────────────────────────────────────────────\e[0m"
|
||||
echo ""
|
||||
}
|
||||
|
||||
cron_to_human() {
|
||||
local schedule="$1"
|
||||
case "$schedule" in
|
||||
"0 0 * * 0") echo "Every Sunday at midnight" ;;
|
||||
"0 0 * * *") echo "Daily at midnight" ;;
|
||||
"0 * * * *") echo "Every hour" ;;
|
||||
*) echo "Custom schedule" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
show_status() {
|
||||
echo ""
|
||||
if [[ -f "$LOCAL_SCRIPT" ]]; then
|
||||
local hash
|
||||
hash=$(sha256sum "$LOCAL_SCRIPT" | awk '{print $1}')
|
||||
ok "Script installed: ${LOCAL_SCRIPT}"
|
||||
echo -e " \e[36mSHA256:\e[0m ${hash}"
|
||||
echo -e " \e[36mInstalled:\e[0m $(stat -c '%y' "$LOCAL_SCRIPT" 2>/dev/null | cut -d. -f1)"
|
||||
else
|
||||
err "Script not installed"
|
||||
fi
|
||||
|
||||
if crontab -l -u root 2>/dev/null | grep -q "${LOCAL_SCRIPT}"; then
|
||||
local schedule
|
||||
schedule=$(crontab -l -u root 2>/dev/null | grep "${LOCAL_SCRIPT}" | awk '{print $1,$2,$3,$4,$5}')
|
||||
ok "Cron active: ${schedule}"
|
||||
else
|
||||
err "Cron not configured"
|
||||
fi
|
||||
|
||||
if [[ -f "$CONF_FILE" ]]; then
|
||||
local excludes
|
||||
excludes=$(grep -oP '^\s*EXCLUDE\s*=\s*\K.*' "$CONF_FILE" 2>/dev/null || echo "(none)")
|
||||
echo -e " \e[36mExcluded:\e[0m ${excludes:-"(none)"}"
|
||||
fi
|
||||
|
||||
if [[ -f "$LOG_FILE" ]]; then
|
||||
local log_size last_run
|
||||
log_size=$(du -h "$LOG_FILE" | awk '{print $1}')
|
||||
last_run=$(grep -oP '^\s+\K\w.*' "$LOG_FILE" | tail -1)
|
||||
echo -e " \e[36mLog file:\e[0m ${LOG_FILE} (${log_size})"
|
||||
[[ -n "${last_run:-}" ]] && echo -e " \e[36mLast run:\e[0m ${last_run}"
|
||||
else
|
||||
echo -e " \e[36mLog file:\e[0m (no runs yet)"
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
run_now() {
|
||||
if [[ ! -f "$LOCAL_SCRIPT" ]]; then
|
||||
err "No local script found at ${LOCAL_SCRIPT}. Use 'Add' first."
|
||||
exit 1
|
||||
fi
|
||||
info "Running update script now..."
|
||||
bash "$LOCAL_SCRIPT" | tee -a "$LOG_FILE"
|
||||
ok "Run completed. Log appended to ${LOG_FILE}"
|
||||
}
|
||||
|
||||
rotate_log() {
|
||||
if [[ ! -f "$LOG_FILE" ]]; then
|
||||
info "No log file to rotate."
|
||||
return
|
||||
fi
|
||||
local log_size
|
||||
log_size=$(stat -c '%s' "$LOG_FILE" 2>/dev/null || echo 0)
|
||||
local log_size_h
|
||||
log_size_h=$(du -h "$LOG_FILE" | awk '{print $1}')
|
||||
if confirm "Rotate log file? (current size: ${log_size_h})"; then
|
||||
mv "$LOG_FILE" "${LOG_FILE}.old"
|
||||
ok "Rotated: ${LOG_FILE} → ${LOG_FILE}.old"
|
||||
fi
|
||||
}
|
||||
|
||||
OPTIONS=(
|
||||
Add "Download, review & install cron schedule"
|
||||
Remove "Remove cron schedule & local script"
|
||||
Update "Update local script from repository"
|
||||
Status "Show installation status & last run"
|
||||
Run "Run update script now (manual trigger)"
|
||||
View "View cron config & installed script"
|
||||
Rotate "Rotate log file"
|
||||
)
|
||||
|
||||
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Cron Update LXCs" --menu "Select an option:" 16 68 7 \
|
||||
"${OPTIONS[@]}" 3>&1 1>&2 2>&3) || exit 0
|
||||
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Cron Update LXCs" --menu "Select an option:" 10 58 2 \
|
||||
"${OPTIONS[@]}" 3>&1 1>&2 2>&3)
|
||||
|
||||
case $CHOICE in
|
||||
"Add") add ;;
|
||||
"Remove") remove ;;
|
||||
"Update") update_script ;;
|
||||
"Status") show_status ;;
|
||||
"Run") run_now ;;
|
||||
"View") view_script ;;
|
||||
"Rotate") rotate_log ;;
|
||||
"Add")
|
||||
add
|
||||
;;
|
||||
"Remove")
|
||||
remove
|
||||
;;
|
||||
*)
|
||||
echo "Exiting..."
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -1,43 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2026 community-scripts ORG
|
||||
# Author: MickLesk (CanbiZ)
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
#
|
||||
# This script is installed locally by cron-update-lxcs.sh and executed
|
||||
# by cron. It updates all LXC containers using their native package manager.
|
||||
|
||||
CONF_FILE="/etc/update-lxcs.conf"
|
||||
# Copyright (c) 2021-2026 tteck
|
||||
# Author: tteck (tteckster)
|
||||
# License: MIT
|
||||
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
|
||||
echo -e "\n $(date)"
|
||||
|
||||
# Collect excluded containers from arguments
|
||||
excluded_containers=("$@")
|
||||
|
||||
# Merge exclusions from config file if it exists
|
||||
if [[ -f "$CONF_FILE" ]]; then
|
||||
conf_exclude=$(grep -oP '^\s*EXCLUDE\s*=\s*\K[0-9,]+' "$CONF_FILE" 2>/dev/null || true)
|
||||
IFS=',' read -ra conf_ids <<<"$conf_exclude"
|
||||
for id in "${conf_ids[@]}"; do
|
||||
id="${id// /}"
|
||||
[[ -n "$id" ]] && excluded_containers+=("$id")
|
||||
done
|
||||
fi
|
||||
|
||||
function update_container() {
|
||||
local container=$1
|
||||
local name
|
||||
name=$(pct exec "$container" hostname 2>/dev/null || echo "unknown")
|
||||
local os
|
||||
container=$1
|
||||
name=$(pct exec "$container" hostname)
|
||||
echo -e "\n [Info] Updating $container : $name \n"
|
||||
os=$(pct config "$container" | awk '/^ostype/ {print $2}')
|
||||
echo -e "\n [Info] Updating $container : $name (os: $os)"
|
||||
case "$os" in
|
||||
alpine) pct exec "$container" -- ash -c "apk -U upgrade" ;;
|
||||
archlinux) pct exec "$container" -- bash -c "pacman -Syyu --noconfirm" ;;
|
||||
fedora | rocky | centos | alma) pct exec "$container" -- bash -c "dnf -y update && dnf -y upgrade" ;;
|
||||
ubuntu | debian | devuan) pct exec "$container" -- bash -c "apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::='--force-confold' dist-upgrade -y; rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED" ;;
|
||||
ubuntu | debian | devuan) pct exec "$container" -- bash -c "apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confold" dist-upgrade -y; rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED" ;;
|
||||
opensuse) pct exec "$container" -- bash -c "zypper ref && zypper --non-interactive dup" ;;
|
||||
*) echo " [Warn] Unknown OS type '$os' for container $container, skipping" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -54,19 +34,16 @@ for container in $(pct list | awk '{if(NR>1) print $1}'); do
|
||||
sleep 1
|
||||
else
|
||||
status=$(pct status "$container")
|
||||
if pct config "$container" 2>/dev/null | grep -q "^template:"; then
|
||||
echo -e "[Info] Skipping template $container"
|
||||
continue
|
||||
fi
|
||||
if [ "$status" == "status: stopped" ]; then
|
||||
template=$(pct config "$container" | grep -q "template:" && echo "true" || echo "false")
|
||||
if [ "$template" == "false" ] && [ "$status" == "status: stopped" ]; then
|
||||
echo -e "[Info] Starting $container"
|
||||
pct start "$container"
|
||||
sleep 5
|
||||
update_container "$container" || echo " [Error] Update failed for $container"
|
||||
update_container "$container"
|
||||
echo -e "[Info] Shutting down $container"
|
||||
pct shutdown "$container" --timeout 60 &
|
||||
pct shutdown "$container" &
|
||||
elif [ "$status" == "status: running" ]; then
|
||||
update_container "$container" || echo " [Error] Update failed for $container"
|
||||
update_container "$container"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user