WSL hosts 更新脚本

日常操作

WSL hosts 更新脚本

WSL2 每次启动时,虚拟网卡的 宿主机 Windows 的 ip 和 wsl 的ip都是变化的,在登录 wsl 的图形界面和测试网络程序时,都很不方便,所以写了一个脚本自动更新 宿主机 和 wsl 的 hosts文件。同时,在wsl的环境变量中加入 winip 和 wslip 两个环境变量指示 ip 地址

在下文中,我将使用“主机”指代运行Windows的主机,wsl 指代 Windows sub Linux 系统

怎么做

如果你只关心达到目的,只看这一节即可

1.创建脚本文件 /opt/cron/boot.sh

写入以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
startDate=`date +"%Y-%m-%d %H:%M:%S"`
echo "----------- Script Start At $startDate ----------"

win_hosts_path='/mnt/c/Windows/System32/drivers/etc/hosts'
msg="##the wsl hosts. Created automatic\n"
tmp="/tmp/hosts_tmp"
unset winip
unset wslip

Exit(){
endDate=`date +"%Y-%m-%d %H:%M:%S"`
echo "----------- Script Finished At $endDate ----------"
# exit
}

Log(){
date=`date +"%H:%M:%S"`
echo "[$date] $*"
}

winip=$(ip route | grep default | awk '{print $3}')
if [ $winip ];then
Log "windows ip:$winip"
export winip=$winip
else
Log "get Windows ip falut,Exiting...."
Exit
fi

wslip=$(ifconfig eth0 | grep 'inet ' | awk '{print $2}')
if [ $wslip ];then
Log "WSL ip:$wslip"
export wslip=$wslip
else
Log "get WSL ip falut,Exiting...."
Exit
fi


# update windows hosts
# rm $tmp
if [ ! -f $tmp ]; then
Log $(touch $tmp && echo "touch $tmp")
else
Log "tmp file:$tmp"
fi

Log "process windows hosts"
sed '/win.host/d' $win_hosts_path |
sed '/wsl.host/d'|
sed '/#Update At/d' |
sed '/'"$msg"'/d' |
sed '$a'"$msg$winip win.host\n$wslip wsl.host\n#Update At $startDate" > $tmp

Log 'writting windows hosts'
cat $tmp > $win_hosts_path
if [ $? -eq 0 ];then
Log "write successfully"
else
Log "write fail"
Exit
fi

Log "process wsl hosts"
sed "/win.host/d" /etc/hosts |
sed "/wsl.host/d" |
sed "/Update At/d" |
sed '/'"$msg"'/d' |
sed '$a'"$msg$winip win.host\n$wslip wsl.host\n#Update At $startDate" > $tmp

Log 'writing wsl hosts'
cat $tmp > /etc/hosts
if [ $? -eq 0 ];then
Log "write successfully"
else
Log "write fail"
Exit
fi
Exit

2.创建 /etc/wsl.conf 文件

写入以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# Automatically mount Windows drive when the distribution is launched
[automount]

# Set to true will automount fixed drives (C:/ or D:/) with DrvFs under the root directory set above. Set to false means drives won't be mounted automatically, but need to be mounted manually or with fstab.
enabled = true

# Sets the directory where fixed drives will be automatically mounted. This example changes the mount location, so your C-drive would be /c, rather than the default /mnt/c.
root = /mnt/

# DrvFs-specific options can be specified.
options = "metadata,uid=1003,gid=1003,umask=077,fmask=11,case=off"

# Sets the `/etc/fstab` file to be processed when a WSL distribution is launched.
mountFsTab = true

# Network host settings that enable the DNS server used by WSL 2. This example changes the hostname, sets generateHosts to false, preventing WSL from the default behavior of auto-generating /etc/hosts, and sets generateResolvConf to false, preventing WSL from auto-generating /etc/resolv.conf, so that you can create your own (ie. nameserver 1.1.1.1).
[network]
hostname = Su
generateHosts = false
generateResolvConf = false

# Set whether WSL supports interop process like launching Windows apps and adding path variables. Setting these to false will block the launch of Windows processes and block adding $PATH environment variables.
[interop]
enabled = false
appendWindowsPath = false

# Set the user when launching a distribution with WSL.
[user]
default = aja

# Set a command to run when a new WSL instance launches. This example starts the Docker container service.
[boot]
command = /bin/bash /opt/cron/boot.sh >> /var/log/user/iboot.log

3.创建日志文件

1
2
3
mkdir -p /var/log/user/
touch /var/log/user/iboot.log
chmod 777 /var/log/iboot.log

4.更改 Windows 主机权限

打开 C:\Windows\System32\drivers\

点击 etc 文件夹的属性,取消只读属性,

点击 安全->高级:

image-20220130011424201image-20220130011424201

更改所有者

image-20220130011442264image-20220130011442264

点击 高级->立即查找

选择 Users ,点击确定

关闭属性窗口,重新打开,将 Users 的权限全部打开。允许完全控制

  1. 一切OK

此时,在Windows 主机和 WSl 内,都可以使用 win.host 和 wsl.host 访问主机和 wsl 网络。

  1. BTW , 在 bash 环境变量中导入 ip

终端运行一下指令

1
2
3
sudo echo "export winip=$(ip route | grep default | awk '{print $3}')" >> /etc/profile
sudo echo "export wslip=$(ifconfig eth0 | grep 'inet ' | awk '{print $2}')" >> /etc/profile
source /etc/profile

在终端有 winip 和 wslip 两个环境变量

一、脚本编写基础条件–信息获取

1.1阻碍

  • wsl 无法在启动时使用 crontab ,意味着无法使用 crontab 自动运行脚本,必须每次启动手动运行

  • profile 无法取得权限修改 hosts 文件,可以更改文件权限,但,,并非上策

1.2信息获取:

WSl2 中有一个配置文件在 /etc/wsl.conf ,默认可能不存在这个文件,可以手动创建,在这个文件中可以指定一个脚本,该脚本将在 WSL 启动时以 root 身份运行,以供用户编写初始化脚本。完美!

条件达成

二、脚本编写

2.1整体流程

脚本获取主机 和 WSL 的 ip ,然后,更新 WSL 和 Windows 的 hosts 文件,从而使用 wsl.host win.host 即可访问 WSL 和 主机

2.2 获取 主机 和 WSL 的ip

1.在默认条件下,WSL 启动时会自动生成 /etc/resolv.conf 文件,文件中将给出主机 IP,一个 resolv.conf 文件内容如下:

1
2
3
4
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 172.22.240.1

此时:

1
2
cat /etc/resolv.conf | grep nameserver | awk {'print $2'} #可获取 主机 ip
ifconfig | grep inet | awk {'print $2'} # 获取 WSL ip

2.使用命令 ip route

1
2
default via 172.22.240.1 dev eth0
172.22.240.0/20 dev eth0 proto kernel scope link src 172.22.245.160

其中 default via 后面的地址即主机 IP ,···src 后面为 WSL ip

命令

1
2
ip route | grep default | awk {'print $3'} # 获取主机 ip
ip route | grep src | awk {'print $2'} # 获取 WSL ip

由于,我们目的是更新 hosts 文件,设置环境变量,所以,resolv.conf 的自动生成就没有必要。我们将关闭 resolv.conf 的生成

更改 /etc/wsl.conf 如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# Automatically mount Windows drive when the distribution is launched
[automount]

# Set to true will automount fixed drives (C:/ or D:/) with DrvFs under the root directory set above. Set to false means drives won't be mounted automatically, but need to be mounted manually or with fstab.
enabled = true

# Sets the directory where fixed drives will be automatically mounted. This example changes the mount location, so your C-drive would be /c, rather than the default /mnt/c.
root = /mnt/

# DrvFs-specific options can be specified.
options = "metadata,uid=1003,gid=1003,umask=077,fmask=11,case=off"

# Sets the `/etc/fstab` file to be processed when a WSL distribution is launched.
mountFsTab = true

# Network host settings that enable the DNS server used by WSL 2. This example changes the hostname, sets generateHosts to false, preventing WSL from the default behavior of auto-generating /etc/hosts, and sets generateResolvConf to false, preventing WSL from auto-generating /etc/resolv.conf, so that you can create your own (ie. nameserver 1.1.1.1).
[network]
hostname = Su
generateHosts = false
generateResolvConf = false

# Set whether WSL supports interop process like launching Windows apps and adding path variables. Setting these to false will block the launch of Windows processes and block adding $PATH environment variables.
[interop]
enabled = false
appendWindowsPath = false

# Set the user when launching a distribution with WSL.
[user]
default = aja

# Set a command to run when a new WSL instance launches. This example starts the Docker container service.
[boot]
command = /bin/bash /opt/cron/boot.sh >> /var/log/user/iboot.log

2.3 脚本内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
startDate=`date +"%Y-%m-%d %H:%M:%S"`
echo "------------ Script Start At $startDate -----------------"

win_hosts_path='/mnt/c/Windows/System32/drivers/etc/hosts'
msg="##the wsl hosts. Created automatic\n"
tmp="/tmp/hosts_tmp"


export winip=$(ip route | grep default | awk '{print $3}') && echo "export winip:$winip" || echo "get winip falut"
export wslip=$(ifconfig eth0 | grep 'inet ' | awk '{print $2}') && echo "export wslip:$wslip" || echo "get wslip fault"

# update windows hosts
if [ ! -f $tmp ]; then
echo $(touch $tmp && echo "touch $tmp")
else
echo "tmp file:$tmp"
fi

echo "process windows hosts"
sed '/win.host/d' $win_hosts_path |
sed '/wsl.host/d'|
sed '/#Update At/d' |
sed '/'"$msg"'/d' |
sed '$a'"$msg$winip win.host\n$wslip wsl.host\n#Update At $startDate" > $tmp

echo 'writting windows hosts'
cat $tmp > $win_hosts_path
if [ $? -eq 0 ];then
echo "write successfully"
else
echo "write fail"
fi

echo "process wsl hosts"
sed "/win.host/d" /etc/hosts |
sed "/wsl.host/d" |
sed "/Update At/d" |
sed '/'"$msg"'/d' |
sed '$a'"$msg$winip win.host\n$wslip wsl.host\n#Update At $startDate" > $tmp

echo 'writing wsl hosts'
cat $tmp > /etc/hosts
if [ $? -eq 0 ];then
echo "write successfully"
else
echo "write fail"
fi

endDate=`date +"%Y-%m-%d %H:%M:%S"`
echo "----------- Script Finished At $endDate ----------"

Author: 哒琳

Permalink: http://blog.jieis.cn/2022/5e943d55-aef9-4015-a39a-ee4807e8a0e8.html

Comments