Sat Mar 23
Run-through on how to make things happen using udev rules and bash scripts.
Before we get started, this should be replicable on any system using Arch Linux but just in case here is my system:
In my case, I made a udev rules file which checks if my laptop is connected to AC power and runs a script.
First we start off in a terminal to find out what the computer sees when we plug and unplug the AC power adapter. We can use the command:
sudo udevadm monitor --environment
Now if you plug in your power adapter, you should see some values change. Make sure to look at the non-kernel values as those are what udev looks at.
We want to create a file in the /udev
directory called onpower.rules
(or whatever you want it to be!). This is where we will define the conditions that need to be met.
For my example of running a script to control refresh rate I had the following lines in my onpower.rules
file:
SUSBSYSTEM=="power_supply", ENV{POWER_SUPPLY_ONLINE}=="1", RUN+="/usr/bin/sudo --user=ary /usr/local/bin/refresh1.sh connected"
SUSBSYSTEM=="power_supply", ENV{POWER_SUPPLY_ONLINE}=="0", RUN+="/usr/bin/sudo --user=ary /usr/local/bin/refresh1.sh disconnected"
The first line executes a script called refresh1.sh with the argument connected when a power supply is detected online, we want to run this with elevated priveledges as the user in the case of refresh rate, you might need to change the permissions for your use case.
The second line executes the same script with the argument disconnected when the power supply goes offline.
Now we can write the script that will be run. In my case, I am calling a swaymsg output eDP-1 mode 3072x1920@120.002Hz
inside of a case statement to change my refresh rate
whenever my power supply is plugged in. When we were figuring this out, I was having an issue where the script was working for basic shell commands like writing to a file but not executing binaries, this was because we were not calling the proper environment variables. You will need to find out what these are for different use-cases.
#!/bin/bash
# This script is called by the udev rule /etc/udev/onpower.rules
export SWAYSOCK="/run/user/1000/$(/bin/ls /run/user/1000 | grep sway)"
export DISPLAY=:0
case $1 in
"connected")
echo "connected :) @ $(date)" > /dev/shm/acstatus # write to a file letting us know if its connected for debugging.
/usr/bin/swaymsg output eDP-1 mode 3072x1920@120.002Hz &>> /dev/shm/acstatus
;;
"disconnected")
echo "disconnected :( @ $(date)" > /dev/shm/acstatus # write to a file letting us know if its connected for debugging.
/usr/bin/swaymsg output eDP-1 mode 3072x1920@60.000Hz &>> /dev/shm/acstatus
;;
*)
echo "unknown" > /dev/shm/acstatus
/usr/bin/swaymsg output eDP-1 mode 3072x1920@60.000Hz &>> /dev/shm/acstatus
;;
esac
exit 0
With this script written, we can make it executable with chmod 777 script.sh
or chmod +x script.sh
and test it. If it works when running manually, we can test it using the udev rules. If not, we should go back and check for any errors in the script.
We can now finish up by reloading the udev rules with:
sudo udevadm control --reload-rules && sudo udevadm trigger
and finally plugging in the ac adapter!
With this, you should have a functioning udev rule that runs a shell script on AC power.