Files
cftunnel/internal/daemon/quick.go
T
晴天 a7e4cf9dff feat: 全面支持 Windows 平台 + 修复 macOS tgz 解压 bug
- goreleaser 添加 windows 构建(zip 格式)
- cloudflared 下载支持 Windows + macOS tgz 解压
- 进程管理跨平台(process_unix/process_windows)
- 信号处理跨平台(signal_unix/signal_windows)
- Windows Service 实现(sc.exe)
- selfupdate 支持 Windows zip 格式
- PowerShell 安装脚本
- README 添加 Windows 安装说明
2026-02-23 01:20:18 +08:00

81 lines
1.6 KiB
Go

package daemon
import (
"bufio"
"fmt"
"io"
"os"
"os/exec"
"os/signal"
"strings"
)
// StartQuick 启动免域名模式(前台运行,Ctrl+C 退出)
func StartQuick(port string) error {
binPath, err := EnsureCloudflared()
if err != nil {
return err
}
if Running() {
return fmt.Errorf("cloudflared 已在运行,请先执行 cftunnel down")
}
cmd := exec.Command(binPath, "tunnel", "--url", "http://localhost:"+port)
// 捕获 stderr 提取随机域名
stderr, err := cmd.StderrPipe()
if err != nil {
return err
}
cmd.Stdout = os.Stdout
if err := cmd.Start(); err != nil {
return fmt.Errorf("启动 cloudflared 失败: %w", err)
}
// 后台读取 stderr,提取域名并转发输出
go scanForURL(stderr)
// 捕获 Ctrl+C 优雅退出
sig := make(chan os.Signal, 1)
signal.Notify(sig, os.Interrupt)
done := make(chan error, 1)
go func() { done <- cmd.Wait() }()
select {
case <-sig:
stopChildProcess(cmd)
<-done
case err := <-done:
if err != nil {
return fmt.Errorf("cloudflared 异常退出: %w", err)
}
}
return nil
}
func scanForURL(r io.Reader) {
scanner := bufio.NewScanner(r)
for scanner.Scan() {
line := scanner.Text()
// cloudflared 输出格式: ... https://xxx.trycloudflare.com ...
if strings.Contains(line, "trycloudflare.com") {
url := extractURL(line)
if url != "" {
fmt.Printf("\n✔ 隧道已启动: %s\n\n", url)
}
}
fmt.Fprintln(os.Stderr, line)
}
}
func extractURL(line string) string {
for _, part := range strings.Fields(line) {
if strings.Contains(part, "trycloudflare.com") && strings.HasPrefix(part, "http") {
return part
}
}
return ""
}