新年要用新系统

这个blog两年没更新过了啊!靠着AI打气又拾起来了!

起因是节前Fusion 360警告我win10不受支持了,Gemini也建议我换个系统,并且疯狂安利Win11,安抚我说Win11已经不是几年前那种费拉不堪的状态了。

再信AI一次。

0 备份

尤其是wsl2!

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
mkdir -p ~/wsl_backup/manifests
cd ~/wsl_backup/manifests

#######
# apt #
#######
# 导出所有手动安装的包(排除依赖包)
comm -23 <(apt-mark showmanual | sort -u) <(gzip -dc /var/log/installer/initial-status.gz | sed -n 's/^Package: //p' | sort -u) > apt-manual-packages.txt
# 如果上面命令报错或太复杂,用这个简单的版本(会包含一些基础包):
apt-mark showmanual > apt-manual-list.txt

###################
# python 和 conda #
###################
# 激活主环境,比如 base 或 pytorch
conda env export --no-builds > conda_environment.yml
pip freeze > requirements.txt

########
# rust #
########
cargo install --list > cargo-crates.txt

########
# node #
########
npm list -g --depth=0 > npm-global-packages.txt

##############
# shell conf #
##############
cd ~
tar -czvf ~/wsl_backup/dotfiles.tar.gz \
.zshrc \
.bashrc \
.profile \
.zsh_history \
.bash_history
.ssh \
.tmux.conf \
.fzf.zsh \
.gitconfig \
.vimrc \
.config/nvim \
.gnupg \
.condarc \
.pip \
.cargo/config.toml \

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 清理微软的垃圾

第一时间防火防盗防微软。

  1. 彻底禁止 Windows 自动更新驱动:
    Win + R 输入 gpedit.msc计算机配置 -> 管理模板 -> Windows 组件 -> Windows 更新 -> 管理从 Windows 更新提供的更新,右侧的 “Windows 更新不包括驱动程序”,选择 “已启用”。如此,让 Windows Update 只推安全补丁和功能更新,绝不会动显卡、网卡、声卡驱动。

  2. 保留 Defender,配置“码农豁免区”
    打开 Windows 安全中心 -> 病毒和威胁防护 -> 管理设置,下拉找到 “排除项” -> 添加或删除排除项,酌情加入:

    • D:\WSL (放 WSL 镜像,防止扫描 vhdx 读写);
    • D:\DEV (放代码);
    • D:\MOEDL (放模型);
    • etc.
  3. 左下角“天气新闻”等等是 小组件” (Widgets)Win + R 输入 gpedit.msc计算机配置 -> 管理模板 -> Windows 组件 -> 小组件,右侧的 “允许小组件”,选择 “已禁用”

  4. 锁屏时“天气新闻”等待是 Windows 聚焦 (Windows Spotlight)

    • 右键桌面 -> “个性化” -> 选择 “锁屏界面”,在个 性化锁屏界面 中选择 “图片” (Picture)
    • 再往下看,如果有 “在锁屏界面上获取花絮、提示、技巧和更多内容”,选择 关闭
    • 如果有 “锁屏界面状态”,改为 无 (None)
  5. 开始菜单里的垃圾,右键桌面 -> “个性化” -> “开始”

    • 显示最近添加的应用 ->
    • 显示最常用的应用 ->
    • 在“开始”菜单中……显示最近打开的项目 ->
  6. 开始菜单的搜索 强行把本地搜索和 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)
  7. 任务栏的搜索框,任务栏空白处 右键 -> “任务栏设置”,第一项就是 “搜索”,选择 “隐藏”

  8. Steam/Epic党可以把XBox相关都端了:

    • 关闭 Xbox Game Bar:在 设置 -> 游戏 -> Xbox Game Bar,关闭 “允许控制器打开 Game Bar”
    • 开始菜单搜 “Xbox”,右键 -> 卸载
    • 唯一例外:游戏模式 (Game Mode) ,留着,在 设置 -> 游戏 -> 游戏模式 里,保持 开 (ON)。
  9. 关闭 OneDrive

    • 解除“文件夹备份”,任务栏右下角的那个“云朵”图标,右上角齿轮进入 设置,找到 “同步并备份” (Sync and backup) -> “管理备份” (Manage backup),把“文档”、“图片”、“桌面”全部关掉(Stop backup)。,此时系统会把这些文件夹的路径从 C:\Users\<username>\OneDrive\Desktop 恢复为 C:\Users\<username>\Desktop
    • 取消链接:设置 里 -> “账户” (Account),点击 “取消链接此电脑” (Unlink this PC)。
    • 卸载:设置 -> 应用 -> 安装的应用,搜 “OneDrive” -> 卸载
  10. 至于 基于虚拟化的安全性 (VBS)” / HVCI,模型和网上的说法都没定论。

    • Win 键搜索 “内核隔离” -> “内存完整性”,收益有限,关不关无所谓。
    • 网上流传的 bcdedit /set hypervisorlaunchtype off 不能设置, wsl2 要用。
  11. 找回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
2
winget install Tencent.WeChat
winget install Tencent.QQ

PotPlayer:

1
winget install Daum.PotPlayer

装powertoys:

1
winget install Microsoft.PowerToys

装Everything和Listary:

1
2
winget install voidtools.Everything
winget install -e --id Bopsoft.Listary

4 安装wsl2

有显卡驱动了再装wsl2。

  1. 先装 WSL 本体,管理员 PowerShell:

    1
    wsl --install
  2. 装完建议重启,确认 WSL 版本:

    1
    wsl --version
  3. 在 D 盘准备一个专门目录 D:\WSL,安装一个临时 Ubuntu(会默认在 C 盘),启动一次 Ubuntu,完成用户名/密码初始化后退出。

    1
    wsl --install -d Ubuntu
  4. 把迁移到 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\ 下面了。

  5. 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
    4
    sudo 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
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
#!/usr/bin/env bash
set -e

# ==========================================
# WSL2 Development Environment Bootstrap
# Target: Debian/Ubuntu
# Role: System, Shell, Rust, Node, Python, Git
# ==========================================

# 颜色定义,方便看日志
GREEN='\033[0;32m'
BLUE='\033[0;34m'
RED='\033[0;31m'
NC='\033[0m'

log() { echo -e "${GREEN}[SETUP] $1${NC}"; }
info() { echo -e "${BLUE}[INFO] $1${NC}"; }
error() { echo -e "${RED}[ERROR] $1${NC}"; }

# 0. 基础检查
# ------------------------------------------
if [ "$EUID" -eq 0 ]; then
error "请不要使用 root 运行此脚本,请使用普通用户运行!"
error "脚本内部会在需要时请求 sudo 权限。"
exit 1
fi

# 保持 sudo 权限活跃,防止脚本运行中途因为超时等待输入密码
sudo -v
while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null &

# 先把文件建好,后面的 Rust/NVM/Conda 就会以为你已经在使用 zsh 了,
# 它们会自动把 export PATH... 写入这两个文件。
touch "$HOME/.bashrc"
touch "$HOME/.zshrc"

### ========================================
### 1. 系统基础 (System Base)
### ========================================
log "📦 1. 更新系统并安装基础依赖..."

sudo apt update && sudo apt upgrade -y

# 安装必备工具
# build-essential: 编译环境
# software-properties-common:以此支持 add-apt-repository
sudo apt install -y \
git git-lfs curl wget ca-certificates \
build-essential pkg-config libssl-dev \
zip unzip btop tmux zsh \
net-tools iproute2 dnsutils \
jq yq tree procps make \
direnv rsync tldr shellcheck \
software-properties-common ffmpeg \
fonts-noto-cjk fonts-wqy-microhei \
language-pack-zh-hans

# 安装fastfetch,因为sudo后常用 gpg/dirmngr 去连 keyserver,
# gpg/dirmngr 不读 apt 的代理配置,
# 而且 sudo 默认还会把 shell 里的 http_proxy/https_proxy 环境变量“清掉”,
# 导致直连 keyserver,然后被墙阻断,表现为“没反应”。
export http_proxy="http://127.0.0.1:7897"
export https_proxy="http://127.0.0.1:7897"
sudo --preserve-env=http_proxy,https_proxy add-apt-repository ppa:zhangsongcui3371/fastfetch -y
sudo apt update
sudo apt install fastfetch -y

### ========================================
### 2. Rust 工具链 (Rust & Modern CLI)
### ========================================
log "🦀 2. 安装 Rust 环境..."

if ! command -v rustup >/dev/null 2>&1; then
# 安装 Rustup
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
else
info "Rustup 已安装,跳过."
fi

# 【关键】加载环境变量,确保 cargo 命令可用
# 如果你分步运行,请务必执行这一行
source "$HOME/.cargo/env"

log "🦀 安装 Cargo Binstall (加速工具安装)..."
if ! command -v cargo-binstall >/dev/null 2>&1; then
curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
fi

log "🦀 安装现代命令行工具 (Rust编写)..."
# 以用户token登录方式,解除 GitHub API 速率限制 (Rate Limiting)
# cargo-binstall 匿名查询API每小时仅60次,
# 不登录超过将报403,登录将提升到5000次
# Settings -> Developer settings -> Personal access tokens -> Tokens (classic),
# Expiration 选 "No expiration",Scopes (权限) 一个都不用勾
export GITHUB_TOKEN="ghp_xxx"

# bob-nvim: Neovim 版本管理器
# starship: 跨 Shell 提示符
# eza(ls), bat(cat), fd(find), ripgrep(grep), zoxide(cd)
cargo binstall -y \
eza bat fd-find ripgrep du-dust procs zoxide hyperfine \
cargo-watch cargo-nextest cargo-update cargo-audit \
starship atuin bob-nvim topgrade tealdeer zellij

# 装了tealdeer可以卸载 ubuntu 自带的 haskell tldr-hs
sudo apt remove -y tldr

### ========================================
### 3. Neovim (via Bob)
### ========================================
log "📝 3. 使用 Bob 安装最新 Neovim..."

# 确保 bob 在路径中
export PATH="$HOME/.cargo/bin:$PATH"

if command -v bob >/dev/null 2>&1; then
# 安装最新的稳定版
bob install stable
bob use stable

# 这一步是为了确保 nvim 能被系统找到
# Bob 默认把 nvim 放在 ~/.local/share/bob/nvim-bin
if [[ ":$PATH:" != *":$HOME/.local/share/bob/nvim-bin:"* ]]; then
info "提示: 请将 $HOME/.local/share/bob/nvim-bin 添加到你的 PATH 中"
fi
else
error "Bob 安装失败,跳过 Neovim 安装。"
fi

# 1. 让当前终端立刻生效(临时)
export PATH="$HOME/.local/share/bob/nvim-bin:$PATH"
# 2. 写入 .bashrc(永久生效,防止下次进 bash 找不到 nvim)
echo 'export PATH="$HOME/.local/share/bob/nvim-bin:$PATH"' >> ~/.bashrc
echo 'export PATH="$HOME/.local/share/bob/nvim-bin:$PATH"' >> ~/.zshrc

# 如果我觉得 neovim 过于毛坯,可以安装 lazyvim: https://www.lazyvim.org/installation
# 备份
mv ~/.config/nvim{,.bak}

# optional but recommended
mv ~/.local/share/nvim{,.bak}
mv ~/.local/state/nvim{,.bak}
mv ~/.cache/nvim{,.bak}

git clone https://github.com/LazyVim/starter ~/.config/nvim
rm -rf ~/.config/nvim/.git

# 第一次打开 nvim 要装东西,会比较慢,记得梯子

### ========================================
### 4. Node.js (NVM)
### ========================================
log "🟢 4. 安装 Node.js 环境..."

export NVM_DIR="$HOME/.nvm"

if [ ! -d "$NVM_DIR" ]; then
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
fi

# 【关键】加载 NVM 环境
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"

log "🟢 安装 Node LTS..."
nvm install --lts
nvm use --lts
nvm alias default lts/*

log "🟢 安装 pnpm 和常用全局包..."
if ! command -v pnpm >/dev/null 2>&1; then
curl -fsSL https://get.pnpm.io/install.sh | sh -
fi

# 临时加载 pnpm 路径
export PATH="$HOME/.local/share/pnpm:$PATH"

# 安装常用开发工具
pnpm add -g typescript tsx eslint prettier @google/gemini-cli @openai/codex
# pnpm 交互式构建批准
pnpm approve-builds -g
curl -fsSL https://claude.ai/install.sh | bash
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc && source ~/.bashrc

### ========================================
### 5. Python uv and miniconda
### ========================================
log "🐍 5. 安装 Python 环境 (uv)..."

if ! command -v uv >/dev/null 2>&1; then
curl -Ls https://astral.sh/uv/install.sh | sh
fi

# 临时加载 uv 路径
export PATH="$HOME/.local/bin:$PATH"

log "🐍 安装 Python 工具链..."
# uv tool install 类似于 pipx,安装到隔离环境
for tool in ruff mypy black poetry httpie; do
uv tool install "$tool" || true
done

log "🐍 5.5 安装 Miniconda..."

# 定义安装路径 (通常在 ~/miniconda3 或 ~/.miniconda3)
MINICONDA_PATH="$HOME/miniconda3"

if [ ! -d "$MINICONDA_PATH" ]; then
# 1. 下载最新的 Linux 安装脚本
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh

# 2. 静默安装 (-b: batch mode, -p: prefix path)
bash miniconda.sh -b -p "$MINICONDA_PATH"

# 3. 删除安装包
rm miniconda.sh

# 4. 【关键配置】初始化 Shell (bash 和 zsh)
# 这步会自动把 conda 的路径写入 .bashrc 和 .zshrc
"$MINICONDA_PATH/bin/conda" init bash
"$MINICONDA_PATH/bin/conda" init zsh

# 5. 【强力推荐】禁止 Conda 默认激活 base 环境
# 否则每次打开终端前面都有个 (base),会干扰 uv 和系统 Python
"$MINICONDA_PATH/bin/conda" config --set auto_activate_base false

log "✅ Miniconda 安装完成 (Base 环境已禁用自动激活)"
else
info "Miniconda 已存在,跳过安装。"
fi

### ========================================
### 6. Git & GitHub
### ========================================
log "🐙 6. 安装 Git 工具..."

# 6.1 GitHub CLI (gh)
if ! command -v gh >/dev/null 2>&1; then
info "安装 gh cli..."
sudo mkdir -p -m 755 /etc/apt/keyrings
wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null
sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
sudo apt update
sudo apt install -y gh
fi

# 6.2 Lazygit (自动架构检测)
if ! command -v lazygit >/dev/null 2>&1; then
info "安装 lazygit..."
LAZYGIT_VERSION=$(curl -s "https://api.github.com/repos/jesseduffield/lazygit/releases/latest" | grep -Po '"tag_name": "v\K[^"]*')
ARCH=$(uname -m)
case $ARCH in
x86_64) LG_ARCH="x86_64" ;;
aarch64) LG_ARCH="arm64" ;;
*) error "不支持的架构: $ARCH"; exit 1 ;;
esac

curl -Lo lazygit.tar.gz "https://github.com/jesseduffield/lazygit/releases/download/v${LAZYGIT_VERSION}/lazygit_${LAZYGIT_VERSION}_Linux_${LG_ARCH}.tar.gz"
tar xf lazygit.tar.gz lazygit
sudo install lazygit /usr/local/bin
rm -f lazygit lazygit.tar.gz
fi

### ========================================
### 7. Shell (Oh-My-Zsh + Starship)
### ========================================
log "💻 7. 配置 Shell 环境..."

# 安装 OMZ
if [ ! -d "$HOME/.oh-my-zsh" ]; then
info "安装 Oh-My-Zsh..."
# --unattended: 不自动进入 zsh
# --keep-zshrc: 如果你已经有配置文件,不覆盖
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended --keep-zshrc
fi

# 安装 fzf
if [ ! -d "$HOME/.fzf" ]; then
info "安装 FZF (命令行模糊搜索)..."
git clone --depth 1 https://github.com/junegunn/fzf.git "$HOME/.fzf"
# --all: 自动启用 key-bindings (Ctrl+R/T) 和 fuzzy-completion
# --no-bash/--no-fish: 我们只配 zsh,不让它乱改其他 shell
"$HOME/.fzf/install" --all
else
info "FZF 已安装,跳过."
fi

ZSHRC="$HOME/.zshrc"

# 确保文件存在
touch "$ZSHRC"

# 3.1 禁用 OMZ 主题 (让位给 Starship)
# 我们用 sed 查找并替换 ZSH_THEME="..." 为 ZSH_THEME=""
if grep -q 'ZSH_THEME=' "$ZSHRC"; then
sed -i 's/^ZSH_THEME=".*"/ZSH_THEME=""/' "$ZSHRC"
fi

# A. 备份现有的 .zshrc (里面有 Conda 和 FZF 的配置,不能丢!)
if [ -f "$ZSHRC" ]; then
cp "$ZSHRC" "$ZSHRC.pre-bootstrap"
info "已备份现有配置到 .zshrc.pre-bootstrap"
fi

# B. 获取 OMZ 官方模板 (作为地基)
# 我们把模板下载下来,追加到现有的 .zshrc 后面,这样既保留了 Conda/FZF,又有了 OMZ 的功能
if [ ! -f "$HOME/.oh-my-zsh/templates/zshrc.zsh-template" ]; then
# 万一模板没下载下来,手动抓取
curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/templates/zshrc.zsh-template > temp_zshrc
else
cp "$HOME/.oh-my-zsh/templates/zshrc.zsh-template" temp_zshrc
fi

# C. 合并配置 (关键一步!)
# 1. 保留 Conda/FZF (在文件头部)
# 2. 插入 OMZ 模板 (在中间)
# 3. 插入我们自定义的 PATH 和 Tool (在底部)

# 读取现有内容 (Conda + FZF)
CURRENT_CONTENT=$(cat "$ZSHRC")

# 覆写 .zshrc:先放 OMZ 模板,再放 原内容
cat temp_zshrc >> "$ZSHRC"
echo "" >> "$ZSHRC"
echo "$CURRENT_CONTENT" > "$ZSHRC"
rm temp_zshrc

# D. 修改配置 (现在里面有东西了,可以改了)

# 1. 禁用 OMZ 主题 (让 Starship 接管)
# 使用 sed 将 ZSH_THEME="robbyrussell" 替换为 ZSH_THEME=""
sed -i 's/^ZSH_THEME=".*"/ZSH_THEME=""/' "$ZSHRC"

# 2. 启用常用插件 (git, extract, sudo)
# 这是 OMZ 的精华,必须开
sed -i 's/^plugins=(git)/plugins=(git extract sudo)/' "$ZSHRC"

# 3. 注入环境变量 (把之前漏在 bashrc 里的补回来)
cat <<EOT >> "$ZSHRC"

# --- Bootstrap Generated Config (PATHs & Tools) ---

# 1. PATH 补全 (Rust, Node, Bob, Local Bin)
# 注意:Miniconda 已经在文件头部配好了,这里不需要重复
export PATH="\$HOME/.local/bin:\$HOME/.cargo/bin:\$HOME/.local/share/bob/nvim-bin:\$HOME/.local/share/pnpm:\$PATH"

# 2. 工具启动
eval "\$(atuin init zsh)" # 启动 atuin (需要在 fzf 初始化之后)
eval "\$(starship init zsh)" # 启动 Starship
eval "\$(zoxide init zsh)" # 启动 Zoxide (z 命令)

# 3. 别名 (Aliases)
alias cat='bat'
alias ls='eza --icons' # 基础 ls 变彩色+图标
alias ll='eza -lah --icons --git ' # ll 显示详情、Git状态、隐藏文件
alias lt='eza -lah --tree --level=2 --icons' # lt 显示目录树(2层)
alias vi='nvim'
alias vim='nvim'
alias zj='zellij'
alias ra='ranger' # 如果装了 ranger

# 4. NVM 懒加载 (加快启动速度)
export NVM_DIR="\$HOME/.nvm"
[ -s "\$NVM_DIR/nvm.sh" ] && . "\$NVM_DIR/nvm.sh"

EOT

# 1. 删掉顶部的那行 FZF 配置 (使用 sed)
#sed -i '/\[ -f ~\/.fzf.zsh \] && source ~\/.fzf.zsh/d' "$ZSHRC"
# 2. 把它追加到文件最末尾
#echo '[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh' >> "$ZSHRC"

# 修改系统shell
chsh -s $(which zsh)

log "✅ .zshrc 修复完成!(Conda + FZF + OMZ + Tools 全部合体)"
log "👉 现在输入 'zsh' 进入新环境吧!"

# 安装 ohmytmux
curl -fsSL "https://github.com/gpakosz/.tmux/raw/refs/heads/master/install.sh#$(date +%s)" | bash

关于yt-dlp

1
2
3
4
5
uv tool install yt-dlp --with curl_cffi --with pycryptodomex --upgrade --force
# 记得装ffmpeg和nvm node,配置node变量
vim ~/.config/yt-dlp/config
--js-runtimes node
--remote-components ejs:github

关于恢复备份的.ssh文件夹,拷过去权限得改对:

1
2
3
4
5
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_*
chmod 644 ~/.ssh/*.pub
# 如果有
chmod 600 ~/.ssh/config

关于中文环境,上面装了字体和中文编码,需要配置语言环境:

1
sudo dpkg-reconfigure locales

zh_CN.UTF-8 UTF-8即可,echo $LANG还不行的话:

1
2
echo "export LANG=zh_CN.UTF-8" >> ~/.bashrc
echo "export LANG=zh_CN.UTF-8" >> ~/.zshrc

现在使用topgrade自动感知并更新安装工具。

6 tailscale 与 ipv6

节后移动给的GPON坏了,运营商换了一个后发现有ipv6了。家里的rock5b、PVE工作站都可以用ipv6直连了。

PVE装tailscale

需要注意的是,PVE默认没打开ipv6支持,所以需要手动设置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
vi /etc/sysctl.conf 

net.ipv6.conf.all.disable_ipv6 = 0
net.ipv6.conf.default.disable_ipv6 = 0
net.ipv6.conf.lo.disable_ipv6 = 0

net.ipv6.conf.all.forwarding = 1

vi /etc/sysctl.d/99-tailscale.conf
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
# 或:
echo 'net.ipv4.ip_forward = 1' | tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | tee -a /etc/sysctl.d/99-tailscale.conf

# 应用网络配置
ifreload -a

此时用ip -6 addr show会发现vmbr0上多出来一个2409(移动)开头的地址,再用手机等公网设备打开tailscale去ping这台PVE就会从relay转到direct了。

1
2
3
5: vmbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
inet6 2409:xxxx:xxx:xxxx:xxxx:xxxx:xxxx:xxxx/64 scope global dynamic mngtmpaddr proto kernel_ra
valid_lft 86181sec preferred_lft 14181sec

全家搬到tailscale

通过rock5b转发流量,可以把家里的192.168.1.x/24都放在tailscale上。在rock5b上配置系统转发:

1
2
3
4
5
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

sudo tailscale up --advertise-routes=192.168.1.0/24 --accept-dns=false

出于安全考虑,被“广播”的网段 Tailscale 默认不信任,需要手动确认:

  1. 登录 Tailscale Admin Console
  2. Rock 5B 点击右侧的 **三个点 (…)**。
  3. 选择 Edit route settings
  4. 在弹出的窗口中,勾选广播的网段 192.168.1.0/24
  5. 点击 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 解析 -> 路由表。

  1. 排除防火墙与物理隔离: 检查了 ufwiptables,未发现拦截规则。
  2. 检查 ARP 缓存 (ip neigh show): 开发板 A 上能成功获取到 B 和 Windows 的 MAC 地址,说明物理层和数据链路层通信正常。
  3. 排查代理软件: 怀疑是 Windows 端的 Clash TUN 模式劫持了局域网流量。关闭 TUN 模式并使用 ping -S 192.168.1.125 192.168.1.140 强制指定源 IP,依然不通,排除发件端代理问题。
  4. 定位核心问题——策略路由 (ip rule):
    在开发板 A (140) 上执行 ip rule 发现异常:
    1
    2
    5270:   from all lookup 52
    32766: from all lookup main
    执行 ip 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/24192.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
2
3
4
5
6
#!/bin/bash
# 忽略报错删除可能存在的旧规则,避免重复
ip rule del from 192.168.1.140 to 192.168.1.0/24 priority 2500 lookup main 2>/dev/null

# 添加本地局域网高优先级规则
ip rule add from 192.168.1.140 to 192.168.1.0/24 priority 2500 lookup main

赋予执行权限:

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
2
3
4
5
6
7
8
9
10
11
12
[Unit]
Description=Fix LAN routing conflict with Tailscale
After=network-online.target tailscaled.service
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/fix-lan-route.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Step 3: 激活服务并验证

重载 systemd 守护进程,并将该服务设为开机自启:

1
2
3
4
5
6
7
8
# 重载系统配置
sudo systemctl daemon-reload

# 设置为开机自启
sudo systemctl enable fix-lan-route.service

# 立即启动该服务进行验证
sudo systemctl start fix-lan-route.service

最终验证:
在终端执行 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启动报错。

  1. 开启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
  2. 关闭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 的建连流量给“劫持”了。

  1. Clash TUN 的霸道机制:当开启 Clash TUN 模式时,它会在系统里建一个虚拟网卡(比如 Mihomo),并通过修改系统路由表(下发 0.0.0.0/1 这种默认路由)或者用 fwmark(防火墙标记)把机器上所有的流量都强行吸进自己的核心里。同时,它通常还会开启 Fake-IP 来劫持 DNS 请求(日志里关闭 TUN 时出现的 198.18.0.1 就是 Clash 的 Fake-IP 网段)。
  2. Tailscale 的迷失tailscaled 服务启动时,需要向它自己的控制面板(login.tailscale.com)和分布在全球的 DERP 中继服务器发送 UDP 握手包来建立状态。
  3. 死锁形成:开启 TUN 后,Tailscale 刚发出建连请求,就被 Clash 一把抓走。如果这些流量被 Clash 丢到了错误的代理节点,或者由于 Fake-IP 导致 Tailscale 拿不到中继服务器的真实 IP,它的握手包就永远发不出去,一直卡在 NoState 等待响应。

3 解决

思路很简单:给 Clash 设个规矩,让它对 Tailscale 相关的 IP、域名和进程“高抬贵手”,直接放行。

添加 Merge (合并) 路由规则

为了万无一失,我们需要让 Mihomo 核心彻底放行 tailscaled 进程和相关域名的流量。

将以下规则添加到你的直连规则(Direct)中,并且要放在规则列表的 最前面

1
2
3
4
5
6
7
8
rules:
# 直连 Tailscale 后台守护进程
- PROCESS-NAME,tailscaled,DIRECT
# 直连 Tailscale 的内网网段
- IP-CIDR,100.64.0.0/10,DIRECT
# 直连 Tailscale 的控制面域名
- DOMAIN-SUFFIX,tailscale.com,DIRECT
- DOMAIN-SUFFIX,tailscale.io,DIRECT

修复 Fake-IP 污染(关键):如果 Clash 配置里开启了 Fake-IP,必须把 Tailscale 的域名加入 fake-ip-filter,否则它连不上中继。在配置(实际配置位于dns_config.yaml)中补充:

1
2
3
4
dns:
fake-ip-filter:
- '*.tailscale.com'
- '*.tailscale.io'

应用这些设置并重启 Clash 的 TUN 开关后,Clash 就会把 Tailscale 的建连流量和 100.x.x.x 的内网流量原封不动地交还给系统路由表,两边就能和平共处了。

注:关于如何查找配置文件位置

在 Linux 中,要查看一个进程在启动时到底读取了哪些文件,最强大且标准的工具是 **strace**。它可以追踪进程调用的所有系统 API,包括打开文件的操作。

因为 clash-verge 是基于 Tauri 的应用,它会启动多个子进程(前端渲染、后端服务等),所以我们需要加上特定参数来追踪所有子进程,并过滤出跟配置文件相关的操作。

Step1: 进程追踪

安装 strace ,用 strace 运行组合命令并输出日志,将 strace 加在 clash 环境变量之后、 clash-verge 之前。为了防止终端输出被海量的系统调用淹没,把日志重定向到一个文本文件中:

1
2
3
sudo apt install strace

WEBKIT_DISABLE_COMPOSITING_MODE=1 WEBKIT_DISABLE_DMABUF_RENDERER=1 WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS=1 GDK_BACKEND=x11 strace -f -e trace=open,openat clash-verge 2> startup_trace.log

参数解释:

  • -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.tomlsync_address = "http://<server-ip:port>"即可。

将本地的shell命令导入 atuin 管理,运行atuin import autoatuin 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-reloadsudo systemctl enable --now atuin.servicesudo systemctl status atuin.service即可看到开机自启的 atuin 服务。

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×