Skip to content

tmtri3102/battery-monitor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 

Repository files navigation

Battery Monitor Script for Ubuntu Server

Overview

This project sets up a Bash script on an Ubuntu laptop (acting as a server) to monitor battery status. It sends email alerts when the battery is discharging (not plugged in) and performs a graceful shutdown when the battery drops below 30% to prevent data loss for hosted apps/websites. The script runs periodically via cron and uses Python for email sending via SMTP (e.g., Gmail).

This is useful if you SSH into your Ubuntu server from another machine (e.g., MacBook) and want notifications to avoid unexpected shutdowns.

Requirements

  • Hardware/Setup:
    • Ubuntu laptop (server) with a battery, always on and hosting your app/website (e.g., via domain).
    • SSH access from another machine (e.g., ssh user@server).
  • Software:
    • Ubuntu 20.04+ (tested on 24.04.3 LTS).
    • Python3 pre-installed (default on Ubuntu).
    • Gmail account (or other SMTP provider) with 2-Step Verification enabled and an App Password generated (for security; do not use your main password).
  • Network:
    • Internet access on the Ubuntu server for email sending.
  • Permissions:
    • User with sudo access to configure cron and passwordless shutdown.

No additional packages needed beyond defaults, but if battery reading fails, install acpi with sudo apt install acpi.

Setup Steps

Step 1: Generate Gmail App Password

  • Go to https://myaccount.google.com/security > "2-Step Verification" > "App passwords."
  • Create a new App Password (e.g., name it "Ubuntu Battery Alert") and copy the 16-character code.
  • Expected Result: You have a secure App Password for SMTP (not your main Gmail password).
  • If Error: If 2-Step Verification isn't enabled, enable it first. If using non-Gmail, adjust SMTP settings accordingly (e.g., Outlook: smtp.office365.com:587).

Step 2: Create the Script

  • SSH into your Ubuntu server: ssh user@server.
  • Create the script: nano ~/battery_monitor.sh.
  • Paste the script code (see "The Script" section below), customize variables (e.g., EMAIL_TO, SMTP_PASS with your App Password).
  • Make executable: chmod +x ~/battery_monitor.sh.
  • Expected Result: Script file created and ready to run.
  • If Error: If nano not found, use vim or install sudo apt install nano. Permission issues? Run chmod again.

Step 3: Configure Passwordless Sudo for Shutdown

  • Run sudo visudo.
  • Add at the end: your_username ALL=(ALL) NOPASSWD: /sbin/shutdown (replace your_username with e.g., tomey-tran).
  • Save and exit (Ctrl+O, Enter, Ctrl+X in nano).
  • Test: sudo shutdown -h now (should shut down without password prompt; restart after).
  • Expected Result: Shutdown works without password, ensuring unattended operation.
  • If Error: "visudo: command not found"? Install sudo apt install sudo. Prompt still appears? Check syntax or username with whoami.

Step 4: Set Up Cron Job

  • Run crontab -e.
  • Add: */5 * * * * ~/battery_monitor.sh >> ~/battery_monitor.log 2>&1 (runs every 5 minutes, logs to ~/battery_monitor.log).
  • Save and exit.
  • Verify: crontab -l.
  • Expected Result: Script runs automatically every 5 minutes; check logs with cat ~/battery_monitor.log.
  • If Error: Cron not running? Check sudo service cron status. Log permission denied? Run chmod u+rw ~/battery_monitor.log.

Step 5: Test the Script

  • Run manually: ~/battery_monitor.sh.
  • To test email without unplugging: Uncomment the temporary test block in the script (see comments in script), save, run, then re-comment it out.
  • To test shutdown: Temporarily change -lt 30 to -lt 90 (if battery >90%, it won't trigger), unplug, run script, observe email and shutdown; revert after.
  • Expected Result: Log shows status; email arrives if discharging; shutdown at low battery with email.
  • If Error: See Troubleshooting section.

The Script

#!/bin/bash

# Email configuration (replace with your details)
EMAIL_TO="[email protected]"  # Your email to receive alerts
EMAIL_FROM="[email protected]"  # Same as SMTP_USER for Gmail
SMTP_SERVER="smtp.gmail.com"
SMTP_PORT=587
SMTP_USER="[email protected]"  # Your Gmail address
SMTP_PASS="your_app_password"  # 16-character App Password from Google
LOG_FILE="$HOME/battery_monitor.log"

# Check battery status
BATTERY_STATUS=$(cat /sys/class/power_supply/BAT*/status 2>/dev/null)
BATTERY_PERCENT=$(cat /sys/class/power_supply/BAT*/capacity 2>/dev/null)

# Log current time and status
echo "$(date): Battery Status: $BATTERY_STATUS, Level: $BATTERY_PERCENT%" >> "$LOG_FILE"

# Check if battery info is readable
if [ -z "$BATTERY_STATUS" ] || [ -z "$BATTERY_PERCENT" ]; then
    echo "$(date): Error: Could not read battery status!" >> "$LOG_FILE"
    exit 1
fi

# Alert if discharging
if [ "$BATTERY_STATUS" = "Discharging" ]; then
    SUBJECT="ALERT: Ubuntu Server Battery Discharging!"
    BODY="Battery is DISCHARGING at $BATTERY_PERCENT%. Server may shut down, risking data loss for your website/app!"

    # Send email using Python
    python3 - <<EOF 2>> "$LOG_FILE"
import smtplib
from email.mime.text import MIMEText

msg = MIMEText("$BODY")
msg['Subject'] = "$SUBJECT"
msg['From'] = "$EMAIL_FROM"
msg['To'] = "$EMAIL_TO"

try:
    server = smtplib.SMTP("$SMTP_SERVER", $SMTP_PORT)
    server.starttls()
    server.login("$SMTP_USER", "$SMTP_PASS")
    server.sendmail("$EMAIL_FROM", "$EMAIL_TO", msg.as_string())
    server.quit()
    print("$(date): Email sent successfully")
except Exception as e:
    print("$(date): Email failed: " + str(e))
EOF

    echo "$(date): Alert triggered: Battery discharging at $BATTERY_PERCENT%" >> "$LOG_FILE"
fi

# Graceful shutdown if battery below 30% while discharging
# Suggestion: For testing, temporarily change -lt 30 to -lt 90 (if battery is ~95%), unplug charger, run script, expect shutdown email and system halt; revert after testing.
if [ "$BATTERY_STATUS" = "Discharging" ] && [ "$BATTERY_PERCENT" -lt 30 ]; then
    SHUTDOWN_SUBJECT="ALERT: Ubuntu Server Shutting Down!"
    SHUTDOWN_BODY="Battery level dropped to $BATTERY_PERCENT%. Server is shutting down now to prevent data loss."

    # Send shutdown email
    python3 - <<EOF 2>> "$LOG_FILE"
import smtplib
from email.mime.text import MIMEText

msg = MIMEText("$SHUTDOWN_BODY")
msg['Subject'] = "$SHUTDOWN_SUBJECT"
msg['From'] = "$EMAIL_FROM"
msg['To'] = "$EMAIL_TO"

try:
    server = smtplib.SMTP("$SMTP_SERVER", $SMTP_PORT)
    server.starttls()
    server.login("$SMTP_USER", "$SMTP_PASS")
    server.sendmail("$EMAIL_FROM", "$EMAIL_TO", msg.as_string())
    server.quit()
    print("$(date): Shutdown email sent successfully")
except Exception as e:
    print("$(date): Shutdown email failed: " + str(e))
EOF

    echo "$(date): Initiating shutdown due to low battery ($BATTERY_PERCENT%)" >> "$LOG_FILE"
    sudo shutdown -h now
fi

# Temporary email test block (uncomment to test email sending while charged; run script, check inbox/log, then re-comment out)
# SUBJECT="TEST: Email Functionality Check"
# BODY="This is a test email from the battery monitor script at $(date). Battery is $BATTERY_PERCENT% and $BATTERY_STATUS."
#
# python3 - <<EOF 2>> "$LOG_FILE"
# import smtplib
# from email.mime.text import MIMEText
#
# msg = MIMEText("$BODY")
# msg['Subject'] = "$SUBJECT"
# msg['From'] = "$EMAIL_FROM"
# msg['To'] = "$EMAIL_TO"
#
# try:
#     server = smtplib.SMTP("$SMTP_SERVER", $SMTP_PORT)
#     server.starttls()
#     server.login("$SMTP_USER", "$SMTP_PASS")
#     server.sendmail("$EMAIL_FROM", "$EMAIL_TO", msg.as_string())
#     server.quit()
#     print("$(date): Test email sent successfully")
# except Exception as e:
#     print("$(date): Test email failed: " + str(e))
# EOF

Testing

  • Manual Run: ~/battery_monitor.sh – Logs status; sends alert if discharging.
  • Email Test: Uncomment the temporary test block, save/run, check email/log for success; re-comment.
  • Shutdown Test: Change -lt 30 to higher value (e.g., -lt 90), unplug, run; expect email and shutdown. Revert threshold.
  • Cron Test: Wait 5 minutes, check log for new entry.

Troubleshooting

  • Email Failed (535 Error): Wrong App Password – regenerate and update script. Check spam folder. Non-Gmail? Adjust SMTP_SERVER/PORT.
  • Battery Read Error: Install acpi, replace status lines: BATTERY_STATUS=$(acpi -b | grep -oP '(Charging|Discharging|Full)') and BATTERY_PERCENT=$(acpi -b | grep -oP '\d+%' | tr -d '%').
  • Shutdown Fails: Sudo prompt? Re-check visudo line. Test sudo shutdown -h now manually.
  • No Logs: Permission issue – chmod u+rw ~/battery_monitor.log. Cron not running? sudo service cron restart.
  • Script Not Executable: Run chmod +x ~/battery_monitor.sh.
  • Data Loss Risk: Always back up your app/website data regularly (e.g., via separate cron job).

For questions, consult Ubuntu docs or adjust script as needed.

About

A Bash script that sends email alerts when the battery is discharging

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published