Skip to content

Commit a54b545

Browse files
committed
feat(cloudflared): 增加版本检测与显示功能
- 更新 cloudflared.go,支持获取 cloudflared 的版本信息并在状态中展示。 - 添加解析版本输出的逻辑,根据命令行结果提取版本号并显示。 - 更新 Cloudflare Tunnel 文档,说明版本查询及相关安装指引链接。 - 设置页面中新增 cloudflared 版本显示内容,增强用户操作体验。 - 补充解析版本号功能的单元测试,提升代码可靠性。
1 parent 850f14e commit a54b545

4 files changed

Lines changed: 80 additions & 5 deletions

File tree

docs/features/cloudflare-tunnel.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ winget install --id Cloudflare.cloudflared
9191
cloudflared version
9292
```
9393

94-
也可以到 Cloudflare 官方下载页或 GitHub Releases 下载 Windows 安装包 / 可执行文件:
94+
也可以到 Cloudflare 官方下载页或 GitHub Releases 下载 Windows 可执行文件:
9595

96-
- [Cloudflare Downloads](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/)
96+
- [Cloudflare Downloads](https://developers.cloudflare.com/tunnel/downloads/)
9797
- [cloudflared Releases](https://github.com/cloudflare/cloudflared/releases)
9898

9999
如果你下载的是单个 `cloudflared.exe`,请把它所在目录加入系统 `PATH`,然后重新打开终端验证:
@@ -130,6 +130,7 @@ cloudflared version
130130
echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared noble main' | sudo tee /etc/apt/sources.list.d/cloudflared.list
131131
sudo apt-get update
132132
sudo apt-get install cloudflared
133+
cloudflared version
133134
```
134135

135136
### RHEL / CentOS / Rocky Linux / AlmaLinux / Fedora / Amazon Linux
@@ -209,7 +210,7 @@ cloudflared version
209210
> [!TIP]
210211
> SublinkPro 不需要你运行 `cloudflared service install`。你只需要安装 `cloudflared` 命令,然后把 Cloudflare 页面里安装命令最后一段 token 粘贴到 SublinkPro 页面。SublinkPro 会托管 `cloudflared` 进程的启动和停止。
211212
212-
官方下载页:[Cloudflare Downloads](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/)
213+
官方下载页:[Cloudflare Downloads](https://developers.cloudflare.com/tunnel/downloads/)
213214

214215
---
215216

services/cloudflared/cloudflared.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type Config struct {
3434
type Status struct {
3535
Installed bool `json:"installed"`
3636
Path string `json:"path"`
37+
Version string `json:"version"`
3738
Running bool `json:"running"`
3839
Enabled bool `json:"enabled"`
3940
HasToken bool `json:"hasToken"`
@@ -121,10 +122,15 @@ func AutoStart() {
121122
// Status 返回当前 cloudflared 状态。
122123
func (m *Manager) Status() Status {
123124
path, installed := lookupCloudflared()
125+
version := ""
126+
if installed {
127+
version = cloudflaredVersion(path)
128+
}
124129
config, err := LoadConfig()
125130
status := Status{
126131
Installed: installed,
127132
Path: path,
133+
Version: version,
128134
CommandLabel: "cloudflared tunnel --no-autoupdate run",
129135
}
130136
if err == nil {
@@ -362,6 +368,31 @@ func lookupCloudflared() (string, bool) {
362368
return path, true
363369
}
364370

371+
func cloudflaredVersion(path string) string {
372+
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
373+
defer cancel()
374+
375+
output, err := exec.CommandContext(ctx, path, "version").CombinedOutput()
376+
if err != nil {
377+
return ""
378+
}
379+
return parseVersionOutput(string(output))
380+
}
381+
382+
func parseVersionOutput(output string) string {
383+
line := strings.TrimSpace(output)
384+
if idx := strings.IndexAny(line, "\r\n"); idx >= 0 {
385+
line = strings.TrimSpace(line[:idx])
386+
}
387+
fields := strings.Fields(line)
388+
for i, field := range fields {
389+
if strings.EqualFold(field, "version") && i+1 < len(fields) {
390+
return fields[i+1]
391+
}
392+
}
393+
return line
394+
}
395+
365396
func settingValue(key string) string {
366397
value, _ := models.GetSetting(key)
367398
return strings.TrimSpace(value)

services/cloudflared/cloudflared_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,23 @@ func TestRedactAssignment(t *testing.T) {
5252
t.Fatalf("redacted message = %q, want %q", got, want)
5353
}
5454
}
55+
56+
func TestParseVersionOutput(t *testing.T) {
57+
tests := []struct {
58+
name string
59+
output string
60+
want string
61+
}{
62+
{name: "standard output", output: "cloudflared version 2026.5.0 (built 2026-05-01)\n", want: "2026.5.0"},
63+
{name: "full version line fallback", output: "cloudflared dev-build\nextra", want: "cloudflared dev-build"},
64+
{name: "empty", output: " ", want: ""},
65+
}
66+
67+
for _, tt := range tests {
68+
t.Run(tt.name, func(t *testing.T) {
69+
if got := parseVersionOutput(tt.output); got != tt.want {
70+
t.Fatalf("parseVersionOutput() = %q, want %q", got, tt.want)
71+
}
72+
})
73+
}
74+
}

webs/src/views/settings/components/CloudflareTunnelSettings.jsx

Lines changed: 25 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)