I'm a UNIX Sysadmin, specializing in Solaris and Linux. We should ALL know this stuff, but sometimes a trick or tip slips by, so every time I teach someone a neat trick (or someone teaches me a neat trick) it'll get shared here.

Tuesday, December 24, 2013

Power Management via udev

If you are running Linux on a laptop, there are times you'll want certain settings, or events to happen when your laptop is running on battery, vs AC.  I have a bunch of settings to extract as much battery life as possible via battery, and extract as much performance as I can via AC.  Many existing tools that do things like this automatically are way too general, so there's plenty of ways to do this kind of thing on your own, very easily.

There are plenty of instructions out there on how to run certain actions when your linux laptop is running on battery vs. AC using pm-utils.

Problem is, pm-utils is depreciated, and is being removed in favor of udev/systemd hooks.  Fedora 20 was one of the distros that did this recently.  Here's the simplest way to replace that functionality if you already have pm-utils scripts, or want to develop your own using udev rules.

First, you'll want to create your udev rule.  mine's /etc/udev/rules.d/99-powermiser.rules

**EDIT**  I have a githup repo with these now, with updates: https://github.com/c0t0d0s2/Powermiser

---begin udev rule---

SUBSYSTEM=="power_supply", ENV{POWER_SUPPLY_ONLINE}=="0", RUN+="/usr/local/sbin/powermiser battery"

SUBSYSTEM=="power_supply", ENV{POWER_SUPPLY_ONLINE}=="1", RUN+="/usr/local/sbin/powermiser ac"

---end udev rule

Now, here's my basic powermiser script:

---begin script---

#!/bin/bash


buslist="pci i2c"




case $1 in
true | battery)
echo "Enable powermiser"
echo '1500' > '/proc/sys/vm/dirty_writeback_centisecs';
for x in /sys/class/scsi_host/host*/link_power_management_policy; do
echo min_power > ${x}
done;
echo '0' > '/proc/sys/kernel/nmi_watchdog';
# System bus
for bus in $buslist; do
for x in /sys/bus/$bus/devices/*/power/control; do
echo 'auto' > ${x}
done
done
# USB powersaving
for x in /sys/bus/usb/devices/*/power/control; do
echo auto > ${x}
done
echo '1' > '/sys/module/snd_hda_intel/parameters/power_save';
# cpu
for x in /sys/devices/system/cpu/*/cpufreq/scaling_governor; do
echo powersave > ${x};
done


;;
false | ac)
echo "Disable powermiser"
echo '500' > '/proc/sys/vm/dirty_writeback_centisecs';
for x in /sys/class/scsi_host/host*/link_power_management_policy; do
echo max_performance > ${x}
done;


echo '1' > '/proc/sys/kernel/nmi_watchdog';
for bus in $buslist; do
for x in /sys/bus/$bus/devices/*/power/control; do
echo on > ${x}
done
done
for x in /sys/bus/usb/devices/*/power/control; do
echo on > ${x}
done
for x in /sys/devices/system/cpu/*/cpufreq/scaling_governor; do
echo performance > ${x};
done




;;
esac

---end script---

This script will change power settings for SATA devices, pci devices, and set the cpu scaling governor to either powersave or performance.  You cna easily add functions as you wish.

HELP!  My script doesnt work!
Make sure /usr/local/sbin/powermiser is owned by root, and chmod u+x -ed
Also make sure your udev rule is named ##-rulename.rule (e.g. 99-powermiser.rule) and also owned by root.

No comments:

Post a Comment

About Me

My photo
I am currently a Unix Systems Engineer for a cloud-based EMR company. I've been making large, complex systems "go" since 1995. I've worked with Novell and Exchange in the past, and now specialize in Solaris and Linux.