Ви хотіли Linux-середовище у Windows, що поводиться як сервери, які ви власне експлуатуєте. Потім ви ввели
systemctl status у WSL і отримали класичне сухе повідомлення: «System has not been booted with systemd.»
Раптом ваш «швидкий dev-бокс» перетворився на дивний петрі-ямник напівробочих демонів, відсутніх логів і сервісів,
які стартують лише якщо ви не забудете їх підштовхнути.
Хороша новина: systemd у WSL тепер — офіційно підтримуваний режим, а не купа хаків. Погана новина: це все ще не повна
VM, це не ваше production-ядро, і деякі речі ламаються так, ніби це особисто. Це практична карта — що працює, що ламається
і як діагностувати, ніби ви на чергуванні.
Стан справ: systemd у WSL сьогодні
Якщо ви на WSL2 і у вас відносно актуальний пакет WSL, ви можете ввімкнути systemd для кожного дистрибутива через
/etc/wsl.conf. WSL тоді запустить systemd як PID 1 всередині дистрибутива, і решта ваших сервісів
поводитиметься так, як на звичайній Linux-машині — більш-менш.
Саме «більш-менш» тут важливе. WSL — це не універсальний гіпервізор. Це Linux-ядро, розміщене в Windows із щільним
інтеграційним шаром. Частина інфраструктури відрізняється за задумом: мережа віртуалізована; маунти транслюються;
життєвий цикл залежить від сесії; Windows усе ще має ключі до управління живленням і хост-мережею.
Моє суб’єктивне керівництво:
-
Використовуйте systemd у WSL, коли вам потрібне реалістичне керування сервісами (Docker Engine, podman, sshd,
таймери, journald, сервіси через dbus). -
Не використовуйте WSL як продакшн (так, люди пробують). Ставтеся до нього як до dev/CI-середовища з
поведінкою, схожою на продакшн, а не як до продакшн-платформи. -
Тримайте межу між «Linux-сервісами» та «відповідальністю хоста Windows». Коли ви розмиваєте цю межу,
усунення несправностей перетворюється на перформанс-арт.
Як systemd фактично завантажується в WSL (і чому це важливо)
Традиційно WSL запускала ваш shell (або сконфігуровану команду) напряму; там не було init-системи. Це означало:
відсутність PID 1 для нагляду за сервісами, відсутність послідовного цільового стану завантаження і відсутність логів
під керуванням journald. Якщо демон помирав, він помирав тихо або лишав після себе застарілий PID-файл, як маленький
надгробок.
З увімкненим systemd, WSL запускає systemd як PID 1. D-Bus приходить разом, і юніти systemd можуть працювати звично.
Тепер у вас є когерентний спосіб запускати сервіси, визначати залежності, встановлювати політики перезапуску та
використовувати таймери замість «я запхав це в rc файли свого shell і надіявся».
Але «завантаження» у WSL — це не апаратне завантаження. Це старт у простору користувача в керованому середовищі.
Дві наслідуючі речі проявляються відразу:
-
Життєвий цикл прив’язаний до екземпляра WSL. Коли WSL зупиняється (або термінується), ваші сервіси зупиняються.
Коли він стартує, відбувається впорядкування юнітів, але це не те саме, що повне серверне завантаження з виявленням пристроїв. -
Шари інтеграції можуть перевизначати Linux-налаштування. DNS-резолюція, мережеві інтерфейси та маунти
можуть поводитися інакше, ніж на звичайній інсталяції дистрибутива.
Практичний висновок: ставтесь до systemd у WSL як до «реального управління Linux-сервісами, що працює в обмеженому контейнері хоста»,
а не як до «я встановив Ubuntu». Таке тлумачення убере багато хибних припущень.
Цікаві факти та історичний контекст
Це короткі, конкретні пункти, що пояснюють, чому ця тема досі «гаряча»:
-
WSL1 взагалі не використовував Linux-ядро; він транслював виклики Linux у виклики ядра Windows NT.
Ця модель була хитрою, але обмежувала сумісність для навантажень, залежних від ядра. - WSL2 перейшов на справжнє Linux-ядро, що працює в легковаговій VM. Саме тому контейнери та cgroups стали придатними.
-
Протягом років systemd не підтримувався в WSL, частково тому, що WSL не представляв себе як традиційна
система з PID 1 і управлінням пристроями. -
Ранні спроби «systemd у WSL» покладалися на обгортки і ручні трюки з PID 1. Вони працювали, поки не перестали,
і ламалися в чудернацько заплутаний спосіб. -
Linux-дистрибутиви дедалі більше очікують systemd. Навіть коли сервіс може працювати без нього, пакування і інтеграція
часто розраховують на наявність unit-файлів. -
systemd — це не просто «init»; це суїта (journald, resolved, networkd, logind, таймери, залежності юнітів).
У WSL ви можете захотіти лише деякі з цих компонентів, а не всі. -
cgroup v2 — сучасний дефолт у багатьох середовищах. Це важливо для Docker, podman та контролю ресурсів;
WSL2 поступово покращує підтримку cgroup. -
WSL мережа історично використовувала NAT із змінним IP віртуальної машини. Це підходить для вихідних з’єднань,
але створює проблеми для вхідних сервісів, якщо ви не плануєте заздалегідь. -
WSL регенерує частини вашої Linux-конфігурації (зокрема
/etc/resolv.conf), якщо ви не скажете інакше,
що конфліктує з очікуваннями systemd-resolved.
Що працює добре (достатньо) з systemd у WSL
Керування сервісами, що поводиться як у Linux
Головна перевага очевидна: systemctl працює. Юніти можуть стартувати під час «завантаження» (старт екземпляра WSL),
перезапускатися при збоях і виражати залежності. Це означає:
- sshd може бути сервісом, а не командою, яку ви запускаєте вручну і забуваєте.
- робота типу cron може бути systemd-таймером із логуванням і обробкою збоїв.
- сервіси, що використовують dbus, поводяться як на серверах.
journald робить відлагодження менш містичним
Без journald ви б рилися по випадкових файлах під /var/log і дивувалися, чому там нічого немає.
З systemd ви можете запитувати структуровані логи по юніту, по «запуску» і по часовому інтервалу. Це не магія, але передбачувано — мій улюблений смак магії.
Docker Engine та подібні можуть бути ближчими до «рідного Linux»
Багато команд використовують Docker Desktop з інтеграцією WSL, що може добре працювати без systemd. Але якщо ви хочете
запускати Docker Engine всередині дистро, як на Linux-хості, підтримка systemd усуває багато дрібних неприємностей:
unit-файли, патерни socket-активації та передбачуване завантаження.
Таймери systemd — здоровий варіант замість «запустив у фоні»
WSL-сесії з’являються й зникають. Фонові процеси, які ви запускали вручну, можуть зникнути або продовжувати працювати
і несподівано вас здивувати пізніше. Таймери + сервіси дають ідемпотентне, перевірне планування.
Що все ще ламається або поводиться дивно
DNS і resolv.conf: вічна пастка
WSL любить керувати DNS за вас. systemd-resolved теж любить керувати DNS за вас. Поєднайте їх — і отримаєте:
відсутню резолюцію імен, різну поведінку між хостом і WSL або «працює, поки я не перепідключусь до Wi‑Fi».
Виправлення зазвичай не складні, але вимагають вибору власника конфігурації. Або дайте WSL генерувати
/etc/resolv.conf і не запускайте systemd-resolved, або відключіть генерацію WSL і налаштуйте resolved коректно.
Невизначеність — найгірший інструмент управління конфігурацією.
Мережа для вхідних сервісів усе ще не «серверна»
Вхідна мережа залежить від того, як Windows експонує порти в WSL-VM. Ваш сервіс може слухати на
127.0.0.1 всередині WSL і бути недоступним із Windows, або навпаки. Іноді «правильна» адреса прив’язки
інтуїтивно неправильна. Іноді вона змінюється після оновлень.
Семантика маунтів: /mnt/c зручний, але повільний
Файлова система Windows під /mnt/c чудова для взаємодії, але жахлива для навантажень, що потребують
Linux-семантики та швидкості (збірки з великою кількістю метаданих, бази даних, великі Git-репозиторії).
systemd цього не виправить; він просто робить біль більш організованим.
Не всі параметри ядра поводяться як у вашому дата-центрі
Ядро WSL справжнє, але кероване. Деякі модулі, sysctl-параметри та поведінка пристроїв можуть відрізнятися від вашого флоту.
Якщо ви тестуєте щось чутливе до ядра — перевіряйте також на реальній Linux-VM.
Жарт №1: WSL із systemd — наче дати вашому dev-ноутбуку пейджер — раптом він починає мати думку про аптайм.
Практичні завдання: команди, виводи та рішення
Найшвидший спосіб зрозуміти, чи ваша конфігурація «достатньо здорова» — допитати її, як ви б робили з production-хостом.
Нижче реальні команди, який вигляд має реалістичний вивід і яке рішення приймати.
Завдання 1: Підтвердіть, що ви на WSL2 (а не WSL1)
cr0x@server:~$ uname -r
5.15.133.1-microsoft-standard-WSL2
Що це означає: Якщо рядок ядра містить microsoft-standard-WSL2, ви на WSL2.
Рішення: Якщо ви на WSL1 — зупиніться. Підтримка systemd є для WSL2. Конвертуйте дистро в WSL2 перед продовженням.
Завдання 2: Перевірте, що PID 1 — це systemd
cr0x@server:~$ ps -p 1 -o pid,comm,args
PID COMMAND COMMAND
1 systemd /sbin/init
Що це означає: PID 1 = systemd — це ключове.
Рішення: Якщо PID 1 — init або bash, systemd не увімкнено (або WSL не перезапустився коректно).
Завдання 3: Перевірте конфігурацію увімкнення systemd у WSL
cr0x@server:~$ cat /etc/wsl.conf
[boot]
systemd=true
Що це означає: Це перемикач для кожного дистрибутива.
Рішення: Якщо відсутній/false — встановіть його, а потім перезапустіть екземпляр WSL з Windows (або завершіть цей дистро), щоб зміни набрали сили.
Завдання 4: Доведіть, що systemd функціональний (не лише присутній)
cr0x@server:~$ systemctl is-system-running
running
Що це означає: running — це здоровий стан. Ви також можете побачити degraded, якщо якийсь юніт зазнав збою.
Рішення: Якщо degraded, негайно перелічте невдалі юніти і виправте перший збій, що має значення.
Завдання 5: Перелічіть невдалі юніти і оберіть правильну боротьбу
cr0x@server:~$ systemctl --failed
UNIT LOAD ACTIVE SUB DESCRIPTION
● systemd-resolved.service loaded failed failed Network Name Resolution
● snapd.service loaded failed failed Snap Daemon
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state.
SUB = The low-level unit activation state, often a more detailed state.
2 loaded units listed.
Що це означає: Деякі дефолти можуть падати у WSL, залежно від дистро та конфігурації.
Рішення: Якщо невдалий юніт неактуальний (наприклад snapd у багатьох dev-налаштуваннях WSL) — замаскуйте його. Якщо це resolved — вирішіть питання власності DNS спочатку.
Завдання 6: Дослідіть, чому юніт впав (з погляду systemd)
cr0x@server:~$ systemctl status systemd-resolved.service --no-pager -l
● systemd-resolved.service - Network Name Resolution
Loaded: loaded (/lib/systemd/system/systemd-resolved.service; enabled; preset: enabled)
Active: failed (Result: exit-code) since Mon 2026-02-05 09:12:17 UTC; 25s ago
Docs: man:systemd-resolved.service(8)
Process: 412 ExecStart=/lib/systemd/systemd-resolved (code=exited, status=1/FAILURE)
Status: "Failed to read /etc/resolv.conf: Too many levels of symbolic links"
Що це означає: Класична петля: resolved очікує символьне посилання на stub resolv.conf, WSL може його перезаписувати, і ви отримуєте цирк із симлинками.
Рішення: Вирішіть, хто володіє /etc/resolv.conf. Потім впорядкуйте це і перезапустіть юніт.
Завдання 7: Перевірте, хто зараз володіє DNS
cr0x@server:~$ ls -l /etc/resolv.conf
-rw-r--r-- 1 root root 116 Feb 5 09:10 /etc/resolv.conf
Що це означає: Звичайний файл зазвичай свідчить, що WSL його згенерував (або ви зафіксували вручну).
Рішення: Якщо ви хочете systemd-resolved, зазвичай прагнете, щоб /etc/resolv.conf був симлінком до stub-файлу resolved або до файлу, згенерованого вами — без перезапису з боку WSL.
Завдання 8: Підтвердіть, що journald захоплює логи (а не марно працює)
cr0x@server:~$ journalctl -b -n 10 --no-pager
Feb 05 09:12:01 server systemd[1]: Starting Network Name Resolution...
Feb 05 09:12:17 server systemd[1]: systemd-resolved.service: Main process exited, code=exited, status=1/FAILURE
Feb 05 09:12:17 server systemd[1]: systemd-resolved.service: Failed with result 'exit-code'.
Feb 05 09:12:17 server systemd[1]: Failed to start Network Name Resolution.
Feb 05 09:12:20 server systemd[1]: Starting OpenSSH Daemon...
Feb 05 09:12:20 server sshd[522]: Server listening on 0.0.0.0 port 22.
Feb 05 09:12:20 server systemd[1]: Started OpenSSH Daemon.
Що це означає: У вас є логи, зв’язані з запуском. Це тепер ваш основний джерело істини.
Рішення: Якщо journald порожній або видає помилки — виправте логування перед тим, як ганятися за багами сервісів. Без логів ви діагностуєте «на відчуття».
Завдання 9: Перевірте стан dbus (багато речей залежить від нього)
cr0x@server:~$ systemctl status dbus --no-pager
● dbus.service - D-Bus System Message Bus
Loaded: loaded (/lib/systemd/system/dbus.service; static)
Active: active (running) since Mon 2026-02-05 09:12:00 UTC; 1min 2s ago
TriggeredBy: ● dbus.socket
Docs: man:dbus-daemon(1)
Main PID: 210 (dbus-daemon)
Tasks: 1 (limit: 18947)
Memory: 2.3M
CGroup: /system.slice/dbus.service
└─210 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
Що це означає: dbus працює, socket-активація працює.
Рішення: Якщо dbus мертвий — очікуйте «дивного» скрізь: hostnamectl, timedatectl, resolved, інструменти, що залежать від logind.
Завдання 10: Перевірте версію cgroup (важливо для контейнерів)
cr0x@server:~$ stat -fc %T /sys/fs/cgroup
cgroup2fs
Що це означає: cgroup2fs означає cgroup v2. Старіші налаштування можуть показувати tmpfs і вимагати іншої конфігурації для контейнерів.
Рішення: Якщо ви запускаєте Docker Engine або podman, узгодьте очікування драйвера cgroup з тим, що доступно.
Завдання 11: Якщо Docker встановлено — перевірте юніт демона
cr0x@server:~$ systemctl status docker --no-pager
● docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; preset: enabled)
Active: active (running) since Mon 2026-02-05 09:12:45 UTC; 35s ago
TriggeredBy: ● docker.socket
Docs: man:dockerd(8)
Main PID: 900 (dockerd)
Tasks: 18
Memory: 78.4M
CGroup: /system.slice/docker.service
└─900 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
Що це означає: Демон працює, socket-активація, виглядає як нормальний шлях cgroup.
Рішення: Якщо Docker падає — перевірте cgroups, припущення iptables/nft і чи не конфліктує він з інтеграцією Docker Desktop.
Завдання 12: Перевірте, що слухає і де (127.0.0.1 проти 0.0.0.0)
cr0x@server:~$ ss -lntp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=522,fd=3))
LISTEN 0 4096 127.0.0.1:5432 0.0.0.0:* users:(("postgres",pid=1203,fd=6))
Що це означає: sshd доступний на всіх інтерфейсах в WSL; postgres прив’язаний лише до loopback.
Рішення: Якщо Windows не може дістатися до сервісу, спочатку перевірте адреси прив’язки. «Він працює» ≠ «він доступний».
Завдання 13: Підтвердіть тип маунту для вашої директорії проєкту
cr0x@server:~$ df -T .
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/sdd ext4 263174212 18234568 231513928 8% /
Що це означає: Якщо у вас ext4 під Linux-файловою системою — продуктивність зазвичай пристойна.
Рішення: Якщо проєкт розташований під /mnt/c (зазвичай 9p або схоже), перемістіть його у файлову систему дистро для важких збірок/БД.
Завдання 14: Визначте, чи WSL перезаписує resolv.conf за вашою спиною
cr0x@server:~$ grep -n "generateResolvConf" /etc/wsl.conf || true
Що це означає: Відсутність виводу зазвичай означає поведінку за замовчуванням (WSL може генерувати resolv.conf).
Рішення: Якщо ви хочете детермінованого DNS з systemd-resolved — явно встановіть generateResolvConf=false і керуйте файлом/симлінком самостійно.
Завдання 15: Перевірте час завантаження та звинувачуйте повільні юніти
cr0x@server:~$ systemd-analyze blame | head
3.214s snapd.service
1.122s docker.service
812ms systemd-resolved.service
402ms ssh.service
211ms systemd-journald.service
Що це означає: У вас є вимірювання часу по юнітах. Це золото, коли «WSL сьогодні гальмує».
Рішення: Замаскуйте або відключіть юніти, що не мають сенсу в WSL і сповільнюють кожний старт.
Завдання 16: Доведіть, що таймер працює і пише логи
cr0x@server:~$ systemctl list-timers --all --no-pager | head
NEXT LEFT LAST PASSED UNIT ACTIVATES
Mon 2026-02-05 09:20:00 UTC 2min 10s Mon 2026-02-05 09:15:00 UTC 2min ago apt-daily.timer apt-daily.service
Mon 2026-02-05 10:00:00 UTC 42min Mon 2026-02-05 09:00:00 UTC 17min ago man-db.timer man-db.service
Що це означає: Таймери заплановані і відстежуються.
Рішення: Якщо ви покладаєтеся на заплановані завдання — віддавайте перевагу таймерам над shell-хаком. Якщо таймери спамлять логи або спалюють CPU — налаштуйте або відключіть їх.
Швидкий план діагностики
Коли systemd у WSL «зламався», він рідко падає новим способом. Більшість інцидентів — це одна невелика множина режимів відмови
під різними масками. Ось порядок, що допоможе швидко вийти на вузьке місце.
Перше: чи systemd насправді PID 1 і чи система працює?
ps -p 1 -o comm,args→ якщо не systemd, зупиніться і виправте увімкнення/перезапустіть WSL.systemctl is-system-running→ якщоdegraded, перелічте невдалі юніти і розберіться з першим релевантним.
Друге: чи логи придатні?
journalctl -b -n 50→ якщо порожньо, у вас немає спостережності; виправте збереження journald/права або очікування.journalctl -u <service> -b→ якщо сервіс падає, віддавайте перевагу цьому над випадковими файлами логів.
Третє: це DNS/мережа чи сам сервіс?
resolvectl status(якщо використовуєте resolved) або перевірте/etc/resolv.conf.ss -lntpщоб підтвердити адреси прив’язки і слушачів.ip addr+ip routeщоб переконатися, що інтерфейси і дефолтний маршрут існують.
Четверте: чи не вбиває продуктивність маунт або повільний юніт?
df -Tі перевірка шляху: не запускайте БД на/mnt/c, якщо хочете задоволення.systemd-analyze blameщоб знайти повільні юніти; відключіть те, що не треба.
П’яте: контейнерні навантаження — підтвердіть cgroups і очікування демона
stat -fc %T /sys/fs/cgroupщоб підтвердити cgroup v2.systemctl status dockerіjournalctl -u docker -bдля помилок демона.
Мета — не «пробувати випадкові фікси». Мета — класифікувати проблему за лічені хвилини.
Три корпоративні міні-історії (усі реальні, жодна — простежувана)
Міні-історія 1: Інцидент через хибне припущення
Команда, наближена до фінансів, стандартизувала розробку на WSL, бо це зменшувало варіативність ноутбуків. Вони додали systemd,
щоб сервіси стартували «як у проді». Це працювало місяцями. Потім приєднався новий розробник, витягнув репозиторій, запустив
bootstrap, і локальна service mesh у нього ніколи не піднялася коректно.
Хибне припущення було тонким: вони вважали, що «завантаження» WSL еквівалентне завантаженню VM і що systemd-юніти будуть
готові до першого shell-процесу надійно. Насправді старт екземпляра WSL ініціюється запуском дистро, і таймінг залежить від
того, що інше робить хост. Скрипт bootstrap негайно виконав клієнтську команду проти сервісу, що ще стартував, один раз
провалився і потім закешував стан помилки в локальній конфігурації.
Симптом виглядав як мережна проблема: таймаути, відмови в з’єднанні і один співробітник наполягав «на моєму компі працює», що одночасно
було і суперечливо, і демонстрацією життя. Корінь проблеми — просто порядок: сервіси були нормальні, але не були готові в момент запиту,
а скрипт не мав повторів/бекофу.
Виправлення було нудним: додали перевірки готовності (systemd After= і Wants= там, де потрібно, плюс
клієнтський цикл повторів із таймаутами), і перестали вважати поведінку першого запуску детермінованою. Також додали одну
команду «health», що перевіряє критичні юніти і виводить дії.
Міні-історія 2: Оптимізація, що відбилася бумерангом
Інша команда гналася за швидшими збірками. Вони помітили, що тримати код під /mnt/c зручно для редагування з Windows,
але збірки повільні. Хтось запропонував «оптимізацію»: зробити симлінки для артефактів і кешів назад у Windows-сховище, щоб вони
виживали після скидів WSL і ділилися між дистро.
Це прискорило кілька невеликих збірок, а потім вибухнуло в тому вигляді, в якому можуть вибухати оптимізації I/O: найбільші збірки
почали давати випадкові помилки. Вони бачили пошкоджені кеші артефактів, спорадичні помилки прав доступу і шквал подій file watcher-ів.
systemd не був прямою причиною, але systemd зробив проблему більш помітною, бо фон-сервіси тепер надійно працювали — індексатори,
language server-и і file watcher-и були активні й підсилювали найгірші риси файлової системи.
Наслідок був класичним: Windows-маунт мав іншу семантику і продуктивність. Операції з метаданими були повільніші, блокування файлів
поводилися інакше, і весь конвеєр став чутливим до таймінгу. Команда тиждень «налаштовувала» перед тим, як визнати, що ідея хибна.
Виправлення — тримати важкі кеші збірок і репозиторії в Linux-файловій системі (ext4 у WSL VHD), а виводити фінальні артефакти
назад у Windows лише за потреби. Вони додали явний крок «sync» замість намагання змусити дві світи ділити гарячу директорію.
Міні-історія 3: Нудна, але правильна практика, що врятувала день
Платформна група підтримувала WSL-орієнтоване dev-середовище для десятків інженерів. Налаштування включало systemd, Docker,
локальне дзеркало реєстру і кілька внутрішніх агентів. Це те середовище, що працює до того ранку вівторка, коли всі щось оновили
і почалося хаос.
Їхня нудна практика: вони тримали мінімальний, версіонований «золотий» діагностичний скрипт, що запускaв ті самі перевірки щоразу:
PID 1, невдалі юніти, логи останнього запуску, власність DNS, слухаючі сокети, тип диску робочої директорії і стан демона контейнерів.
Він друкував прості рядки pass/fail і підказував наступну команду.
Коли оновлення WSL змінило мережеву поведінку достатньо, щоб зламати вхідні з’єднання на підмножині ноутбуків, група не витрачала годин
на суперечки про «чиє машина проклята». Вони запустили скрипт, побачили, що сервіси слухають на 127.0.0.1, і Windows більше
не може їх досягти. Картина була послідовною.
Тому вони змогли зробити цілеспрямоване виправлення: налаштувати адреси прив’язки для dev-сервісів, оновити правила фаєрволу на хості
і задокументувати один обхід для уражених користувачів, чекаючи більш постійного виправлення з боку Windows. Не було нічого гламурного,
але це запобігло тривалому падінню продуктивності.
Поширені помилки: симптом → корінь → виправлення
1) «System has not been booted with systemd»
Симптом: systemctl помилки, юніти не можна керувати.
Корінь: systemd не увімкнено або екземпляр WSL не перезапущено після зміни конфігурації.
Виправлення: Встановіть [boot] systemd=true у /etc/wsl.conf і перезапустіть екземпляр WSL. Підтвердіть, що PID 1 — systemd.
2) DNS працює один раз, потім ламається після змін мережі
Симптом: apt update не вдається, внутрішні імена перестають резолвитися після VPN/Wi‑Fi змін.
Корінь: Конфлікт власності: WSL авто-генерує /etc/resolv.conf, тоді як systemd-resolved очікує контроль (або навпаки).
Виправлення: Оберіть одного власника. Якщо використовуєте resolved — встановіть generateResolvConf=false і з’єднайте
/etc/resolv.conf із очікуваним файлом resolved без петель. Якщо не використовуєте resolved — вимкніть/замаскуйте його.
3) Сервіси працюють, але недоступні з Windows
Симптом: curl localhost:PORT працює у WSL, але не з Windows, або навпаки.
Корінь: Невідповідність адреси прив’язки (127.0.0.1 vs 0.0.0.0), припущення про NAT/проброс портів або фаєрвол хоста.
Виправлення: Використовуйте ss -lntp, щоб побачити прив’язки. Прив’язуйте dev-сервіси свідомо. Якщо потрібно — відредагуйте правила фаєрволу Windows.
4) WSL сповільнилося «після увімкнення systemd»
Симптом: Старт дистро відчутно важчий; команди гальмують; CPU під час запуску стрибає.
Корінь: Непотрібні сервіси авто-стартують (snapd, apt-таймери, індексатори) або вибір файлової системи (праця під /mnt/c).
Виправлення: Використовуйте systemd-analyze blame і systemctl --failed. Вимкніть/замаскуйте непотрібні юніти. Перенесіть важкі проєкти в Linux-файлову систему.
5) Docker у WSL падає дивно (iptables, cgroups, права)
Симптом: Демон Docker не стартує, контейнери не можуть створювати мережі, помилки про cgroups або nft.
Корінь: Розбіжність очікувань: cgroup v2 vs v1, відмінності бекенду фаєрволу або конфлікт з інтеграцією Docker Desktop.
Виправлення: Підтвердіть режим cgroup, перегляньте journalctl -u docker -b, і оберіть одну модель: Docker Desktop-керований або дистро-керований. Змішування підвищує ентропію.
6) systemd-resolved падає з петлями симлінків
Симптом: resolved не стартує; помилки згадують глибину симлінків у /etc/resolv.conf.
Корінь: Некоректний ланцюг симлінків, часто через регенерацію WSL або ручні правки поверх дефолтів дистро.
Виправлення: Видаліть петлю і відновіть задумані файли. Забезпечте одного власника файлу і переконайтеся, що WSL не перезаписує його без вашого відома.
7) Таймери запускаються тоді, коли не треба
Симптом: Випадкове навантаження CPU/мережі; apt-daily прокидається під час демо; вентилятори крутяться як реактивні.
Корінь: Таймери дефолтного дистро не підлаштовані під «ноутбучне dev-середовище».
Виправлення: Вимкніть або переналаштуйте таймери, що не потрібні. Перевірте з systemctl list-timers і гляньте логи, щоб оцінити фактичний вплив.
Контрольні списки / покроковий план
Покроково: безпечне увімкнення systemd
-
Підтвердіть WSL2: запустіть
uname -rі шукайте рядок ядра WSL2. -
Увімкніть systemd у дистро: відредагуйте
/etc/wsl.conf:cr0x@server:~$ sudo sh -c 'cat > /etc/wsl.conf <<EOF [boot] systemd=true EOF' - Перезапустіть екземпляр WSL: з Windows завершіть роботу дистро або перезапустіть WSL, щоб зміни набрали сили.
-
Перевірте PID 1:
ps -p 1 -o comm,args. -
Перевірте на degraded стан:
systemctl is-system-running, потімsystemctl --failed. -
Зробіть DNS свідомим вибором: вирішіть, чи використовувати systemd-resolved. Якщо не потрібно — замаскуйте і йдіть далі.
cr0x@server:~$ sudo systemctl mask systemd-resolved.service Created symlink /etc/systemd/system/systemd-resolved.service → /dev/null. -
Вимкніть повільні/непотрібні юніти: скористайтеся
systemd-analyze blameі відключіть ті, що вам не потрібні. -
Перемістіть чутливу до продуктивності роботу в ext4: тримайте репозиторії/БД у Linux-файловій системі, не в
/mnt/c.
Контрольний список: production-подібне dev-середовище (розумна версія)
- Критичні сервіси мають systemd-юнити з політиками перезапуску.
- Логи читаються через
journalctl, а не «який файл там є». - Власність DNS явна і задокументована.
- Припущення про вхідну мережу протестовані (з Windows і всередині WSL).
- Таймери обрізані до того, що вам справді потрібно.
- Репозиторії і БД живуть у Linux-файловій системі.
- Інструменти контейнеризації мають одного власника (інтеграція Docker Desktop або Docker у дистро), а не обох.
Контрольний список: коли не варто морочитися з systemd у WSL
- Вам потрібен лише shell, компілятори й кілька CLI-інструментів.
- Ваш робочий процес — «запустити один foreground-процес» і закрити його по завершенні.
- Ви покладаєтеся на Windows-native сервіси й використовуєте WSL лише для скриптів.
Питання та відповіді
1) Чи потрібен systemd у WSL для запуску Docker?
Не обов’язково. Docker Desktop може інтегруватися з WSL без того, щоб ви керували systemd.
Але якщо ви хочете Docker Engine усередині дистро, як на Linux-хості, systemd допомагає.
Виберіть одну модель і дотримуйтеся її.
2) Чому systemctl працює, а мій сервіс все одно не стартує під «завантаженням» WSL?
«Завантаження» WSL — це «старт екземпляра», і таймінг змінний. Переконайтеся, що у вашого юніта правильні залежності, і використовуйте перевірки готовності.
Потім перевірте systemctl is-enabled і дивіться journalctl -u your.service -b.
3) Чи варто запускати systemd-resolved у WSL?
Тільки якщо вам це потрібно і ви готові явно керувати DNS-конфігурацією. Багатьом dev-середовищам достатньо дозволити WSL керувати
/etc/resolv.conf і замаскувати resolved. Найгірший варіант — працювати напів-на-пів.
4) Чому мої логи відсутні в /var/log?
З systemd багато сервісів логують у journald, а не у плоскі файли. Використовуйте journalctl. Якщо хочете файли — налаштуйте сервіс
або пересиляння journald спеціально.
5) Чи стабільний systemd у WSL для щоденної роботи?
Так для dev-воркфлоу, особливо якщо тримати конфіг простим і уникати файлових та DNS-готів. Ні, якщо ваша дефініція «стабільності» означає
«повністю збігається з нашим production-ядром і мережею».
6) Чому мій сервіс слухає, але недоступний з Windows?
Зазвичай він прив’язаний до 127.0.0.1 всередині WSL, або змінилася поведінка фаєрволу/пробросу портів у Windows. Почніть з
ss -lntp і явно прив’яжіть адресу. Перевірте з обох боків.
7) Чи сповільнить увімкнення systemd WSL?
Може, якщо дистро вмикає купу сервісів/таймерів, які вам не потрібні. Виправлення просте: міряйте з
systemd-analyze blame, потім вимикайте/маскуйте шум.
8) Чи можна використовувати systemd-таймери замість cron у WSL?
Так, і, ймовірно, варто. Таймери мають краще логування й контроль залежностей. Просто пам’ятайте, що якщо екземпляр WSL не запущено,
таймери не спрацюють, поки він не стартує.
9) Який найпоширеніший режим відмови systemd у WSL?
Конфлікти власності DNS, за якими йдуть повільні або падаючі «додаткові» юніти (snapd, авто-оновлювачі), що не адаптовані до життєвого циклу WSL.
10) Якщо це для dev, навіщо така сувора діагностика?
Бо простої розробників — це справжні простої, тільки платять ними інженери, а не клієнти. Також чистий шлях діагностики запобігає
культу практик, які пізніше ламають інші речі.
Наступні кроки, які ви справді можете зробити
systemd у WSL тепер — легітимний інструмент: ви можете керувати сервісами, мати когерентні логи і запускати dev-середовище,
схоже на продакшн, без костилів. Але WSL має власну фізику. Ставтесь до нього як до обмеженого Linux-хоста з Windows як платформою —
а не як до маленького сервера, що просто живе на ноутбуку.
Практичні наступні кроки:
- Увімкніть systemd, перезапустіть WSL і підтвердіть PID 1 +
systemctl is-system-running. - Видаліть непотрібні сервіси: вимкніть/замаскуйте те, що не належить вашому dev-середовищу.
- Оберіть власника DNS і дотримуйтеся цього рішення. Напівзаходи породжують найскладніші інциденти.
- Перенесіть продуктивно-чутливі репозиторії/БД з
/mnt/cв ext4. - Напишіть невеликий командний «health check» для команди, що виконує ті самі 8–10 перевірок щодня.
Цитата (перефразована ідея), припис: Вернер Фогельс часто приписують принцип «build it, run it, and own it»
як частину культури надійності.
Жарт №2: Якщо ви замаскували snapd у WSL і нічого не зламалося — ви виявили найрідкіснішу істоту в опсах: залежність, яка вам не потрібна.