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

HELP-ME-24.COM (Freelance Team), Черноусов Антон

Согласно определения, 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.

Оставьте комментарий

Вы должны быть вошедший в чтобы отправить комментарий