I wrote a script that lets me toggle my laptop screen's brightness (I run if from a hotkey bound by xbindkeys
),
but it involves writing to /sys/class/backlight/acpi_video0/brightness
.
For now, I've just been making it able to write to that file by doing
sudo chown $USER: /sys/class/backlight/acpi_video0/brightness
but that resets after every time I reboot the laptop,
so I need to rerun it before I can use my hotkey.
What's the proper and persistent way to do this?
EDIT_3 (ie, added after the below 2 edits) (technically "the answer"):
I got fed up trying to make the udev stuff work,
and (after much confusion (an unknown amount of which was caused by me simply typoing and missing the "t" in "brightness"))
finally got it to work like so:
(To be explicit, my echo $USER
is o1
.)
So
I created a file:
/home/o1/.icanhasbrightness.sh
containing:
#!/usr/bin/bash
chown o1: /sys/class/backlight/acpi_video0/brightness
I did:
> sudo chown root:root /home/o1/.icanhasbrightness.sh
and
> sudo chmod 0711 /home/o1/.icanhasbrightness.sh
(
such that
> stat /home/o1/.icanhasbrightness.sh|head -n 4|tail -n 1
#=>
Access: (0711/-rwx--x--x) Uid: ( 0/ root) Gid: ( 0/ root)
)
I did:
> sudo visudo
and added the line:
o1 ALL=(ALL) NOPASSWD: /home/o1/.icanhasbrightness.sh
I modified my fishshell function to check if I'm not the owner of the brightness file, and if not, run that script.
(
function brightness_set_current
#todo this is prolly the "wrong" way of handling this but whatever it works
if test $USER != (stat -c %U /sys/class/backlight/acpi_video0/brightness)
sudo /home/o1/.icanhasbrightness.sh
end
echo $argv > /sys/class/backlight/acpi_video0/brightness
end
)
... So I guess that technically answers my own question, but...
- (1) I feel this is probably the "wrong" way of doing it(?)
- (2) I'm so tired of messing around with this by now that I don't feel like posting it an an "answer" right now anyway
(((
And for the benefit of any hypothetical future equivalents of my past self
(
ie, admittedly unrelated to the actual question I was trying to get an answer to here,
but I'll leave it here for now and figure out some better place to put it later, where it's actually likely to be seen by someone who would find it useful
),
who just want a hotkey to toggle brightness and screen colour temperatures,
then, assuming you're already using fishshell (and know to save these as autoloading functions and all that), the code was:
function brightness_get_current
cat /sys/class/backlight/acpi_video0/brightness
end
function brightness_set_current
#td FIX(?)
if test $USER != (stat -c %U /sys/class/backlight/acpi_video0/brightness)
sudo /home/o1/.icanhasbrightness.sh
end
echo $argv > /sys/class/backlight/acpi_video0/brightness
end
function brightness_get_max --description 'max brightness, mb'
cat /sys/class/backlight/acpi_video0/max_brightness
end
function brightness_set_max --description 'max brightness, mb'
brightness_set_current (brightness_get_max)
end
function brightness_toggle
#
#
set -l verbose $argv
set -l current_brightness (brightness_get_current)
set -l current_ct (xsct|g --nocolor -o '\d+$')
#bk
# echo current_ct $current_ct
#
set -l brightness
if test $current_brightness -eq 0
set brightness 'min'
else if test $current_brightness -eq (brightness_get_max)
set brightness 'max'
else
set brightness 'mid'
end
set -l redness
if test $current_ct -eq 1000
set redness 'red'
else if test $current_ct -lt 1000
set redness 'red_super'
else if test $current_ct -lt 700
set redness 'red_impossible'
else if test $current_ct -lt 6500
set redness 'mid'
else if test $current_ct -eq 6500
set redness 'white'
else
set redness 'blue'
end
#
function brightness_set_to_max_white
brightness_set_max
D0 xsct 0 #ie 6500
end
function brightness_set_to_min_red
brightness_set_current 0
D0 xsct 1000
end
function brightness_set_to_min_white
brightness_set_current 0
D0 xsct 0 #ie 6500
end
#
#bk
if test "$verbose"
echo \t'current state:'
echo \t\t'brightness:' \t$brightness
echo \t\t'redness:' \t$redness
end
#
if test "$brightness" = 'max' -a "$redness" = 'white'
#bk
test "$verbose"
and echo "1 - setting to min_red ( from max_white )"
brightness_set_to_min_red
else if test "$brightness" = 'min' -a "$redness" = 'red'
#bk
test "$verbose"
and echo "2 - setting to min_white ( from min_red )"
brightness_set_to_min_white
else if test "$brightness" = 'min' -a "$redness" = 'white'
#bk
test "$verbose"
and echo "3 - setting to max_white ( from min_white )"
brightness_set_to_max_white
else
#bk
test "$verbose"
and echo "4 - setting to max_white ( from other )"
brightness_set_to_max_white
end
end
and to bind it to a key,
I just put into ~/.xbindkeysrc
this content:
"fish -c 'brightness_toggle'"
Mod4 + less
(Mod4 + less
just being what xbindkeys -mk
told me it called that key combo when I pressed it)
... oh yeah, except to install xsct
you also gotta do
> git clone 'https://github.com/faf0/sct.git'
(while in whatever dir you want the sct
dir to end up in)
then
> sudo apt install libxrandr-dev
(a dependency you need to compile it)
then (while in that sct
dir created by the git clone
-ing)
> sudo make install
(
Also, I set up hotkeys to flip which edge of the screen is "up"
(which also relies on that brightness_set_current
function cuz, at least for me, using xrandr -o
messes with the brightness for some reason)
with fishshell:
function screen_orientation --description 'screen/monitor orientation - possible arguments are normal/left/right/inverted'
set current_brightness (cat /sys/class/backlight/acpi_video-0/max_brightness)
xrandr -o $argv
and brightness_set_current $current_brightness
# guess i don't need this really?
# if thnpadd
# nitrogen --restore
# # and D0 nitrogen --restore
# end
end
and ~/.xbindkeysrc
:
"fish -c 'screen_orientation left'"
Mod4 + Left
"fish -c 'screen_orientation normal'"
Mod4 + Up
"fish -c 'screen_orientation right'"
Mod4 + Right
"fish -c 'screen_orientation inverted'"
Mod4 + Down
)
)))
EDIT_1 ("udev maybe?"):
I found on the archwiki:
By default, only root
can change the brightness by this method. To allow users in [for example] the video
group to change the brightness, a udev rule such as the following can be used:
[write to this file:]
/etc/udev/rules.d/backlight.rules
[this content:]
ACTION=="add", SUBSYSTEM=="backlight", KERNEL=="acpi_video0", GROUP="video", MODE="0664"
So I did that, then did:
sudo groupadd video
and:
sudo usermod -aG video o1
(
Well, assuming I'm correctly remembering exactly what I did in what order,
but regardless, groups $USER
does confirm that I am in the video
group.
)
but after restarting, still, trying to write to it like this still gets:
> echo 5 > /sys/class/backlight/acpi_video0/brightness
#=>
warning: An error occurred while redirecting file '/sys/class/backlight/acpi_video0/brightness'
open: Permission denied
and this:
> stat /sys/class/backlight/acpi_video0/brightness
#=>
File: /sys/class/backlight/acpi_video0/brightness
Size: 4096 Blocks: 0 IO Block: 4096 regular file
Device: 16h/22d Inode: 22741 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2021-09-24 10:51:53.894540644 -0700
Modify: 2021-09-24 10:51:53.888124116 -0700
Change: 2021-09-24 10:51:53.888124116 -0700
Birth: -
which means it's still only root
that has write permissions to the file, right?
That udev rule was supposed to... change ownership of the file to the video
group, right?
(
Assuming "this file is owned by this group" is getting the concept and/or terminology correct...?
At any rate, it was supposed to give the video
group write-permission for the file, right?
)
So why didn't it work?
-- I mean, since I can't exactly hop on arch and give it a try,
I can only assume that what I did would've worked on arch(?),
so how does ubuntu differ?
EDIT_2 ("udev should work??"):
From what I can understand from this udev tutorial,
it should work?
(
Or at any rate, it does say:
Reading rules file: /etc/udev/rules.d/backlight.rules
-- but it doesn't say anything about "GROUP
" OR "MODE
".
)
(I also tried changing the =
's to :=
's (to "make sure that it is not overridden by other rules"), just in case.)
> udevadm info -a /sys/class/backlight/acpi_video0/
#=>
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
looking at device '/devices/pci0000:00/0000:00:01.0/backlight/acpi_video0':
KERNEL=="acpi_video0"
SUBSYSTEM=="backlight"
DRIVER==""
ATTR{max_brightness}=="15"
ATTR{actual_brightness}=="15"
ATTR{bl_power}=="0"
ATTR{type}=="firmware"
ATTR{brightness}=="15"
ATTR{scale}=="unknown"
looking at parent device '/devices/pci0000:00/0000:00:01.0':
KERNELS=="0000:00:01.0"
SUBSYSTEMS=="pci"
DRIVERS=="radeon"
ATTRS{local_cpulist}=="0-1"
ATTRS{msi_bus}=="1"
ATTRS{max_link_width}=="255"
ATTRS{consistent_dma_mask_bits}=="40"
ATTRS{driver_override}=="(null)"
ATTRS{power_dpm_state}=="balanced"
ATTRS{revision}=="0x00"
ATTRS{device}=="0x9648"
ATTRS{local_cpus}=="3"
ATTRS{subsystem_device}=="0x21ea"
ATTRS{d3cold_allowed}=="1"
ATTRS{power_method}=="dpm"
ATTRS{numa_node}=="-1"
ATTRS{broken_parity_status}=="0"
ATTRS{power_state}=="D0"
ATTRS{boot_vga}=="1"
ATTRS{irq}=="31"
ATTRS{current_link_width}=="0"
ATTRS{current_link_speed}=="Unknown"
ATTRS{class}=="0x030000"
ATTRS{power_profile}=="default"
ATTRS{dma_mask_bits}=="40"
ATTRS{vendor}=="0x1002"
ATTRS{subsystem_vendor}=="0x17aa"
ATTRS{enable}=="1"
ATTRS{power_dpm_force_performance_level}=="auto"
ATTRS{ari_enabled}=="0"
ATTRS{max_link_speed}=="Unknown"
looking at parent device '/devices/pci0000:00':
KERNELS=="pci0000:00"
SUBSYSTEMS==""
DRIVERS==""
and:
> udevadm test --action="add" '/devices/pci0000:00/0000:00:01.0/backlight/acpi_video0'
#=>
Load module index
Parsed configuration file /usr/lib/systemd/network/99-default.link
Parsed configuration file /usr/lib/systemd/network/73-usb-net-by-mac.link
Created link configuration context.
Reading rules file: /usr/lib/udev/rules.d/39-usbmuxd.rules
Reading rules file: /usr/lib/udev/rules.d/40-usb-media-players.rules
Reading rules file: /usr/lib/udev/rules.d/40-usb_modeswitch.rules
Reading rules file: /usr/lib/udev/rules.d/40-vm-hotadd.rules
Reading rules file: /usr/lib/udev/rules.d/50-apport.rules
Reading rules file: /usr/lib/udev/rules.d/50-firmware.rules
Reading rules file: /usr/lib/udev/rules.d/50-udev-default.rules
Reading rules file: /usr/lib/udev/rules.d/55-dm.rules
Reading rules file: /usr/lib/udev/rules.d/55-ippusbxd.rules
Reading rules file: /usr/lib/udev/rules.d/56-hpmud.rules
Reading rules file: /usr/lib/udev/rules.d/56-lvm.rules
Reading rules file: /usr/lib/udev/rules.d/60-autosuspend-chromiumos.rules
Reading rules file: /usr/lib/udev/rules.d/60-block.rules
Reading rules file: /usr/lib/udev/rules.d/60-cdrom_id.rules
Reading rules file: /usr/lib/udev/rules.d/60-crda.rules
Reading rules file: /usr/lib/udev/rules.d/60-drm.rules
Reading rules file: /usr/lib/udev/rules.d/60-evdev.rules
Reading rules file: /usr/lib/udev/rules.d/60-fido-id.rules
Reading rules file: /usr/lib/udev/rules.d/60-input-id.rules
Reading rules file: /usr/lib/udev/rules.d/60-inputattach.rules
Reading rules file: /usr/lib/udev/rules.d/60-libgphoto2-6.rules
Reading rules file: /usr/lib/udev/rules.d/60-libsane.rules
Reading rules file: /usr/lib/udev/rules.d/60-pcmcia.rules
Reading rules file: /usr/lib/udev/rules.d/60-persistent-alsa.rules
Reading rules file: /usr/lib/udev/rules.d/60-persistent-input.rules
Reading rules file: /usr/lib/udev/rules.d/60-persistent-storage-dm.rules
Reading rules file: /usr/lib/udev/rules.d/60-persistent-storage-tape.rules
Reading rules file: /usr/lib/udev/rules.d/60-persistent-storage.rules
Reading rules file: /usr/lib/udev/rules.d/60-persistent-v4l.rules
Reading rules file: /usr/lib/udev/rules.d/60-sensor.rules
Reading rules file: /usr/lib/udev/rules.d/60-serial.rules
Reading rules file: /usr/lib/udev/rules.d/60-tpm-udev.rules
Reading rules file: /usr/lib/udev/rules.d/61-autosuspend-manual.rules
Reading rules file: /usr/lib/udev/rules.d/61-kde-bluetooth-rfkill.rules
Reading rules file: /usr/lib/udev/rules.d/61-persistent-storage-android.rules
Reading rules file: /usr/lib/udev/rules.d/64-btrfs.rules
Reading rules file: /usr/lib/udev/rules.d/64-xorg-xkb.rules
Reading rules file: /usr/lib/udev/rules.d/65-libwacom.rules
Reading rules file: /usr/lib/udev/rules.d/66-snapd-autoimport.rules
Reading rules file: /usr/lib/udev/rules.d/69-cd-sensors.rules
Reading rules file: /usr/lib/udev/rules.d/69-libmtp.rules
Reading rules file: /usr/lib/udev/rules.d/69-lvm-metad.rules
Reading rules file: /usr/lib/udev/rules.d/69-wacom.rules
Reading rules file: /usr/lib/udev/rules.d/70-joystick.rules
Reading rules file: /usr/lib/udev/rules.d/70-mouse.rules
Reading rules file: /usr/lib/udev/rules.d/70-pcspkr-beep.rules
Reading rules file: /usr/lib/udev/rules.d/70-power-switch.rules
Reading rules file: /usr/lib/udev/rules.d/70-printers.rules
Reading rules file: /usr/lib/udev/rules.d/70-spice-vdagentd.rules
Reading rules file: /usr/lib/udev/rules.d/70-touchpad.rules
Reading rules file: /usr/lib/udev/rules.d/70-u2f.rules
Reading rules file: /usr/lib/udev/rules.d/70-uaccess.rules
Reading rules file: /usr/lib/udev/rules.d/71-power-switch-proliant.rules
Reading rules file: /usr/lib/udev/rules.d/71-seat.rules
Reading rules file: /usr/lib/udev/rules.d/71-u-d-c-gpu-detection.rules
Reading rules file: /usr/lib/udev/rules.d/73-seat-late.rules
Reading rules file: /usr/lib/udev/rules.d/73-special-net-names.rules
Reading rules file: /usr/lib/udev/rules.d/75-net-description.rules
Reading rules file: /usr/lib/udev/rules.d/75-probe_mtd.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-broadmobi-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-cinterion-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-dell-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-dlink-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-ericsson-mbm.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-fibocom-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-foxconn-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-gosuncn-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-haier-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-huawei-net-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-longcheer-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-mtk-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-nokia-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-pcmcia-device-blacklist.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-qdl-device-blacklist.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-quectel-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-sierra.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-simtech-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-telit-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-tplink-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-ublox-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-usb-device-blacklist.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-usb-serial-adapters-greylist.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-x22x-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/77-mm-zte-port-types.rules
Reading rules file: /usr/lib/udev/rules.d/78-graphics-card.rules
Reading rules file: /usr/lib/udev/rules.d/78-sound-card.rules
Reading rules file: /usr/lib/udev/rules.d/80-debian-compat.rules
Reading rules file: /usr/lib/udev/rules.d/80-drivers.rules
Reading rules file: /usr/lib/udev/rules.d/80-iio-sensor-proxy.rules
Reading rules file: /usr/lib/udev/rules.d/80-libinput-device-groups.rules
Reading rules file: /usr/lib/udev/rules.d/80-mm-candidate.rules
Reading rules file: /usr/lib/udev/rules.d/80-net-setup-link.rules
Reading rules file: /usr/lib/udev/rules.d/80-udisks2.rules
Reading rules file: /usr/lib/udev/rules.d/81-net-dhcp.rules
Reading rules file: /usr/lib/udev/rules.d/84-nm-drivers.rules
Reading rules file: /usr/lib/udev/rules.d/85-hdparm.rules
Reading rules file: /usr/lib/udev/rules.d/85-hplj10xx.rules
Reading rules file: /usr/lib/udev/rules.d/85-nm-unmanaged.rules
Reading rules file: /usr/lib/udev/rules.d/85-regulatory.rules
Reading rules file: /usr/lib/udev/rules.d/85-tlp-rdw.rules
Reading rules file: /usr/lib/udev/rules.d/85-tlp.rules
Reading rules file: /usr/lib/udev/rules.d/90-alsa-restore.rules
Reading rules file: /usr/lib/udev/rules.d/90-bolt.rules
Reading rules file: /usr/lib/udev/rules.d/90-console-setup.rules
Reading rules file: /usr/lib/udev/rules.d/90-fwupd-devices.rules
Reading rules file: /usr/lib/udev/rules.d/90-libinput-fuzz-override.rules
Reading rules file: /usr/lib/udev/rules.d/90-nm-thunderbolt.rules
Reading rules file: /usr/lib/udev/rules.d/90-pulseaudio.rules
Reading rules file: /usr/lib/udev/rules.d/95-cd-devices.rules
Reading rules file: /usr/lib/udev/rules.d/95-dm-notify.rules
Reading rules file: /usr/lib/udev/rules.d/95-upower-csr.rules
Reading rules file: /usr/lib/udev/rules.d/95-upower-hid.rules
Reading rules file: /usr/lib/udev/rules.d/95-upower-hidpp.rules
Reading rules file: /usr/lib/udev/rules.d/95-upower-wup.rules
Reading rules file: /usr/lib/udev/rules.d/96-e2scrub.rules
Reading rules file: /usr/lib/udev/rules.d/97-hid2hci.rules
Reading rules file: /usr/lib/udev/rules.d/99-systemd.rules
Reading rules file: /etc/udev/rules.d/backlight.rules
Unload module index
Unloaded link configuration context.
This program is for debugging only, it does not run any program
specified by a RUN key. It may show incorrect results, because
some values may be different, or not available at a simulation run.
DEVPATH=/devices/pci0000:00/0000:00:01.0/backlight/acpi_video0
ACTION=add
SUBSYSTEM=backlight
TAGS=:seat:systemd:
ID_PATH=pci-0000:00:01.0
ID_PATH_TAG=pci-0000_00_01_0
ID_FOR_SEAT=backlight-pci-0000_00_01_0
SYSTEMD_WANTS=systemd-backlight@backlight:acpi_video0.service
USEC_INITIALIZED=2680045