新年要用新系统
这个blog两年没更新过了啊!靠着AI打气又拾起来了!
起因是节前Fusion 360警告我win10不受支持了,Gemini也建议我换个系统,并且疯狂安利Win11,安抚我说Win11已经不是几年前那种费拉不堪的状态了。
再信AI一次。
0 备份
尤其是wsl2!:
1 | mkdir -p ~/wsl_backup/manifests |
1 装系统
装专业版即可,需要注意,分区别在跟Linux似的一块/用到底,2T盘可以先给C盘384G($384 \times 1024 = 393216 \text{ MB}$),剩下的给D盘。使用的时候:
- wsl2放D盘
- 尽量用protable软件,全放D盘,那些死皮赖脸要待在C盘的软件再放C盘。
如此,重装的时候不会一锅端。
另外,装好了第一次见到Windows初始化配置的时候,微软强制登录Microsoft账号。此时Shift + F10,输入OOBE\BYPASSNRO自动重启,就可以选“我没有 Internet 连接”跳过账号登录。好处是可以完全自己决定user文件夹的名字。
进了系统先装驱动,尤其是显卡驱动,先装完驱动再装wsl2,但是主板带的什么MSI Center装完驱动可以卸了。
NVIDIA APP 选 NVIDIA studio 驱动,对跑CUDA的场景来说,Game Ready 驱动更新过于频繁。
2 清理微软的垃圾
第一时间防火防盗防微软。
彻底禁止 Windows 自动更新驱动:
Win+R输入gpedit.msc:计算机配置 -> 管理模板 -> Windows 组件 -> Windows 更新 -> 管理从 Windows 更新提供的更新,右侧的 “Windows 更新不包括驱动程序”,选择 “已启用”。如此,让 Windows Update 只推安全补丁和功能更新,绝不会动显卡、网卡、声卡驱动。保留 Defender,配置“码农豁免区”
打开 Windows 安全中心 -> 病毒和威胁防护 -> 管理设置,下拉找到 “排除项” -> 添加或删除排除项,酌情加入:D:\WSL(放 WSL 镜像,防止扫描 vhdx 读写);D:\DEV(放代码);D:\MOEDL(放模型);- etc.
左下角“天气新闻”等等是 小组件” (Widgets):
Win+R输入gpedit.msc:计算机配置 -> 管理模板 -> Windows 组件 -> 小组件,右侧的 “允许小组件”,选择 “已禁用”。锁屏时“天气新闻”等待是 Windows 聚焦 (Windows Spotlight) :
- 右键桌面 -> “个性化” -> 选择 “锁屏界面”,在个 性化锁屏界面 中选择 “图片” (Picture) 。
- 再往下看,如果有 “在锁屏界面上获取花絮、提示、技巧和更多内容”,选择 关闭。
- 如果有 “锁屏界面状态”,改为 无 (None) 。
开始菜单里的垃圾,右键桌面 -> “个性化” -> “开始”:
- 显示最近添加的应用 -> 关。
- 显示最常用的应用 -> 关。
- 在“开始”菜单中……显示最近打开的项目 -> 关
开始菜单的搜索 强行把本地搜索和 Bing 搜索混合:
Win + R输入gpedit.msc:用户配置 (User Configuration) -> 管理模板 (Administrative Templates) -> Windows 组件 (Windows Components) -> 文件资源管理器 (File Explorer),右侧找:“关闭文件资源管理器搜索框中的最近搜索条目显示” (Turn off display of recent search entries in the Windows Search box) ,选择 “已启用” (Enabled) 。重启资源管理器即可,taskkill /f /im explorer.exe; start explorer.exe。注意:微软经常改这个策略的名字,比如也可能叫“关闭搜索框建议”。- 也可以执行
reg add "HKCU\Software\Policies\Microsoft\Windows\Explorer" /v "DisableSearchBoxSuggestions" /t REG_DWORD /d 1 /f修改。 - 关闭 “搜索要点” (Search Highlights):设置 -> 隐私和安全性 -> 搜索权限,往下找到 “更多设置”,关掉 “显示搜索要点” (Show search highlights) 。
任务栏的搜索框,任务栏空白处 右键 -> “任务栏设置”,第一项就是 “搜索”,选择 “隐藏”。
Steam/Epic党可以把XBox相关都端了:
- 关闭 Xbox Game Bar:在 设置 -> 游戏 -> Xbox Game Bar,关闭 “允许控制器打开 Game Bar”。
- 开始菜单搜 “Xbox”,右键 -> 卸载。
- 唯一例外:游戏模式 (Game Mode) ,留着,在 设置 -> 游戏 -> 游戏模式 里,保持 开 (ON)。
关闭 OneDrive:
- 解除“文件夹备份”,任务栏右下角的那个“云朵”图标,右上角齿轮进入 设置,找到 “同步并备份” (Sync and backup) -> “管理备份” (Manage backup),把“文档”、“图片”、“桌面”全部关掉(Stop backup)。,此时系统会把这些文件夹的路径从
C:\Users\<username>\OneDrive\Desktop恢复为C:\Users\<username>\Desktop - 取消链接:设置 里 -> “账户” (Account),点击 “取消链接此电脑” (Unlink this PC)。
- 卸载:设置 -> 应用 -> 安装的应用,搜 “OneDrive” -> 卸载。
- 解除“文件夹备份”,任务栏右下角的那个“云朵”图标,右上角齿轮进入 设置,找到 “同步并备份” (Sync and backup) -> “管理备份” (Manage backup),把“文档”、“图片”、“桌面”全部关掉(Stop backup)。,此时系统会把这些文件夹的路径从
至于 基于虚拟化的安全性 (VBS)” / HVCI,模型和网上的说法都没定论。
Win键搜索 “内核隔离” -> “内存完整性”,收益有限,关不关无所谓。- 网上流传的
bcdedit /set hypervisorlaunchtype off不能设置, wsl2 要用。
找回Win10右键菜单:
1
reg add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /f /ve
重启资源管理器即可。后悔的话:
1
reg delete "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}" /f
3 清理其他垃圾,装Windows下的常用工具
- 搜狗自带桌面壁纸和汪仔,记得删掉和关闭。
- 取消WPS的云盘资源管理器图标、取消传输助手自启。
- 装cherrystudio。
- 装no machine。
- Snipaste用portable。
- Motrix用portable。
装Git:
1 | winget install --id Git.Git |
装微信QQ:
1 | winget install Tencent.WeChat |
PotPlayer:
1 | winget install Daum.PotPlayer |
装powertoys:
1 | winget install Microsoft.PowerToys |
装Everything和Listary:
1 | winget install voidtools.Everything |
4 安装wsl2
有显卡驱动了再装wsl2。
先装 WSL 本体,管理员 PowerShell:
1
wsl --install
装完建议重启,确认 WSL 版本:
1
wsl --version
在 D 盘准备一个专门目录
D:\WSL,安装一个临时 Ubuntu(会默认在 C 盘),启动一次 Ubuntu,完成用户名/密码初始化后退出。1
wsl --install -d Ubuntu
把迁移到 D 盘:
- 先关掉 WSL:
1
wsl --shutdown
- 导出为 tar(临时文件建议也放 D 盘):
1
wsl --export Ubuntu D:\WSL\ubuntu.tar
- 注销原来的 Ubuntu(这一步会删除 C 盘那个实例的注册与磁盘):
1
wsl --unregister Ubuntu
- 导入到 D 盘(强制 WSL2):
1
wsl --import Ubuntu D:\WSL D:\WSL\ubuntu.tar --version 2
现在 Ubuntu 的 ext4.vhdx 就在
D:\WSL\下面了。wsl2网络配置:建议按老方法,默认NAT,不要配自动代理、DNS隧道等配置。装个clash-verge,用自己写的订阅发布程序让Windows、wsl、PVE、rock5b、o6n等设备同步订阅配置,虽然heavy但是最稳妥:
1
2
3
4
5[wsl2]
networkingMode=nat
autoProxy=false
dnsTunneling=false
dnsProxy=false新wsl2支持mirror,直接走Windows的网卡,别的没什么问题,但是gemini-cli或codex可能会用不了:
1
2
3
4
5[wsl2]
networkingMode=mirrored
dnsTunneling=true
autoProxy=true
firewall=true此时wget下载chrome会自动拿到autoproxy配置走clash,但是apt不行,还得手动指定proxy
1
2
3
4sudo tee /etc/apt/apt.conf.d/99proxy <<'EOF'
Acquire::http::Proxy "http://127.0.0.1:7897";
Acquire::https::Proxy "http://127.0.0.1:7897";
EOF
5 初始化wsl2
用gemini和chatgpt写了个一键安装脚本,也可以一步一步执行。
1 |
|
关于yt-dlp:
1 | uv tool install yt-dlp --with curl_cffi --with pycryptodomex --upgrade --force |
关于恢复备份的.ssh文件夹,拷过去权限得改对:
1 | chmod 700 ~/.ssh |
关于中文环境,上面装了字体和中文编码,需要配置语言环境:
1 | sudo dpkg-reconfigure locales |
选zh_CN.UTF-8 UTF-8即可,echo $LANG还不行的话:
1 | echo "export LANG=zh_CN.UTF-8" >> ~/.bashrc |
现在使用
topgrade自动感知并更新安装工具。
6 tailscale 与 ipv6
节后移动给的GPON坏了,运营商换了一个后发现有ipv6了。家里的rock5b、PVE工作站都可以用ipv6直连了。
PVE装tailscale
需要注意的是,PVE默认没打开ipv6支持,所以需要手动设置:
1 | vi /etc/sysctl.conf |
此时用ip -6 addr show会发现vmbr0上多出来一个2409(移动)开头的地址,再用手机等公网设备打开tailscale去ping这台PVE就会从relay转到direct了。
1 | 5: vmbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000 |
全家搬到tailscale
通过rock5b转发流量,可以把家里的192.168.1.x/24都放在tailscale上。在rock5b上配置系统转发:
1 | echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf |
出于安全考虑,被“广播”的网段 Tailscale 默认不信任,需要手动确认:
- 登录 Tailscale Admin Console。
- Rock 5B 点击右侧的 **三个点 (…)**。
- 选择 Edit route settings。
- 在弹出的窗口中,勾选广播的网段
192.168.1.0/24。 - 点击 Save。
此时,手机用运营商的网,打开tailscale,也可以使用192.168.1.0/24的IP控制家里的设备了。
tailscale可能存在的坑1 - 外带设备o6n回家后只能单向ping
1. 现象
在家里的局域网 (192.168.1.0/24) 有:
- 开发板 A (o6n):
192.168.1.140 - 开发板 B (Rock5B):
192.168.1.120 - Windows 11 (含 WSL2):
192.168.1.125
症状: 开发板 A (140) 可以正常 Ping 通局域网内的 B (120) 和 Windows (125),但是 B 和 Windows 无法 Ping 通 A。呈现典型的 “单向失联” 状态。
2. 排查
遇到单向不通,通常的排查链路是:物理连接 -> 防火墙 -> ARP 解析 -> 路由表。
- 排除防火墙与物理隔离: 检查了
ufw和iptables,未发现拦截规则。 - 检查 ARP 缓存 (
ip neigh show): 开发板 A 上能成功获取到 B 和 Windows 的 MAC 地址,说明物理层和数据链路层通信正常。 - 排查代理软件: 怀疑是 Windows 端的 Clash TUN 模式劫持了局域网流量。关闭 TUN 模式并使用
ping -S 192.168.1.125 192.168.1.140强制指定源 IP,依然不通,排除发件端代理问题。 - 定位核心问题——策略路由 (
ip rule):
在开发板 A (140) 上执行ip rule发现异常:执行1
25270: from all lookup 52
32766: from all lookup mainip route show table 52发现:1
192.168.1.0/24 dev tailscale0
3. 原因
网络中存在另一台设备——开发板 B (Rock5B, 192.168.1.120) 通过 Tailscale 执行了 --advertise-routes=192.168.1.0/24,广播了该局域网的 Subnet Route(子网路由),而开发板 A (140) 默认接受了该路由。
Tailscale 会接管系统的策略路由,创建一个高优先级(5270)的路由表 52。
当开发板 A (140) 收到局域网(比如来自 Windows 或 Rock5B 本身)发来的 Ping 请求时,它需要发送 ICMP Echo Reply(回包)。在查找路由时,它优先命中了表 52 的规则,导致本该通过物理网卡(wlan0/eth0)发回本地局域网的数据包,被错误地塞进了 Tailscale 的虚拟隧道 (tailscale0) 中,造成了“有去无回”的路由黑洞。
4. 解决
由于既需要在家时局域网直连,又需要带开发板外出时能通过 Tailscale 访问家里的内网,直接关闭 accept-routes 并不符合需求。
最优解:基于源 IP 的智能分流 (Smart Routing)
在开发板 A (140) 上添加一条比 Tailscale 优先级更高(例如 2500)的策略路由规则:
1 | sudo ip rule add from 192.168.1.140 to 192.168.1.0/24 priority 2500 lookup main |
原理解析:
- 在家时: 开发板 A 分配到的物理 IP 是
192.168.1.140。当局域网设备 Ping 它时,它使用该 IP 作为源 IP 回包,精确命中此规则,流量直接走main表(物理网卡),瞬间连通。 - 外出时: 开发板 A 连接其他网络,物理 IP 改变(不再是
192.168.1.140)。该规则失效,系统继续往下匹配,命中 Tailscale 的表 52,从而实现正常的异地组网访问。
避坑
尽量避免将家中的主路由网段设置为192.168.1.0/24或192.168.0.0/24这种极其常见的默认网段。如果携带开启了异地组网的设备去酒店或单位,一旦公共 Wi-Fi 也是这个网段,就会引发严重的子网冲突(Overlapping Subnets)。建议改成类似10.88.99.0/24的冷门私有网段。
5. 进阶固化:使用 systemd 实现路由规则开机自启
为了在 Armbian/Debian 12 等现代 Linux 环境下一劳永逸地解决此问题,最稳妥的方案是创建一个标准的 systemd 服务,确保在网络和 Tailscale 均就绪后,自动注入我们的高优先级本地路由规则。
Step 1: 编写路由修复脚本
创建一个专门的 Shell 脚本,采用“先清理后添加”的逻辑,防止因网络服务重启导致规则重复堆叠。
1 | sudo vim /usr/local/bin/fix-lan-route.sh |
内容为:
1 |
|
赋予执行权限:
1 | sudo chmod +x /usr/local/bin/fix-lan-route.sh |
Step 2: 编写 systemd 服务文件
配置服务依赖,确保脚本在网络连通 (network-online.target) 且 Tailscale 服务启动 (tailscaled.service) 之后再执行。
1 | sudo vim /etc/systemd/system/fix-lan-route.service |
内容为:
1 | [Unit] |
Step 3: 激活服务并验证
重载 systemd 守护进程,并将该服务设为开机自启:
1 | # 重载系统配置 |
最终验证:
在终端执行 ip rule 命令。如果列表中清晰地出现了 2500: from 192.168.1.140 to 192.168.1.0/24 lookup main,即代表配置大功告成。从此,无论设备重启还是随时启停 Tailscale,本地局域网的通信策略都将稳如泰山。
tailscale可能存在的坑2 - 子网发布网关rock5b开启TUN导致tailscale无法链接
1 现象:
Clash开TUN以后,tailscale启动报错。
开启TUN时的异常日志:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22➜ ~ sudo systemctl status tailscaled.service
● tailscaled.service - Tailscale node agent
Loaded: loaded (/lib/systemd/system/tailscaled.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2026-03-28 10:00:48 CST; 28s ago
Docs: https://tailscale.com/docs/
Main PID: 578694 (tailscaled)
Tasks: 15 (limit: 18526)
Memory: 54.6M
CPU: 878ms
CGroup: /system.slice/tailscaled.service
└─578694 /usr/sbin/tailscaled --state=/var/lib/tailscale/tailscaled.state --socket=/run/tailscale/tailscaled.sock --port=41641
Mar 28 10:00:48 rock-5b tailscaled[578694]: logpolicy: using $STATE_DIRECTORY, "/var/lib/tailscale"
Mar 28 10:00:48 rock-5b tailscaled[578694]: linkChange: in state NoState; PAC or proxyConfig changed; updating routes
Mar 28 10:00:48 rock-5b tailscaled[578694]: got LocalBackend in 56ms
Mar 28 10:00:48 rock-5b tailscaled[578694]: Start
Mar 28 10:00:48 rock-5b tailscaled[578694]: ipnext: active extensions: conn25, portlist, posture, clientupdate, relayserver, taildrop
Mar 28 10:00:48 rock-5b tailscaled[578694]: Backend: logs: be:de27a4d50030bb2fa9eba85172884903b5e6894feb434ee6ece1a4b0f407b618 fe:
Mar 28 10:00:48 rock-5b tailscaled[578694]: control: client.Login(0)
Mar 28 10:00:48 rock-5b tailscaled[578694]: health(warnable=warming-up): error: Tailscale is starting. Please wait.
Mar 28 10:00:48 rock-5b tailscaled[578694]: control: doLogin(regen=false, hasUrl=false)
Mar 28 10:00:53 rock-5b tailscaled[578694]: health(warnable=warming-up): ok此时:
1
2➜ ~ tailscale status
unexpected state: NoState关闭tun后的正常日志:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22➜ ~ sudo systemctl status tailscaled.service
● tailscaled.service - Tailscale node agent
Loaded: loaded (/lib/systemd/system/tailscaled.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2026-03-28 10:01:28 CST; 3s ago
Docs: https://tailscale.com/docs/
Main PID: 579582 (tailscaled)
Tasks: 15 (limit: 18526)
Memory: 42.3M
CPU: 708ms
CGroup: /system.slice/tailscaled.service
└─579582 /usr/sbin/tailscaled --state=/var/lib/tailscale/tailscaled.state --socket=/run/tailscale/tailscaled.sock --port=41641
Mar 28 10:01:31 rock-5b tailscaled[579582]: monitor: RTM_DELROUTE: src=198.18.0.1/0, dst=198.18.0.1/32, gw=, outif=16, table=255
Mar 28 10:01:31 rock-5b tailscaled[579582]: LinkChange: major, rebinding: old: interfaces.State{defaultRoute=enP4p65s0 ifs={Meta:[198.18.0.>
Mar 28 10:01:31 rock-5b tailscaled[579582]: dns: Set: {DefaultResolvers:[] Routes:{} SearchDomains:[] Hosts:6}
Mar 28 10:01:31 rock-5b tailscaled[579582]: dns: Resolvercfg: {Routes:{} Hosts:6 LocalDomains:[]}
Mar 28 10:01:31 rock-5b tailscaled[579582]: dns: OScfg: {}
Mar 28 10:01:31 rock-5b tailscaled[579582]: wgengine: set DNS config again after major link change
Mar 28 10:01:31 rock-5b tailscaled[579582]: router: portUpdate(port=41641, network=udp6)
Mar 28 10:01:31 rock-5b tailscaled[579582]: Rebind; defIf="enP4p65s0", ips=[192.168.1.120/24 2409:8a70:b61:b91::1005/128 2409:8a70:b61:b91:>
Mar 28 10:01:31 rock-5b tailscaled[579582]: magicsock: 0 active derp conns
Mar 28 10:01:31 rock-5b tailscaled[579582]: router: portUpdate(port=41641, network=udp4)此时:
1
2
3
4
5
6
7➜ ~ tailscale status
100.xx.xx.xx rock-5b xxx@ linux -
100.xx.xx.xx server xxx@ linux offline, last seen xxd ago
100.xx.xx.xx phone1 xxx@ android offline, last seen xxd ago
100.xx.xx.xx orion-o6 xxx@ linux offline, last seen xxh ago
100.xx.xx.xx phone2 xxx@ android offline, last seen xxh ago
100.xx.xx.xx macbook-pro xxx@ macOS offline, last seen xxd ago
2 原因
简单来说,Clash 的 TUN 模式把 Tailscale 的建连流量给“劫持”了。
- Clash TUN 的霸道机制:当开启 Clash TUN 模式时,它会在系统里建一个虚拟网卡(比如
Mihomo),并通过修改系统路由表(下发0.0.0.0/1这种默认路由)或者用fwmark(防火墙标记)把机器上所有的流量都强行吸进自己的核心里。同时,它通常还会开启 Fake-IP 来劫持 DNS 请求(日志里关闭 TUN 时出现的198.18.0.1就是 Clash 的 Fake-IP 网段)。 - Tailscale 的迷失:
tailscaled服务启动时,需要向它自己的控制面板(login.tailscale.com)和分布在全球的 DERP 中继服务器发送 UDP 握手包来建立状态。 - 死锁形成:开启 TUN 后,Tailscale 刚发出建连请求,就被 Clash 一把抓走。如果这些流量被 Clash 丢到了错误的代理节点,或者由于 Fake-IP 导致 Tailscale 拿不到中继服务器的真实 IP,它的握手包就永远发不出去,一直卡在
NoState等待响应。
3 解决
思路很简单:给 Clash 设个规矩,让它对 Tailscale 相关的 IP、域名和进程“高抬贵手”,直接放行。
添加 Merge (合并) 路由规则
为了万无一失,我们需要让 Mihomo 核心彻底放行 tailscaled 进程和相关域名的流量。
将以下规则添加到你的直连规则(Direct)中,并且要放在规则列表的 最前面:
1 | rules: |
修复 Fake-IP 污染(关键):如果 Clash 配置里开启了 Fake-IP,必须把 Tailscale 的域名加入 fake-ip-filter,否则它连不上中继。在配置(实际配置位于dns_config.yaml)中补充:
1 | dns: |
应用这些设置并重启 Clash 的 TUN 开关后,Clash 就会把 Tailscale 的建连流量和 100.x.x.x 的内网流量原封不动地交还给系统路由表,两边就能和平共处了。
注:关于如何查找配置文件位置
在 Linux 中,要查看一个进程在启动时到底读取了哪些文件,最强大且标准的工具是 **strace**。它可以追踪进程调用的所有系统 API,包括打开文件的操作。
因为 clash-verge 是基于 Tauri 的应用,它会启动多个子进程(前端渲染、后端服务等),所以我们需要加上特定参数来追踪所有子进程,并过滤出跟配置文件相关的操作。
Step1: 进程追踪
安装 strace ,用 strace 运行组合命令并输出日志,将 strace 加在 clash 环境变量之后、 clash-verge 之前。为了防止终端输出被海量的系统调用淹没,把日志重定向到一个文本文件中:
1 | sudo apt install strace |
参数解释:
-f:告诉strace追踪所有由clash-verge派生出来的子进程(关键,因为配置通常是核心子进程读取的)。-e trace=open,openat:只监听“打开文件”相关的系统调用,过滤掉网络、内存等无关操作。2> startup_trace.log:将strace的标准错误输出(它的追踪日志默认输出到这里)保存到startup_trace.log文件中。
运行上面这条命令后,等终端停留在之前的状态(说明应用已经启动并转入后台监听),按 Ctrl + C 结束它。
Step2: 分析追踪日志
现在当前目录下生成了一个 startup_trace.log 文件。可以用 grep 过滤出所有常见的配置文件后缀(如 .yaml, .yml, .json):
1 | grep -i -E '\.yaml|\.yml|\.json' startup_trace.log | grep -v "ENOENT" |
参数解释:
-i -E '\.yaml|\.yml|\.json':忽略大小写,匹配这三种常见的配置文件格式。grep -v "ENOENT":过滤掉“文件不存在(Error No Entry)”的记录。程序在启动时通常会按照一定顺序去多个默认目录“试探性”地寻找配置文件,过滤掉找不到的记录,剩下的就是它真正成功读取到的文件路径:1
2
3
4
5
6
7
8
9
10
11
12
13➜ ~ grep -i -E '\.yaml|\.yml|\.json' startup_trace.log | grep -v "ENOENT"
[pid 568056] openat(AT_FDCWD, "/home/pi/.local/share/io.github.clash-verge-rev.clash-verge-rev/verge.yaml", O_RDONLY|O_CLOEXEC) = 19
[pid 568057] openat(AT_FDCWD, "/home/pi/.local/share/io.github.clash-verge-rev.clash-verge-rev/config.yaml", O_RDONLY|O_CLOEXEC) = 19
[pid 568057] openat(AT_FDCWD, "/home/pi/.local/share/io.github.clash-verge-rev.clash-verge-rev/verge.yaml", O_RDONLY|O_CLOEXEC) = 19
[pid 568056] openat(AT_FDCWD, "/home/pi/.local/share/io.github.clash-verge-rev.clash-verge-rev/profiles.yaml", O_RDONLY|O_CLOEXEC) = 19
[pid 568036] openat(AT_FDCWD, "/home/pi/.config/io.github.clash-verge-rev.clash-verge-rev/window_state.json", O_RDONLY|O_CLOEXEC) = 20
[pid 568057] openat(AT_FDCWD, "/home/pi/.local/share/io.github.clash-verge-rev.clash-verge-rev/profiles/RrCXXb9eVReP.yaml", O_RDONLY|O_CLOEXEC) = 30
[pid 568058] openat(AT_FDCWD, "/home/pi/.local/share/io.github.clash-verge-rev.clash-verge-rev/profiles/Merge.yaml", O_RDONLY|O_CLOEXEC <unfinished ...>
[pid 568058] openat(AT_FDCWD, "/home/pi/.local/share/io.github.clash-verge-rev.clash-verge-rev/dns_config.yaml", O_RDONLY|O_CLOEXEC) = 21
[pid 568057] openat(AT_FDCWD, "/home/pi/.local/share/io.github.clash-verge-rev.clash-verge-rev/clash-verge.yaml", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 21
[pid 568058] openat(AT_FDCWD, "/home/pi/.local/share/io.github.clash-verge-rev.clash-verge-rev/clash-verge-check.yaml", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 21
[pid 568095] openat(AT_FDCWD, "/home/pi/.local/share/io.github.clash-verge-rev.clash-verge-rev/clash-verge-check.yaml", O_RDONLY|O_CLOEXEC) = 3
[pid 568057] openat(AT_FDCWD, "/home/pi/.local/share/io.github.clash-verge-rev.clash-verge-rev/clash-verge.yaml", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 21```
7 self host atuin
atuin 的主机间 sync 命令行历史记录非常有用,按照官方说明 Self Hosting - Docker 用 Docker Compose 的方式可以很容易的拉起来一个私有服务。之后,在任意需要 atuin sync 的主机上,修改 atuin 的配置文件 ~/.config/atuin/config.toml:sync_address = "http://<server-ip:port>"即可。
将本地的shell命令导入 atuin 管理,运行atuin import auto或atuin import zsh。注:如果要 atuin 接管 ctrl-r,则要保证.zshrc中 atuin 在 fzf 之后初始化。
接下来,在第一台要同步的主机命令行里,运行首次用户注册:atuin register -u <username> -e <email>,此时 atuin 会让你运行atuin key拿到助记词,用来在之后的登录时使用。注册完毕后运行atuin sync向服务器同步历史记录。完成注册后,再在其他主机上只需要执行登录即可:atuin login -u <username>再输入助记词即可,成功后atuin sync。
此时ctrl-r打开 atuin ,多次按ctrl-r就会在 全局、本机、本次会话、此目录 等环境中切换。在全局环境,选中命令按ctrl-o进入检视页会看到此命令所属的主机。
最后设置系统服务,新建sudo vim /etc/systemd/system/atuin.service,把官方说明中systemd那段脚本贴进去,然后将WorkingDirectory换成刚才docker-compose.yml所在的绝对路径即可,再sudo systemctl daemon-reload、sudo systemctl enable --now atuin.service、sudo systemctl status atuin.service即可看到开机自启的 atuin 服务。

