In this scenario, I have a Mele Quieter 3C that I wanted to prevent from throttling due to higher CPU temperatures. These mini pcs don’t have any fans for cooling as they are marketed as low noise devices. This pc is running my PLEX server on Ubuntu 24 and few other small apps. At time, it gets pretty hot. So, I decided to setup a usb powered fan, plugged into a Shelly Outlet Gen 4 and setup a script and a system service for temperature monitoring to trigger the outlet to turn on or off based on the temperature.
Below is the script for monitoring. I saved this file in my home folder. I recommend the same for you to make it easier to adjust the script. This script is meant for monitoring the localhost and 1 or more other servers running ubuntu with lm-sensors. So, if you want to monitor just the localhost, you still need to enter in something for the <user> and [host] when running the script. See Usage: in script below.
Create a file named temp_shelly_control.sh
nano temp_shelly_control.sh
Copy the block of code below and paste it into the editor, adjust the service ON_URL and OFF_URL ot match your specific Shelly Outlet and save the file.
#!/bin/bash
# Script: temp_shelly_control.sh
# Purpose: Monitor CPU temps (local + remote) and control Shelly outlet
# Usage: ./temp_shelly_control.sh <user> [host1 host2 ...]
# Edit the service file sudo nano /etc/systemd/system/temp_shelly_control.service
ON_URL="http://office.shelly.outlet/rpc/Switch.Set?id=0&on=true"
OFF_URL="http://office.shelly.outlet/rpc/Switch.Set?id=0&on=false"
CHECK_INTERVAL=10 # seconds between checks
ON_THRESHOLD=68 # °C
OFF_THRESHOLD=55 # °C
set -e
usage() {
echo "Usage: $0 <user> [host1 host2 ...]"
exit 1
}
# Function to get CPU temperature locally (integer °C)
get_local_cpu_temp() {
if command -v sensors >/dev/null 2>&1; then
sensors 2>/dev/null | grep -m 1 "Package id 0" | awk '{gsub(/\+|°C/,""); printf "%d\n", $4}' ||
sensors 2>/dev/null | grep -m 1 "temp1" | awk '{gsub(/\+|°C/,""); printf "%d\n", $2}'
elif [ -f /sys/class/thermal/thermal_zone0/temp ]; then
awk '{printf "%d\n", $1/1000}' /sys/class/thermal/thermal_zone0/temp
fi
}
# Function to get CPU temperature remotely (integer °C)
get_remote_cpu_temp() {
local server="$1"
ssh -o BatchMode=yes -o ConnectTimeout=10 "$USER@$server" '
if command -v sensors >/dev/null 2>&1; then
sensors 2>/dev/null | grep -m 1 "Package id 0" | awk "{gsub(/\\+|°C/,\"\"); printf \"%d\n\", \$4}" ||
sensors 2>/dev/null | grep -m 1 "temp1" | awk "{gsub(/\\+|°C/,\"\"); printf \"%d\n\", \$2}"
elif [ -f /sys/class/thermal/thermal_zone0/temp ]; then
awk "{printf \"%d\n\", \$1/1000}" /sys/class/thermal/thermal_zone0/temp
fi
' 2>/dev/null || echo "NaN"
}
# Validate arguments
if [ "$#" -lt 1 ]; then
usage
fi
USER="$1"
shift
SERVERS=("$@")
# Track Shelly state (0 = OFF, 1 = ON)
SHELLY_STATE=0
while true; do
TEMPS=()
# Get local temp
local_temp=$(get_local_cpu_temp)
TEMPS+=("$local_temp")
# Get remote temps
for server in "${SERVERS[@]}"; do
remote_temp=$(get_remote_cpu_temp "$server")
TEMPS+=("$remote_temp")
done
# Debug output (optional)
echo "Temps: ${TEMPS[*]}"
# Determine if any temp exceeds ON threshold
any_over=0
all_below=1
for t in "${TEMPS[@]}"; do
if [ "$t" != "NaN" ]; then
if [ "$t" -gt "$ON_THRESHOLD" ]; then
any_over=1
fi
if [ "$t" -ge "$OFF_THRESHOLD" ]; then
all_below=0
fi
fi
done
# Control Shelly outlet
if [ "$any_over" -eq 1 ] && [ "$SHELLY_STATE" -eq 0 ]; then
echo "🔥 Temp exceeded $ON_THRESHOLD°C — Turning Shelly ON"
curl -s "$ON_URL" >/dev/null
SHELLY_STATE=1
elif [ "$all_below" -eq 1 ] && [ "$SHELLY_STATE" -eq 1 ]; then
echo "❄️ Temps dropped below $OFF_THRESHOLD°C — Turning Shelly OFF"
curl -s "$OFF_URL" >/dev/null
SHELLY_STATE=0
fi
sleep "$CHECK_INTERVAL"
done
Next, create the service file…
sudo nano /etc/systemd/system/temp_shelly_control.service
Copy and paste the following code block into the editor, then save and close it. Be sure to adjust your ExecStart path to match where you put your script as well as the User and WorkingDirectory.
[Unit]
Description=CPU Temperature Monitor and Shelly Control
After=network.target
[Service]
Type=simple
ExecStart=/home/matt/Scripts/temp_shelly_control.sh matt landscape.nwd.bz
Restart=always
RestartSec=5
User=matt
# Optional: set a working directory
WorkingDirectory=/home/matt/Scripts
# Optional: log output to journal
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
Next, enable the system service and start it
sudo systemctl daemon-reload
sudo systemctl enable temp_shelly_control.service
sudo systemctl start temp_shelly_control.service
That’s it! Now, you can view the status in terminal.
sudo systemctl status temp_shelly_control.service