用wsl迁移
rem 关闭docker, 关闭wsl
wsl --shutdown
rem 查看有所的wsl应用
wsl --list -v
set wsl_path=D:\projects\wsl
mkdir %wsl_path%
rem 重新设置docker-desktop-data 位置
wsl --export docker-desktop-data "%wsl_path%\docker-desktop-data.tar"
wsl --unregister docker-desktop-data
wsl --import docker-desktop-data %wsl_path%\docker-desktop-data "%wsl_path%\docker-desktop-data.tar" --version 2
rem 重新设置docker-desktop 位置
wsl --export docker-desktop "%wsl_path%\docker-desktop.tar"
wsl --unregister docker-desktop
wsl --import docker-desktop %wsl_path%\docker-desktop "%wsl_path%\docker-desktop.tar" --version 2
rem 删除多余的tar备份
del "%wsl_path%\docker-desktop-data.tar"
del "%wsl_path%\docker-desktop.tar"
ubuntu迁移
rem 重新设置ubuntu 位置
wsl --export ubuntu "%wsl_path%\ubuntu.tar"
wsl --unregister ubuntu
wsl --import ubuntu %wsl_path%\ubuntu "%wsl_path%\ubuntu.tar" --version 2
rem 删除多余的tar备份
del "%wsl_path%\ubuntu.tar"
ubuntu迁移默认用户失败, 参考build no. 18980
/etc/wsl.conf
文件
[user]
default=username
# 移除多余path参数
[interop]
appendWindowsPath = false
wsl访问代理
WSL 每次启动的时候都会有不同的 IP 地址,所以并不能直接用静态的方式来设置代理(参考以下方式设置静态ip)。WSL2 会把 IP 写在 /etc/resolv.conf
中,因此可以用 cat /etc/resolv.conf | grep nameserver | awk '{ print $2 }'
这条指令获得宿主机 IP 。
WSL2 自己的 IP 可以用 hostname -I | awk '{print $1}'
得到。
设置代理,别忘了代理软件中设置允许来自局域网的连接。
export http_proxy='http://<Windows IP>:<Port>'
export https_proxy='http://<Windows IP>:<Port>'
别忘了修改代理端口, 点击下载proxy.sh
#!/bin/sh
hostip=$(cat /etc/resolv.conf | grep nameserver | awk '{ print $2 }')
wslip=$(hostname -I | awk '{print $1}')
port=${2:-'10808'}
protocol=${3:-'socks5'}
PROXY_HTTP="${protocol}://${hostip}:${port}"
set_proxy(){
export http_proxy="${PROXY_HTTP}"
export HTTP_PROXY="${PROXY_HTTP}"
export https_proxy="${PROXY_HTTP}"
export HTTPS_PROXY="${PROXY_HTTP}"
}
unset_proxy(){
unset http_proxy
unset HTTP_PROXY
unset https_proxy
unset HTTPS_PROXY
}
test_setting(){
echo "Host ip:" ${hostip}
echo "WSL ip:" ${wslip}
echo "Current proxy:" $https_proxy
}
if [ "$1" = "set" ]
then
set_proxy
elif [ "$1" = "unset" ]
then
unset_proxy
elif [ "$1" = "test" ]
then
test_setting
else
echo "Unsupported arguments."
fi
如果希望 git 也能通过代理,可以分别在 set_proxy 和 unset_proxy 函数中加上如下命令
# 添加代理
git config --global http.proxy "${PROXY_HTTP}"
git config --global https.proxy "${PROXY_HTTP}"
# 移除代理
git config --global --unset http.proxy
git config --global --unset https.proxy
然后执行. ./proxy.sh set 端口号 协议
, 默认. ./proxy.sh set
相当于. ./proxy.sh set 10808 socks5
或者添加到~/.bashrc
中
alias proxy="source /path/to/proxy.sh"
. /path/to/proxy.sh set
第一句话可以为这个脚本设置别名 proxy,这样在任何路径下都可以通过 proxy 命令使用这个脚本了,之后在任何路径下,都可以随时都可以通过输入 proxy unset 来暂时取消代理。
第二句话就是在每次 shell 启动的时候运行该脚本实现自动设置代理,这样以后不用额外操作就默认设置好代理啦~
wsl中ls绿油油一片
主要是因为在 WSL 中,Microsoft 实现了两种文件系统,用于支持不同的使用场景:
-
VolFs 着力于在 Windows 文件系统上提供完整的 Linux 文件系统特性,通过各种手段实现了对 Inodes、Directory entries、File objects、File descriptors、Special file types 的支持。比如为了支持 Windows 上没有的 Inodes,VolFs 会把文件权限等信息保存在文件的 NTFS Extended Attributes 中。就是因为 Windows 中新建的文件缺少这个扩展参数,VolFs 无法正确获取该文件的 metadata,而且有些 Windows 上的编辑器会在保存时抹掉这些附加参数。
WSL 中的 / 使用的就是 VolFs 文件系统。
-
DrvFs 着力于提供与 Windows 文件系统的互操作性。与 VolFs 不同,为了提供最大的互操作性,DrvFs 不会在文件的 NTFS Extended Attributes 中储存附加信息,而是从 Windows 的文件权限(Access Control Lists,就是你右键文件 > 属性 > 安全选项卡中的那些权限配置)推断出该文件对应的的 Linux 文件权限。
所有 Windows 盘符挂载至 WSL 下的 /mnt 时都是使用的 DrvFs 文件系统。
解决方法, 在 WSL 中创建 /etc/wsl.conf
,在其中填写如下内容:
[automount]
enabled = true
root = /mnt/
options = "metadata,umask=22,fmask=111"
mountFsTab = true
通过此方法改动可能会产生通过
VS Code
的WSL targets
打不开, 报错sh: 1: /mnt/c/Users/XXXX/.vscode-insiders/extensions/ms-vscode-remote.remote-wsl-0.42.0/scripts/wslServer.sh: Permission denied
在wsl2中进入报错目录,
chmod +x *
添加可执行权限
或者直接
chmod +x /mnt/c/Users/*/.vscode/extensions/ms-vscode-remote.remote-wsl*/scripts/*.sh
参考
wsl修改host名称
修改/etc/wsl.conf
, 参考hostname
[network]
hostname=WSL
wsl注册表
HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss
注册表地址
wsl服务重启
net stop LxssManager
net start LxssManager
sc stop LxssManager
sc start LxssManager
rem 查看服务
sc query LxssManager
安装其他wsl版本的linux系统
安装方法
# 安装
{InstanceName}.exe
# 修改用户
{InstanceName}.exe config --default-user user
# 卸载
{InstanceName}.exe clean
# wsl 转 wsl2
wsl --set-version {name} 2
wsl 限制内存
%userprofile%\.wslconfig
, 参考wsl-config,
英文原版
[wsl2]
memory=2GB
processors=4
swap=512MB
wsl静态ip
-
创建脚本,在
/home/lautumn
下, 注意修改为自己的ip地址, 如果没特殊要求的话, 可直接使用, 其中wsl的ip地址为172.30.38.138
, “vEthernet (WSL)”的ip地址为172.30.32.1
cat <<EOF > static_ip.sh #!/bin/bash # config wsl ip /sbin/ip addr flush dev eth0 /sbin/ip addr add 172.30.38.138/20 broadcast 172.30.47.255 dev eth0 label eth0 /sbin/route add default gw 172.30.32.1 [ ! -f /etc/resolv.conf ] && echo "nameserver 172.30.32.0" > /etc/resolv.conf sed -rzi 's/(\n*# this is replace by init script\n*)*nameserver.*/\n# this is replace by init script\nnameserver 172.30.32.1/' /etc/resolv.conf # config vEthernet (WSL) ip /mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -c "Get-NetAdapter 'vEthernet (WSL)' -IncludeHidden | Get-NetIPAddress | Remove-NetIPAddress -Confirm:\\\$False; New-NetIPAddress -IPAddress 172.30.32.1 -PrefixLength 20 -InterfaceAlias 'vEthernet (WSL)';" # config WSLNat /mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -c "Get-NetNat | ? Name -Eq WSLNat | Remove-NetNat -Confirm:\\\$False; New-NetNat -Name WSLNat -InternalIPInterfaceAddressPrefix 172.30.32.0/20;" EOF chmod +x static_ip.sh
如果
/mnt/c/Windows/System32/netsh.exe
在wsl中不能用, 取消自动挂载, 启动mountFsTab挂载[automount] enabled = false mountFsTab = true
如果还要去除绿油油的一片的话, 修改
/etc/fstab
LABEL=cloudimg-rootfs / ext4 defaults 0 1 C: /mnt/c drvfs rw,relatime,uid=1000,gid=1000,fmask=111,umask=022,metadata,case=off 0 0 //localhost/C$/Windows/System32 /mnt/c/Windows/System32 drvfs defaults,ro,relatime,uid=1000,gid=1000,fmask=222,umask=222,case=off 0 0 D: /mnt/d drvfs rw,relatime,uid=1000,gid=1000,fmask=111,umask=022,metadata,case=off 0 0
-
windows启动目录
shell:startup
中添加脚本,static-ip.vbs
, 内容如下Set ws = CreateObject("Wscript.Shell") ws.run "wsl -d Ubuntu -u root /home/lautumn/static_ip.sh", vbhide
- 方式一, 由于
netsh.exe
需要管理员权限, 所以直接放到启动
目录下不能用, 可以增加在taskschd.msc
, 任务计划程序中, 添加任务, 勾选使用最高权限运行
- 方式二, 脚本前增加, 以下代码, 参考How to run vbs as administrator from vbs?
If Not WScript.Arguments.Named.Exists("elevate") Then CreateObject("Shell.Application").ShellExecute WScript.FullName _ , """" & WScript.ScriptFullName & """ /elevate", "", "runas", 1 WScript.Quit End If 'actual code
如果此linux下的脚本不能用, 可使用windows下的脚本, 设置为
.bat
或.cmd
格式, 管理员权限运行wsl -d Ubuntu -u root ip addr del $(ip addr show eth0 ^| grep 'inet\b' ^| awk '{print $2}' ^| head -n 1) dev eth0 wsl -d Ubuntu -u root ip addr add 172.30.38.138/20 broadcast 172.30.47.255 dev eth0 wsl -d Ubuntu -u root ip route add 0.0.0.0/0 via 172.30.32.1 dev eth0 wsl -d Ubuntu -u root echo nameserver 172.30.32.1 ^> /etc/resolv.conf powershell -c "Get-NetAdapter 'vEthernet (WSL)' -IncludeHidden | Get-NetIPAddress | Remove-NetIPAddress -Confirm:$False; New-NetIPAddress -IPAddress 172.30.32.1 -PrefixLength 20 -InterfaceAlias 'vEthernet (WSL)'; Get-NetNat | ? Name -Eq WSLNat | Remove-NetNat -Confirm:$False; New-NetNat -Name WSLNat -InternalIPInterfaceAddressPrefix 172.30.32.0/20;"
- 方式一, 由于
脚本管理员权限
-
bat文件, 参考怎样自动以管理员身份运行bat文件? - 墨子 2200MHz的回答 - 知乎
@echo off cd /d "%~dp0" cacls.exe "%SystemDrive%\System Volume Information" >nul 2>nul if %errorlevel%==0 goto Admin if exist "%temp%\getadmin.vbs" del /f /q "%temp%\getadmin.vbs" echo Set RequestUAC = CreateObject^("Shell.Application"^)>"%temp%\getadmin.vbs" echo RequestUAC.ShellExecute "%~s0","","","runas",1 >>"%temp%\getadmin.vbs" echo WScript.Quit >>"%temp%\getadmin.vbs" "%temp%\getadmin.vbs" /f if exist "%temp%\getadmin.vbs" del /f /q "%temp%\getadmin.vbs" exit :Admin rem actual code
一句命令版, 原理, 第一次
%1
为""
, 第二次为::
即注释, 为管理员权限, 适合没有参数的脚本%1 start "" mshta vbscript:CreateObject("Shell.Application").ShellExecute("cmd.exe","/c ""%~s0"" ::","","runas",1)(window.close)&&exit rem actual code
-
vbs文件, 参考How to run vbs as administrator from vbs?
If Not WScript.Arguments.Named.Exists("elevate") Then CreateObject("Shell.Application").ShellExecute WScript.FullName _ , """" & WScript.ScriptFullName & """ /elevate", "", "runas", 1 WScript.Quit End If 'actual code
wsl2不能上网
-
有时重置网络时, 可能会把WSL的Nat删除, 需要重新设置一下, 在powershell中使用管理员权限执行以下代码
Get-NetNat | ? Name -Eq WSLNat | Remove-NetNat -Confirm:$False; New-NetNat -Name WSLNat -InternalIPInterfaceAddressPrefix 172.30.32.0/20;
docker exec定时任务无法执行
-
没有执行的原因是, 不应该加
-it
, 这样就可以正常执行了, 参考ubuntu中Crontab执行docker exec后台任务失败的问题0 2 * * * docker exec -it sphinx /bin/bash -c '/bin/indexer -c /usr/local/etc/csft.conf base_04007cn --rotate' >> /opt/logs/sphinx.log;
wsl2不能使用tail -f
由于windows中的文件系统会在wsl中的ubuntu以/mnt/c, /mnt/d 这种方式挂载, Linux是通过inotify来获取文件变动的, wsl2中还不支持, 所以在wsl2使用tail -f
监控不到windows系统中文件的变化
可以禁用inotify
, 使用轮询的方式进行文件的监控, 虽然效率低, 但是兼容性好.
可以直接设置为tail的别名
alias tail="tail ---disable-inotify"
参考How do I examine the tail of a growing file on WSL-2