Skip to content

Commit cdd1619

Browse files
feat: 零配置开箱(自动生成演示配置探测 baidu)+ 多平台打包发布流水线
1 parent 4950113 commit cdd1619

4 files changed

Lines changed: 94 additions & 15 deletions

File tree

.github/workflows/release.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: release
2+
on:
3+
push:
4+
tags: ['v*']
5+
permissions:
6+
contents: write
7+
jobs:
8+
build:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v4
12+
- uses: actions/setup-go@v5
13+
with:
14+
go-version: '1.22'
15+
- name: test
16+
run: go test ./...
17+
- name: build & package
18+
run: |
19+
set -e
20+
for target in linux/amd64 linux/arm64 darwin/amd64 darwin/arm64; do
21+
GOOS=${target%/*}; GOARCH=${target#*/}
22+
dir="pingping-${GITHUB_REF_NAME}-${GOOS}-${GOARCH}"
23+
mkdir -p "$dir"
24+
CGO_ENABLED=0 GOOS=$GOOS GOARCH=$GOARCH \
25+
go build -trimpath -ldflags "-s -w -X main.version=${GITHUB_REF_NAME}" \
26+
-o "$dir/pingping" .
27+
cp README.md LICENSE config.example.jsonc "$dir/"
28+
tar czf "$dir.tar.gz" "$dir"
29+
done
30+
sha256sum pingping-*.tar.gz > SHA256SUMS
31+
- uses: softprops/action-gh-release@v2
32+
with:
33+
files: |
34+
pingping-*.tar.gz
35+
SHA256SUMS
36+
body: |
37+
## 开箱即用
38+
```bash
39+
tar xzf pingping-*.tar.gz && cd pingping-*/
40+
./pingping
41+
```
42+
首次运行自动生成演示配置(探测 www.baidu.com),打开 http://localhost:8517 即见烟雾图。
43+
Linux 静态编译,所有发行版通用;非 root 运行若提示无法创建 ICMP socket,执行
44+
`sudo setcap cap_net_raw+ep ./pingping` 或放开 `net.ipv4.ping_group_range`。

README.md

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,16 @@ A single-binary network link quality oscilloscope — modern Smokeping semantics
2525

2626
## 快速开始
2727

28+
[Releases](https://github.com/githubflyideas/pingping/releases) 下载对应平台的包(Linux 静态编译,所有发行版通用;另有 macOS 双架构):
29+
2830
```bash
29-
# 1. 构建(或从 Releases 下载)
30-
go build -o pingping .
31+
tar xzf pingping-v*-linux-amd64.tar.gz && cd pingping-*/
32+
./pingping
33+
```
3134

32-
# 2. 配置
33-
cp config.example.jsonc pingping.jsonc && vi pingping.jsonc # 填 targets 和飞书 webhook
35+
首次运行自动生成演示配置(探测 www.baidu.com),按提示打开 http://localhost:8517,几分钟后第一缕烟雾成形。之后编辑 `pingping.jsonc` 换成你自己的目标和飞书 webhook,重启生效。
3436

35-
# 3. 运行
36-
./pingping -c pingping.jsonc
37-
# 浏览器打开 http://<host>:8517 看烟雾图
38-
```
37+
也可以源码构建:`go build -o pingping .`(无任何第三方依赖)。
3938

4039
无 root 环境需要放开 unprivileged ICMP(多数发行版默认已放开):
4140

main.go

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,31 @@ import (
1414

1515
var version = "dev"
1616

17+
// demoConfig 是首次运行自动生成的演示配置。fast 档让第一屏的烟雾几分钟内成形。
18+
const demoConfig = `{
19+
// pingping 演示配置 —— 首次运行自动生成,按需修改后重启生效
20+
// 完整字段说明见仓库内 config.example.jsonc
21+
"listen": "0.0.0.0:8517",
22+
"targets": [
23+
{ "name": "演示 · 百度", "type": "icmp", "host": "www.baidu.com", "pace": "fast" }
24+
]
25+
// 飞书推送:去掉下面的注释,填入你的群机器人 webhook
26+
//,"webhooks": [
27+
// { "name": "运维群", "url": "https://open.feishu.cn/open-apis/bot/v2/hook/xxxx" }
28+
//]
29+
}
30+
`
31+
32+
// portOf 从监听地址提取给人看的端口后缀。
33+
func portOf(listen string) string {
34+
for i := len(listen) - 1; i >= 0; i-- {
35+
if listen[i] == ':' {
36+
return listen[i:]
37+
}
38+
}
39+
return ":8517"
40+
}
41+
1742
func main() {
1843
cfgPath := flag.String("c", "pingping.jsonc", "配置文件路径 (JSONC)")
1944
showVer := flag.Bool("version", false, "打印版本")
@@ -26,7 +51,17 @@ func main() {
2651

2752
cfg, err := LoadConfig(*cfgPath)
2853
if err != nil {
29-
log.Fatalf("配置加载失败: %v", err)
54+
// 零配置开箱:找不到配置文件时自动生成演示配置(探测 www.baidu.com),
55+
// 下载解压、执行、开浏览器,三十秒看到第一缕烟。
56+
if os.IsNotExist(err) {
57+
if werr := os.WriteFile(*cfgPath, []byte(demoConfig), 0o644); werr == nil {
58+
log.Printf("未找到配置文件,已生成演示配置 %s(探测 www.baidu.com),按需修改后重启生效", *cfgPath)
59+
cfg, err = LoadConfig(*cfgPath)
60+
}
61+
}
62+
if err != nil {
63+
log.Fatalf("配置加载失败: %v", err)
64+
}
3065
}
3166

3267
store, err := NewStore(cfg.DataDir, cfg.Targets)
@@ -53,6 +88,7 @@ func main() {
5388

5489
log.Printf("pingping %s 启动 · %d 个目标 · 监听 %s · 数据目录 %s",
5590
version, len(cfg.Targets), cfg.Listen, cfg.DataDir)
91+
log.Printf("➜ 打开浏览器访问 http://localhost%s 查看烟雾图", portOf(cfg.Listen))
5692

5793
sig := make(chan os.Signal, 1)
5894
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)

probe.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -140,14 +140,14 @@ func collect(fd int, raw bool, id int, nonce [4]byte, sendAt []time.Time, got []
140140
if remain <= 0 {
141141
return
142142
}
143-
tvUsec := remain.Microseconds()
144-
if tvUsec > 50000 {
145-
tvUsec = 50000 // 50ms 一跳,保证按时退出
143+
wait := remain
144+
if wait > 50*time.Millisecond {
145+
wait = 50 * time.Millisecond // 50ms 一跳,保证按时退出
146146
}
147-
if tvUsec < 1000 {
148-
tvUsec = 1000
147+
if wait < time.Millisecond {
148+
wait = time.Millisecond
149149
}
150-
tv := syscall.Timeval{Sec: 0, Usec: tvUsec}
150+
tv := syscall.NsecToTimeval(wait.Nanoseconds()) // 可移植:linux/darwin 的 Timeval 字段类型不同
151151
syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv)
152152
n, _, err := syscall.Recvfrom(fd, buf, 0)
153153
now := time.Now()

0 commit comments

Comments
 (0)