Montag, 30. November 2020

WSL - ein paar Notizen zur Verwendung

Es gibt eine Menge im Netz zum WSL, aber vieles ist nicht klar mit Versionshinweisen beschrieben. Ich habe etwas mit WSL herum gespielt und hier meine Notizen dazu.

Versionen

Windows Server 2019: unterstützt nur V1, Tools: wsl.exe, wslconfig.exe, keine Store - nur manuelle Installation der (älteren) Distributionen.

Windows 10: unterstützt V1 und V2, Tools: wsl.exe mit erweitertem Umfang

Version 1: keine virtuelle Netzwerkkarte, verwendet direkt das Hostnetzwerk

Version 2: eine virtuelle Netzwerkkarte (bei jedem Neustart neue IP Adresse, Bereich 172.x.x.x) für alle Distributionen, besserer Kernel

Hier der offizielle Vergleich von MS.

Zugriff mit der virtuellen Maschine

wsl.exe öffnet quasi das "Terminal" ssh braucht man für die "Bedienung" nicht. 

Im Zusammenhang mit dem Thema "Kommandozeile" lohnt sich ein Blick auf Windows Terminal, dies ist seit kurzem über Windows Store installierbar.

Alle Datenträger vom Host sind direkt erreichbar (/mnt/c/...)

Die Ports aus der virtuellen Maschine werden an den Host durchgereicht, man kann über localhost:port oder 127.0.0.1:port zugreifen. Will man aus dem Netzwerk über den Host auf Ports in der virtuellen Maschine zugreifen, ist das Vorgehen bei V1 und V2 unterschiedlich. Die virtuelle IP ist aus dem Netzwerk nicht direkt erreichbar (NAT). 

Die Ports kann man mit ss -lntu innerhalb WSL V2 anzeigen, netstat und lsof sind nicht installiert (und funktionieren wohl nicht?). In WSL V1 habe ich keine Port Ausgabe hinbekommen, die Meldung klingt so, als ob im Kernel V1 etwas nicht implementiert ist.

Interessant: 

  • Aus dem ubuntu Subsystem heraus kann man direkt Windows Programme starten.
  • Mit einer kleinen Vorbereitung geht das auch umgekehrt, siehe diese Beschreibung.
  • In Windows kann man mit bash -c "Kommando" auch direkt Linux Befehle ausführen.

Die Distributionen (Ubuntu, debian) in WSL haben offenbar generell kein init System (wie systemd) aber eventuell kann man darauf auch verzichten. Mann kann den WSL und Prozesse darin direkt über die Windows Aufgabenplanung (Taskscheduler) starten.

Eine Kommando in Windows mit wsl.exe an WSL übergeben liefert die Ausgabe an Windows zurück. Die Ermittlung der IP Adresse gibt uns dafür ein paar Beispiele.  

Die einfachste Variante, funktioniert in CMD und Powershell - hat allerdings ein Leerzeichen am Ende. Dies kann man in PS einfach abschneiden (Befehl liefert String).trim()
wsl hostname -I

Ich habe die anderen Varianten mal zur Dokumentation und als Beispiel stehen lassen:

cmd Variante (fragt die wsl Umgebung ab, funktioniert aber nicht in powershell. Anmerkung: ^ ist ein Escape Zeichen der batch Umgebung)

WSL -d debian -- ip addr show eth0 ^| grep -oP '(?^<=inet\s)\d+(\.\d+){3}'

Powershell Variante Anmerkung: ` ist das Escape Zeichen in Powershell. Der Code braucht eine zweite Zeile!

(wsl -- ip addr show eth0 `| grep 'inet ') -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
$matches[0]


Installation und Konfiguration

Das Root Dateisystem jeder Linux Distribution wird in einer dynamischen 256GB VHDX Datei installiert. Den Speicherort kann man sich in Powershell so ausgeben lassen:

& cmd "/c dir %LOCALAPPDATA%\Packages\$((Get-AppxPackage -Name "*debian*").PackageFamilyName)\LocalState"

Statt über die interaktive Installation über den Store kann man die Pakete auch manuell herunterladen. Achtung: Das praktische Ergebnis (November 2020) ist anders, als die über den MS Store. Die Versionen sind viel älter!

Und offenbar teilweise sogar unvollständig:

  • In einer Variante fehlte wget und gnupg 
  • Die öffentlichen Zertifikaten waren alt oder nicht vorhanden! Ein apt install ca-certificates behebt das Problem.

Mit der kurzen url von dieser Seite geht das auch mit Powershell. 

Get-AppxPackage *Ubuntu*|Remove-AppxPackage
Get-AppxPackage *debian*|Remove-AppxPackage
Invoke-WebRequest -Uri https://aka.ms/wsl-debian-gnulinux -OutFile Debian.appx -UseBasicParsing
Add-AppxPackage .\Debian.appx

Man kann in WSL V2 auch komplette Distributionen exportieren (einpacken) und wieder importieren.

Der Windows Server hat keinen Store, die Installation funktioniert nur so wie hier beschrieben

Der Server 2019 Version kennt anstatt Enable-WindowsOptionalFeature.

Install-WindowsFeature -Name Microsoft-Windows-Subsystem-Linux

Die Hyper-V Umgebung

Ob Hyper-V schon aktiv ist kann man mit diesem Powershell Einzeiler testen:

(gcim Win32_ComputerSystem).HypervisorPresent

Ob die Hardware Hyper-V und damit auch WSL unterstützt kann man mit einem Powershell Einzeiler testen:

$list=@('Name', 'SecondLevelAddressTranslationExtensions', 'VirtualizationFirmwareEnabled', 'VMMonitorModeExtensions');Get-CimInstance -ClassName win32_processor -Property $list|Format-List $list

Ich habe diesen Test in einer virtuellen Maschine (Hyper-V) durchgeführt. Hier muss man auf dem Hyper-V Host die Virtualisierung an die Maschine "weiterreichen":

$vm=Get-Vm -Name <MaschineName>
Stop-Vm $vm
Set-VMProcessor $vm -ExposeVirtualizationExtensions $true
Start-Vm $vm


Die Ports

Achtung: Das Verhalten der Portweiterleitung ist unmittelbar nach der Einrichtung und nach einem Neustart unter Umständen komplett anders! 

Irgendwie gelingt es relativ leicht, dass man sich das Portmapping aus WSL heraus auf 127.0.0.1 zerschießt - ein netsh interface portproxy reset bewirkt dies zuverlässig. 

Hat man einmal einen Portproxy eingerichtet, funktioniert das Ganze nach einem Neustart nicht mehr. Man muss alles löschen und neu einrichten. Will man portproxy Einträge wieder löschen, kann man dies auch einzeln mit delete v4tov4 listenport=8083 tun! Dabei bleibt offenbar das (nicht sichtbare?) default Mapping erhalten. Löscht man den Eintrag für portproxy, stellt ein Neustart die ursprüngliche Funktion wieder her. 

Die Lösung für meine beobachteten Probleme liegt darin, den portproxy nicht auf localhost einzurichten (obwohl dies zunächst funktioniert) sondern auf die WSL eth0 Adresse. Hier ein Beispiele, die ich im Weiteren auch verwendet habe: 

  1. Artikel WSL Port forwarding 
  2. Artikel auf superuser

Mit tasklist | findstr wslhost kann man nachschauen auf welcher PID wsl arbeitet, mit netstat -aon | findstr <Suchstring> kann man den Prozess oder das Port darstellen. Die Prozesse innerhalb von wsl werden aber separat geführt. Mir ist es noch nicht die gesamte Prozesskette darzustellen.

Die wsl Kommanozeile

Es gibt einen Unterschied in der Verarbeitung zwischen dem Parameter -e und -- 

  • Bei -- kann man mehrere Befehle übergeben, getrennt mit Semikolon Befehl1;Befehl2,
  • das funktioniert offenbar bei -e nicht!
  • Gibt man den Linux Account mit:  -u username - funktioniert die Übergabe mehrere Befehle aber nicht mehr.

Empfehlung: Einfach eine Scriptdatei machen, das funktioniert viel einfacher als sich mit escapen und Variablenauflösung herumzuschlagen. Das Konstrukt wsl -e bash Script.sh funktioniert in gleicher Art in CMD, Powershell.


1 Kommentar: