Automatic Power Profile Switching on AC/Battery
Problem
I wanted my laptop to automatically switch between power profiles when plugging/unplugging the AC adapter. The default behavior either doesn’t exist or requires manual intervention every time (and let’s be honest, I will forget).
Solution
A simple Ruby script triggered by udev rules that detects AC power state and switches TuneD profiles accordingly.
The Ruby Script
Save as /usr/local/bin/power-profile-switch.rb:
#!/usr/bin/env ruby
# Check if on AC power by reading the online status
ac_online = false
# Find AC adapter(s) and check if any are online
Dir.glob('/sys/class/power_supply/AC*/online').each do |path|
if File.read(path).strip == '1'
ac_online = true
break
end
end
# Using TuneD
if ac_online
system('tuned-adm', 'profile', 'throughput-performance')
else
system('tuned-adm', 'profile', 'powersave')
end
The udev Rule
Save as /etc/udev/rules.d/99-power-profile.rules:
# Trigger on AC adapter state changes
SUBSYSTEM=="power_supply", ATTR{online}=="0", RUN+="/usr/local/bin/power-profile-switch.rb"
SUBSYSTEM=="power_supply", ATTR{online}=="1", RUN+="/usr/local/bin/power-profile-switch.rb"
Boot-time Profile Setting
There’s one gap: if you shut down in one state and boot up in another state, the power profile won’t match the current power state until you plug/unplug the adapter. A systemd timer solves this by checking the power state at boot.
systemd Service File
Save as
/etc/systemd/system/power-profile-switch.service:
[Unit]
Description=Set power profile based on AC adapter status
After=multi-user.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/power-profile-switch.rb
User=root
systemd Timer File
Save as
/etc/systemd/system/power-profile-switch.timer:
[Unit]
Description=Run power profile switch at boot
Requires=power-profile-switch.service
[Timer]
OnBootSec=30sec
[Install]
WantedBy=timers.target
Installation
# Make the script executable
sudo chmod +x /usr/local/bin/power-profile-switch.rb
# Set correct SELinux context (if SELinux is enabled)
sudo restorecon -v /usr/local/bin/power-profile-switch.rb
# Reload udev rules
sudo udevadm control --reload-rules
# Enable and start the systemd timer
sudo systemctl enable power-profile-switch.timer
sudo systemctl start power-profile-switch.timer
How It Works
The udev rule triggers whenever the online attribute of
any power supply changes (i.e., when you plug or unplug the AC adapter).
The Ruby script then checks all AC adapters and switches to:
-
throughput-performancewhen plugged in -
powersavewhen on battery
The timer runs once, 30 seconds after boot, allowing time for power supply detection. This preserves your ability to manually change power profiles without the system constantly overriding your choices.