对比 链接到标题
NetBird 和 Tailscale 都是 mesh VPN,但 CLI 体验有个明显差距:
| 操作 | Tailscale | NetBird |
|---|---|---|
| 查看节点列表 | tailscale status — 简洁表格 |
netbird status — 只显示本机状态 |
| 查看详情 | tailscale status --json |
netbird status --detail — 散文体 |
tailscale status 输出是这样的:
100.121.*.* peer-a linux -
100.121.*.* server linux -
100.121.*.* laptop macOS -
而 netbird status --detail 的节点信息散布在两处:
- Peers detail 区块:每个对端分多行(FQDN、IP、Status)
- Summary 区块:本地节点的 FQDN 和 IP 在底部
解析思路 链接到标题
以 Peers detail 中的一段为例:
peer-a.netbird.selfhosted:
NetBird IP: 100.121.*.*
NetBird IPv6: fdd2:*:*:*:*:*:*:*
Public key: xJwCVGGIjZGeEKzzPEXtcZZav2HIoYtLcfyjOyH9KR0=
Status: Connected
需要提取的三行:
- 缩进的主机名行(前面有一个空格 + 主机名 +
:) NetBird IP:行Status:行
本地节点在 Summary 中格式相似,但主机名以 FQDN: 开头。
实现 链接到标题
nb-list() {
(echo "FQDN IP Status"
netbird status --detail | awk '
/^ [a-zA-Z]/ { name = $1; sub(/:$/, "", name) }
/NetBird IP:/ { ip = $NF }
/Status:/ {
status = $NF
if (name) printf "%-35s %-18s %s\n", name, ip, status
name = ""; ip = ""
}
/^FQDN:/ { local_name = $NF }
/^NetBird IP:/ && !/NetBird IPv6/ { local_ip = $NF }
END {
if (local_name) printf "%-35s %-18s %s\n", local_name, local_ip, "Connected"
}') | column -t
}
关键点:
/^ [a-zA-Z]/— 匹配开头带一个空格的 FQDN 行,去掉末尾冒号作为节点名name = ""; ip = ""在打印后立即清空,避免后续无关行误触- Summary 部分用独立的
local_name/local_ip变量存放,END 块输出
效果 链接到标题
FQDN IP Status
peer-a.netbird.selfhosted 100.121.*.* Connected
server.netbird.selfhosted 100.121.*.* Connected
laptop.netbird.selfhosted 100.121.*.*/16 Connected
含本地节点,与远程对端并列。
保存 链接到标题
将函数添加到 ~/.zshrc,source 后即可使用:
source ~/.zshrc
nb-list
替代方案 链接到标题
sudo wg show— 直接看 WireGuard 对端(最底层)- Dashboard 界面 — 自托管 Dashboard 地址
- API — 用 Personal Access Token 调
GET /api/peers