Запуск графических OpenGL приложений Linux в chroot-окружении

    Общий рейтинг статьи: 5 (проголосовало 1 )
    Опубликовано:  [просмотров 543]


    Согласно определения, chroot - это системная утилита Unix, используемая для смены текущего корневого каталога с целью создания нового окружения, логически отдельного от основной системы, а LXC-контейнеры которые я подробно рассматривал в прошлых статьях обычно называют chroot на стероидах, так как там дополнительно используются ядерных механизмы cgroups для обеспечения безопасности.

    Для запуска устаревших приложений обычно используется виртуализация, но в большинстве случаев можно обойтись контейнерной изоляцией или банальным chroot, но что делать с графическим приложением? Сегодня мы разберем кейс по запуску устаревшего графического приложения с минимальными потерями производительности в chroot-окружении.

    В статье "Полноценный терминальный сервер на базе Ubuntu Linux" я описывал несколько методов проброса графического приложения из изолированного окружения, но эти методы не предусматривали проброс OpenGL, а лишь реализовывали механизмы похожие на RemoteFX в Windows (но без механизмов графического ускорения).

    Видео карта с поддержкой OpenGL

    В этой статье я подробно рассмотрю запуск приложения PCSX2 в chroot-окружении. PCSX2 - это эмулятор Play Station 2, зависимости для установки пакета которого окончательно сломали в дистрибутиве KDE NEON и на данный момент попытка его установки вызывает ряд неразрешимых зависимостей.

    Неразрешимые зависимости при установке PCSX2 в KDE NEON

    Меня всем устраивает KDE-неон, кроме невозможности установить мой любимый эмулятор второй плойки. И поэтому, пожалуй решим эту задачу.

    Подготовка chroot-окружения для запуска Linux-приложения

    chroot-окружение фактически представляет собой корневую файловую систему Linux-дистрибутива и довольно подробно рассматривалось в статье "Запуск нативных Linux-приложений в Android-окружении на примере TV-приставки NV-501-Wac" и единственным отличием было, то что мы скачали ARM-окружение дистрибутива для linux chroot.

    Так как у нас сейчас обычное x86 окружение, то нам проще создать файл который будет использоваться как RAW-образ диска и банально установить туда Ubuntu server 14.04, после чего скопировать корень файловой системы в каталог нашего окружения.

    Использование KVM для работы с RAW-образами дисков я уже рассматривал в статье "Запуск простой машины KVM/QEMU напрямую из консоли" поэтому просто приведу набор команд которые необходимо выполнить:

    # dd count=10240 bs=1024000 if=/dev/zero of=/data/ubuntu-image.raw
    # qemu-system-x86_64 -m 2G -boot once=d -enable-kvm -machine q35,accel=kvm \
    -cdrom /data/tmp-data/kvm/iso/ubuntu-14.04.5-server-amd64.iso \
    -drive file=/data/ubuntu-image.raw,format=raw -net nic,vlan=0 -net tap,vlan=0,ifname=tap0

    В результате будет запущена установка Ubuntu Server, а в качестве raw-диска будет использован файл /data/ubuntu-image.raw и обратите внимание, что установку производите без выделения элементов файловой системы. 

    Установка Ubuntu в KVM

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

    Определяем имя подключаемого раздела.

    # losetup -f --show -P /data/ubuntu-image.raw
    # fdisk -lu /data/ubuntu-image.raw

    Подключаем loop-устройство требуемого раздела и монтируем его.

    # mkdir /tmp/tmp-image
    # mount /dev/loop0p1 /tmp/tmp-image/

    Создаем локальное хранилище и копируем данные.

    Обратите внимание, на параметр --numeric-ids он предотвращает переименование идентификаторов копируемых файлов (пользователей и групп в локальные) и при переносе используются только числовые идентификаторы.

    # mkdir /data/chroot-ubuntu
    # rsync -av --numeric-ids /tmp/tmp-image/ /data/chroot-ubuntu/

    Новый корень для chroot подготовлен и можно переходить к следующему этапу.

    Переход в созданный корень Linux-окружения

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

    Тестовый запуск chroot-окружения:

    # mount -o bind /dev/ /data/chroot-ubuntu/dev/
    # mount -o bind /proc/ /data/chroot-ubuntu/proc/   
    # mount -o bind /sys/ /data/chroot-ubuntu/sys/
    # chroot /data/chroot-ubuntu/ /bin/bash

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

    # cat /etc/hostname

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

    Например, не сконфигурирована сетевая подсистема и файл описывающий сервера для разрешения DNS-имен будет пуст. Первым делом, отредактируйте файл /etc/resolv.conf указав DNS-сервер гугла:

    nameserver 8.8.8.8

    Теперь можно установить программное обеспечение:

    # apt-get update
    # apt-get upgrade
    # apt-get install mc aptitude
    # aptitude install xterm

    Как вы наверное поняли, сейчас мы уже полноценно работаем в консоли нашего chroot и можем переходить к запуску графических приложений.

    Запуск графического приложения в chroot

    Попробуем запустить простейший графический linux-терминал xterm:

    # xterm

    При запуске вы естественно получите ошибку:

    xterm: Xt error: Can't open display: %s

    Это совершенно логично, так как приложение просто не знает на какой дисплей ему выводить результат своей работы, для того чтобы сообщить приложению выполните команду:

    export DISPLAY=:0

    Следующей ошибкой которую вы получите будет:

    xterm: Error 32, errno 2: Нет такого файла или каталога
    Reason: get_pty: not enough ptys

    Это связано с тем, что отсутствует устройство pty и для его создания выполните из хост-системы команду:

    # mount -t devpts devpts /data/chroot-ubuntu/dev/pts

    Теперь графическое приложение запускается из chroot-окружения.

    Запуск xterm в chroot

    xterm является простейшим графическим приложением и особого интереса не представляет, а меня в свою очередь интересует работа полноценного графического OpenGL-приложения и сейчас мы его установим:

    # add-apt-repository ppa:gregory-hainaut/pcsx2.official.ppa
    # apt-get update
    # aptitude install pcsx2:i386

    PCSX2, это уже полноценное графическое приложение запустив которое в chroot от имени непривилегированного пользователя мы сможем сказать, что добились поставленного результата.

    Подготовка скрипта запуска приложения от имени непривилегированного пользователя

    В рамках эксперимента я так-же монтирую домашний каталог пользователя в домашний каталог одноименного пользователя в chroot. Эта операция особых вопросов не вызывает и выполняется как и любое bind-монтирование, единственное на что необходимо обращать внимание, это то, что идентификаторы локального пользователя и пользователя в chroot должны совпадать.

    Представляю вашему вниманию скрипт осуществляющий все описанные выше операции, запускающий приложение от имени внутреннего пользователя (в chroot), а по завершении работы размонтирует временные каталоги.

    В моем случае эти операции выполняет скрипт/data/chroot-ubuntu/run-pcsx2.sh содержащий следующие записи:

    #!/bin/sh

    mount -o bind /dev/ /data/chroot-ubuntu/dev/
    mount -o bind /proc/ /data/chroot-ubuntu/proc/
    mount -o bind /sys/ /data/chroot-ubuntu/sys/
    mount -t devpts devpts /data/chroot-ubuntu/dev/pts
    mount -o bind /home/chernousov/ /data/chroot-ubuntu/home/chernousov/

    chroot /data/chroot-ubuntu/ "./pcsx2.sh"

    umount /data/chroot-ubuntu/home/chernousov/
    umount /data/chroot-ubuntu/dev/pts
    umount /data/chroot-ubuntu/sys/
    umount /data/chroot-ubuntu/proc/
    umount /data/chroot-ubuntu/dev/

    В корне chroot-окружения находится скрипт pcsx2.sh осуществляющий запуск приложения от имени непривилегированного пользователя:

    #!/bin/sh
    su - chernousov -c PCSX2

    Как вы понимаете операция chroot осуществляется от имени суперпользователя root, что на рабочей станции банально не удобно, поэтому мы разрешим запуск данного скрипта в sudo-режиме без ввода пароля. Для разрешения запуска только этого скрипта от имени пользователя root без ввода пароля внесите следующую запись в файл /etc/sudoers запись:

    chernousov ALL = NOPASSWD:/data/chroot-ubuntu/run-pcsx2.sh

    Теперь центральный скрипт может быть запущен командой:

    $ sudo /data/chroot-ubuntu/run-pcsx2.sh

    Эта операция не требует дополнительных полномочий и соответственно мы добавим ее в меню приложений пользователя и на рабочий стол.

    Создание значка приложения KDE вручную

    Запуск OpenGL-приложений в chroot

    Вот мы и подошли к основному вопросу ради чего все это и затевалось и если вы сейчас попробуете запустить саму игру, то получите сообщение:

    OpenGL не работает в chroot-режиме

    Это связано с тем, что приложение не может найти поддержку графического ускорителя. Этот вопрос решается довольно просто и вам потребуется лишь установить драйвера графической подсистемы аналогичные хосту.

    В моем случае этот вопрос решился выполнением команды:

    # aptitude install nvidia-375

    Примечание

    Когда я решил повторить описанную реализацию на чистой системе, я обратил внимание на несколько специфичных подводных камней.

    Устройство /dev/input/js0 существует внутри chroot, но PCSX2 не видит подключенных джойстиков и работает только с клавиатурой или мышью.

    Все оказалось довольно просто и решилось обновлением библиотек SDL.


    Связанные записи в блоге

    Обсуждение статьи

    Ваш комментарий: