![](http://l0st.ws/f/f5/vnc.png)
Как выяснилось, серверная версия OSX не содержит такой полезной функции, как терминальные сессии (несколько удаленных подключений с GUI). С другой стороны, несколько пользователей одновременно GUI использовать могут (через Fast User Switching). Сегодня я решил поковырять этот механизм и выжать из него максимум возможного.
Немного теоретической части. За все графические сессии в OSX отвечает WindowServer — основной и единственный процесс, который общается с видеокартой, принимает запросы на отрисовку и, собственно, рисует картинку. С некоторой натяжкой он похож на сервер X11.
Основное отличие — конкретно пользовательские сессии держат несколько процессов loginwindow. Первичный запускается WindowServer'ом (от пользователя root), производит авторизацию и понижает себя до уровня соответствующего пользователя. Активный пользователь (тот, сессия которого отрисовывается на физическом мониторе) получает loginwindow с флагом «console». Как только он попробует переключиться на другого пользователя через Fast User Switching, WindowServer отберет у него статус консоли, создаст новый loginwindow, и все повторится. При переключении пользователей, WindowServer просто делает консольным необходимый процесс loginwindow.
Итак, проблема первая. Fast User Switching очень коряво работает по VNC/RDC, зачастую убивая GUI вообще.
![](http://l0st.ws/f/e9/bug.png)
Баг был отправлен в Эппл и закрыт как дубликат. Первым найденным мною воркэраундом был
killall -9 WindowServer
, который гарантированно решал проблему, заодно убивая все графические сессии, что было абсолютно неприемлимо, но хотя бы возвращало контроль над GUI. Второй воркэраунд — убивать консольный сеанс loginwindow — оказался намного эффективнее. При последующем перезапуске баг неожиданно пропадал (впрочем, до первого использования Fast User Switching).Таким образом, стало возможно использовать GUI на сервере удаленно любым количеством пользователей, но только одним пользователем за раз. Неплохо, но не интересно. Конечно, это решало несколько проблем, таких, как unit-тестирование iPhone приложений (ibtool принципиально не работает без активной GUI-сессии пользователя, так что скомпилировать xib'ы нельзя).
И VNC и RDC, реализованные эпплом, работают одинаково. Стало интересно, а что же происходит в тех «фоновых» loginwindow, которые остаются за кадром? Ответ на этот вопрос мне помог дать OSX VNC, независимый VNC-сервер для OSX. Я запустил две сессии от разных пользователей и на каждой поднял VNC-сервер. Как оказалось, WindowServer полностью отрисовывает и фоновые сессии, так что при подключении к VNC-серверу конкретного пользователя можно работать в GUI-сессии абсолютно полноценно.
![](http://l0st.ws/f/e29/2vnc.png)
Теперь в эту потенциальную бочку меда я подмешаю дёготь. Для работы VNC-сервера пользователю надо создать сессию на loginwindow. Это можно сделать через основной VNC/RDC-сервер (и ограничение прав на Login Window), но основной сервер позволяет контролировать текущую консольную сессию и, потенциально, является брешью безопасности. VNC-сервера пользователей «жестко» забиты по портам, надо знать номер своего терминала, а пароли устанавливать вручную (и забыть про общую базу авторизации в LDAP). Эта схема не подходит для большого числа GUI-сессий и развертывания в строгих условиях безопасности, но те задачи, которые я перед ней поставил, она решает на все 100%.
Возможно, я найду время и сделаю аггрегатор VNC-серверов для того, чтобы был один сервер-маршрутизатор, который по LDAP-авторизации разруливал бы доступ к конечным VNC-серверам у пользователей. Но я надеюсь, что Эппл реализует поддержку терминальных сессий раньше.