mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-06-28 02:04:58 +02:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1595d25b97 | |||
| b5361e5278 | |||
| 4f9f556a93 | |||
| 4b23f2c72c | |||
| 2ded16ed4b | |||
| e1f61aeeb9 | |||
| fb9f5a0047 | |||
| 17b5f8c10c | |||
| 8b99d3b1cc | |||
| 039470965b |
@@ -486,6 +486,27 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
## 2026-06-27
|
||||||
|
|
||||||
|
### 🆕 New Scripts
|
||||||
|
|
||||||
|
- tool: add disk-health tool (SMART + NVMe) [@MickLesk](https://github.com/MickLesk) ([#15417](https://github.com/community-scripts/ProxmoxVE/pull/15417))
|
||||||
|
|
||||||
|
### 🚀 Updated Scripts
|
||||||
|
|
||||||
|
- #### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- Deluge openssl fix [@asylumexp](https://github.com/asylumexp) ([#15435](https://github.com/community-scripts/ProxmoxVE/pull/15435))
|
||||||
|
- fix command syntax in tunarr.sh [@asylumexp](https://github.com/asylumexp) ([#15434](https://github.com/community-scripts/ProxmoxVE/pull/15434))
|
||||||
|
|
||||||
|
- #### 🔧 Refactor
|
||||||
|
|
||||||
|
- Storyteller: bump Node.js version to Node 24 [@thinusn](https://github.com/thinusn) ([#15439](https://github.com/community-scripts/ProxmoxVE/pull/15439))
|
||||||
|
|
||||||
|
### ❔ Uncategorized
|
||||||
|
|
||||||
|
- fix(endurain): replace Poetry/uv-pip backend setup with uv sync --frozen --no-dev [@Copilot](https://github.com/Copilot) ([#15429](https://github.com/community-scripts/ProxmoxVE/pull/15429))
|
||||||
|
|
||||||
## 2026-06-26
|
## 2026-06-26
|
||||||
|
|
||||||
### 🚀 Updated Scripts
|
### 🚀 Updated Scripts
|
||||||
|
|||||||
+2
-2
@@ -12,7 +12,7 @@ var_ram="${var_ram:-2048}"
|
|||||||
var_disk="${var_disk:-4}"
|
var_disk="${var_disk:-4}"
|
||||||
var_os="${var_os:-debian}"
|
var_os="${var_os:-debian}"
|
||||||
var_version="${var_version:-13}"
|
var_version="${var_version:-13}"
|
||||||
var_arm64="${var_arm64:-yes}"
|
var_arm64="${var_arm64:-no}"
|
||||||
var_unprivileged="${var_unprivileged:-1}"
|
var_unprivileged="${var_unprivileged:-1}"
|
||||||
|
|
||||||
header_info "$APP"
|
header_info "$APP"
|
||||||
@@ -31,7 +31,7 @@ function update_script() {
|
|||||||
msg_info "Updating Deluge"
|
msg_info "Updating Deluge"
|
||||||
ensure_dependencies python3-setuptools
|
ensure_dependencies python3-setuptools
|
||||||
$STD apt update
|
$STD apt update
|
||||||
$STD pip3 install deluge[all] --upgrade
|
$STD pip3 install deluge[all] "pyopenssl<25" --upgrade
|
||||||
msg_ok "Updated Deluge"
|
msg_ok "Updated Deluge"
|
||||||
msg_ok "Updated successfully!"
|
msg_ok "Updated successfully!"
|
||||||
exit
|
exit
|
||||||
|
|||||||
+1
-4
@@ -63,10 +63,7 @@ function update_script() {
|
|||||||
cd /opt/endurain/backend
|
cd /opt/endurain/backend
|
||||||
UV_VERSION=$(grep -Po 'required-version\s*=\s*"\K[^"]+' pyproject.toml 2>/dev/null || echo "0.11.18")
|
UV_VERSION=$(grep -Po 'required-version\s*=\s*"\K[^"]+' pyproject.toml 2>/dev/null || echo "0.11.18")
|
||||||
UV_VERSION="$UV_VERSION" setup_uv
|
UV_VERSION="$UV_VERSION" setup_uv
|
||||||
$STD poetry export -f requirements.txt --output requirements.txt --without-hashes
|
$STD uv sync --frozen --no-dev
|
||||||
$STD uv venv --clear
|
|
||||||
$STD uv pip install -r requirements.txt
|
|
||||||
$STD uv pip install pytz
|
|
||||||
msg_ok "Backend Updated"
|
msg_ok "Backend Updated"
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ function update_script() {
|
|||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
NODE_VERSION="24" NODE_MODULE="corepack,yarn" setup_nodejs
|
||||||
|
|
||||||
if check_for_gl_release "storyteller" "storyteller-platform/storyteller"; then
|
if check_for_gl_release "storyteller" "storyteller-platform/storyteller"; then
|
||||||
msg_info "Stopping Service"
|
msg_info "Stopping Service"
|
||||||
systemctl stop storyteller
|
systemctl stop storyteller
|
||||||
|
|||||||
+2
-7
@@ -33,17 +33,12 @@ function update_script() {
|
|||||||
systemctl stop tunarr
|
systemctl stop tunarr
|
||||||
msg_ok "Stopped Service"
|
msg_ok "Stopped Service"
|
||||||
|
|
||||||
msg_info "Creating Backup"
|
create_backup /root/.local/share/tunarr
|
||||||
if [ -d "/root/.local/share/tunarr" ]; then
|
|
||||||
tar -czf "/opt/${APP}_backup_$(date +%F).tar.gz" /root/.local/share/tunarr $STD
|
|
||||||
msg_ok "Backup Created"
|
|
||||||
else
|
|
||||||
msg_error "Backup failed: /root/.local/share/tunarr does not exist"
|
|
||||||
fi
|
|
||||||
|
|
||||||
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "tunarr" "chrisbenincasa/tunarr" "prebuild" "latest" "/opt/tunarr" "*linux-$(arch_resolve "x64" "arm64").tar.gz"
|
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "tunarr" "chrisbenincasa/tunarr" "prebuild" "latest" "/opt/tunarr" "*linux-$(arch_resolve "x64" "arm64").tar.gz"
|
||||||
cd /opt/tunarr
|
cd /opt/tunarr
|
||||||
mv tunarr* tunarr
|
mv tunarr* tunarr
|
||||||
|
restore_backup
|
||||||
|
|
||||||
msg_info "Starting Service"
|
msg_info "Starting Service"
|
||||||
systemctl start tunarr
|
systemctl start tunarr
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ cat >~/.config/pip/pip.conf <<EOF
|
|||||||
[global]
|
[global]
|
||||||
break-system-packages = true
|
break-system-packages = true
|
||||||
EOF
|
EOF
|
||||||
$STD pip install deluge[all]
|
$STD pip install deluge[all] "pyopenssl<25"
|
||||||
msg_ok "Installed Deluge"
|
msg_ok "Installed Deluge"
|
||||||
|
|
||||||
msg_info "Creating Service"
|
msg_info "Creating Service"
|
||||||
|
|||||||
@@ -83,14 +83,7 @@ msg_info "Setting up Backend"
|
|||||||
cd /opt/endurain/backend
|
cd /opt/endurain/backend
|
||||||
UV_VERSION=$(grep -Po 'required-version\s*=\s*"\K[^"]+' pyproject.toml 2>/dev/null || echo "0.11.18")
|
UV_VERSION=$(grep -Po 'required-version\s*=\s*"\K[^"]+' pyproject.toml 2>/dev/null || echo "0.11.18")
|
||||||
UV_VERSION="$UV_VERSION" setup_uv
|
UV_VERSION="$UV_VERSION" setup_uv
|
||||||
$STD uv tool install poetry
|
$STD uv sync --frozen --no-dev
|
||||||
$STD uv tool update-shell
|
|
||||||
export PATH="/root/.local/bin:$PATH"
|
|
||||||
$STD poetry self add poetry-plugin-export
|
|
||||||
$STD poetry export -f requirements.txt --output requirements.txt --without-hashes
|
|
||||||
$STD uv venv --clear
|
|
||||||
$STD uv pip install -r requirements.txt
|
|
||||||
$STD uv pip install pytz
|
|
||||||
msg_ok "Setup Backend"
|
msg_ok "Setup Backend"
|
||||||
|
|
||||||
msg_info "Creating Service"
|
msg_info "Creating Service"
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ $STD apt install -y \
|
|||||||
ffmpeg
|
ffmpeg
|
||||||
msg_ok "Installed Dependencies"
|
msg_ok "Installed Dependencies"
|
||||||
|
|
||||||
NODE_VERSION="22" NODE_MODULE="corepack,yarn" setup_nodejs
|
NODE_VERSION="24" NODE_MODULE="corepack,yarn" setup_nodejs
|
||||||
|
|
||||||
fetch_and_deploy_gh_release "readium" "readium/cli" "prebuild" "latest" "/opt/readium" "readium_linux_$(arch_resolve "x86_64" "arm64").tar.gz"
|
fetch_and_deploy_gh_release "readium" "readium/cli" "prebuild" "latest" "/opt/readium" "readium_linux_$(arch_resolve "x86_64" "arm64").tar.gz"
|
||||||
ln -sf /opt/readium/readium /usr/local/bin/readium
|
ln -sf /opt/readium/readium /usr/local/bin/readium
|
||||||
|
|||||||
Executable
+156
@@ -0,0 +1,156 @@
|
|||||||
|
#!/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 <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/refs/heads/main/misc/core.func)
|
||||||
|
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||||
|
load_functions
|
||||||
|
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "disk-health" "pve"
|
||||||
|
|
||||||
|
function header_info {
|
||||||
|
clear
|
||||||
|
cat <<"EOF"
|
||||||
|
____ _ __ __ __ ____ __
|
||||||
|
/ __ \(_)____/ /__ / / / /__ ____ _/ / /_/ /_
|
||||||
|
/ / / / / ___/ //_/ / /_/ / _ \/ __ `/ / __/ __ \
|
||||||
|
/ /_/ / (__ ) ,< / __ / __/ /_/ / / /_/ / / /
|
||||||
|
/_____/_/____/_/|_| /_/ /_/\___/\__,_/_/\__/_/ /_/
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
header_info
|
||||||
|
|
||||||
|
# Must run as root (SMART access requires it)
|
||||||
|
if [ "$(id -u)" -ne 0 ]; then
|
||||||
|
msg_error "This script must be run as root."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v pveversion >/dev/null 2>&1; then
|
||||||
|
msg_error "No Proxmox VE detected!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install required tooling on demand
|
||||||
|
if ! command -v smartctl >/dev/null 2>&1; then
|
||||||
|
msg_info "Installing smartmontools"
|
||||||
|
apt-get update &>/dev/null
|
||||||
|
if apt-get install -y smartmontools &>/dev/null; then
|
||||||
|
msg_ok "Installed smartmontools"
|
||||||
|
else
|
||||||
|
msg_error "Failed to install smartmontools"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if ! command -v nvme >/dev/null 2>&1; then
|
||||||
|
msg_info "Installing nvme-cli"
|
||||||
|
if apt-get install -y nvme-cli &>/dev/null; then
|
||||||
|
msg_ok "Installed nvme-cli"
|
||||||
|
else
|
||||||
|
msg_error "nvme-cli not available (NVMe details limited)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Collect physical disks (exclude loop, zram and device-mapper devices)
|
||||||
|
mapfile -t DISKS < <(lsblk -dn -o NAME,TYPE | awk '$2=="disk"{print $1}' | grep -vE '^(loop|zram|dm-)' | sort)
|
||||||
|
|
||||||
|
if [ "${#DISKS[@]}" -eq 0 ]; then
|
||||||
|
msg_error "No physical disks found."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Pull a single attribute value out of "smartctl -A" output by attribute name
|
||||||
|
sata_attr() {
|
||||||
|
local output="$1" name="$2"
|
||||||
|
echo "$output" | awk -v n="$name" '$2==n {print $10; exit}'
|
||||||
|
}
|
||||||
|
|
||||||
|
report_disk() {
|
||||||
|
local dev="$1"
|
||||||
|
local path="/dev/${dev}"
|
||||||
|
local model size health
|
||||||
|
model=$(lsblk -dn -o MODEL "$path" 2>/dev/null | sed 's/[[:space:]]*$//')
|
||||||
|
size=$(lsblk -dn -o SIZE "$path" 2>/dev/null | tr -d ' ')
|
||||||
|
|
||||||
|
echo -e "\n${BL}======================================================${CL}"
|
||||||
|
echo -e "${GN}${path}${CL} ${YW}${size:-?}${CL} ${model:-Unknown model}"
|
||||||
|
echo -e "${BL}======================================================${CL}"
|
||||||
|
|
||||||
|
# Overall SMART health verdict
|
||||||
|
health=$(smartctl -H "$path" 2>/dev/null | grep -iE "SMART overall-health|SMART Health Status" | sed 's/.*: *//')
|
||||||
|
if [ -z "$health" ]; then
|
||||||
|
echo -e " Health: ${YW}SMART not available for this device${CL}"
|
||||||
|
elif echo "$health" | grep -qiE "PASSED|OK"; then
|
||||||
|
echo -e " Health: ${GN}${health}${CL}"
|
||||||
|
else
|
||||||
|
echo -e " Health: ${RD}${health}${CL}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$dev" == nvme* ]]; then
|
||||||
|
local a
|
||||||
|
a=$(smartctl -A "$path" 2>/dev/null)
|
||||||
|
echo "$a" | grep -iE "Temperature:|Available Spare:|Percentage Used:|Data Units Written:|Power On Hours:|Unsafe Shutdowns:|Media and Data Integrity Errors:" |
|
||||||
|
sed 's/^/ /'
|
||||||
|
else
|
||||||
|
local a poh temp realloc pending offline crc wear
|
||||||
|
a=$(smartctl -A "$path" 2>/dev/null)
|
||||||
|
poh=$(sata_attr "$a" "Power_On_Hours")
|
||||||
|
temp=$(sata_attr "$a" "Temperature_Celsius")
|
||||||
|
realloc=$(sata_attr "$a" "Reallocated_Sector_Ct")
|
||||||
|
pending=$(sata_attr "$a" "Current_Pending_Sector")
|
||||||
|
offline=$(sata_attr "$a" "Offline_Uncorrectable")
|
||||||
|
crc=$(sata_attr "$a" "UDMA_CRC_Error_Count")
|
||||||
|
wear=$(sata_attr "$a" "Wear_Leveling_Count")
|
||||||
|
[ -z "$wear" ] && wear=$(sata_attr "$a" "Media_Wearout_Indicator")
|
||||||
|
|
||||||
|
[ -n "$temp" ] && echo -e " Temperature: ${temp} C"
|
||||||
|
[ -n "$poh" ] && echo -e " Power On Hours: ${poh}"
|
||||||
|
[ -n "$wear" ] && echo -e " Wear Leveling/Wearout: ${wear}"
|
||||||
|
print_attr() {
|
||||||
|
local label="$1" val="$2"
|
||||||
|
[ -z "$val" ] && return
|
||||||
|
if [ "$val" -gt 0 ] 2>/dev/null; then
|
||||||
|
echo -e " ${label} ${RD}${val}${CL}"
|
||||||
|
else
|
||||||
|
echo -e " ${label} ${GN}${val}${CL}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
print_attr "Reallocated Sectors: " "$realloc"
|
||||||
|
print_attr "Pending Sectors: " "$pending"
|
||||||
|
print_attr "Offline Uncorrectable:" "$offline"
|
||||||
|
print_attr "UDMA CRC Errors: " "$crc"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
header_info
|
||||||
|
echo -e "${YW}Scanning ${#DISKS[@]} disk(s) for SMART health...${CL}"
|
||||||
|
for d in "${DISKS[@]}"; do
|
||||||
|
report_disk "$d"
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Offer an optional, non-destructive short self-test
|
||||||
|
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "SMART Self-Test" \
|
||||||
|
--yesno "Health report complete.\n\nDo you want to start a non-destructive SHORT SMART self-test on a disk?\n\n(The test runs in the background; check results later with: smartctl -a /dev/XXX)" 14 70; then
|
||||||
|
TEST_MENU=()
|
||||||
|
for d in "${DISKS[@]}"; do
|
||||||
|
TEST_MENU+=("$d" "/dev/$d" "OFF")
|
||||||
|
done
|
||||||
|
sel=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Select Disk for Short Self-Test" \
|
||||||
|
--radiolist "\nSelect a disk:\n" 16 60 6 "${TEST_MENU[@]}" 3>&1 1>&2 2>&3 | tr -d '"')
|
||||||
|
if [ -n "$sel" ]; then
|
||||||
|
msg_info "Starting short self-test on /dev/$sel"
|
||||||
|
if smartctl -t short "/dev/$sel" &>/dev/null; then
|
||||||
|
msg_ok "Short self-test started on /dev/$sel"
|
||||||
|
echo -e "${YW}Check progress/result with: ${GN}smartctl -a /dev/$sel${CL}"
|
||||||
|
else
|
||||||
|
msg_error "Could not start self-test on /dev/$sel"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "\n${GN}Disk health check complete.${CL}\n"
|
||||||
Reference in New Issue
Block a user