Настройка 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
Автор :

Cookies and IP addresses allow us to deliver and improve our web content, resolve technical errors, and provide you with a personalized experience. Our website uses cookies and collects your IP address for these purposes.