Compare commits

..

18 Commits

Author SHA1 Message Date
community-scripts-pr-app[bot] 8e4a9829cf Update CHANGELOG.md (#15428)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-06-26 19:58:28 +00:00
community-scripts-pr-app[bot] f1eee5f5ed Update CHANGELOG.md (#15427)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-06-26 19:58:10 +00:00
CanbiZ (MickLesk) fb14e6ae8b fix(setup_docker): don't abort update on docker pull failure (#15410)
During the container update check, a failing 'docker pull' (local-only images, registry or permission errors) aborted the whole script under errexit. Ignore pull failures and skip containers whose digest could not be resolved.
2026-06-26 21:58:08 +02:00
CanbiZ (MickLesk) 4142c5c2d3 fix(docuseal): use real SECRET_KEY_BASE for db:migrate on update (#15411)
SECRET_KEY_BASE_DUMMY forced Rails to write tmp/local_secret.txt, which failed with EACCES during update and aborted db:migrate. Drop the dummy flag so the real SECRET_KEY_BASE from .env is used, and ensure tmp exists.
2026-06-26 21:57:46 +02:00
community-scripts-pr-app[bot] d85914530f Update CHANGELOG.md (#15426)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-06-26 19:57:30 +00:00
community-scripts-pr-app[bot] 3d9e67292b Update CHANGELOG.md (#15425)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-06-26 19:57:21 +00:00
community-scripts-pr-app[bot] ae60dc138b Update CHANGELOG.md (#15424)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-06-26 19:57:10 +00:00
community-scripts-pr-app[bot] 14a85a8591 Update CHANGELOG.md (#15423)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-06-26 19:56:54 +00:00
CanbiZ (MickLesk) 1be64c1994 bun: correct install for degoog (#15412)
* fix(degoog): restore bun symlinks after curl-impersonate update

The curl-impersonate CLEAN_INSTALL wipes /usr/local/bin, which removed the bun/bunx symlinks during update. Re-create them after the release deploy.

* clean install curl-impersonate

* sorting
2026-06-26 21:56:48 +02:00
community-scripts-pr-app[bot] 340695b9bd Update CHANGELOG.md (#15422)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-06-26 19:56:34 +00:00
CanbiZ (MickLesk) ba31c925e3 Validate kernel selection input in kernel-clean (#15414)
- Trim whitespace, skip empty tokens and reject non-numeric input so a
  malformed selection no longer feeds garbage into `sed -n "<index>p"`.
- Reject reversed ranges (start greater than end) with a clear message.
- Replace `grep | wc -l` with `grep -c` (ShellCheck SC2126).
2026-06-26 21:56:28 +02:00
CanbiZ (MickLesk) 868b405082 Fix clean-lxcs exclude matching and set -e cancel handling (#15413)
- Replace the array-style exclude check (`${excluded_containers[@]}` on a
  plain string) with an explicit per-VMID loop, resolving the ShellCheck
  SC2199/SC2076 errors and avoiding accidental substring matches.
- Abort cleanly when the checklist dialog is cancelled instead of relying
  on an unreachable `$?` test under `set -eEuo pipefail`.
- Exit gracefully on a declined confirmation prompt.
- Use `pct exec ... -- hostname` for consistent argument handling.
2026-06-26 21:56:23 +02:00
community-scripts-pr-app[bot] 60266b9c17 Update CHANGELOG.md (#15421)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-06-26 19:56:21 +00:00
community-scripts-pr-app[bot] ea8b87fd7f Update CHANGELOG.md (#15420)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-06-26 19:56:14 +00:00
CanbiZ (MickLesk) 58145d5bd3 Harden microcode download/install in microcode and pbs-microcode (#15415)
- AMD: download directly to "$microcode" instead of a convoluted, unquoted
  basename of the full URL (fixes ShellCheck SC2046) and pin to https.
- Quote dpkg install and cleanup paths (SC2086) and use rm -f.
- Normalize the Debian pool URLs (drop the stray double/triple slashes).
- Define color variables directly instead of via $(echo ...) (SC2116/SC2028).
2026-06-26 21:56:00 +02:00
CanbiZ (MickLesk) 9fbe2de1cb Refactor: reduce IP-Tag resource usage and clean up ShellCheck findings (#15418)
* Reduce IP-Tag resource usage and clean up ShellCheck findings

Performance / resource fixes in the generated service:
- VM IP detection only queries the QEMU guest agent when it is actually
  enabled in the VM config. Previously every VM without an agent stalled
  the loop for the full `qm guest cmd` timeout on each cycle; the timeout
  is also lowered from 8s to 5s.
- Skip the ARP/ping fallback for VMs entirely when the guest agent already
  returned addresses, avoiding needless ping probes every run.
- Snapshot `ip neighbor show` once per host instead of invoking it per MAC
  in the VM and LXC lookups.
- Lower ping verification to a 1s timeout (`-W 1`).

ShellCheck cleanup in the installer:
- Define color variables directly instead of via $(echo ...) (SC2116/SC2028).
- Use `read -rp` everywhere (SC2162).
- Replace Unicode quotes with ASCII in a status message (SC1111).

* Cut IP-Tag CPU usage by avoiding per-guest pct/qm status calls

The periodic check spawned one `pct status` per container and one
`qm status` per VM each cycle. Both are heavy Perl tools (~hundreds of ms
CPU per invocation), so on hosts with many guests the 5-minute run caused
a noticeable CPU spike.

- Derive LXC status from the single `pct list` call that is already made
  for enumeration.
- Add one `qm list` call to collect all VM statuses at once.
- Store both in a per-cycle STATUS_CACHE and read from it instead of
  calling `pct status` / `qm status` per guest (with a fallback for direct
  calls outside the cycle).
2026-06-26 21:55:53 +02:00
community-scripts-pr-app[bot] c918dee5fe Update CHANGELOG.md (#15419)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-06-26 19:53:49 +00:00
CanbiZ (MickLesk) 0774772b87 QoL: scaling-governor extend selection and guard missing cpufreq (#15416) 2026-06-26 21:53:22 +02:00
9 changed files with 87 additions and 47 deletions
+13
View File
@@ -494,15 +494,28 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
- #### 🐞 Bug Fixes
- Docuseal: use real SECRET_KEY_BASE for db:migrate on update [@MickLesk](https://github.com/MickLesk) ([#15411](https://github.com/community-scripts/ProxmoxVE/pull/15411))
- bun: correct install for degoog [@MickLesk](https://github.com/MickLesk) ([#15412](https://github.com/community-scripts/ProxmoxVE/pull/15412))
- fix databasus update/install errors [@asylumexp](https://github.com/asylumexp) ([#15403](https://github.com/community-scripts/ProxmoxVE/pull/15403))
### 💾 Core
- #### 🐞 Bug Fixes
- tools.func: fix setup_docker - don't abort update on docker pull failure [@MickLesk](https://github.com/MickLesk) ([#15410](https://github.com/community-scripts/ProxmoxVE/pull/15410))
- fix(build.func): set /dev/kfd GID in fix_gpu_gids for AMD ROCm [@jamiej](https://github.com/jamiej) ([#15401](https://github.com/community-scripts/ProxmoxVE/pull/15401))
- fix alpine mktmp error [@asylumexp](https://github.com/asylumexp) ([#15398](https://github.com/community-scripts/ProxmoxVE/pull/15398))
### 🧰 Tools
- #### 🔧 Refactor
- Refactor: reduce IP-Tag resource usage and clean up ShellCheck findings [@MickLesk](https://github.com/MickLesk) ([#15418](https://github.com/community-scripts/ProxmoxVE/pull/15418))
- QoL: kernel-clean: Validate kernel selection input [@MickLesk](https://github.com/MickLesk) ([#15414](https://github.com/community-scripts/ProxmoxVE/pull/15414))
- QoL: clean-lxcs exclude matching and set -e cancel handling [@MickLesk](https://github.com/MickLesk) ([#15413](https://github.com/community-scripts/ProxmoxVE/pull/15413))
- QoL: Harden microcode download/install in microcode and pbs-microcode [@MickLesk](https://github.com/MickLesk) ([#15415](https://github.com/community-scripts/ProxmoxVE/pull/15415))
- QoL: scaling-governor extend selection and guard missing cpufreq [@MickLesk](https://github.com/MickLesk) ([#15416](https://github.com/community-scripts/ProxmoxVE/pull/15416))
## 2026-06-25
### 🆕 New Scripts
+2 -2
View File
@@ -38,7 +38,7 @@ function update_script() {
create_backup /opt/degoog/.env \
/opt/degoog/data
if ! command -v bun >/dev/null 2>&1; then
if [[ ! -x /root/.bun/bin/bun ]]; then
msg_info "Installing Bun"
export BUN_INSTALL="/root/.bun"
curl -fsSL https://bun.sh/install | $STD bash
@@ -52,7 +52,7 @@ function update_script() {
msg_ok "Updated Valkey"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "degoog" "fccview/degoog" "prebuild" "latest" "/opt/degoog" "degoog_*_prebuild.tar.gz"
CLEAN_INSTALL=1 fetch_and_deploy_gh_release "curl-impersonate" "lexiforest/curl-impersonate" "prebuild" "latest" "/usr/local/bin" "curl-impersonate-v*.$(uname -m)-linux-gnu.tar.gz"
fetch_and_deploy_gh_release "curl-impersonate" "lexiforest/curl-impersonate" "prebuild" "latest" "/usr/local/bin" "curl-impersonate-v*.$(uname -m)-linux-gnu.tar.gz"
restore_backup
+1 -1
View File
@@ -55,7 +55,7 @@ function update_script() {
eval "$(rbenv init - bash)" 2>/dev/null || true
export RAILS_ENV=production
export NODE_ENV=production
export SECRET_KEY_BASE_DUMMY=1
mkdir -p /opt/docuseal/tmp
set -a
source /opt/docuseal/.env
set +a
+7 -7
View File
@@ -4614,11 +4614,11 @@ EOF
local image=$(echo "$container" | awk '{print $2}')
local current_digest=$(docker inspect "$name" --format='{{.Image}}' 2>/dev/null | cut -d':' -f2 | cut -c1-12)
# Pull latest image digest
docker pull "$image" >/dev/null 2>&1
# Pull latest image digest (ignore failures, e.g. local-only images or registry/permission issues)
docker pull "$image" >/dev/null 2>&1 || true
local latest_digest=$(docker inspect "$image" --format='{{.Id}}' 2>/dev/null | cut -d':' -f2 | cut -c1-12)
if [ "$current_digest" != "$latest_digest" ]; then
if [ -n "$latest_digest" ] && [ "$current_digest" != "$latest_digest" ]; then
containers_with_updates+=("$name")
container_info+=("${index}) ${name} (${image})")
((index++))
@@ -7561,8 +7561,8 @@ setup_nodejs() {
}
# Install global Node modules
if [[ -n "$NODE_MODULE" ]] || (( node_major >= 25 )); then
if (( node_major >= 25 )) && [[ ",${NODE_MODULE}," != *",corepack,"* ]] && [[ "$NODE_MODULE" != corepack* ]]; then
if [[ -n "$NODE_MODULE" ]] || ((node_major >= 25)); then
if ((node_major >= 25)) && [[ ",${NODE_MODULE}," != *",corepack,"* ]] && [[ "$NODE_MODULE" != corepack* ]]; then
NODE_MODULE="${NODE_MODULE:+$NODE_MODULE,}corepack"
fi
@@ -7624,12 +7624,12 @@ setup_nodejs() {
fi
fi
done
if (( failed_modules > 0 )); then
if ((failed_modules > 0)); then
msg_warn "$failed_modules Node.js module(s) failed: $NODE_MODULE"
fi
fi
if [[ "$NODE_COREPACK_ENABLE" == "1" ]] && (( wants_corepack )) && command -v corepack >/dev/null 2>&1; then
if [[ "$NODE_COREPACK_ENABLE" == "1" ]] && ((wants_corepack)) && command -v corepack >/dev/null 2>&1; then
msg_info "Enabling corepack"
if $STD corepack enable 2>/dev/null; then
msg_ok "Enabled corepack"
+15 -8
View File
@@ -30,7 +30,7 @@ declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "clean-lxcs" "
header_info
echo "Loading..."
whiptail --backtitle "Proxmox VE Helper Scripts" --title "Proxmox VE LXC Updater" --yesno "This will clean logs, cache and update package lists on selected LXC Containers. Proceed?" 10 58
whiptail --backtitle "Proxmox VE Helper Scripts" --title "Proxmox VE LXC Updater" --yesno "This will clean logs, cache and update package lists on selected LXC Containers. Proceed?" 10 58 || exit 0
NODE=$(hostname)
EXCLUDE_MENU=()
@@ -42,17 +42,17 @@ while read -r TAG ITEM; do
EXCLUDE_MENU+=("$TAG" "$ITEM " "OFF")
done < <(pct list | awk 'NR>1')
excluded_containers=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Containers on $NODE" --checklist "\nSelect containers to skip from cleaning:\n" \
16 $((MSG_MAX_LENGTH + 23)) 6 "${EXCLUDE_MENU[@]}" 3>&1 1>&2 2>&3 | tr -d '"')
if [ $? -ne 0 ]; then
exit
# Capture the selection; abort cleanly if the user cancels the dialog
# (set -e would otherwise terminate on the failing command substitution).
if ! excluded_containers=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Containers on $NODE" --checklist "\nSelect containers to skip from cleaning:\n" \
16 $((MSG_MAX_LENGTH + 23)) 6 "${EXCLUDE_MENU[@]}" 3>&1 1>&2 2>&3 | tr -d '"'); then
exit 0
fi
function run_lxc_clean() {
local container=$1
header_info
name=$(pct exec "$container" hostname)
name=$(pct exec "$container" -- hostname)
pct exec "$container" -- bash -c '
BL="\033[36m"; GN="\033[1;92m"; CL="\033[m"
@@ -84,7 +84,14 @@ function run_lxc_clean() {
}
for container in $(pct list | awk '{if(NR>1) print $1}'); do
if [[ " ${excluded_containers[@]} " =~ " $container " ]]; then
excluded=0
for ex in $excluded_containers; do
if [[ "$ex" == "$container" ]]; then
excluded=1
break
fi
done
if [[ "$excluded" -eq 1 ]]; then
header_info
echo -e "${BL}[Info]${GN} Skipping ${BL}$container${CL}"
sleep 1
+14 -4
View File
@@ -55,12 +55,23 @@ read -r selected
selected_indices=()
IFS=',' read -r -a tokens <<<"$selected"
for token in "${tokens[@]}"; do
# Strip surrounding whitespace and skip empty tokens
token="${token//[[:space:]]/}"
[ -z "$token" ] && continue
if [[ "$token" =~ ^([0-9]+)-([0-9]+)$ ]]; then
for ((i = BASH_REMATCH[1]; i <= BASH_REMATCH[2]; i++)); do
start=${BASH_REMATCH[1]}
end=${BASH_REMATCH[2]}
if ((start > end)); then
echo -e "${RD}Ignoring invalid range '${token}' (start greater than end).${CL}"
continue
fi
for ((i = start; i <= end; i++)); do
selected_indices+=("$i")
done
else
elif [[ "$token" =~ ^[0-9]+$ ]]; then
selected_indices+=("$token")
else
echo -e "${RD}Ignoring invalid selection '${token}'.${CL}"
fi
done
@@ -101,8 +112,7 @@ for kernel in "${kernels_to_remove[@]}"; do
remaining=$(dpkg --list |
awk '/^ii/ {print $2}' |
grep -E "^proxmox-kernel-${minor_version}\." |
grep -v "^${kernel}$" |
wc -l)
grep -cv "^${kernel}$")
if [ "$remaining" -eq 0 ]; then
pkgs_to_remove+=("$meta")
fi
+11 -11
View File
@@ -16,10 +16,10 @@ function header_info {
EOF
}
RD=$(echo "\033[01;31m")
YW=$(echo "\033[33m")
GN=$(echo "\033[1;92m")
CL=$(echo "\033[m")
RD="\033[01;31m"
YW="\033[33m"
GN="\033[1;92m"
CL="\033[m"
BFR="\\r\\033[K"
HOLD="-"
CM="${GN}${CL}"
@@ -47,7 +47,7 @@ intel() {
sleep 1
fi
intel_microcode=$(curl -fsSL "https://ftp.debian.org/debian/pool/non-free-firmware/i/intel-microcode//" | grep -o 'href="[^"]*amd64.deb"' | sed 's/href="//;s/"//')
intel_microcode=$(curl -fsSL "https://ftp.debian.org/debian/pool/non-free-firmware/i/intel-microcode/" | grep -o 'href="[^"]*amd64.deb"' | sed 's/href="//;s/"//')
[ -z "$intel_microcode" ] && {
whiptail --backtitle "Proxmox VE Helper Scripts" --title "No Microcode Found" --msgbox "It appears there were no microcode packages found\n Try again later." 10 68
msg_info "Exiting"
@@ -80,17 +80,17 @@ intel() {
msg_ok "Downloaded the Intel Processor Microcode Package $microcode"
msg_info "Installing $microcode (Patience)"
dpkg -i $microcode &>/dev/null
dpkg -i "$microcode" &>/dev/null
msg_ok "Installed $microcode"
msg_info "Cleaning up"
rm $microcode
rm -f "$microcode"
msg_ok "Cleaned"
echo -e "\nIn order to apply the changes, a system reboot will be necessary.\n"
}
amd() {
amd_microcode=$(curl -fsSL "https://ftp.debian.org/debian/pool/non-free-firmware/a/amd64-microcode///" | grep -o 'href="[^"]*amd64.deb"' | sed 's/href="//;s/"//')
amd_microcode=$(curl -fsSL "https://ftp.debian.org/debian/pool/non-free-firmware/a/amd64-microcode/" | grep -o 'href="[^"]*amd64.deb"' | sed 's/href="//;s/"//')
[ -z "$amd_microcode" ] && {
whiptail --backtitle "Proxmox VE Helper Scripts" --title "No Microcode Found" --msgbox "It appears there were no microcode packages found\n Try again later." 10 68
@@ -120,15 +120,15 @@ amd() {
}
msg_info "Downloading the AMD Processor Microcode Package $microcode"
curl -fsSL "https://ftp.debian.org/debian/pool/non-free-firmware/a/amd64-microcode/$microcode" -o $(basename "https://ftp.debian.org/debian/pool/non-free-firmware/a/amd64-microcode/$microcode")
curl -fsSL --proto '=https' "https://ftp.debian.org/debian/pool/non-free-firmware/a/amd64-microcode/$microcode" -o "$microcode"
msg_ok "Downloaded the AMD Processor Microcode Package $microcode"
msg_info "Installing $microcode (Patience)"
dpkg -i $microcode &>/dev/null
dpkg -i "$microcode" &>/dev/null
msg_ok "Installed $microcode"
msg_info "Cleaning up"
rm $microcode
rm -f "$microcode"
msg_ok "Cleaned"
echo -e "\nIn order to apply the changes, a system reboot will be necessary.\n"
}
+9 -9
View File
@@ -18,10 +18,10 @@ EOF
}
# Color definitions
RD=$(echo "\033[01;31m")
YW=$(echo "\033[33m")
GN=$(echo "\033[1;92m")
CL=$(echo "\033[m")
RD="\033[01;31m"
YW="\033[33m"
GN="\033[1;92m"
CL="\033[m"
BFR="\\r\\033[K"
HOLD="-"
CM="${GN}${CL}"
@@ -94,11 +94,11 @@ intel() {
msg_ok "Downloaded Intel processor microcode package $microcode"
msg_info "Installing $microcode (this might take a while)"
dpkg -i $microcode &>/dev/null
dpkg -i "$microcode" &>/dev/null
msg_ok "Installed $microcode"
msg_info "Cleaning up"
rm $microcode
rm -f "$microcode"
msg_ok "Clean up complete"
echo -e "\nA system reboot is required to apply the changes.\n"
}
@@ -137,15 +137,15 @@ amd() {
}
msg_info "Downloading AMD processor microcode package $microcode"
curl -fsSL "https://ftp.debian.org/debian/pool/non-free-firmware/a/amd64-microcode/$microcode" -o $(basename "https://ftp.debian.org/debian/pool/non-free-firmware/a/amd64-microcode/$microcode")
curl -fsSL --proto '=https' "https://ftp.debian.org/debian/pool/non-free-firmware/a/amd64-microcode/$microcode" -o "$microcode"
msg_ok "Downloaded AMD processor microcode package $microcode"
msg_info "Installing $microcode (this might take a while)"
dpkg -i $microcode &>/dev/null
dpkg -i "$microcode" &>/dev/null
msg_ok "Installed $microcode"
msg_info "Cleaning up"
rm $microcode
rm -f "$microcode"
msg_ok "Clean up complete"
echo -e "\nA system reboot is required to apply the changes.\n"
}
+15 -5
View File
@@ -20,16 +20,26 @@ header_info() {
EOF
}
header_info
whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU Scaling Governors" --yesno "View/Change CPU Scaling Governors. Proceed?" 10 58
current_governor=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor)
whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU Scaling Governors" --yesno "View/Change CPU Scaling Governors. Proceed?" 10 58 || exit 0
GOV_BASE="/sys/devices/system/cpu/cpu0/cpufreq"
if [[ ! -r "$GOV_BASE/scaling_governor" || ! -r "$GOV_BASE/scaling_available_governors" ]]; then
whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU Scaling Not Available" \
--msgbox "CPU frequency scaling is not available on this system.\n\nThis is normal when no cpufreq driver is active (e.g. CPU power management handled by the BIOS, or certain virtualized hosts)." 12 70
clear
exit 0
fi
current_governor=$(cat "$GOV_BASE/scaling_governor")
GOVERNORS_MENU=()
MSG_MAX_LENGTH=0
while read -r TAG ITEM; do
OFFSET=2
((${#ITEM} + OFFSET > MSG_MAX_LENGTH)) && MSG_MAX_LENGTH=${#ITEM}+OFFSET
GOVERNORS_MENU+=("$TAG" "$ITEM " "OFF")
done < <(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors | tr ' ' '\n' | grep -v "$current_governor")
scaling_governor=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Current CPU Scaling Governor is set to $current_governor" --checklist "\nSelect the Scaling Governor to use:\n" 16 $((MSG_MAX_LENGTH + 58)) 6 "${GOVERNORS_MENU[@]}" 3>&1 1>&2 2>&3 | tr -d '"')
done < <(tr ' ' '\n' <"$GOV_BASE/scaling_available_governors" | sed '/^$/d' | grep -vxF "$current_governor")
# A radiolist is used on purpose: only a single governor can be active at a time.
scaling_governor=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Current CPU Scaling Governor is set to $current_governor" --radiolist "\nSelect the Scaling Governor to use:\n" 16 $((MSG_MAX_LENGTH + 58)) 6 "${GOVERNORS_MENU[@]}" 3>&1 1>&2 2>&3 | tr -d '"')
[ -z "$scaling_governor" ] && {
whiptail --backtitle "Proxmox VE Helper Scripts" --title "No CPU Scaling Governor Selected" --msgbox "It appears that no CPU Scaling Governor was selected" 10 68
clear
@@ -49,7 +59,7 @@ yes)
EXISTING_CRONTAB=$(crontab -l 2>/dev/null)
if [[ -n "$EXISTING_CRONTAB" ]]; then
TEMP_CRONTAB_FILE=$(mktemp)
echo "$EXISTING_CRONTAB" | grep -v "@reboot (sleep 60 && echo*" >"$TEMP_CRONTAB_FILE"
echo "$EXISTING_CRONTAB" | grep -vF "@reboot (sleep 60 && echo" >"$TEMP_CRONTAB_FILE"
crontab "$TEMP_CRONTAB_FILE"
rm "$TEMP_CRONTAB_FILE"
fi