Глава 7. Персонализация WSL

Теперь, когда вы изучили с архитектурой WSL и знакомы с её настройками и конфигурированием, давайте поговорим относительно некоторых моментов по индивидуализации WSL.

Применение графических приложений при помощи X

Официальная поддержка для установки графических приложений Linux в WSL с названием WSLg в настоящее время в предварительном просмотре в Insider Dev Channel Windows и должна быть выпущена в версиях Windows позднее. Однако, имеется возможность применения графических приложений Linux в WSL в уже выпущенных версиях Windows. На данный момент это требует запущенного в Windows X сервера стороннего разработчика и немного настроек для указания соответствующему дистро WSL на такой сервер на стороне Windows.

Если вы устанавливаете графические приложения в своём дистро WSL, они зачастую доставляются в X сервер самого дистро в качестве зависимости, однако в действительности мы не применяем такой X сервер. Вместо этого мы будем передавать весь вывод X от каждого приложения в X сервер, запущенный в Windows поверх локального порта.

Установка X Server в Windows

Прежде всего нам следует выбрать некий X сервер в Windows и установить его. Должны работать такие:

  • VcXsrv

  • X410

  • Xmanager

  • Xming

  • Cygwin/X

  • MobaXterm

Двумя наиболее распространёнными X серверами, которые вы можете обнаружить в нашем сообществе WSL выступают X410 и VcSrv. VcSrv является бесплатным и обладает открытым исходным кодом и собирается из восходящего базового кода Xorg. Хотя он и может быть слегка более проблемным в плане правильного запуска. X410 платный и доступен через Microsoft Store, однако он прелестно издаётся и требует меньше настроек вручную.

 

Рисунок 7-1


Перечисление Microsoft Store для X410, X сервера Windows

 

Рисунок 7-2


Страница проекта VcXsrv в SourceForge.net, X сервера Windows

Настройка WSL для проброса X в ваш Windows X Server

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

В WSL1 это достаточно просто:


> export DISPLAY=127.0.0.1:0.0
		

В WSL2 мы обязаны переправлять его на соответствующий IP адрес своего хоста среды Windows. Мы можем выхватить этот IP адрес из настроек DNS, которые этот WSL настроил в /etc/resolv.conf:


> export DISPLAY=$(awk '/nameserver/ {print $2}' /etc/resolv.conf 2>/dev/null):0
		

Если вы переопределили автоматическую выработку resolv.conf, он может не обновляться IP адресом вашего хоста среды Windows; в таком случае вам придётся создать сценарий для его получения из вашей системы Windows, например:


> export DISPLAY= $ (powershell.exe -c "(Get-NetIPAddress -InterfaceAlias '*wsl*' -AddressFamily IPv4).ipaddress + ':0.0'")
		

Когда вы намерены запускать приложения графического интерфейса на постоянной основе, вам следует поместить эту команду в ваш файл .bashrc, или, в Windows 10 со сборкой 21286 и выше в качестве параметра команды [boot] в /etc/wsl.conf. Прочтите приводимые ниже сведения о файле .bashrc, если вы не знакомы с ним.

Если запускаемое вами приложение графического интерфейса предлагает ускорение libGL, вам также следует настроить приводимое ниже, что разгрузит построение изображений из WSL на сторону X сервера Windows:


> export LIBGL_ALWAYS_INDIRECT=1
		

Это приведёт к ускорению построения изображений OpenGL 1.4 и более ранней графики.

WSL 2, GUI Apps и межсетевой экран Windows

В WSL2 вам потребуется открыть доступ в вашем Брандмаэуре Защитника (межсетевом экране, Firewall) Windows для X сервера стороны Windows.

В X410 кликните правой кнопкой по лоточной иконке, выберите “Allow Public Access” (Разрешить общедоступные сети) проверьте “Public networks” (Общедоступные сети) в приглашении вашего Брандмаэура Защитника (Firewall) Windows и затем перезапустите X410.

 

Рисунок 7-3


Разрешение Общего доступа для включения X410 в WSL2

 

Рисунок 7-4


Проверьте “Public networks” (Общедоступные сети) в приглашении Брандмаэура Защитника Windows для включения X410 в WSL2

В VcXsrv проверьте “Disable access control” (Блокировать) в приглашении межсетевого экрана Windows при настройке XLaunch и, как и в X410, проверьте “Public networks” (Общедоступные сети) в приглашении своего межсетевого экрана Windows.

 

Рисунок 7-5


Проверьте “Disable access control” в VcXsrv для включения VcXsrv в WSL2

 

Рисунок 7-6


Проверьте “Public networks” (Общедоступные сети) в приглашении Брандмаэура Защитника Windows для включения VcXsrv в WSL2

Вы можете спросить себя: не является ли некая открытая служба в моём межсетевом экране на общедоступной сетевой среде иском для безопасности? Совершенно верно.

Имеется два момента, которые вы можете сделать в отношении этого. Никогда не применяйте приложения с графическим интерфейсом при подключении к общедоступным сетевым средам, таким как в кафе или в самолёте. В качестче альтернативы вы можете настроить некое правило межсетевого экрана Windows, которое ограничивает ваше выставление допуская общедоступный TCP доступ к X серверу лишь из подсети вашего локального дистро.

В WSL откройте Дополнительные настройки своего Брандмаэура Защитника (Firewall) Windows:


> cmd.exe /C wf.msc
		
 

Рисунок 7-7


Локализация вашего X сервера Windows в случае X410 из настроек Windows Firewall

В закладке “Inbound Rules” (Правила для входящих подключений) отыщите свой X сервер в списке приложений. Будут иметься правила для Общедоступной и Частной сетей и протоколов TCP и UDP. Мы изменяем правило протокола TCP Общедоступной сети.

 

Рисунок 7-8


Локализация входящих правил “public” для вашего X сервера Windows, в данном случае X410

Вам моет понадобиться отмотать столбец “Protocol” чтобы найти разграничение TCP/UDP.

 

Рисунок 7-9


Локализация входящих правил “public” TCP межсетевого экрана для вашего X сервера Windows

Откройте правило общедоступного входящего TCP для своего X сервера, кликнув правой кнопкой и выбрав “Properties” (Свойства).

В “General” (Общие), выберите “Allow the connection” (Разрешить подключение).

 

Рисунок 7-10


Разрешение входящих соединений во входящих правилах “public” TCP межсетевого экрана

Затем пройдите в закладку “Protocols and Ports” (Протоколы и порты), установите “Protocol type” (Тип протокола) в “TCP”, и из “Local port” (Локальный порт) выберите “Specific Ports” (Специальные порты) и введите порт 6000.

 

Рисунок 7-11


Ограничение входящих соединений во входящих правилах “public” TCP межсетевого экрана для X порта, порта 6000

Пройдите в закладку “Scope” (Обласьь), выберите “These IP addresses” (Указанные IP адреса) ➤ “Add…” (Добавить…) и вставьте 172.16.0.0/12.

172.16.0.0/12 это диапазон виртуальной подсети вашей WSL.

 

Рисунок 7-12


Ограничение входящих соединений во входящих правилах “public” TCP межсетевого экрана для для диапазона IP адресов в виртуальной подсети WSL

Кликните “OK” и “Apply” (Применить).

Наконец, вы можете настроить или оставить правило общедоступного UDP для своего X сервера как “Block the connection” (Блокировать подключение), поскольку обычно X протокол не пользуется UDP.

Теперь ваш X сервер в большей безопасности.

Установка приложения GUI

После того как X сервер установлен, порты межсетевого экрана открыты для WSL2 и мы имеем настроенным перенаправление для своего дистро WSL, настало время установить приложение графического интерфейса. Это скорее всего доставит некоторые относящиеся к Xorg зависимости, включая некий X сервер, однако мы не будем запускать X сервер из своего дистро WSL:


> sudo apt -y install synaptic
		

Если всё настроено верно, вы теперь должны быть способны запускать своё приложение графического интерфейса:


> sudo synaptic
		
 

Рисунок 7-13


Synaptic простой диспетчер пакетов с графическим интерфейсом для Ubuntu, Debian и прочих дистрибутивов Linux на основе apt

Отладка приложения GUI

Наиболее распространённой ошибкой, встречающейся при попытке запуска приложений с графическим интерфейсом в WSL2, это нечто подобное “cannot open display:” или “Unable to init server: Could not connect: Connection refused”. Это обусловлено тем, что ваш дистро WSL не может соединиться с X сервером вашей среды Windows.

 

Рисунок 7-14


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

Контрольный список:

  • X сервер установлен, например, VcXsrv или X410

  • X сервер запущен - проверьте область своего лотка

  • Переменная DISPLAY установлена подобающим образом в зависимости от отго запускаете ли вы WSL1 или WSL2

dbus

Порой приложение с графическим интерфейсом Linux не запускается по той причине, что оно не может подключиться к шине. dbus это служба обмена сообщениями рабочего стола Linux. Когда X настроен правильно и вы можете запускать прочие приложения с графическим интерфейсом, однако одно из приложений отказывает, возможно, стоит попытаться установить и настроить dbus когда вы обнаруживаете упоминания о dbus в сообщении об ошибке.

Установите dbus как вы это делаете для любого прочего пакета Linux:


> sudo apt install dbus-x11
		

Выработайте идентификатор устройства dbus, который вам потребуется лишь один раз при установке дистро WSL:


> dbus-uuidgen –ensure
		

Затем запустите dbus-launch перед стартом своего приложения с графическим интерфейсом:


> dbus-launch --exit-with-x11
		

Раскрутка вашей собственной системы init

WSL не обладает традиционным init, таким как SysVinit, systemd-init или OpenRC. Она обладает некой программой init, которая обрабатывает такие базовые задачи как взаимодействие с Windows, совместное использование файлов и поддержка сетевой среды. Однако она не стартует службы и не выступает адресатом большинства приложений Linux, которые ищут init.

Если вы хотите запускать службы при каждом открытии WSL у вас есть два основных варианта. Вы можете следовать сценарию как части своей оболочки, или же вы можете запускать команду при помощи Планировщика заданий (Task Scheduler) Windows.

.bashrc

Добавление команд оболочки в ваш файл настроек bash это самый простой способ автоматизации команд, которые вы бы хотели исполнять при каждом запуске. Bash исполняет этот файл при каждом открытии нового окна, будь то традиционная консоль, или новый Терминал Windows.

.bashrc это хорошее место для настройки переменных среды, например, переменной дисплея для применения внешнего X сервера (Рисунок 7-15).

Обычно он содержит некоторый стандартные настройки, устанавливаемые вашим дистро WSL; просто добавьте в конец то что вам нужно.

 

Рисунок 7-15


Образец файла .bashrc в Ubuntu

.bashrc располагается в домашней папке вашего пользователя, ~ или /home/<username>. Его можно открыть при помощи текстового редактора nano следующим образом:


> nano ~/.bashrc
		

.bashrc специфичен для Bash. Если вы измените его на альтернативную оболочку, такую как fish, zsh, csh или ksh, вам потребуется определить ту команду, которую вы пожелаете исполнять при каждом запуске в соответствующих файлах настроек для каждой из этих оболочек.

.bashrc специфичен для пользователя. Если вы создаёте другого пользователя и запускаете WSL от имени этого пользователя, например, при помощи wsl.exe -u или через изменение пользователя по умолчанию, вам потребуется добавлять эти команды в .bashrc для этого пользователя, соответственно в их домашние каталоги.

Если же вы желаете сделать некий сценарий исполнения или запуска для всех пользователей, вам потребуется создать некий новый сценарий в /etc/profile.d/, такой как


> sudo nano /etc/profile.d/displayvar.sh
		

Затем скопировать и вставить:


#!/bin/bash
export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2>/dev/null):0
export LIBGL_ALWAYS_INDIRECT=1
 	   

Покиньте nano (Ctrl+X и затем “Y”), подтвердите изменения и превратите этот сценарий в исполняемый:


> sudo chmod /etc/profile.d/displayvar.sh
		

Обратите внимание, что сценарии /etc/profile.d/ выполняются только в интерактивных оболочках; это те оболочки, которые запускаются в терминалах. Он не будет исполняться когда вы запускаете WSL в фоновом режиме при помощи удалённого расширения VS Code. В таких случаях вам надлежит добавлять сценарий в /etc/bash.bashrc и затем устанавливать переменную среды Windows для WSL на считывание /etc/bash.bashrc при каждом запуске:


> export WSLENV="BASH_ENV/u"
		

Не являющиеся POSIX- совместимыми оболочкиЮ например, fish, могут не считывать файлы /etc/profile.d/* или /etc/bash.bashrc при запуске; вам потребуется проконсультироваться с документацией таких оболочек относительно того каково надлежащее поведение запуска сценария.

Когда у вас есть сценарий, который запускает некое приложение или сужбу в фоновом режиме (Рисунок 7-16), он будет включаться всякий раз когда вы открываете некий новый терминал; в результате это может приводить к дублированию запущенных приложений или подвешиваниям.

 

Рисунок 7-16


Запущенный в дистро WSL apache2

Таким образом, вам может потребоваться добавлять некоторый дополнительный сценарий, который вначале проверяет не запущено ли это приложение перед тем как предпринимать попытку его запуска, например


#!/bin/bash
SERVICE="dbus-daemon"
if pgrep -x "$SERVICE" >/dev/null
then
    echo "$SERVICE is running"
else
    echo "$SERVICE stopped"
    sudo /etc/init.d/dbus start
fi
 	   

Вы можете поместить этот сценарий в свой файл .bashrc для создания нового сценария в вашей папке /etc/profile.d/ для всех пользователей, однако проверьте что вы добавили префикс в новый сценарий с соответствующим магическим куком (shebang), например, #!/bin/bash и превратили его в исполняемый при помощи chmod.

Даже хотя внути WSL и не имеется традиционного init, классические сценарии, расположенные в каталоге /etc/init.d/ всё ещё полезны для запуска и останова служб в WSL. Сама команда service также работает в WSL. Даже хотя она обычно и ассоциируется с systemd, на самом деле service это вспомогательный сценарий, который будет, если это необходимо, сценарием по умолчанию для init.d.

Опытные пользователи оболочки могут отметить некую проблему в нашем предыдущем сценарии; он вызывает sudo. это может оказаться обременительным, поэтому что бы мы могли поделать с этим? Мы могли бы добавить некое исключение для конкретно этой команды в соответствующий файл sudoers.

Для тех, кто не знаком с ним, sudoers это файл, который управляет тем какая эскалация допустима с командой sudo (Рисунок 7-17). Для изменения этого файла вам следует применять visudo. Не изменяйте этот файл иным редактором; это разрушит ваши настройки sudoers и может препятствовать дальнейшим изменениям, необходимым для сброса вашего дистро WSL или может приводить в результате к потенциальной утрате данных.

 

Рисунок 7-17


Изменение файла sudoers при помощи команды visudo

К счастью, visudo больше не применяет редактор vi, а вместо него в Ubuntu по умолчанию установлен nano, которым намного проще пользоваться. Откройте файл sudoers:


> sudo visudo
		

И затем добавьте


ALL ALL=NOPASSWD: /etc/init.d/dbus start
		

Покиньте nano (Ctrl+X и затем “Y”) и подтвердите изменения.

Службы Windows

Что если вы желаете запускать приложение или службу Linux когда вы зарегистрированы в Windows и при этом не запуская Терминал Windows или не открывая WSL в фоновом режиме в неком IDE, таком как VS Code?

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

Для этого примера мы воспользуемся веб сервером Apache.

Установим Apache:


> sudo apt -y install apache2
		

Создадим некий сценарий оболочки:


> sudo nano /opt/runapache.sh
		

Скопируем и вставим соответствующий сценарий оболочки, индивидуализируя, в случае необходимости, ту службу, которую вы бы желали запускать (Рисунок 7-18):


#!/bin/bash
SERVICE="apache2"
if pgrep -x "$SERVICE" >/dev/null
then
    echo "$SERVICE is running"
else
    echo "$SERVICE stopped"
    sudo /etc/init.d/apache2 start
fi
		
 

Рисунок 7-18


Изменение в nano сценария для запуска Apache

Превращаем этот сценарий в исполняемый:


> sudo chmod /opt/runapache.sh
		

Изменим владельца этого сценария оболочки на своего первичного пользователя:


> sudo chown hayden /opt/runapache.sh
		

Создадим пакетный файл Windows в вашем домашнем каталоге Windows для вызова этого сценария оболочки (Рисунок 7-19):


> nano $(wslpath $(wslvar USERPROFILE))/runapache.bat
		

Скопируем и вставим туда следующее, индивидуализируя, если это требуется:


@echo off
wsl.exe /opt/runapache.sh
		
 

Рисунок 7-19


Изменение пакетного файла Windows для вызова нашего сценария

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


> wsl.exe --setdefault <distribution>
		

Если вы желаете применять иной дистро, вы можете подставлять его псевдоним .exe, например, ubuntu1804.exe если он был установлен из Store или сторонним образом загруженным .appx, либо при помощи wsl.exe –d Ubuntu2004 с последующей командой:


> wsl.exe -d Ubuntu-20.04 sudo /etc/init.d/apache2 start
		

Когда вы желаете запускать само приложение от имени иного пользователя, вы можете определять его при помощи -u:


> wsl.exe -u apacheuser sudo /etc/init.d/apache2 start
		

Вы видите, что данная команда обладает префиксом sudo, что означает, что вам потребуется добавить эту команду в свой файл sudoers для своего пользователя по умолчанию или для пользователя, определяемого в -u.

Исполните


> sudo visudo
		

И добавьте


ALL ALL=NOPASSWD: /etc/init.d/apache2 start
		
 

Рисунок 7-20


Добавление запуска /etc/init.d/apache2 для файла sudoers

Имеется возможность определить -u root и обойти необходимость в добавлении в файл sudoers, однако это не рекомендуется. Запуск сетевых служб от имени root, доступ к которым имеется из Интернета, это плохая мысль.

Затем проверьте созданный нами пакетный файл Windows. Откройте PowerShell и убедитесь что Apache2 не запущена:


PS C:> wsl.exe --exec ps -A
		

Вы не должны увидеть никаких процессов apache2; если это так, исполните


PS C:> wsl.exe --exec sudo killall apache2
		

Затем выполните свой пакетный файл следующим образом:


PS C:> C:\Users\Hayden\runapache.bat
		
 

Рисунок 7-21


Тестирование пакетного файла, который вызывает наш сценарий оболочки для запуска apache2

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

 

Рисунок 7-22


Тестирование работающего пакетного файла/ сценария apache2 через открытие localhost в веб браузере

Обратите внимание, что если вы запускаете свой пакетный файл снова немедленно, он обнаружит что apache2 уже исполняется и не запустит второй экземпляр.

 

Рисунок 7-23


Запуск пакетного файла/ сценария apache2 снова, которое определяет что apache2 уже запущен

Наконец, воспользуйтесь Диспетчером управления службами Windows (Windows Service Control Manager), sc.exe, для того чтобы запланировать запуск своего пакетного файла при запуске Windows.

Откройте PowerShell в качестве Администратора и выполните


PS C:> sc create 'Apache in WSL' binpath= C:\Users\Hayden\runapache.bat type= share start= auto displayname= 'Apache in WSL'
		

Обратите внимание на пробел после “=” в команде sc create.

Эта служба теперь может управляться с панели служб Windows.

 

Рисунок 7-24


Управление Apache в службе WSL из Служб Windows

Планировщик задач Windows

Если редактирование сценариев bash и пакетных файлов кажется перегибом для автоматизации некоторых команд WSL из Windows, имеется и более простой вариант: Применение Планировщика заданий (Task Scheduler) Windows.

 

Рисунок 7-25


Планировщик заданий Windows

Планировщик заданий Windows это более дружественный способ автоматизации задач в Windows и он способен исполнять команды в WSL.

Откройте Планировщик заданий Windows и кликните “Create Basic Task…” (Создайте простую задачу). В своём примере мы собираемся реализовать обновления в Windows без сопровождения.

Для поля Название наберите “Unattended Upgrades in Ubuntu”.

 

Рисунок 7-26


Именование нашей новой задачи

Для этой задачи установите переключатель; в нашем примере мы будем запускать это “Daily” (Ежедневно).

 

Рисунок 7-27


Настройка задачи на ежедневный запуск

И затем настроим запуск задачи в час ночи.

 

Рисунок 7-28


Настройка времени запуска задачи

Мы хотим “Start a program” (Запустить программу) для своей задачи.

 

Рисунок 7-29


Определение того что данная задача запустит программу

Мы намерены запускать wsl.exe при помощи таких параметров: -u root -e apt update.

Это должно проверить apt на обновления пакетов из репозитория Ubuntu в качестве root.

Обратите внимание, что это будет исполнено в установленном по умолчанию дистро WSL; если вы обладаете множеством установленных дистро WSL и хотите запускать конкретный дистро, если это необходимо, определите это дистро при помощи -d, например, -d Ubuntu.

 

Рисунок 7-30


Определение программы для запуска wsl.exe и аргументы, -u root -e apt update

Закончите эту новую задачу, проверив “Open the Properties dialog for this task when I click Finish”, поскольку мы ещё не сделали этого (Рисунок 7-31). На данный момент мы создали некое действие для проверки обновления пакетов из репозитория Ubuntu. Однако нам всё ещё требуется добавить свой следующий шаг для применения всех доступных обновлений.

 

Рисунок 7-31


Завершение создания нашей новой задачи

В Properties (Свойствах), кликните по закладке “Actions” (Действия) (Рисунок 7-32) и затем кликните “New”, потому что мы намерены добавить команду модернизации пакетов apt после проверки на обновления пакетов из репозитория Ubuntu.

 

Рисунок 7-32


Открытие закладки Actions в нашей новой задаче для добавления дополнительных шагов

В окне New Action мы намерены запустить wsl.exe с такими аргументами: -u root -e apt -y upgrade.

Это выполнит команду модернизации пакетов apt, без взаимодействия, от имени root.

Панель Actions теперь отразит обе команды в задаче (Рисунок 7-33).

 

Рисунок 7-33


Два наших действия в нашей задаче, проверяющая наличие обновления и затем применяющая доступные обновления

При выполнении действия обновления apt, вначале, мы проверяем доступность обновлений пакетов и затем выполняем действие модернизации для применения этих обновлений.

Кликните “OK” и вы всё сделали.

Теперь вы можете обнаружить созданную нами задачу в Диспетчере заданий в “Active Tasks”.

 

Рисунок 7-34


Локализация задача среди Активных задач в Диспетчере задач

Чтобы проверить только что созданную нами задачу, кликните дважды по этой задаче и затем по “Run” под “Selected Item” (Рисунок 7-35).

 

Рисунок 7-35


Открытие и, если необходимо, изменение этой задачи, через двойной клик её в Активных задачах. Мы также можем запустить эту задачу через клик Run с последующим Выбрать элемент с правой стороны

Команда запуска

В Windows 10 сборки 21286 и выше теперь имеется возможность вручную включать команды при старте в вашем дистро WSL через /etc/wsl.conf.

Эти команды исполняются от имени root. Это может работать как некая минимальная система init при запуске WSL в качестве терминала.

Это не запускает службы автоматически в фоновом режиме, как некую запланированную службу Windows или запускать как спланированную задачу подобно Планировщику заданий, а только при открытии дистро WSL в неком терминале. Тем не менее, это может заполнить ваши потребности если вам просто требуется запускать службу, которая намного сложнее чем то, чему удовлетворяет файл .bashrc.

Для дополнительных сведений относительно этого варианта отсылаем вас к Главе 5, Настройка дистрибутивов WSL, где подробно обсуждаются параметры для /etc/wsl.conf.