Текст ниже не мой. Спасибо автору.
Динамическая настройка видеокарты с помощью udev
Подключитесь к загрузочному серверу. И создайте файл с правилами:
export root=/srv/nfs/diskless
nano $root/etc/udev/rules.d/10-graphics.rules
KERNEL=="card[0-9]*", SUBSYSTEM=="drm", RUN+="/etc/default/xdevice %n"
KERNEL=="card*", SUBSYSTEM=="drm", ATTR{enabled}=="enabled", ATTR{status}=="connected", RUN+="/etc/default/xdevice %n %k"
Каждое правило записывается в новой строке. Первая часть служит для идентификации события udev, к которому нужно применить действие, указанное в конце строки.
Для опознания события используются данные, которые можно получить в выводе команды
«udevadm info -a -p /sys/class/drm/card0».
Правило из первой строки срабатывает для всех устройств с именем (ядром) card0, card1… подсистемы drm. Второе правило сработает только для активных устройств из подсистемы drm, к которым в данный момент подключен монитор (оно не сработает для card0, card1, а только для имен вида card0-HDMI-1, т. к. только у таких устройств есть атрибуты enabled и status). При совпадении события с его описанием выполняется одна и та же программа, в которую в первом случае передаётся один параметр %n (порядковый номер ядра, который для card0 будет «0»), а во втором — дополнительный параметр %k (само имя ядра «card0»).
Программа /etc/default/xdevice будет изменять содержимое файла в папке /etc/X11/xorg.conf.d/, в котором содержится информация о настройках видеоадаптера для xorg. Для разных производителей мы подготовим разные шаблоны, учитывающие особенности реализации. Достаточно указать минимально необходимую информацию для однозначной идентификации устройства, а остальное xorg сделает сам:
Section "Device"
Identifier "уникальный идентификатор устройства"
Driver "используемый драйвер"
Option "AccelMethod" "метод ускорения"
BusID "PCI:идентификатор шины PCI, куда физически установлен адаптер"
EndSection
Необходимые данные мы укажем в самом шаблоне или получим исследуя вывод команды «udevadm info».
Программа будет срабатывать для каждого выхода каждой видеокарты, к которому подключен монитор. Для упрощения задачи заставим работать последний обнаруженный вариант, чтобы на мультимониторных системах работал хотя бы один монитор. Это не самый оптимальный способ настройки, и было бы лучше проверить графическую подсистему один раз перед достижением graphical.target, но наш вариантрабочий и подходит для изучения правил udev в действии.
Создаём файл программы со следующим содержанием:
nano $root/etc/default/xdevice
Скрытый текст
#!/bin/sh
# в этом файле будем хранить настройки устройства для xorg
CONF_FILE=/etc/X11/xorg.conf.d/20-device.conf
# получаем первое слово в названии производителя в "человеческом" виде
# лучше было бы использовать идентификаторы, но для наглядности оставим как есть
get_vendor(){
local card=$(get_path $1)
udevadm info -q property -p ${card%\/drm*} | \
awk '/^ID_VENDOR_FROM_DATABASE/{split($1,a,"=");print tolower(a[2])}'
}
# получаем идентификатор шины PCI из пути устройства и приводим его к виду x:y:z
get_bus(){
local bus=$(get_path $1)
echo ${bus%\/drm*} | \
sed 's\:\.\g' | \
awk '{n=split($0,a,".");printf "%i:%i:%i",a[n-2],a[n-1],a[n]}'
}
# получаем полный путь к устройству
get_path(){
udevadm info -q path -p /sys/class/drm/$1
}
# Выбираем шаблон на основании имени производителя и заполняем его данными.
make_conf(){
local filename="xorg-device-$(get_vendor $1).conf"
cat /etc/X11/$filename | \
sed 's\%BUS%\'$(get_bus $1)'\g'| \
sed 's\%ID%\'$1'\g' > $CONF_FILE
}
# если мы в virtualbox, то запускаем для него службу
check_vbox(){
local vendor=$(get_vendor $1)
[ "$vendor" == "innotek" ]] && systemctl start vboxservice
}
#начало программы
card_numb=$1
if [ -z "$2" ] # обрабатываем исключение для virtualbox
then
card_name="card$card_numb"
check_vbox $card_name && make_conf $card_name
else
card_name=$2
make_conf $card_name
fi
Сделаем файл исполняемым:
chmod +x $root/etc/default/xdevice
Отключаем автоматическую загрузку службы VirtualBox, т. к. теперь она будет запускаться нашей программой только при необходимости:
systemctl disable vboxservice
Добавляем шаблоны конфигурационных файлов xorg, с оптимизированными под основных производителей настройками:
nano $root/etc/X11/xorg-device-intel.conf
Section "Device"
Identifier "Intel %ID%"
Driver "intel"
Option "AccelMethod" "uxa"
BusID "PCI:%BUS%"
EndSection
AMD, nVidia, VirtualBox
В завершение настройки xorg сделаем ”Windows like” переключение раскладки клавиатуры комбинацией Alt+Shift:
nano $root/etc/X11/xorg.conf.d/50-keyboard.conf
Section "InputClass"
Identifier "keyboard-layout"
MatchIsKeyboard "on"
Option "XkbLayout" "us,ru"
Option "XkbVariant" ",winkeys"
Option "XkbOptions" "grp:alt_shift_toggle"
EndSection