· переезд distrohopping elementary elementaryos lvm luks cryptsetup swap intel video tray indicators ayatana power management layout switching костыли

Переезд в elementaryOS Juno

Пару дней назад глубоко уважаемый мною дистрибутив sysrescuecd похерил мне полдиска при попытке расширить размер корневого раздела с 50 до 100 гигабайт. В результате мой любимый арчик с кедами хоть и загружался, но работал откровенно плохо - приложения (практически все) сегфолтились, так как получали на вход белиберду вместо нужных данных. Посидев-подумав я решил что-то поменять в своей жизни и поменял используемый мною дистрибутив линукса :D.

Пользуясь случаем передаю лучи негодования и презрения разработчикам sysrescuecd, которые решили оставить включенным DPMS и хранитель экрана. Собственно, выключение экрана (точнее, его кривая попытка) и включение заставки (опять же, точнее, кривая попытка) повесили ноут нахрен после перемещения 110 из 200 гигабайт данных. Может быть, я им однажды и зашлю багрепорт, но пока я хочу их только прибить.

Но пост не об этом, а о моем переезде и обо всех приколах, что я встретил.

The Beginning - установка, LVM, шифрование диска, SWAP

Сам переезд, кстати, прошел вполне мягко, мне понравились некоторые (почти все, если честно) дизайнерские решения. Единственное, что немного омрачило мой переезд - это сраный убунтовский установщик, который не позволил мне создать LVM внутри криптоконтейнера, а сразу запихнул туда раздел ext4 на “всю ширину” этого самого контейнера. А я то думал сделать отдельно корень, отдельно своп, отдельно хомяк, отдельно данные… Не, хрен мне там, я слишком умный для всего этого и установщик знает все за меня!

Второй прикол - это оказался все-таки не раздел ext4, а LVM!

Третий и самый смачный “прикол” всего этого - что мне автоматом создался SWAP размером в 1 гигабайт! То есть фиг мне, а не гибернация, ага. Недолго думая, я загрузился с LiveCD и поправил это все руками. Последовательность действий:

  1. Монтируем шифрованный раздел: cryptsetup luksOpen /dev/nvme0n1p3 (замените nvme0n1p3 на ваш зашифрованный раздел)
  2. Выполняем pvscan, vgscan, lvscan
  3. resize2fs /dev/mapper/elementary-vg--root НУЖНЫЙРАЗМЕРВГИГАБАЙТАХG
  4. lvreduce -L НУЖНЫЙРАЗМЕРВГИГАБАЙТАХG /dev/mapper/elementary-vg--root
  5. lvextend -L НУЖНЫЙРАЗМЕРВГИГАБАЙТАХG /dev/mapper/elementary-vg--swap_1
  6. mkswap /dev/mapper/elementary-vg--swap_1 для переинициализации свапа на весь раздел

Замените НУЖНЫЙРАЗМЕРВГИГАБАЙТАХ на нужные размеры.

Hibernation

Если вы расширили-таки свап до размера RAM - то нужно немного поправить настройки GRUB и хук initramfs, чтобы выход из hibernation заработал.

Первое - правим хук в /etc/initramfs-tools/conf.d/resume:

RESUME=/dev/mapper/elementary--vg-swap_1

Можно тут использовать и UUID, но у нас внутри шифрованного контейнера LVM, который всегда присваивает статичные имена в device-mapper, поэтому можно использовать вот такой путь.

Теперь надо поправить конфиг GRUB в /etc/default/grub:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash cryptdevice=/dev/nvme0n1p3:data root=/dev/mapper/elementary--vg-root resume=/dev/mapper/elementary--vg-swap_1"

Замените /dev/nvme0n1p3 на ваш раздел, который используется под шифрванный контейнер. После этого можно обновить конфиг GRUB:

sudo update-grub

После ребута у вас будет рабочий hibernate.

Трееиконки и индикаторы

Первое разочарование и первый ступор возник у меня от того, что сначала все ломают хорошо работающий трей, а потом они депрекейтят заменяющую его технологию. Хотя стоит признать, что по ссылке в ответе разработчика все вполне логично для гнома - это нелогично для меня, переселенца из кед. Ну да ладно, каждой бочке найдется затычка, каждой монтировке - другая монтировка, и тут нашелся свой маневр. Он позволил вернуть иконки в трее.

Хотя, стоит признать, они мне оказались практически не нужны. Единственное приложение, которое сидит только в трее у меня - это Nextcloud client, от которого я тоже отказаться не могу (простите, но WebDav - ссанина, и использовать я его точно не буду), так что приходится держать “устаревшую технологию”.

Приколы с менеджером питания

Используя Arch с кедами я уже привык, что можно настроить менеджер питания очень хорошо, например, у меня было так:

  1. При подключенном питании и закрытии крышки ноутбука - простая блокировка экрана.
  2. При отключенном питании и закрытии крышки ноутбука - suspend.
  3. Кнопка питания - игнорировать все нажатия.

А вот в elementaryOS, которая на базе Ubuntu 18.04 LTS, такое сделать нельзя. Более того - гномовский демон питания, который и используется для управления питанием, настолько багнутый, что игнорирует настройки из dconf (всякие *-lid-closed)! И еще более того - в настройках питания нету разделения на “При питании от сети” и “При питании от батарейки”. И ведь странно же, да, что дистрибутив, который ориентируется на маскимальную дружелюбность к пользователю, творит вот такое непотребство и не реализовывает нужный для ноутбуков функционал?

Оставим это на совести разработчиков (я им еще зашлю багрепорт или может даже сразу MR который чинит это в Juno), а пока я нашел вот такой вот костыль, который малец поправил под реалии elementaryOS и Pantheon:

#!/usr/bin/env python3

import gi
from gi.repository import GLib
from gi.repository import Gio

import dbus
from dbus.mainloop.glib import DBusGMainLoop

import subprocess

class Action():
    def blank(self):
        return subprocess.call(['light-locker-command', '-a', '-l'])

    def suspend(self):
        return subprocess.call(['systemctl', 'suspend', '-i'])

    def shutdown(self):
        return subprocess.call(['systemctl', 'poweroff', '-i'])

    def hibernate(self):
        return subprocess.call(['systemctl', 'hibernate', '-i'])

    def interactive(self):
        return subprocess.call(['gnome-session-quit'])

    def nothing(self):
        return

    def logout(self):
        return subprocess.call(['gnome-session-quit', '--no-prompt'])



class CustomSuspendMonitor():
    DBUS_UPOWER_PATH = '/org/freedesktop/UPower'
    DBUS_UPOWER_BUS = 'org.freedesktop.UPower'
    DBUS_PROPERTIES_IFACE = 'org.freedesktop.DBus.Properties'

    UPOWER_LID_CLOSED = 'LidIsClosed'
    UPOWER_ON_BATTERY = 'OnBattery'
    DBUS_PROPERTIES_CHANGED = 'PropertiesChanged'

    action = Action()
    on_battery = False
    lid_closed = False
    bus = None

    def __init__(self):
        DBusGMainLoop(set_as_default=True)
        self.bus = dbus.SystemBus()

    def init_status (self):
        upower_object = self.bus.get_object (self.DBUS_UPOWER_BUS, self.DBUS_UPOWER_PATH)
        upower_intf = dbus.Interface (upower_object, self.DBUS_PROPERTIES_IFACE)
        self.lid_closed = upower_intf.Get(self.DBUS_UPOWER_BUS, self.UPOWER_LID_CLOSED)
        self.on_battery = upower_intf.Get(self.DBUS_UPOWER_BUS, self.UPOWER_ON_BATTERY)


    def perform_action (self,msg):
        getattr(self.action, msg)()
        self.init_status()   # in case the user plugged/unplugged during suspend or hibernate

    def apply_policy (self):
        if self.lid_closed:
            action = ""
            gsettings = Gio.Settings.new ('org.gnome.settings-daemon.plugins.power')
            if self.on_battery:
                action = gsettings.get_string ('lid-close-battery-action')
            else:
                action = gsettings.get_string ('lid-close-ac-action')

            self.perform_action(action)



    def handle_prop_changed(self,arg1, arg2, arg3):
        for key in arg2:
            if key == self.UPOWER_LID_CLOSED:
                self.lid_closed = arg2[key]
            elif  key == self.UPOWER_ON_BATTERY:
                self.on_battery = arg2[key]
        self.apply_policy()


    def start (self):
        self.init_status()
        self.apply_policy()
        self.bus.add_signal_receiver (lambda a,b,c: self.handle_prop_changed(a,b,c) ,
                                 self.DBUS_PROPERTIES_CHANGED,
                                 self.DBUS_PROPERTIES_IFACE,
                                 self.DBUS_UPOWER_BUS,
                                 self.DBUS_UPOWER_PATH)
        loop = GLib.MainLoop()
        try:
            loop.run()
        except (KeyboardInterrupt, SystemExit):
            return

if __name__ == '__main__':
    CustomSuspendMonitor().start()

Скрипт читает настройки гномовского менеджера питания и выполняет команды согласно им. Единственное (пока) отличие от скрипта из багрепорта выше - использование другой команды блокировки экрана.

Добавляем в автозапуск следующую пользовательскую команду:

systemd-inhibit --who=me --why=because --mode=block --what=handle-lid-switch /path/to/power_management.py

Замените --who=me на вашего системного пользователя (для лучшей идентификации) и /path/to/power_management.py на правильный путь скрипта. Также сделайте скрипт исполняемым:

chmod +x /path/to/power_management.py

После ребута или релогина у вас все должно заработать.

Интеловское видео

С интеловским видео у меня проблем не было, кроме довольно “тягостного” переключения TTY и глюков LightDM в виде “не могу сразу показать лок-скрин, переключись сначала в какой-либо TTY (1-6), а потом вернись в TTY 7”. Решается это использованием интеловского драйвера вместо новомодного modesetting, который сейчас позиционируется как “единый драйвер для всех видеокарт”. Пишем в /etc/X11/xorg.conf.d/20-intel-video.conf такое:

Section "Device"
    Identifier "Intel Graphics"
    Driver "intel"
EndSection

Попутно получаем нужные новым чипам HuC/GuC и прочее добро, включая автоматическое обновление фирмвари. Правда, чтобы все это включить (а заодно избавиться от возможных глюков при переключении видеорежимов после старта initramfs) надо запилить такое в /etc/modprobe.d/i915.conf:

options i915 enable_guc=2 fastboot=1

И выполнить:

sudo update-initramfs -k all -u

HWE

Рекомендую также поставить HWE версии ядра и иксов, чтобы использовать чуть более свежие версии, не подключая дополнительные PPA для этого. У меня на T480 это починило некоторые проблемы с играми, например.

Переключение раскладок с задержкой

А вот это та беда, которую я так и не смог зачинить. Перепробовал тонну советов, но отключить перехват комбинаций гномом я не смог - pantheon в любом случае перехватывает управление клавиатурой и переключает языки через медленный “прием гнома” - смену параметра в dconf. Если у кого-то есть рецепт как это обойти - очень прошу поделиться в комментариях. Что пробовал:

  1. Отключениче плагина gnome-settings-daemon, который управляет клавиатурой путем убирания .desktop файла из /etc/xdg/autostart
  2. Отключение переключения раскладок в настройках клавиатуры

Вместо послесловия

Тут, наверное, надо сказать, что “пацаны идут правильной дорогой” и все такое вот. Но не буду. Причина проста - слишком много дополнительных действий надо сделать после установки “дружелюбного” дистрибутива, а некоторые баги остаются незафикшенными уже продолжительное время. Мой вывод таков: если вы хотите красоты и “макопохожести” - приходите на elementaryOS, но будьте готовы к некоторому сексу с системой, так как “искаропки” она много чего делает не то чтобы “так себе”, а даже “совсем из рук вон плохо”. Я потратил почти 4 дня в перерывах между работой и домашними делами, чтобы привести систему в более-менее удобоваримый вид. Подумайте внимательно - нужно ли оно вам? Если не нужно - порекомендую KDE, и Arch Linux вместо базы (ну или Manjaro, для ленивых задниц, которые хотят графический установщик).

Сам Pantheon работает вполне стабильно, память с ресурсами не жрет, выглядит красиво - использовать можно.

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket