RemoteApp по-линуксовому

Dec 16, 2022 14:49


Про технологию "RemoteApp", когда услужливая форточка (Windows Server) транслирует на RDP-клиента отдельно взятое окошко с отдельно взятым приложением, наверное все слышали. Особенно она распространена среди 1С-пользователей, хотя в последнее время всё больше вытесняется HTML5-интерфейсом. Довелось тут городить на Linux-е нечто подобное.

Задача. Есть некая очень кривая Java-софтина, доступ к которой нужен для N разных сотрудников. Ситуацию отягощают нижеследующие вводные.
  1. Она обвешана всевозможными лицензионными ограничениями, поэтому запускается только на строго определенной виртуалке.
  2. Нельзя допустить, чтобы её запустили два разных пользователя одновременно, иначе она побьёт свою внутреннюю базу данных.
  3. Путь к этой самой внутренней базе данных где-то внутри hard-coded и не меняется.
  4. Как следствие, предыдущего пункта, приложение может запускаться только от имени какого-то определенного заранее заданного пользователя.

До меня это решалось так. "Полноценный" виртуальный Linux-десктоп с "иксами". Все желающие туда ходят VNC-ой, логинятся под тем самым "определенным" пользователем, делают что им нужно. Но не всегда удобно, потому что местами не работает clipboard, местами проблемы с раскладками, местами VNC-клиенты кривые и всё вот это. Поэтому я решил закопать стюардессу и пересадить всё это безобразие на XPRA.

Штука довольно мощная и фичастая. Умеет много разных режимов работы. Но плотно завязана на "иксы" и D-Bus, поэтому как системный демон запускается крайне неохотно. Во всяком случае, у меня не получилось. Я довольно долго с ней промучался, но из-под systemd завести её так и не смог. То прав в пользовательские rundirs не хватало, то переменных окружения, то xauth / magic cookies, то с Dbus не получалось общаться, то ещё чего-нибудь. И тогда я вспомнил, что бывают systemd user units.

Отлично. Пишем unit типа такого.
[Unit]
Description=Xpra SuperApp

[Service]
Type=simple
ExecStart=/usr/bin/xpra start :10 --daemon=no --start='/usr/bin/chmod 660 /run/xpra/myhost-10' --start-child='/usr/bin/java -Xms128M -Xmx128M -jar /opt/SuperApp/foo-applet.jar' --exit-with-children
Restart=always
RestartSec=5

[Install]
WantedBy=default.target

Называем эту штуку, например, 'xpra.service' и кладём в '/home/john/.config/systemd/user', где 'john' - имя пользователя, от которого всё это будет запускаться.

Дальше есть несколько нюансов.

Первый. Этому самому "Джону" нужно разрешить lingering, то есть запуск каких-то процессов без его непосредственного интерактивного участия. Делается так, из-под рута:

loginctl enable-linger john

Второй. Из-под самого Джона нужно один раз произнести заклининания интерактивно, без повышения:

systemctl --user daemon-reload
systemctl --user enable xpra
systemctl --user start xpra

чтобы поставить сервис в автозагрузку и опционально сразу же стартовать его.

Третий. У xpra есть самые разные параметры запуска. Например, "--window-close=disconnect". Тогда при закрытии окна приложения на клиенте оно не будет завершено на сервере. Но при этом никто не запретит пользователю сделать что-нибудь типа "File → Exit" в меню. Тогда приложение таки закроется, но xpra останется "висеть". Следующий пользователь успешно подключится, но ничего не увидит. Потому что терминал формально есть, а работать внутри него нечему. Поэтому персонально я предпочитаю комбинацию параметров "--start-child=", "--exit-with-children", "Restart=always". Тогда xpra остановится вместе с приложением, systemd обнаружит данный факт и сам запустит всё взад.

Четвёртый. Пришлось городить вот такой костыль: "--start='/usr/bin/chmod 660 /run/xpra/myhost-10'", где "myhost" - имя машины (hostname), на которой всё запускается, "10" - номер X-дисплея (мы его придумываем сами), задается параметром ранее после двоеточия. После запуска xpra создает три Unix-сокета в разных папках с правами типа "john:xpra 600" или вариациями на тему. То есть по умолчанию подключиться к "чужой" X-сессии нельзя, только сам Джон может сделать это. Меня же это не устраивает, т.к. по условию задачи требуется выдать доступ некоей большой ораве пользователей. Поэтому всех заинтересованных приходится включать в группы "john" и "xpra", плюс накидывать прав на чтение-запись для группы "xpra" на один из трёх таких создаваемых сокетов. Тогда подключиться к созданному X-дисплею смогут все, кто входит в группу "xpra".

Клиенту остается только загрузить в SSH-агента свой закрытый ключ и сделать "attach" на сервер типа такого: "xpra attach ssh:superserver.com:10". Я у себя протестировал под Linux-ом и под виндой, всё работает как задумано. Под Mac-ом протестировать не могу, но xpra-клиент для него тоже существует. Если к серверу цепляются одновременно двое пользователей, то первого "вышибает". Если первый сделает "disconnect", то второй увидит приложение в том же состоянии, в котором его оставил первый. Если же первый именно что закроет приложение, то второй увидит его "с нуля" в "свежезапущенном" облике.

При перезагрузке сервера всё запускается автомагически посредством systemd, это тоже я проверил.

Всем поменьше кривых приложений и быстрых терминалов.

hints, ссылки, linux, трудовыебудни, it, manual

Previous post Next post
Up