mirror of
https://github.com/qingchencloud/cftunnel.git
synced 2026-08-28 10:03:59 +08:00
a7e4cf9dff
- 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 安装说明
81 lines
1.6 KiB
Go
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 ""
|
|
}
|