Skip to content

Instantly share code, notes, and snippets.

@MichaelBelgium
Created June 5, 2020 07:46
Show Gist options
  • Save MichaelBelgium/2243e5713833ba44b5675d844eeb1c85 to your computer and use it in GitHub Desktop.
Save MichaelBelgium/2243e5713833ba44b5675d844eeb1c85 to your computer and use it in GitHub Desktop.
WSL v2 windows hosts sync (powershell - updates domains to wsl2 ip)
# Requires -RunAsAdministrator
# Only works for WSL v2, this is completely not needed for WSL v1 where u always can use 127.0.0.1 in hosts file
Clear-Host
if ((Get-InstalledModule "Carbon" -ErrorAction SilentlyContinue) -eq $null) {
Install-Module -Name 'Carbon' -AllowClobber
}
Import-Module 'Carbon'
$wslIp = (wsl hostname -I) -replace ' ',''
Write-Host "Setting wsl v2 hosts entries to $wslIp"
$domains = @(
'wsl2.local'
# add more domains if necessary
)
foreach($domain in $domains) {
Set-HostsEntry -IPAddress $wslIp -HostName $domain
}
Write-Host "Done!"
@MichaelBelgium
Copy link
Author

MichaelBelgium commented Jun 24, 2020

Using hostname -I is unreliable. I found that this worked some of the time but not consistently. At present my distros (I have several) are returning multiple IPs (eth0, docker0 and br-xxxxx) which is clearly not whats needed:

@goffinf Interesting, I didn't know that as I only have one WSL instance (ubuntu). It probably lists all ips from all the instances u have yes/

@goffinf
Copy link

goffinf commented Jun 24, 2020

That may be partly correct, in the sense that hostname -I appears to only return the IP associated with eth0 when only a single distro is running (although I couldn't swear to it be consistent all the time). As soon as another WSL distro is started (in my case one that has been configured for systemd) hostname -I startes returning the ip for each bound device, for example below we can see eth0, docker0 and br-f69dc3652dfd ... and it does so in any of the wsl sessions until they are all shutdown (terminating doesn't appear to have any impact). The alternate method will always return the IP for eth0 so I think thats a better bet ?

ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 22:d7:2a:85:69:2f brd ff:ff:ff:ff:ff:ff
3: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 5e:ac:84:b2:47:08 brd ff:ff:ff:ff:ff:ff
4: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:15:5d:68:fc:62 brd ff:ff:ff:ff:ff:ff
    inet 172.26.19.142/20 brd 172.26.31.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::215:5dff:fe68:fc62/64 scope link
       valid_lft forever preferred_lft forever
5: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0
6: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:eb:f4:41:8a brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
7: br-f69dc3652dfd: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:c6:c9:99:21 brd ff:ff:ff:ff:ff:ff
    inet 172.22.0.1/16 brd 172.22.255.255 scope global br-f69dc3652dfd
       valid_lft forever preferred_lft forever

@derik007
Copy link

derik007 commented Oct 6, 2020

# Requires -RunAsAdministrator
# Only works for WSL v2,  this is completely not needed for WSL v1 where u always can use 127.0.0.1 in hosts file
$currentUser = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())
$testadmin = $currentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
if ($testadmin -eq $false) {
Start-Process powershell.exe -Verb RunAs -ArgumentList ('-noprofile -noexit -file "{0}" -elevated' -f ($myinvocation.MyCommand.Definition))
exit $LASTEXITCODE
}


Clear-Host

if ((Get-InstalledModule "Carbon" -ErrorAction SilentlyContinue) -eq $null) {
    Install-Module -Name 'Carbon' -AllowClobber
}

Import-Module 'Carbon'

$wslHostIp = (wsl cat /etc/resolv.conf | Select-String -Pattern "\d{1,3}(\.\d{1,3}){3}" -AllMatches).Matches.Value
$wslSelfIp = (wsl hostname -I) -replace ' ',''

Write-Host "Setting wsl v2 host ip to $wslHostIp"
Write-Host "Setting wsl v2 self ip to $wslSelfIp"

$wsl_host_domains = @(
    'wsl2.host'
)
$wsl_self_domains = @(
    'wsl2.self'
)

foreach($domain in $wsl_host_domains) {
    Set-HostsEntry -IPAddress $wslHostIp -HostName $domain
}

foreach($domain in $wsl_self_domains) {
    Set-HostsEntry -IPAddress $wslSelfIp -HostName $domain
}

Write-Host "Done!"

This is the script that I changed a little bit.

@derik007
Copy link

derik007 commented Oct 6, 2020

#!/bin/sh
export WINIP=$(cat /etc/resolv.conf | grep 'nameserver' | cut -f 2 -d ' ') 
export WSLIP=$(ip addr show eth0 | grep 'inet ' | cut -f 6 -d ' ' | cut -f 1 -d '/')
echo WINIP $WINIP
echo WSLIP $WSLIP

echo <Your Password> | sudo -S sed -i "/winip/c $WINIP\twinip" /etc/hosts
echo <Your Password> | sudo -S sed -i "/wslip/c $WSLIP\twslip" /etc/hosts

vim "+:%s/^.*winip/$WINIP\t\twinip/g" "+:%s/^.*wslip/$WSLIP\t\twslip/g" '+:wq' -E /mnt/c/Windows/System32/drivers/etc/hosts 

This is another solution. Run this script in ~/.bashrc can set hosts file both in win and linux.

@kallookoo
Copy link

Hi Guys!
The @derik007 bash version not working. :(
This is my version using Powershell; https://github.com/kallookoo/lamp/blob/feccb3e3c507f2d97afcc0962cb7e449ec0eeffb/src/win/hosts.ps1

@msitarzewski
Copy link

Amazing. Thank you. It's perfect for my use case.

@brunorafaeI
Copy link

brunorafaeI commented Aug 3, 2021

just for info, the @derik007 solution needs to use PowerShell as admin and execute "wsl", I've changed the last line :

vim "+:%s/^.*winip/$WINIP\t\twinip/g" "+:%s/^.*wslip/$WSLIP\t\twslip/g" '+:wq' -E /mnt/c/Windows/System32/drivers/etc/hosts

to

vi "+:%s/^.*wsl2.local/^$WSLIP wsl2.local/g" "+:wq" -E /mnt/c/Windows/System32/drivers/etc/hosts

@kakkun61
Copy link

kakkun61 commented Aug 9, 2022

I forked: https://gist.github.com/kakkun61/2139c240ac0dce1bb1606c1e8bc8038c

Added features:

  • admin check
  • run as admin
  • install Carbon module if necessary
  • remove old hosts entry
  • multiple ip addr support

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment