Лирика
За прошедшие пару месяцев мне довольно часто приходилось вступать в дискуссии о всевозможных портативных компьютерах: ломать копья в спорах какой производитель лучше и почему, обсуждать совместимость с GNU/Linux и то, как в этой системе настроить ту или иную функцию и, периодически, меня таки просят поделиться конфигами. Под влиянием этих самых обсуждений и родилась данная статья.
Большую часть своего компьютерного стажа я пользуюсь лаптопами так называемой «бизнес серии»: IBM ThinkPad 600, HP-Compaq nc2400, Lenovo ThinkPad X61T, Lenovo ThinkPad X220.
Были кратковременные перерывы, когда приходилось перебиваться абы-чем, то бишь компьютерами потребительского сегмента: Apple ibook G4 и Acer aspire 5112 и именно в эти моменты приходило понимание того, как сильно не хватает таких очевидных и привычных вещей, как трекпоинт и док-станция.
Что это такое? Подставка для лаптопа с разъемом питания и всевозможными дополнительными портами. В некоторые модели можно установить дополнительный жесткий диск или аккумулятор. Док-станция избавляет от необходимости каждый раз подключать весь набор кабелей, приходя на рабочее место и отсоединять, уходя.
Особенно удобна такая конфигурация под управлением GNU/Linux (в моем случае, Debian stable), где несколькими скриптами можно детально описать поведение компьютера.
Описание сценария работы
На работе я использую конфигурацию с внешним монитором и bluetooth клавиатурой Lenovo ThinkPad kt1255. Лаптоп практически никогда не выключается, вместо этого используется suspend to ram. Опишу сценарии обработчиков:
— Пробуждение в доке с закрытой крышкой: включить внешний монитор, активировать bluetooth и подключить клавиатуру, cpu performance
— Открытие крышки в доке: погасить внешний монитор и перевести изображение на внутренний
— Извлечение с открытой крышкой: дополнительно отключит клавиатуру и bt, cpu on-demand
— Извлечении с закрытой крышкой: залочить экран, перевести изображение на внутренний экран отключив внешний, вырубить клавиатуру и bt-модуль, cpu в on-demand, перейти в pm-suspend
— Закрытие крышки не в доке: блокировка экрана, pm-suspend
Непосредственно настройка
Какими-либо DE я не пользуюсь, да и не вижу смысла возлагать на них функцию управления питанием. Потому, настраивать будем средствами acpid.
Настройку начинаем, как обычно, с установки нужных программ:
#apt-get install acpid acpi-support cpufrequtils
Далее, смотрим какие события у нас генерятся при отстыковке лаптопа:
#acpi_listen
ac_adapter ACPI0003:00 00000080 00000000
ibm/hotkey LEN0068:00 00000080 00006030
thermal_zone LNXTHERM:00 00000081 00000000
battery PNP0C0A:00 00000080 00000001
ibm/hotkey LEN0068:00 00000080 00004011
При стыковке:
#acpi_listen
ibm/hotkey LEN0068:00 00000080 00004010
ac_adapter ACPI0003:00 00000080 00000001
ibm/hotkey LEN0068:00 00000080 00006030
thermal_zone LNXTHERM:00 00000081 00000000
battery PNP0C0A:00 00000080 00000001
button/lid LID close
Стоит отметить, что ThinkPad Mini Dock Series 3 не предоставляет proc интерфейса.
Напишем правила для событий:
#vim /etc/acpi/events/thinkpad-dock
event=ibm/hotkey LEN0068:00 00000080 00004010
action=/etc/acpi/thinkpad-dock.sh
#vim /etc/acpi/events/thinkpad-undock
event=ibm/hotkey LEN0068:00 00000080 00004011
action=/etc/acpi/thinkpad-undock.sh
Правило на закрытие крышки идет в комплекте с пакетом acpi-support. Приведем его к надлежащему виду, указав путь к скрипту-обработчику:
#vim /etc/acpi/events/lidbtn
event=button[ /]lid
action=/etc/acpi/lid.sh
А теперь перейдем к самому интересному: скриптам, описывающим реакцию на события при описанных выше условиях.
#vim /etc/acpi/lid.sh
#!/bin/bash
#проверяем, подключен ли лаптоп к док-станции
grep -q on /etc/tp_dock_state;
if [ $? = 0 ]
then
#если да, проверяем открыта ли крышка
grep -q open /proc/acpi/button/lid/*/state
if [ $? = 0 ]
then
#если да, включаем встроенный монитор, гасим внешний
DISPLAY=:0.0 su user -c 'xrandr --output LVDS1 --auto'
DISPLAY=:0.0 su user -c 'xrandr --output HDMI3 --off'
else
#если нет, включаем внешний, гасим встороенный
DISPLAY=:0.0 su user -c 'xrandr --output HDMI3 --auto'
DISPLAY=:0.0 su user -c 'xrandr --output LVDS1 --off'
#включаем bluetooth-модуль и запускаем сервис
echo enabled> /proc/acpi/ibm/bluetooth
/etc/init.d/bluetooth start
#подключаем bluetooth клавиатуру.
echo 'connect 90:7F:61:10:A3:BC'|bluetoothctl
#выставляем переключение раскладки по alt_gr, подгружаем кастомные биндинги
DISPLAY=:0.0 su user -c 'setxkbmap -option grp:toggle us,ru'
DISPLAY=:0.0 su user -c 'xmodmap ~/.xmodmaprc'
fi
else
#если не подключен
grep -q closed /proc/acpi/button/lid/*/state
if [ $? = 0 ]
then
#отключаем отключаем клавиатуру, останавливаем сервис и отключаем bt-модуль
echo 'disconnect 90:7F:61:10:A3:BC'|bluetoothctl
/etc/init.d/bluetooth stop
echo disabled> /proc/acpi/ibm/bluetooth
#вызываем с правами пользователя user блокировщик экрана
DISPLAY=:0.0 su user -c /home/user/bin/lock
#переводим изоражение на встроенный экран
DISPLAY=:0.0 su user -c 'xrandr --output LVDS1 --auto'
#отключаем внешний
DISPLAY=:0.0 su user -c 'xrandr --output HDMI3 --off'
#отправляем лаптоп спать
pm-suspend
#при пробуждении проверяем, в доке ли thinkpad:
grep -q closed /proc/acpi/button/lid/*/state
if [ $? = 0 ]
then
#если да, то, сообщаем об этом:
echo on >/etc/tp_dock_state
#включаем внешний монитор и гасим встроенный
DISPLAY=:0.0 su user -c 'xrandr --output HDMI3 --auto'
DISPLAY=:0.0 su user -c 'xrandr --output LVDS1 --off'
#включаем bt-модуль, запускаем сервис, подключаем bt-клавиатуру
echo enabled> /proc/acpi/ibm/bluetooth
/etc/init.d/bluetooth start
echo 'connect 90:7F:61:10:A3:BC'|bluetoothctl
#подгружаем раскладку и биндинги
DISPLAY=:0.0 su user -c 'setxkbmap -option grp:toggle us,ru'
DISPLAY=:0.0 su user -c 'xmodmap ~/.xmodmaprc &'
fi
else
#если нет, то просто включаем встроенный экран
DISPLAY=:0.0 su user -c 'xrandr --output LVDS1 --auto'
fi
Поясню, на всякий случай, что 90:7F:61:10:A3:BC — это адрес моей клавиатуры. Настраиваются bluetooth устройства достаточно просто:
#apt-get install bluez
#bluetoothctl
[NEW] Controller 40:2C:F4:BB:3C:FC nethack [default]
[bluetooth]# agent on
Agent registered
[bluetooth]# default-agent
Default agent request successful
[bluetooth]# scan on
Discovery started
[CHG] Controller 40:2C:F4:BB:3C:FC nethack [default]
[NEW] Device 90:7F:61:10:A3:BC ThinkPad Compact Bluetooth Keyboard with TrackPoint
[bluetooth]# pair 90:7F:61:10:A3:BC
Attempting to pair with 90:7F:61:10:A3:BC
[CHG] Device 90:7F:61:10:A3:BC Connected: yes
[agent] PIN code: 12345 #вводим с клавиатуры PIN
[bluetooth]# connect 90:7F:61:10:A3:BC
Attempting to connect to 90:7F:61:10:A3:BC
Connection successful
В дальнейшем, когда устройства связаны, достаточно передать
#echo 'connect 90:7F:61:10:A3:BC'| bluetoothctl
Чем мы в скриптах и пользуемся.
Опишем обработчик стыковки:
#vim /etc/acpi/thinkpad-dock.sh
#!/bin/sh
#сообщаем о стыковке
echo on >/etc/tp_dock_state
#переводим процессор в режим performance
cpufreq-set -c 0 -g performance
cpufreq-set -c 1 -g performance
cpufreq-set -c 2 -g performance
cpufreq-set -c 3 -g performance
#подключаем клавиатуру, на случай, если мы куда-нибудь уносили лаптоп
echo 'connect 90:7F:61:10:A3:BC'|bluetoothctl
И отстыковки:
#vim /etc/acpi/thinkpad-undock.sh
#!/bin/bash
#сообщаем об отстыковке
echo off >/etc/tp_dock_state
#переводим процессор в экономичный режим
cpufreq-set -c 0 -g powersave
cpufreq-set -c 1 -g powersave
cpufreq-set -c 2 -g powersave
cpufreq-set -c 3 -g powersave
#проверяем, закрыта ли крышка:
grep -q closed /proc/acpi/button/lid/*/state
if [ $? = 0 ]
then
#если да, то вызываем локскрин
DISPLAY=:0.0 su user -c /home/user/bin/lock
#отключаем bt-клавиатуру, останавливаем сервис, отключаем модуль
echo 'disconnect 90:7F:61:10:A3:BC'|bluetoothctl
/etc/init.d/bluetooth stop
echo disabled> /proc/acpi/ibm/bluetooth
#переклюочаем изображение на встроенный экран
DISPLAY=:0.0 su user -c 'xrandr --output LVDS1 --auto'
DISPLAY=:0.0 su user -c 'xrandr --output HDMI3 --off'
#усыпляем лаптоп
pm-suspend
#после пробуждения вновь проверяем, закрыта ли крышка
grep -q closed /proc/acpi/button/lid/*/state
if [ $? = 0 ]
then
#если да, то включаем внешний монитор и выключаем внутренний
DISPLAY=:0.0 su user -c 'xrandr --output HDMI3 --auto'
DISPLAY=:0.0 su user -c 'xrandr --output LVDS1 --off'
#включаем bt-модуль, запускаем сервис, подключаем клавиатуру
echo enabled> /proc/acpi/ibm/bluetooth
/etc/init.d/bluetooth start
echo 'connect 90:7F:61:10:A3:BC'|bluetoothctl
#сообщаем о стыковке
echo on >/etc/tp_dock_state
fi
fi
Подводные камни
После обновления до debian 8, где в системе появился systemd, я столкнулся со следующей проблемой: при закрытии крышки, pm-suspend почему-то отрабатывал два раза. То есть выполнялся скрипт lid.sh, но параллельно с ним производилось действие pm-suspend без всяких скриптовых обвязок.
Главным подозреваемым, конечно же, стал новый инициализационный комбайн. И не зря: после десяти минут гугления выяснилось, что, оказывается, systemd пытается, до кучи, брать на себя и функцию по управлению событиями acpi, но делает это покамест не слишком хорошо: на данный момент не может обрабатывать события подключения адаптера питания и батареи.
Переписывать скрипты под новые веяния моды желание также не возникло, потому было проделано следующее:
#sed -i 's/HandleLidSwitch=yes/HandleLidSwitch=ignore/' /etc/systemd/logind.conf
Тем самым мы отучили systemd делать то, о чем не просят и все встало на круги своя. В принципе, то же самое стоит сделать с HandleSuspendKey, HandleHibernateKey и HandlePowerKey, если есть желание обрабатывать нажатия через acpid.
Заключение
Таким образом, получаем удобную конфигурацию, не требующую каких-то лишних рутинных манипуляций. Приходя утром на работу, я достаю лаптоп из рюкзака, вставляю его в док-станцию и нажимаю кнопку питания на этой самой док-станции, после чего работаю как со стационарным компьютером. Уходя, просто жму кнопку отстыковки и убираю компьютер в рюкзак.
Недостаток у такого подхода ровно один: вызывает сильное привыкание.
evg_krsk
Всё не дочитал ещё, но выглядит вкусно. С systemd уже и сам натолкнулся. Только наверное лучше не править /etc/systemd/logind.conf, а создавать снипет в /etc/systemd/logind.conf.d/
evg_krsk
А, нет, вру, systemd отлично отрабатывает события ACPI (ну, у меня), достаточно было ему сказать HandleLidSwitch=suspend, HandleLidSwitchDocked=suspend, чтобы снова начал засыпать при закрытии крышки ноута (в апстриме это починили для более другого случая, мне не подошло новое поведение). acpid лежит на случай непредвиденного возврата к sysv :-)
d7s2di
Проблема в том, что просто сделать suspend недостаточно, тут совершенно разные действия в зависимости от того, находится ли лаптоп в доке, подключен ли адаптер и тому подобное. А чтобы все это заработало, нужно писать юниты.
Нужно ли это? Мне покамест не нужно. Не люблю менять решения, которые работают хорошо на что-то более модное.
kstep
Ну у меня всё просто:
1) в /etc/systemd/logind.conf.d лежит файлик no-lid-sleep.conf
[Login] HandleLidSwitch=ignore
kstep
Парсер убил переносы строк в спойлерах. Надеюсь, понятно, где там нужно разбить на строчки?
d7s2di
Да, с этим все понятно. В общем, похоже, что рано или поздно systemd заменит собой очень многие демоны. Уж не знаю, хорошо это или плохо.
d7s2di
>не править /etc/systemd/logind.conf, а создавать снипет в /etc/systemd/logind.conf.d/
Тут интересно, как оно расставит приоритеты. Проще поправить logind.conf, я считаю. Вообще, с переходом на это самое, лишнее засыпание было не единственной проблемой: до кучи автомонтирование на скриптах udev отвалилось по причине нововведения с килянием процессов по таймауту…
Надо бы назад на sysv откатиться, благо в дебиане есть такая возможность.
evg_krsk
Нормально оно расставляет приоритеты. Сначала грузит файл, потом сниппеты (насколько помню, их в лексикологическом порядке). В итоге и обновляется systemd штатно и конфиг не слетает.
У меня наоборот, засыпание нормально работало и в sysv и в systemd, но потом «сломали» дефолт в logind.conf, пришлось настроить. В systemd есть родное монтирование юнитами и/или настройкой в /e/fstab. Сам не пробовал (использую aufos ещё с sysv), но говорят что работает. Попробуйте.
Я наоборот последние пару лет плавно перевожусь на systemd. Не без шероховатостей конечно, но прогресс впечатляет :-)
d7s2di
Меня в systemd пугает концепция «все в одном». Как-то неюниксвейно. Ну и проблемы с переходом: перспектива переписывать под systemd конфиги тоже не разу не радуют.
grossws
Это «всё в одном» состоит из более чем 80 бинарников.
Ну и поддерживает старые rc и init-скрипты для совместимости. Естественно, вопрос поддержки этого перехода в конкретном дистрибутиве ложится на плечи мейнтейнеров, которые могут положить болт и рассказывать, как им всё сломали.
d7s2di
>состоит из более чем 80 бинарников.
По-моему, это многовато для системы инициализации. Хотя, у нас тут вместо системы инициализации, получается эдакая маленькая операционная система. На ум приходит шутка про OS GNU/Emacs, в которой есть все, но нет нормального текстового редактора.
grossws
Оно и не позиционируется, как init. init — только один из кусков systemd.
evg_krsk
… а могут, как я, наоборот, собирать новые пакеты только с юнитами, ибо их можно написать и отладить в разумное время, в отличии от :-)
grossws
Я локальные пакеты так и собираю. Но, если вы мейнтейнер дистрибутива ещё активно использующего sysv, то это не очень гуманно по отношению к пользователям =)
evg_krsk
Ну, как админу приходится серверный софт собирать с sysv-портянками (хорошо хоть в последнее время крайне редко). Для пользователей — по запросу в багтрекере (никто пока не жаловался :-)).
kstep
Почему же, конфиги в системд прекрасно разбиваются по логическим частям, можно перекрывать общесистемные настройки юнитов на уровне пользователя и т.п.
Например, если не нравится настройки запуска сервиса по умолчанию, можно создать каталог /etc/systemd/system/имясервиса.service.d/local.conf и прописать их в этом файле, эти настройки перекроют общесистемные, и при обновлении пакетов не затронутся.
khim
systemd
меня всегда убивает.Как может концепция используемая в 100% UNIX'ов быть «неюниксвейной»?
Все, абсолютно все «настоящие» UNIX'ы (то есть системы ведущие родословную кодобазы от творения Кернигана и Ритчи) собирают «базовую систему» (состоящую из десятков, а то и сотен, программ) из одного дерева, которое может быть обновлено только и исключительно синхронно (login из System 6 в System 5 не вставить и наоборот).
systemd
— это как раз во-многом «возврат к истокам».ragesteel
Вот вы говорите что вам нужен trackpoint, а судя по MACу у вас bluetooth клавиатура от Chicony, у них моделей с TrackPoint'ом нет. Или вам указательное устройство больше не нужно?
d7s2di
Клавиатура у меня не от chiconi (: Вот она, собственно:
kstep
О, класс. Хочу такую! Где взяли? Или просто выдрали из старого Thinkpad и доработали напильником? У меня лично уже лет 5 блютусная Logitech diNovo Edge, пока устраивает, но рано или поздно аккумулятор сядет, надо будет искать замену…
d7s2di
Заказывал на ali, когда деревья были большие, а бакс стоил 30 рублей. Сейчас стоит жутких 6-7 тысяч деревянных.
sashkin
У меня такая же, но USB. Заказывал на Амазоне. Очень долго выбирал из десятков других. У Вас, кстати, все клавиши работают ОК? У меня вертикальный ряд возле Enter неприятно поскрипывает при нажатии. С остальными такое не наблюдается. Ну и трекпоинт весьма туговат, что отбивает желание его использовать: месяца 1,5-2 на нём сидел, но так и не привык, а ведь когда брал, то очень надеялся на работу в духе «руки постоянно на клавиатуре». С укороченной клавой мышь показала себя всё же более удобной.
d7s2di
Да вроде все работают нормально. Верхним рядом (функциональными) я не пользуюсь, но сейчас специально потыкал: скрипа нет. Ускорение трекпоинта можно настороить через xset m. Хотя, по ощущениям, чувствительность примерно как на x220. А вот на 31P9490 трекпоинт тугой, да.
Впрочем, задача трекпоинта — быстро передвинуть графический курсор, когда руки лежат на клавиатуре. А мышью я не пользуюсь. Совсем (:
Arceny
У меня была проводная и с классической раскладкой, к сожалению блютус таких не было.
Новую thinkpad'овскую клавиатуру не признаю :-С