Настройка WSL2 для разработки
Table of contents
Introduction
С выходом Windows 10 2004 (20H1)
и обновления KB4556803
, после которого сборка ОС становится 19041.264
, появилась возможность использования WSL2
.
WSL2
- одно из долгожданных изменений в Windows 10 2004 (20H1)
для разработчиков, т.к. теперь используется реальное ядро Linux
, которое предоставляет полноценное окружение Linux
на Windows
.
WSL2
значительно производительнее WSL1
и поддерживает полную совместимость системных вызовов, т.е. теперь Docker
на WSL2
работает без проблем.
Но после перехода на WSL2
появляются свои сложности и неудобства, такие как:
-
Изменение
IP
при перезагрузкеWSL2
, т.е. для проброса домена вWSL2
необходимо после перезагрузки править файлhosts
. -
При использовании оперативной памяти
WSL2
не отдает ее обратно вWindows
. Т.е., когдаWSL2
нужна оперативная память, то растет и потребление памяти виртуальной машиной, следовательно, память хоста будет уменьшаться. Но после завершения процесса, потребляющего память вWSL2
, она не будет возвращена на хост. -
При использовании дискового пространства происходит такая же проблема, как и с оперативной памятью. При загрузке файла большого объема в
WSL2
размер образаvhdx
будет расти пропорционально, но при его удалении изWSL2
пространство, занимаемое образом, не уменьшится.
Рассмотрим каким образом можно бороться с данными проблемами.
Репозиторий с рассматриваемыми ниже скриптами: https://github.com/superrosko/wsl2-scripts.
Автоматическое изменение IP в hosts
При перезапуске WSL2
IP
постоянно меняется и его приходится актуализировать в файле hosts
. Посмотреть текущий IP
можно командой:
ip addr show eth0
Чтобы избежать ручной актуализации, напишем скрипт prepare-hosts
, который будет производить обновление IP
в файле hosts
:
#!/bin/bash
WIN_HOSTS="/mnt/c/Windows/System32/drivers/etc/hosts"
TMP_HOSTS="/tmp/prepare-hosts"
WIN_IP=$(grep </etc/resolv.conf 'nameserver' | cut -f 2 -d ' ')
WSL_IP=$(ip addr show eth0 | grep 'inet ' | cut -f 6 -d ' ' | cut -f 1 -d '/')
export WIN_IP
export WSL_IP
check_ip() {
IP_NAME=$1
IP=$2
if [[ "$IP" == "" ]]; then
printf "%s: \x1b[31mIP is empty!\x1b[0m\n" "$IP_NAME"
else
printf "%s: \x1b[32m%s\x1b[0m\n" "$IP_NAME" "$IP"
fi
}
prepare_hosts() {
HOSTS_FILE=$1
TMP_HOSTS_FILE=$2
MARK=$3
IP=$4
if [[ "$IP" != "" ]]; then
if grep -q "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\s\{1,\}$MARK" "$HOSTS_FILE"; then
printf "\x1b[32mFound %s marks!\x1b[0m\n" "$MARK"
rm -f "$TMP_HOSTS_FILE"
cp "$HOSTS_FILE" "$TMP_HOSTS_FILE"
sed -i -e "s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\(\s\{1,\}\)$MARK/$IP\1$MARK/g" "$TMP_HOSTS_FILE"
sed -i -e "s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\(\s\{1,\}\)\(.*\)\(\s\{1,\}\)#$MARK/$IP\1\2\3#$MARK/g" "$TMP_HOSTS_FILE"
cat "$TMP_HOSTS_FILE" >"$HOSTS_FILE"
else
printf "%s %s\n" "$IP" "$MARK" >>"$HOSTS_FILE"
fi
fi
}
check_ip "Windows IP" "$WIN_IP"
check_ip "WSL IP" "$WSL_IP"
prepare_hosts $WIN_HOSTS $TMP_HOSTS "wsl2" "$WSL_IP"
prepare_hosts $WIN_HOSTS $TMP_HOSTS "winhost" "$WIN_IP"
printf "\nNew hosts file: \n\n"
printf "\x1b[34m=====================================================================\x1b[0m\n"
cat "$WIN_HOSTS"
printf "\x1b[34m=====================================================================\x1b[0m\n"
rm -f "$TMP_HOSTS"
printf "\n\x1b[32mDONE!\x1b[0m\n\n"
Для работы скрипта первоначально добавим хосты wsl2
и winhost
, а также отметим комментарием #wsl2
те хосты, IP
которых мы хотим подменять:
127.0.0.1 wsl2
127.0.0.1 winhost
127.0.0.1 example.com #wsl2
127.0.0.1 example.ru
127.0.0.1 example.com.localhost #wsl2
127.0.0.1 example.localhost
Запустим скрипт и получим обновленный результат:
172.22.80.60 wsl2
172.22.80.1 winhost
172.22.80.60 example.com #wsl2
127.0.0.1 example.ru
172.22.80.60 example.com.localhost #wsl2
127.0.0.1 example.localhost
IP прописались только к wsl2
, winhost
и отмеченным комментарием #wsl2
хостам.
Для работы данного скрипта необходимо открыть в Windows права на редактирование файла
%SystemRoot%\system32\drivers\etc\hosts
для пользователя, который будет запускать данный скрипт вWSL2
.
Также можно прописать автоматический запуск данного скрипта при старте сессии пользователя в WSL2
.
Проблема с возвратом оперативной памяти
Решение данной проблемы состоит из двух шагов.
Вначале зададим ограничение использования оперативной памяти в конфиге WSL2
.
Создадим или откроем файл %UserProfile%\.wslconfig
и добавим в него следующие опции:
[wsl2]
memory=16GB
swap=8GB
Таким образом мы ограничили передачу памяти от хоста в параметре memory, но это решило только часть проблемы.
Т.е. теперь WSL2
будет потреблять указанное в параметре memory
количество памяти, но при ее использовании не будет спешить ее освобождать.
Связано это с механизмом кэширования для ускорения работы при выполнении повторных действий.
Для того, чтобы принудительно вернуть занятую память, используем простой скрипт memory-reclaim
:
#!/bin/bash
echo 3 >/proc/sys/vm/drop_caches
touch /root/drop_caches_last_run
Запустив данный скрипт с root
-правами, WSL2
начнет процесс освобождения памяти.
Можно запускать данный скрипт по требованию или же настроить cron
, по которому скрипт будет периодически запускаться и производить возврат памяти.
Проблема с возвратом дискового пространства
Предупреждение: выполнение следующих команд может привести к потере данных, поэтому выполняйте их при крайней необходимости, сделав предварительный бэкап!
Для решения проблемы с возвратом дискового пространства можно воспользоваться следующими вариантами:
Для не Home
версии Windows
выполняем следующие команды в консоли Windows
:
wsl --shutdown
optimize-vhd -Path .\ext4.vhdx -Mode full
Для любой версии Windows
подойдет также следующая последовательность команд:
wsl --shutdown
diskpart
select vdisk file="C:\PATH-TO-WSL2-DISTR\ext4.vhdx"
attach vdisk readonly
compact vdisk
detach vdisk
exit
Предупреждение: выполнение перечисленных команд может привести к потере данных, поэтому выполняйте их при крайней необходимости, сделав предварительный бэкап!
Мы рассмотрели варианты решения проблем, которые возникают при работе с WSL2
.
Возможно в будущих релизах они будут устранены на системном уровне, а пока можно воспользоваться приведенными выше решениями.
Дата редактирования : 2020-11-12 00:37:49
Автор : Rosko