#!/usr/bin/env bash # echo "Starting sensor setup." monidir="/opt/monitoring" snmpdconf="/etc/snmp/snmpd.conf" mkdir -p "$monidir" # Install snmp & snmpd if apt install -y smartmontools snmp snmpd tmux vim && systemctl enable --now snmpd; then echo "SmartMonTools, SNMP, SNMPD, tmux & vim installed." else echo "Something went wrong during installation of smartmontools, snmp, snmpd, tmux & vim." exit 1 fi # Configure snmpd if grep -E '\brocommunity\b' "$snmpdconf" | grep -v 'rocommunity:' | grep -v public; then echo "rocommunity password already set, check line above for details." else read -p "Enter the rocommunity password: " rocompw echo "rocommunity $rocompw" >> "$snmpdconf" fi sed -i 's/agentaddress.*/agentaddress udp:161/' "$snmpdconf" sed -i 's/-u Debian-snmp/-u root/' /lib/systemd/system/snmpd.service systemctl daemon-reload read -p "Install Ceph sensors? [y/n] " answer case "$answer" in [Yy]|[Yy][Ee][Ss]) echo "Installing Ceph sensors." touch "$monidir"/snmp-ceph-free.bash touch "$monidir"/snmp-ceph-used.bash echo "Files touched." echo -e "#!/bin/bash if [ \"\$1\" = \"-g\" ]; then echo .1.3.6.1.2.1.25.1.8 echo integer ceph osd df | grep \"TOTAL\" | awk '{print \$12}' fi exit 0 # EOF" > "$monidir"/snmp-ceph-free.bash echo "snmp-ceph-free.bash written." echo -e "#!/bin/bash if [ \"\$1\" = \"-g\" ]; then echo .1.3.6.1.2.1.25.1.9 echo gauge ceph osd df | grep \"TOTAL\" | awk '{print \$14}' fi exit 0 # EOF" > "$monidir"/snmp-ceph-used.bash echo "snmp-ceph-used.bash written." chmod u+x $monidir/* echo "Executable flags set." if grep -q ceph-free "$snmpdconf"; then echo "snmp-ceph-free already added to $snmpdconf" else echo "pass .1.3.6.1.2.1.25.1.8 /bin/sh /opt/monitoring/snmp-ceph-free.bash" >> "$snmpdconf" echo "Added snmp-ceph-free.bash to snmpd config." fi if grep -q ceph-used "$snmpdconf"; then echo "snmp-ceph-used already added to $snmpdconf" else echo "pass .1.3.6.1.2.1.25.1.9 /bin/sh /opt/monitoring/snmp-ceph-used.bash" >> "$snmpdconf" echo "Added snmp-ceph-used.bash to snmpd config." fi systemctl restart snmpd echo "ceph sensor configuration done." ;; [Nn]|[Nn][Oo]|*) echo "Skipping Ceph sensors." ;; esac read -p "Install RAM sensor? [y/n] " answer case "$answer" in [Yy]|[Yy][Ee][Ss]) echo "Installing RAM sensor." touch "$monidir"/snmp-memusedpercent.bash echo "File touched." echo -e "#!/bin/bash # # Real Memory Percent Calculation total=\"\$(cat /proc/meminfo | grep 'MemTotal' | awk '{print \$2}')\" avail=\"\$(cat /proc/meminfo | grep 'MemAvailable' | awk '{print \$2}')\" used=\$((total - avail)) prcnt=\$(( (used * 100) / total )) if [ \"\$1\" = \"-g\" ]; then echo \".1.3.6.1.2.1.25.1.69\" echo \"integer\" echo \"\$prcnt\" fi exit 0 # EOF" > "$monidir"/snmp-memusedpercent.bash echo "snmp-memusedpercent.bash written." chmod u+x $monidir/* echo "Executable flags set." if grep -q memusedpercent "$snmpdconf"; then echo "snmp-memusedpercent already added to $snmpdconf" else echo "pass .1.3.6.1.2.1.25.1.69 /bin/sh /opt/monitoring/snmp-memusedpercent.bash" >> "$snmpdconf" echo "Added snmp-memusedpercent.bash to snmpd config." fi systemctl restart snmpd echo "RAM sensor configuration done." ;; [Nn]|[Nn][Oo]|*) echo "Skipping RAM sensor." ;; esac read -p "Install SMART sensor? [y/n] " answer case "$answer" in [Yy]|[Yy][Ee][Ss]) echo "Installing SMARTEST sensor." username="monitoring" userhome="/home/$username" monidir="/opt/monitoring" prtgdir="/var/prtg/scriptsxml" croncmd="/opt/monitoring/smartest.bash >> "$userhome"/prtg_smartest.log 2>&1" crontime="0 * * * * $croncmd" # Create user if useradd -m $username; then echo "$username created" # Set password read -p "Enter password for the "$username" user: " password echo "$username:$password" | chpasswd echo "Password set" else echo "$username already exists" fi # Create directories and files mkdir -p $prtgdir # Create files in user home touch $userhome/active_disks.txt touch $userhome/excluded_disks.txt touch $userhome/prtg_smartest.log touch $userhome/prtgout.xml touch $monidir/smartest.bash touch $prtgdir/prtg_smartest.bash echo "Files touched." # Change ownership of files chown $username:$username $userhome/* chown $username:$username $prtgdir/* echo "Ownership changed." # Set executable flags chmod u+x $prtgdir/* chmod u+x $monidir/* echo "Executable flags set." # Create crontab to check disks every hour if crontab -l | grep smartest; then echo "Cronjob already exists." else (crontab -l 2>/dev/null; echo "$crontime") | crontab - echo "Cronjob created" fi # Write prtg_smartest.bash echo -e "#!/usr/bin/env bash # cat \"/home/monitoring/prtgout.xml\" # EOF" > $prtgdir/prtg_smartest.bash echo "$prtgdir/prtg_smartest.bash written" # Write smartest.bash echo -e "#!/usr/bin/env bash # #Proxmox SMART Monitoring for PRTG | v2.0 Mar 2025 | exaSys AG # channel_id=2 output=\"/home/monitoring/prtgout.xml\" log=\"/home/monitoring/prtg_smartest.log\" active_disks=\"/home/monitoring/active_disks.txt\" excluded_disks=\"/home/monitoring/excluded_disks.txt\" disk_count_real=\"\$(lsblk -d | tail -n +2 | wc -l)\" disk_count_current=\"\$(cat \"\$active_disks\" | wc -l)\" if [ ! -f \"\$active_disks\" ] || [ ! -s \"\$active_disks\" ]; then lsblk -d | awk '{print \$1}' | tail -n +2 > \"\$active_disks\" elif [ \"\$disk_count_real\" -gt \"\$disk_count_current\" ]; then lsblk -d | awk '{print \$1}' | tail -n +2 > \"\$active_disks\" echo \"Disk(s) added\" >> \"\$log\" 2>&1 else echo \"\" > \"\$output\" for disk in \$(cat \"\$active_disks\") do if grep \"\$disk\" \"\$excluded_disks\" >> \"\$log\" 2>&1; then echo \"\$disk is excluded\" >> \"\$log\" 2>&1 elif [[ \"\$disk\" == zd* ]]; then echo \"\$disk is a ZFS device node, excluding\" >> \"\$log\" 2>&1 elif [[ \"\$disk\" == rbd* ]]; then echo \"\$disk is a Ceph device node, excluding\" >> \"\$log\" 2>&1 else smartresult=\$(/usr/sbin/smartctl -a /dev/\"\$disk\") if grep -E \"OK|PASSED\" <<< \"\$smartresult\" >> \"\$log\" 2>&1; then echo \"\$disk is okay\" >> \"\$log\" echo -e \"\\\nchannel_\$channel_id\\\n\$disk SMART Status\\\n1\\\n0.5\\\nCustom\\\n\\\n1\\\n\" >> \"\$output\" channel_id=\$((channel_id + 1)) if grep -i \"Wear_Leveling_Count\" <<< \"\$smartresult\" >> \"\$log\" 2>&1; then wlcresult=\$(/usr/sbin/smartctl -a /dev/\"\$disk\" | grep -i Wear_Leveling_Count | awk '{print \$4}' | sed 's/^0*//') echo \"\$disk: \$wlcresult% Lifetime remaining\" >> \"\$log\" 2>&1 echo -e \"\\\nchannel_\$channel_id\\\n\$disk WLC Lifetime\\\n1\\\n25\\\n10\\\nCustom\\\n%\\\n\$wlcresult\\\n\" >> \"\$output\" channel_id=\$((channel_id + 1)) else echo \"\$disk: No WLC available\" >> \"\$log\" 2>&1 fi else echo \"\$disk: SMART failed\" >> \"\$log\" 2>&1 echo -e \"\\\nchannel_\$channel_id\\\n\$disk SMART Status\\\n1\\\n0.5\\\nCustom\\\n\\\n0\\\n\" >> \"\$output\" fi fi done fi echo \"\" >> \"\$output\" # EOF" > $monidir/smartest.bash echo "$monidir/smartest.bash written." chmod u+x $monidir/* echo "Executable flags set." echo "SMART monitoring configuration done." # Exclude disks read -p "Enter raw disk name to exclude (e.g. sr0) or leave empty: " exclude if [[ -n $exclude ]]; then echo "$exclude" >> "$userhome"/excluded_disks.txt fi echo "Exclusion disk list updated." # Execute smartest.bash to populate disk list source /opt/monitoring/smartest.bash source /opt/monitoring/smartest.bash echo "Active disk list populated." ;; [Nn]|[Nn][Oo]|*) echo "Skipping SMART sensor." ;; esac echo "All done." # EOF