随便写写 | Working on Windows

2021 03 14, Sun

新配的机器网卡型号太奇怪,我打算先用Windows顶两天。简单记一下自己用到什么配了什么。

Windows桶

Windows自己带了非常多的工具。尝试了WSL2,也尝试了Windows Terminal、Powershell和Edge。除了这些就是比较常见的VSCode

Powershell

Powershell是MS在Windows上的一个脚本引擎和交互式终端,可以做非常多的自动化工作,可以配置系统,可以当成一个独立的语言使用。

和Unix相比有一个不一样的是,PS在支持的情况下会在命令之间通过PIPE传递对象,而不是Unix的文本流。有趣,但是写习惯bash以后暂时没觉得有用。

ExecutionPolicy

为了执行包括profile在内的脚本,PS有一个设置是ExecutionPolicy。Win10默认是Restricted,执行本地脚本需要设置为RemoteSigned(只有远程需要签名),如果还需要执行在线的代码,可以设置为Unrestricted(远程代码需要手动允许执行)。

Windows Terminal

现在都可以直接从应用商店下载。比较奇怪的地方是这玩意儿没有设置界面,用的是Unix常用的配置手段:配置文件。

WT的配置文件是一个JSON。对我们来说常用的就三个地方:

  • 一个是profiles,设置打开以后启动Powershell还是cmd还是其他的什么命令
  • 一个是schemes,设置样子,什么底儿,什么色儿,透明不透明。 可以参考: https://windowsterminalthemes.dev/
  • 一个是actions,设置快捷键啊什么的。

我们改的大部分东西都是profiles,在里面增减终端的类型。默认的主要是PowerShell和cmd:

{
    // Make changes here to the powershell.exe profile.
    "guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
    "name": "Windows PowerShell",
    "commandline": "powershell.exe",
    "hidden": false
},
{
    // Make changes here to the cmd.exe profile.
    "guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}",
    "name": "命令提示符",
    "commandline": "cmd.exe",
    "hidden": false
},

装了WSL/WSL2子系统以后,会自动建数条子系统的,比如说Ubuntu(装了Ubuntu但是没有入口的也可以自己加一条这个):

{
    "guid": "{2c4de342-38b7-51cf-b940-2309a097f518}",
    "hidden": false,
    "name": "Ubuntu",
    "source": "Windows.Terminal.Wsl"
},

除了这些,我们还可以加自己的入口,主要是通过commandline来设置具体的命令,比如说我们可以用这些命令替代Anaconda Shell(但是有点问题是这样打开的Anaconda环境中,conda命令无法联网)

{
    "commandline": "cmd.exe \"/K\" C:\\Users\\12548\\miniconda3\\Scripts\\activate.bat C:\\Users\\12548\\miniconda3",
    "name": "Anaconda - cmd",
    "closeOnExit": "always"
},
{
    "commandline": "powershell.exe -ExecutionPolicy ByPass -NoExit -Command \"& 'C:\\Users\\12548\\miniconda3\\shell\\condabin\\conda-hook.ps1' ; conda activate 'C:\\Users\\12548\\miniconda3' \"",
    "name": "Anaconda - Powershell",
    "closeOnExit": "always"
},

或者ssh到远程的机器上

{
    "hidden": false,
    "name": "Hyper-V | Gentoo",
    "commandline": "ssh guochao@172.30.244.195",
    "closeOnExit": "always"
},

我的Windows Terminal

自动配置Powershell和cmd

在macOS和Linux上用习惯了bashrc zshrc profile和env.d,Windows有的东西很少有听说直接通过脚本设置,花了一点时间折腾。

对于Powershell来说有一个功能近似相等的文件叫profile,对于日常使用来说修改$env:USERPROFILE\Documents\WindowsPowerShell\profile.ps1就足够了,如果我们需要在更多文件里面分别写逻辑,也可以用和bash类似的.来引入其他文件的执行并保留执行的环境,比如说. test.ps1

cmd会相对来说复杂一些,需要在注册表的HKEY_CURRENT_USER\SOFTWARE\Microsoft\Command Processor中写入字符串AutoStart=路径,这样bat启动的时候就会执行这个文件并且保留执行的环境。修改注册表要谨慎哦。

举例来说的话,minikube启动k8s虚拟机以后,我们也可以通过minikube docker-env得到让docker命令行连接到虚拟机中docker的环境变量。但是每次都执行很麻烦,而且minikube操作列举虚拟机都需要特权,但是重启以后不执行的话minikube会无法启动起来,就非常的无奈。于是写了个简单的batch,特权启动,删掉老的minikube、启动新的、把环境变量写到临时文件里面。在profile.ps1中我只需要. 输出的.ps1就够了,如果没有这个文件说明minikube还没启动,我重新执行batch脚本就ok。

启动minikube的批处理:

@echo off
echo Trying to start minikube in 1 minute, or it will be deleted and recreate

del /f %userprofile%\AppData\Local\Temp\minikube-docker-env.ps1
del /f %userprofile%\AppData\Local\Temp\minikube-docker-env.bat

minikube delete
minikube start --driver=hyperv --docker-env HTTP_PROXY=http://192.168.1.22:7890 --docker-env HTTPS_PROXY=http://192.168.1.22:7890 --docker-env NO_PROXY=localhost,127.0.0.1/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0.16,169.254.0.0/16,.cn --nfs-share=C:\Users\12548\Documents --addons=dashboard,default-storageclass,storage-provisioner,registry,metallb,metrics-server --cpus 4 --memory 4096m --insecure-registry "10.0.0.0/24"

minikube docker-env --shell=powershell > %userprofile%\AppData\Local\Temp\minikube-docker-env.ps1
if %ERRORLEVEL% != 0 (
  del /f %userprofile%\AppData\Local\Temp\minikube-docker-env.ps1
)
minikube docker-env --shell=cmd           > %userprofile%\AppData\Local\Temp\minikube-docker-env.bat
if %ERRORLEVEL% != 0 (
  del /f %userprofile%\AppData\Local\Temp\minikube-docker-env.bat
)
minikube dashboard

Powershell的profile.ps1:

$dockerenv = "$env:TEMP\minikube-docker-env.ps1"

if ($(Test-Path $dockerenv)) {
    . $dockerenv
} else {
    Write-Output "Minikube Not Started"
}

WSL2

一开始考虑到虚拟机资源消耗比较大,我尝试着用了一下WSL2。WSL2是一个基于轻量级Hyper-V虚拟机的Linux环境解决方案,类似于KataContainer但是因为不需要容器化所以几乎是个完整的虚拟机,只是没有systemd,包含了sys proc dev cgroup/cg2这些正常的Linux都有的文件系统(但是有的依赖sys和proc的工具不能正常工作,比如说lspci),也有通过9p挂载的Windows的目录,从Windows也可以在文件管理器中直接打开\wsl$通过网络访问到各个WSL2虚拟机中的文件。

看起来还挺美好的,测试以后除了systemd需要换掉,得通过类似于init脚本的方法启动服务以外,大致可以满足需求。

但是用了一段时间以后发现两个问题。

  1. 我工作需要的代码在Linux的一个磁盘上装着,复制出来太慢,发现没有办法在WSL2的轻量级虚拟机里面挂载磁盘,新的WSL2允许WSL2挂载一个脱机的磁盘到虚拟机上,但是仅限于Windows 10 Insider Build 20211以后的版本。我不大想复制一遍项目,40G有点大,也不想重新下载。
  2. 图形化界面可以搞,麻烦的很。尤其是我现在工作和GUI有关系,没有xserver真的会死。

所以干脆放弃了WSL2搞事情的计划。

WSL2挂载ext4磁盘以及VSCode中的Remote: WSL2插件

写完博客以后刚刚好Hyper-V出了严重的Bug,导致我无法使用PIN登录系统,似乎是文件损坏了,所以我干脆升到了Insider Dev Channel重新建了用户。并且用上了WSL2挂载磁盘,速度还行。

有个VSCode的奇怪bug是,如果用wsl --mount <DRIVE> --bare,然后在WSL里面挂载卷的话,VSCode里面看不到WSL里面挂载的目录。所以如果要用VSCode,一定要用wsl在主机一侧挂载,不要在wsl里面挂载。

Hyper-V

但是我寻思着Linux的工具在Windows上也跑不起来。所以还是启动了一个虚拟机来做事情。考虑到我们要搞CrOS,其中工具很多都和Gentoo的portage有关系,所以我选择了Gentoo作为虚拟机的Guest OS,但是其他系统差别不会多大。

Hyper-V是WSL2和Docker for Desktop/Windows的基础。除了个别时候有点傻以外,也不算太差。

我在Hyper-V中建了一个虚拟机,磁盘直接使用了我之前Linux用的NVME和SATA SSD。SATA SSD上有所有我需要的代码,NVME盘作为物理机和虚拟机通用的系统盘。

Gentoo in Hyper-V

参照:https://wiki.gentoo.org/wiki/Hyper-V 但是比如说选项参数经常不准,建议在menuconfig里面/HYPERV搜索一下,保证每一个都=y或者=m

需要在genkernel的时候调整一些内核的编译选项,同时调整启动参数。以5.4.97为例:

  • genkernel带了Linux guest support和ACPI
    • 自己编译的话需要找到
      • Processor type and features > Linux guest support > Enable paravirtualization code > Paramvirtualization layer for spinlocks
      • Power management and ACPI options > ACPI (Advanced Configuration and Power Interface) Support
  • Device Drivers
    • Microsoft Hyper-V guest support
      • 所有都要
        • 动态内存Balloon
        • 客户端驱动client drivers
        • 工具驱动utilities driver
  • 一部分模块的基础vsocket:Networking support > Network options > Virtual Socket protocol > Hyper-V transport for Virtual Sockets
  • Device Drivers
    • PCI: PCI support > Hyper-V PCI Frontend
    • IRQ: IOMMU Hardware support > Hyper-V x2APIC IRQ Handling
    • SCSI: SCSI device support > SCSI low-level drivers > Microsoft Hyper-V virtual storage driver
    • 网卡: Network devices support > Microsoft Hyper-V virtual network driver
    • 图形: Graphics support > Frame buffer devices> Support for frame buffer devices > Microsoft Hyper-V Synthetic Video support
    • 鼠标: HID support > HID bus support > Special HID drivers > Microsoft Hyper-V mouse driver
    • 键盘: Input device support > Hardware I/O ports > Microsoft Synthetic Keyboard driver

Ubuntu

比较奇怪,不知道为什么没有hyperv内存这方面的驱动。没有动态内存。

Arch Linux

只需要hyperv这个包,然后开启所有hv_开头的服务就行。

自动化

包管理

Unix上习惯了包管理,Windows一个个安装程序维护升级让我头大,所谓的软件中心不停的弹广告,所以我还是维持了以前使用包管理的习惯。

具体来说主要是用到了Chocolatey和conda。

Chocolatey

Choco是一个基于Powershell的包管理工具。没有镜像,依然需要你有良好的访问境外网站的网络。自动化了非常多的软件和Windows组件的安装过程。

Conda

Conda是Anaconda自带的一个包管理。主要是可以管理多个Python环境,同时对Linux(x86/x64/arm64)、macOS和Windows都有很多编译好的二进制Python包,安装即用,本身也带着vcredist这类东西,所以不需要在系统里面全局装VS的Runtime。

除去Anaconda自带的Python环境,本身conda这个包管理相对来说也是比较好使的。除了官方源,也有R、conda forge这类社区补充软件包,还有bioconda、menpo、pytorch这类的第三方仓库。在科学计算方面,软件非常丰富。

msys2

msys2是一个在Windows上模拟Unix环境的工具,用出自ArchLinux的pacman做包管理,用mingw64之类的工具的话会非常好使。

但是有个缺点是这玩意儿有时候会很慢。软件包也不大丰富。

脚本

有不少工作自动化会比较简单。比如说上面的Powershell

AutoIt v3

很多年以前大概是我初中(2011年前后)的时候,接触到的一个脚本。可以非常方便的读窗口的信息,发送鼠标或者键盘事件,执行各种任务。语法接近于Basic,所以在我初中的时候就很亲切。

这两年更新频率越来越低,但是我觉得还是蛮好用的,可以说是Windows上最棒的自动化工具。

AutoHotkey

AutoHotkey是相对AutoIt的另一个选择,一开始是AutoIt v2的一个分支。也是百度上热度比较高的一个自动化工具。

感觉AHK可以做但是其他的不好做需要精力的就是键映射。

Powershell

之前提到Powershell也可以做一定的自动化。但是Powershell更多的是和系统集成、和微软的服务集成。比如说设置Windows的选项、简单的做一些Azure配置的操作。

Python

这个不解释了。利用pywinauto和pyautogui可以做很多事情。需要图形化的话还有PyQt和wxpython。

其他工具

除了这些以外,还装了一些其他的工具

  • Everything: 利用NTFS日志ID动态建立文件索引,超快的路径搜索引擎
  • Quicklook: 类似于macOS快速预览的功能。Gnome桌面下面这个叫sushi
  • Win-X Menu Editor: 修改win+x菜单的工具,实际上是修改了一个目录里面的lnk文件。主要是为了把打开cmd/Powershell改成打开Windows Terminal