ACPI
События ACPI в Linux
ACPI(Advanced Configuration and Power Interface) это стандарт (с 1996?) для управления питанием (но не только?)
- В современых системах события ACPI обрабатывает
systemd-logind
- Более сложнве сценарии можно реализовать через
acpid service
События ACPI
обрабатываемые systemd-logind
Часть событий обрабатывает сервис systemd-logind
Какие именно события обрабатываются и как описано в файле /etc/systemd/logind.conf
(сокращенный пример)
[Login] [...] #HandlePowerKey=poweroff #HandleSuspendKey=suspend #HandleHibernateKey=hibernate #HandleLidSwitch=suspend #HandleLidSwitchExternalPower=suspend #HandleLidSwitchDocked=ignore #HandleRebootKey=reboot [...]
Значения по-умолчанию закоментированы, и нужны только для того что бы понимать, например не смотря на комментарий: #HandlePowerKey=poweroff
означает что при нажатии кнопки питания (или в случае виртуальной машины - получении соответвующего события) произойдет выключение
Возможные значения:
- ignore
- poweroff
- reboot
- suspend
- hibernate
- hybrid-sleep
Синтаксис файла очевиден - событие
=действие из списка
If we need to manage acpi events not covered by systemd-logind, with more complex or custom actions, we need to change strategy, install and run the acpid daemon. Let’s see how to proceed.
Однако если ни одно из действий не подходит, то нужно использовать ACPID
Сервис acpid
Установка:
$ sudo apt install acpid $ sudo systemctl enable --now acpid
Обработака событий ACPI
Мониторинг событий
- Для тесторивания можно воспользоваться утилитой
acpi_listen
которая покажет какие события происходят - Для виртуальной машины (а это именно мой случай) можно использовать команду
virsh shutdown guest1 --mode acpi
, естественно сначала отключив обработку этого события вsustemd
(В logind изменить HandlePowerKey на ignore)
Например
button/power PBTN 00000080 00000000 button/power LNXPWRBN:00 00000080 00000004 </PTE> Тут 4 столбца * device class * kernel name for the device (по этому имени можно смотреть в /sys/bus/acpi/devices) Например <PRE> cat /sys/bus/acpi/devices/LNXPWRBN\:00/input/input0/name Power Button
- код события
- последнее значение контекстно-зависимо,и имеет различное значение в зависимости от события
Создание обработчика событий
В случае Убунты
/etc/acpi/events/010_power_button
/etc/acpi/events/999_all
Associating an ACPI event with an action it’s quite easy. It basically involves two files: the first is the one parsed by the acpid service (by default it must be created inside the /etc/acpi/events directory) and is where we specify the code of the event to be handled and the path of the script which contains the commands that should be executed; the second is the script itself. Where the scripts are placed in the fileystem varies depending on the distribution. In Fedora, for example, we have the following directories by default: ├── actions │ └── power.sh └── events ├── powerconf └── videoconf As we already said, the /etc/acpi/events directory contains the files which handles the events. The /etc/acpi/actions directory, instead, contains the scripts associated with the events. By default, as you can see, the powerconf and power.sh scripts are installed, and they manage the handling of the power button. On Debian, files are arranged differently. The /etc/acpi/actions directory doesn’t exist: /etc/acpi ├── events │ └── powerbtn-acpi-support └── powerbtn-acpi-support.sh On Archlinux things are handled differently: there is only one file by default, in which all events are handled: /etc/acpi/events/anything: # Pass all events to our one handler script event=.* action=/etc/acpi/handler.sh %e What makes the file handle all events is the .* regular expression. The code of the events are than passed as argument to the /etc/acpi/handler.sh file (the %e string will be replaced by the event code). In the script, the actions to be executed are selected depending on the latter, in a case statement. How files are arranged, however, doesn’t matter that much. It doesn’t change how things work. Let’s manage the event we talked about previously: since an hibernate key doesn’t exist on the machine I am using, I will make so that when the Fn+f3key combination is pressed, the system is put into hibernation. As a first thing let’s create the event file, we will call it hibernateconf; it will contain only two lines: event=hotkey ATK0100:00 00000050 action=/etc/acpi/actions/hibernate.sh In the first line we specify the event code as value of event: in this case we simply used the literal code we discovered by using the acpi_listen utility. In the second line we specify the path of the script which should be executed: /etc/acpi/actions/hibernate.sh. One important thing to remember is that if using SELinux (on Fedora it is active by default), we must make sure the “event” file has the appropriate context associated to it, otherwise the event will not be handled. To know what context should be applied to the file, we can take a look at the existing files in the /etc/acpi/events directory as reference. All we have to do is to run ls with the -Z option: $ ls -lZ /etc/acpi/events -rw-r--r--. 1 root root system_u:object_r:etc_t:s0 168 Oct 5 21:27 powerconf -rw-r--r--. 1 root root system_u:object_r:etc_t:s0 236 Oct 5 21:27 videoconf As we can see, on Fedora, the two existing files in the /etc/acpi/events directory have the system_u:object_r:etc_t context. To apply the same context to our hibernateconf file, we can use them as reference with the chcon command: $ sudo chcon --reference /etc/acpi/events/powerconf /etc/acpi/events/hibernateconf The script invoked by the event file will contain the following lines: #!/bin/bash systemctl hibernate In the script we simply use systemctl to hibernate the system. All that remains to do is to make the script executable: $ sudo chmod +x /etc/acpi/actions/hibernate.sh For our new configurations to become effective, we need to restart the acpid daemon: $ sudo systemctl restart acpid.service When we press Fn+F3, the system should now be hibernated. Conclusions In this article we saw how ACPI events can be handled on Linux. We saw how basic events like the press of the power button, the suspend key and the closing of a laptop lid are managed by systemd-logind and can be configured via the /etc/systemd/logind.conf file. We also saw how to handle custom events by installing the acpid daemon on some of the most used Linux distributions.