Глава 7. Персонализация WSL
Содержание
Теперь, когда вы изучили с архитектурой WSL и знакомы с её настройками и конфигурированием, давайте поговорим относительно некоторых моментов по индивидуализации WSL.
Официальная поддержка для установки графических приложений Linux в WSL с названием WSLg в настоящее время в предварительном просмотре в Insider Dev Channel Windows и должна быть выпущена в версиях Windows позднее. Однако, имеется возможность применения графических приложений Linux в WSL в уже выпущенных версиях Windows. На данный момент это требует запущенного в Windows X сервера стороннего разработчика и немного настроек для указания соответствующему дистро WSL на такой сервер на стороне Windows.
Если вы устанавливаете графические приложения в своём дистро WSL, они зачастую доставляются в X сервер самого дистро в качестве зависимости, однако в действительности мы не применяем такой X сервер. Вместо этого мы будем передавать весь вывод X от каждого приложения в X сервер, запущенный в Windows поверх локального порта.
Прежде всего нам следует выбрать некий X сервер в Windows и установить его. Должны работать такие:
-
VcXsrv
-
X410
-
Xmanager
-
Xming
-
Cygwin/X
-
MobaXterm
Двумя наиболее распространёнными X серверами, которые вы можете обнаружить в нашем сообществе WSL выступают X410 и VcSrv. VcSrv является бесплатным и обладает открытым исходным кодом и собирается из восходящего базового кода Xorg. Хотя он и может быть слегка более проблемным в плане правильного запуска. X410 платный и доступен через Microsoft Store, однако он прелестно издаётся и требует меньше настроек вручную.
После того как ваш 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 и более ранней графики.
В WSL2 вам потребуется открыть доступ в вашем Брандмаэуре Защитника (межсетевом экране, Firewall) Windows для X сервера стороны Windows.
В X410 кликните правой кнопкой по лоточной иконке, выберите “Allow Public Access” (Разрешить общедоступные сети) проверьте “Public networks” (Общедоступные сети) в приглашении вашего Брандмаэура Защитника (Firewall) Windows и затем перезапустите X410.
Рисунок 7-4
Проверьте “Public networks” (Общедоступные сети) в приглашении Брандмаэура Защитника Windows для включения X410 в WSL2
В VcXsrv проверьте “Disable access control” (Блокировать) в приглашении межсетевого экрана Windows при настройке XLaunch и, как и в X410, проверьте “Public networks” (Общедоступные сети) в приглашении своего межсетевого экрана Windows.
Рисунок 7-6
Проверьте “Public networks” (Общедоступные сети) в приглашении Брандмаэура Защитника Windows для включения VcXsrv в WSL2
Вы можете спросить себя: не является ли некая открытая служба в моём межсетевом экране на общедоступной сетевой среде иском для безопасности? Совершенно верно.
Имеется два момента, которые вы можете сделать в отношении этого. Никогда не применяйте приложения с графическим интерфейсом при подключении к общедоступным сетевым средам, таким как в кафе или в самолёте. В качестче альтернативы вы можете настроить некое правило межсетевого экрана Windows, которое ограничивает ваше выставление допуская общедоступный TCP доступ к X серверу лишь из подсети вашего локального дистро.
В WSL откройте Дополнительные настройки своего Брандмаэура Защитника (Firewall) Windows:
> cmd.exe /C wf.msc
В закладке “Inbound Rules” (Правила для входящих подключений) отыщите свой X сервер в списке приложений. Будут иметься правила для Общедоступной и Частной сетей и протоколов TCP и UDP. Мы изменяем правило протокола TCP Общедоступной сети.
Вам моет понадобиться отмотать столбец “Protocol” чтобы найти разграничение TCP/UDP.
Рисунок 7-9
Локализация входящих правил “public” TCP межсетевого экрана для вашего X сервера Windows
Откройте правило общедоступного входящего TCP для своего X сервера, кликнув правой кнопкой и выбрав “Properties” (Свойства).
В “General” (Общие), выберите “Allow the connection” (Разрешить подключение).
Затем пройдите в закладку “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 сервер в большей безопасности.
После того как X сервер установлен, порты межсетевого экрана открыты для WSL2 и мы имеем настроенным перенаправление для своего дистро WSL, настало время установить приложение графического интерфейса. Это скорее всего доставит некоторые относящиеся к Xorg зависимости, включая некий X сервер, однако мы не будем запускать X сервер из своего дистро WSL:
> sudo apt -y install synaptic
Если всё настроено верно, вы теперь должны быть способны запускать своё приложение графического интерфейса:
> sudo synaptic
Рисунок 7-13
Synaptic простой диспетчер пакетов с графическим интерфейсом для Ubuntu, Debian и прочих дистрибутивов Linux на основе apt
Наиболее распространённой ошибкой, встречающейся при попытке запуска приложений с графическим интерфейсом в 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
Порой приложение с графическим интерфейсом 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
WSL не обладает традиционным init, таким как SysVinit, systemd-init или OpenRC. Она обладает некой программой init, которая обрабатывает такие базовые задачи как взаимодействие с Windows, совместное использование файлов и поддержка сетевой среды. Однако она не стартует службы и не выступает адресатом большинства приложений Linux, которые ищут init.
Если вы хотите запускать службы при каждом открытии WSL у вас есть два основных варианта. Вы можете следовать сценарию как части своей оболочки, или же вы можете запускать команду при помощи Планировщика заданий (Task Scheduler) Windows.
Добавление команд оболочки в ваш файл настроек bash это самый простой способ автоматизации команд, которые вы бы хотели исполнять при каждом запуске. Bash исполняет этот файл при каждом открытии нового окна, будь то традиционная консоль, или новый Терминал Windows.
.bashrc
это хорошее место для настройки переменных среды, например, переменной дисплея для
применения внешнего X сервера (Рисунок 7-15).
Обычно он содержит некоторый стандартные настройки, устанавливаемые вашим дистро WSL; просто добавьте в конец то что вам нужно.
.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), он будет включаться всякий раз когда вы открываете некий новый терминал; в результате это может приводить к дублированию запущенных приложений или подвешиваниям.
Таким образом, вам может потребоваться добавлять некоторый дополнительный сценарий, который вначале проверяет не запущено ли это приложение перед тем как предпринимать попытку его запуска, например
#!/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 или может приводить в результате к потенциальной утрате данных.
К счастью, visudo
больше не применяет редактор vi
, а вместо
него в Ubuntu по умолчанию установлен nano
, которым намного проще пользоваться. Откройте файл sudoers:
> sudo visudo
И затем добавьте
ALL ALL=NOPASSWD: /etc/init.d/dbus start
Покиньте nano (Ctrl+X и затем “Y”) и подтвердите изменения.
Что если вы желаете запускать приложение или службу 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
Превращаем этот сценарий в исполняемый:
> 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
Обратите внимание на то, что 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
Имеется возможность определить -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.
Если редактирование сценариев bash и пакетных файлов кажется перегибом для автоматизации некоторых команд WSL из Windows, имеется и более простой вариант: Применение Планировщика заданий (Task Scheduler) Windows.
Планировщик заданий Windows это более дружественный способ автоматизации задач в Windows и он способен исполнять команды в WSL.
Откройте Планировщик заданий Windows и кликните “Create Basic Task…” (Создайте простую задачу). В своём примере мы собираемся реализовать обновления в Windows без сопровождения.
Для поля Название наберите “Unattended Upgrades in Ubuntu”.
Для этой задачи установите переключатель; в нашем примере мы будем запускать это “Daily” (Ежедневно).
И затем настроим запуск задачи в час ночи.
Мы хотим “Start a program” (Запустить программу) для своей задачи.
Мы намерены запускать wsl.exe
при помощи таких параметров:
-u root -e apt update
.
Это должно проверить apt на обновления пакетов из репозитория Ubuntu в качестве root.
Обратите внимание, что это будет исполнено в установленном по умолчанию дистро WSL; если вы обладаете множеством установленных дистро WSL
и хотите запускать конкретный дистро, если это необходимо, определите это дистро при помощи -d
, например,
-d Ubuntu
.
Закончите эту новую задачу, проверив “Open the Properties dialog for this task when I click Finish”, поскольку мы ещё не сделали этого (Рисунок 7-31). На данный момент мы создали некое действие для проверки обновления пакетов из репозитория Ubuntu. Однако нам всё ещё требуется добавить свой следующий шаг для применения всех доступных обновлений.
В Properties (Свойствах), кликните по закладке “Actions” (Действия) (Рисунок 7-32) и затем кликните “New”, потому что мы намерены добавить команду модернизации пакетов apt после проверки на обновления пакетов из репозитория Ubuntu.
В окне New Action мы намерены запустить wsl.exe
с такими аргументами:
-u root -e apt -y upgrade
.
Это выполнит команду модернизации пакетов apt, без взаимодействия, от имени root.
Панель Actions теперь отразит обе команды в задаче (Рисунок 7-33).
Рисунок 7-33
Два наших действия в нашей задаче, проверяющая наличие обновления и затем применяющая доступные обновления
При выполнении действия обновления apt, вначале, мы проверяем доступность обновлений пакетов и затем выполняем действие модернизации для применения этих обновлений.
Кликните “OK” и вы всё сделали.
Теперь вы можете обнаружить созданную нами задачу в Диспетчере заданий в “Active Tasks”.
Чтобы проверить только что созданную нами задачу, кликните дважды по этой задаче и затем по “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
.