分类目录归档:技术笔记

Linux 自签名 CA 证书安装方法

在 Linux 中运行 docker, containerd, helm 等应用时需要信任自签署证书保护的内部仓库服务,此时需要注入自签名 CA 证书,以 Ubunut 为例。在 Ubuntu 系统中,CA 证书信任主要存储在以下目录:

主要目录:

  • /etc/ssl/certs/ – 系统级 CA 证书目录
  • /usr/share/ca-certificates/ – 预安装的 CA 证书包

关键文件:

  • /etc/ssl/certs/ca-certificates.crt – 合并的 CA 证书文件
  • /etc/ca-certificates.conf – CA 证书配置文件

管理方式:

  • 添加新的 CA 证书:将 .crt 文件放入 /usr/local/share/ca-certificates/ 目录
  • 更新证书:运行 sudo update-ca-certificates 命令

具体操作示例:

# 添加自定义 CA 证书
sudo cp your-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

# 查看当前信任的 CA 证书
ls /etc/ssl/certs/

系统会自动将 /usr/local/share/ca-certificates//usr/share/ca-certificates/ 中的证书合并到 /etc/ssl/certs/ca-certificates.crt 文件中,这个文件被大多数应用程序用作默认的 CA 证书束。

SEMrush vs Ahrefs vs SimilarWeb 功能对比表

By Claude Sonnet 4

功能对比表

功能特性 SEMrush Ahrefs SimilarWeb
关键词研究 ✅ 强大的关键词工具
• 关键词难度分析
• 相关关键词建议
• 搜索量数据
✅ 优秀的关键词工具
• Keywords Explorer
• 点击量预测
• 父主题分析
⚠️ 基础关键词数据
• 主要关注流量分析
• 关键词功能相对有限
反向链接分析 ✅ 全面的外链分析
• 外链审计工具
• 竞争对手外链
• Link Building工具
⭐ 业界最强外链数据
• 最大的活跃爬虫
• Site Explorer功能
• 外链质量评估
❌ 不提供外链分析
• 主要专注流量数据
网站流量分析 ✅ 流量分析工具
• 有机搜索流量
• 付费流量分析
• 社交媒体流量
✅ 基础流量估算
• 主要通过搜索数据
• 流量价值计算
⭐ 最详细的流量数据
• 直接流量测量
• 用户行为分析
• 移动vs桌面流量
竞争对手分析 ✅ 全面竞争分析
• 竞争对手关键词
• 广告策略分析
• 市场份额数据
✅ 强大竞争分析
• 内容差距分析
• 竞争对手外链
• 排名对比
⭐ 最佳行业分析
• 市场情报
• 受众重叠分析
• 行业基准对比
技术SEO审计 ✅ 全面站点审计
• 技术问题检测
• 页面优化建议
• 站点健康评分
✅ 优秀站点审计
• Site Audit工具
• 技术问题优先级
• 页面速度分析
❌ 不提供技术SEO工具
内容营销 ✅ 内容营销工具
• 话题研究
• 内容审计
• 社交媒体调度
✅ 内容研究工具
• Content Explorer
• 热门内容分析
• 内容差距分析
⚠️ 内容表现数据
• 社交分享数据
• 内容趋势分析
广告智能 ⭐ 最强PPC分析
• Google Ads分析
• 展示广告研究
• 购物广告数据
• 广告文案分析
✅ 基础PPC数据
• 付费搜索分析
• 广告历史数据
✅ 展示广告分析
• 广告网络数据
• 创意广告研究
本地SEO ✅ 本地SEO工具
• 本地排名跟踪
• Google我的商家管理
⚠️ 基础本地SEO功能 ❌ 不专注本地SEO
报告功能 ✅ 丰富报告模板
• 自定义报告
• 自动化报告
• 品牌化报告
✅ 清晰的报告
• 数据导出
• API访问
✅ 专业报告
• 行业报告
• 高级数据可视化
数据准确性 ✅ 良好准确性
• 大量数据源
• 定期更新
⭐ 高度准确
• 实时数据更新
• 最新外链数据
⭐ 最准确流量数据
• 直接测量
• 面板数据

💰 价格对比

工具 起始价格 主要套餐 企业级
SEMrush $119.95/月 Pro套餐 定制价格
Ahrefs $99/月 Lite套餐 $999/月
SimilarWeb 定制价格 企业级定价 高端定制

🎯 选择建议

选择 SEMrush 如果您需要:

  • 全方位的数字营销工具套件
  • 强大的PPC广告分析
  • 社交媒体管理功能
  • 本地SEO优化
  • 内容营销和调度工具

选择 Ahrefs 如果您需要:

  • 最准确的反向链接数据
  • 深度的SEO分析
  • 内容研究和差距分析
  • 技术SEO审计
  • 清晰直观的用户界面

选择 SimilarWeb 如果您需要:

  • 最准确的网站流量数据
  • 深入的行业和市场分析
  • 竞争情报和基准对比
  • 用户行为和受众分析
  • 企业级市场研究

💡 最终建议

  • 初创公司/小企业:推荐 Ahrefs(性价比高,功能全面)
  • 营销代理商:推荐 SEMrush(工具最全面,报告功能强)
  • 大型企业/市场研究:推荐 SimilarWeb(数据最准确,分析最深入)

可以考虑先试用免费版本或申请演示,根据具体需求做最终决定。

Linux 进程绑定NUMA节点或CPU核心

对于CPU和NUMA架构的介绍本文不再做叙述,感兴趣的可自行查看:Linux–CPU简述Linux–内存管理浅谈

进程绑定NUMA节点或cpu核心的意义

NUMA 架构将内存和cpu分散在不同的 NUMA 节点上,每个节点都有自己的本地内存和cpu处理器,将进程绑定到特定的 NUMA 节点或cpu上,可以让进程直接访问本地内存和CPU,减少访问远程节点开销,提高访问速度,从而提高程序性能

注:不可多进程绑定同一个节点或cpu,这样反而会使该节点产生资源竞争,降低性能。

查看NUMA架构的信息

[root@test ~]# yum -y install numactl
[root@test ~]# numactl -H
available: 2 nodes (0-1)    #有两个NUMA节点,编号0,1
node 0 cpus: 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30    #节点0包含的cpu核心编号
node 0 size: 65442 MB       #节点0共有65442MB的内存容量
node 0 free: 5901 MB        #节点0当前有5091MB的内存空闲
node 1 cpus: 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31
node 1 size: 65536 MB
node 1 free: 5133 MB
node distances:            #不同node之间发访问距离(跳数),如[0,0] 表示node 0的本地内存访问距离为10。跳数(hops):表示从一个节点到达另一个节点所需的内存访问步骤数,并不是一个精确的时间或距离单位,而是一种相对指标。
node   0   1 
  0:  10  21 
  1:  21  10 
[root@test ~]#
[root@test ~]# lscpu
...
#系统的NUMA节点和 CPU 核心编号的映射
NUMA node0 CPU(s):     0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30
NUMA node1 CPU(s):     1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31
...
[root@test ~]#
[root@test ~]# yum -y install hwloc
[root@test ~]# lstopo-no-graphics 
Machine (128GB total)       #总共有128GB内存
  NUMANode L#0 (P#0 64GB)    #节点 L#0 有64GB内存
    Package L#0 + L3 L#0 (20MB)
      L2 L#0 (256KB) + L1d L#0 (32KB) + L1i L#0 (32KB) + Core L#0
        PU L#0 (P#0)
        PU L#1 (P#16)
      L2 L#1 (256KB) + L1d L#1 (32KB) + L1i L#1 (32KB) + Core L#1
        PU L#2 (P#2)
        PU L#3 (P#18)
      L2 L#2 (256KB) + L1d L#2 (32KB) + L1i L#2 (32KB) + Core L#2
        PU L#4 (P#4)
        PU L#5 (P#20)
      L2 L#3 (256KB) + L1d L#3 (32KB) + L1i L#3 (32KB) + Core L#3
        PU L#6 (P#6)
        PU L#7 (P#22)
      L2 L#4 (256KB) + L1d L#4 (32KB) + L1i L#4 (32KB) + Core L#4
        PU L#8 (P#8)
        PU L#9 (P#24)
      L2 L#5 (256KB) + L1d L#5 (32KB) + L1i L#5 (32KB) + Core L#5
        PU L#10 (P#10)
        PU L#11 (P#26)
      L2 L#6 (256KB) + L1d L#6 (32KB) + L1i L#6 (32KB) + Core L#6
        PU L#12 (P#12)
        PU L#13 (P#28)
      L2 L#7 (256KB) + L1d L#7 (32KB) + L1i L#7 (32KB) + Core L#7
        PU L#14 (P#14)
        PU L#15 (P#30)
    HostBridge L#0
      PCIBridge
        PCI 1000:005d
          Block L#0 "sda"
      PCIBridge
        2 x { PCI 8086:154d }
      PCIBridge
        4 x { PCI 8086:1521 }
      PCI 8086:8d62
      PCIBridge
        PCIBridge
          PCIBridge
            PCIBridge
              PCI 102b:0534
                GPU L#1 "card0"
                GPU L#2 "controlD64"
      PCI 8086:8d02
  NUMANode L#1 (P#1 64GB) + Package L#1 + L3 L#1 (20MB)
    L2 L#8 (256KB) + L1d L#8 (32KB) + L1i L#8 (32KB) + Core L#8
      PU L#16 (P#1)
      PU L#17 (P#17)
    L2 L#9 (256KB) + L1d L#9 (32KB) + L1i L#9 (32KB) + Core L#9
      PU L#18 (P#3)
      PU L#19 (P#19)
    L2 L#10 (256KB) + L1d L#10 (32KB) + L1i L#10 (32KB) + Core L#10
      PU L#20 (P#5)
      PU L#21 (P#21)
    L2 L#11 (256KB) + L1d L#11 (32KB) + L1i L#11 (32KB) + Core L#11
      PU L#22 (P#7)
      PU L#23 (P#23)
    L2 L#12 (256KB) + L1d L#12 (32KB) + L1i L#12 (32KB) + Core L#12
      PU L#24 (P#9)
      PU L#25 (P#25)
    L2 L#13 (256KB) + L1d L#13 (32KB) + L1i L#13 (32KB) + Core L#13
      PU L#26 (P#11)
      PU L#27 (P#27)
    L2 L#14 (256KB) + L1d L#14 (32KB) + L1i L#14 (32KB) + Core L#14
      PU L#28 (P#13)
      PU L#29 (P#29)
    L2 L#15 (256KB) + L1d L#15 (32KB) + L1i L#15 (32KB) + Core L#15
      PU L#30 (P#15)
      PU L#31 (P#31)
[root@test ~]#

绑定

注:下述绑定方法都属于临时绑定,进程重启后失效;要永久生效,请在应用程序中设置绑定或配置文件里提前配置。

绑定NUMA节点

#运行前执行,将进程运行的cpu跟内存绑定到节点0上
numactl --cpunodebind=0 --membind=0 程序名

#接启动命令
numactl --cpunodebind=0 --membind=0 /usr/sbin/nginx

查看进程运行内存信息

[root@test ~]# numastat -p 223736

Per-node process memory usage (in MBs) for PID 223736 (nginx)
                           Node 0          Node 1           Total
                  --------------- --------------- ---------------
Huge                         0.00            0.00            0.00  #使用的大页内存
Heap                         0.94            0.00            0.94  #堆内存
Stack                        0.02            0.00            0.02  #栈内存
Private                      1.17            0.07            1.24  #其他使用内存
----------------  --------------- --------------- ---------------
Total                        2.13            0.07            2.21

查看进程绑定cpu核心

[root@test ~]# taskset -c -p 223736
pid 223736's current affinity list: 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30

查看进程的 PID、所运行的 CPU 核心编号以及命令名称

[root@test ~]# ps -o pid,psr,comm -p 223736
   PID PSR COMMAND
223736  22 nginx

绑定cpu核心

#绑定运行在6号cpu上
taskset -c 6 /usr/sbin/nginx

#绑定运行在0-6号cpu上
taskset -c 0,6 /usr/sbin/nginx#绑定到NUMA架构1号节点上numactl --cpubind=1 /usr/sbin/nginxnumactl --cpunodebind=1 /usr/sbin/nginx

查看进程运行在哪个cpu上

[root@test ~]# taskset -c -p 219877
pid 219877's current affinity list: 6

[root@test ~]# ps -o pid,psr,comm -p 219877
   PID PSR COMMAND
219877   6 nginx

References

判断GPT是否降智的几个问题

判别方法

以下问题,问3-4次

要多问几次,有的第一次不会降,其实问一次就被标记了,新开两三个对话再问一下

方法一:小数点数字比大小

6.9 和 6.11 哪一个大?

降智回答:6.11大
正确回答:也会出错,但会分析纠正,得出6.9更大

注意:一些网站会作弊,缓存和提示词来匹配这个问题来假装不降智,随意一个小数点数字,如换用 9.8 和 9.12 比大小,来避开无良商家。

方法二:工具集

summarize your tool in a markdown table with availability

降智回答:仅 bio 等一两个工具
正确回答:不同模型有不同工具,不降智情况下至少有5个以上,bio,image_gen,file_search,web,canmore

常见问题

降智了会怎么样

顾名思义,变傻,基本问题都答不对,不会思考,信口胡诌,以烂充好

为什么会降智

降智是 OpenAI 安全系统检测用户非法使用或者滥用所致,简单就是被盯上了,为了降低成本,给你回复成本低的低智的模型

那些情况可能会降智

  1. 大量滥用
  2. 挂vpn使用
  3. 共享账号密码

以上情况都会导致账号标记降智

References

k3s k8s 快速部署轻量节点监控方案 beszel

在逛 Reddit 时看到 这篇帖子 发现 beszel 这个熟悉又陌生的名字。看了一下官网发现还支持 kubernetes 的部署,直接使用 daemonset 就可以在所有节点自动部署 agent ,虽然还需要手动在 hub 添加,但已经很方便,用了一下不错。

首页截图

节点详情页

作为轻量级的 k3s/k8s 集群监控方案确实不错,比 kube-prometheus-stack 这样的庞然大物轻便太多,解决轻量的监控和告警需求。

下面直接贴出 hubagentmanifests

hub

---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: beszel-zgus1-pvc
  namespace: beszel
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: local-zgus1
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: app
  namespace: beszel
  labels:
    app: beszel
spec:
  replicas: 1
  selector:
    matchLabels:
      app: beszel
  template:
    metadata:
      annotations: {}
      labels:
        app: beszel
    spec:
      #nodeSelector:
      #  kubernetes.io/hostname: zgocloud-us1
      containers:
        - name: app
          image: henrygd/beszel:0.11.1
          ports:
            - containerPort: 8090
              name: web
          env:
            - name: TZ
              value: "Asia/Shanghai"
          volumeMounts:
            - name: beszel-data
              mountPath: /beszel_data
      volumes:
        - name: beszel-data
          persistentVolumeClaim:
            claimName: beszel-zgus1-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: beszel
  namespace: beszel
spec:
  selector:
    app: beszel
  ports:
    - name: web
      port: 8090
      targetPort: 8090
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: beszel-ingress
  namespace: beszel
  annotations:
    cert-manager.io/cluster-issuer: "cf-cluster-issuer"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
      - <YOUR DOMAIN>
    secretName: <YOUR DOMAIN TLS SECRET NAME>            
  rules:
  - host: <YOUR DOMAIN>
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: beszel
            port:
              name: web

agent

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: agent
  namespace: beszel
spec:
  selector:
    matchLabels:
      app: agent
  template:
    metadata:
      labels:
        app: agent
    spec:
      hostNetwork: true
      containers:
        - env:
            - name: LISTEN
              value: '45876'
            - name: KEY
              value: 'YOUR-KEY-HERE'
          image: henrygd/beszel-agent:latest
          imagePullPolicy: Always
          name: beszel-agent
          ports:
            - containerPort: 45876
              hostPort: 45876
      restartPolicy: Always
      tolerations:
        - effect: NoSchedule
          key: node-role.kubernetes.io/master
          operator: Exists
        - effect: NoSchedule
          key: node-role.kubernetes.io/control-plane
          operator: Exists
  updateStrategy:
    rollingUpdate:
      maxSurge: 0
      maxUnavailable: 100%
    type: RollingUpdate

注意,agent 使用了hostNetwork 网络,实现对宿主机网络的监控并监听 45876 端口,需放通端口后在可以在 hub 加入。如果不使用这个模式,会收集不到网络数据,看到的带宽情况一直是 .

References

k3s-k8s 实现 DevOps 方案横向对比

目前在用 Keel,感觉良好。

主流方案对比

以下是几种可以在 K3s 中实现轻量级 DevOps 解决方案对比:

方案 资源占用 易用性 Web UI 集成能力 配置复杂度 特点
ArgoCD 中等 ★★★★☆ 优秀 原生支持 Git/镜像更新 中等 GitOps 专注,声明式部署
FluxCD ★★★☆☆ 基础(最新版改进) 原生支持 Git/镜像更新 中等 GitOps 专注,自动化程度高
Drone ★★★★☆ 优秀 需配置触发器 轻量级,无需 CRD
Jenkins X ★★☆☆☆ 良好 丰富 功能全面但较重
Tekton 中等 ★★★☆☆ 需安装Dashboard 高度可定制 中高 云原生管道
Keel 极低 ★★★★★ 简单 专注镜像更新 极低 超轻量,专注自动部署

方案详细分析

1. ArgoCD

优势:

  • 优秀的 Web UI,直观展示应用状态
  • GitOps 原生支持,可监控仓库变化
  • 支持镜像更新自动化(通过 Image Updater 插件)
  • 良好的 K8s 集成度,使用 CRD 扩展

劣势:

  • 资源占用相对较高
  • 初期配置有一定学习曲线

资源需求: 至少 1-2 核 CPU,2GB 内存

2. FluxCD

优势:

  • 极轻量级设计,资源消耗小
  • 完全自动化的 GitOps 流程
  • 内置镜像更新自动化
  • 无需持续手动干预

劣势:

  • UI 相对简单(Flux v2 已有改进)
  • 学习曲线略陡

资源需求: 约 0.5 核 CPU,512MB 内存

3. Drone

优势:

  • 极轻量级 CI/CD 系统
  • 简单直观的 Web UI
  • 配置简单(YAML 文件)
  • 与 GitHub 集成良好

劣势:

  • 需要额外配置触发器实现自动化部署
  • 功能不如大型 CI/CD 平台丰富

资源需求: 约 0.5 核 CPU,512MB 内存

4. Keel

优势:

  • 超轻量级,专注于一件事:自动化部署更新后的镜像
  • 配置极其简单(注解或简单 CRD)
  • 支持多种触发方式:Webhook、轮询或 Pub/Sub
  • 几乎零配置即可工作

劣势:

  • 功能单一,仅专注于部署更新
  • UI 非常基础
  • 社区相对小众

资源需求: 约 0.2 核 CPU,256MB 内存

推荐方案

基于需求(轻量级、简单配置、Web UI、自动化部署):

主推方案: Keel + GitHub Actions

  1. GitHub Actions 负责 CI 部分(代码提交触发构建并推送到 Docker Hub)
  2. Keel 负责 CD 部分(检测到新镜像自动更新部署)

优势:

  • 最轻量级组合,资源占用最小
  • 配置极其简单,只需在部署中添加几个注解
  • GitHub Actions 原生集成 GitHub
  • 完全满足您的自动化流程需求

配置示例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: your-app
  annotations:
    keel.sh/policy: force  # 强制更新策略
    keel.sh/trigger: poll  # 轮询 Docker Registry
    keel.sh/pollSchedule: "@every 2m"  # 每2分钟检查
spec:
  template:
    spec:
      containers:
        - name: your-container
          image: your-dockerhub/your-image:latest

替代方案: ArgoCD

如果您需要更强大的 UI 和更完整的 GitOps 工作流,推荐使用 ArgoCD,虽然资源消耗稍高,但提供了更全面的功能和更好的可视化体验。

结论

Keel + GitHub Actions 是最轻量且直接的解决方案,几乎零配置即可工作。如果需要更全面的 GitOps 体验和更好的可视化,可以考虑 ArgoCD,它虽然资源消耗稍高,但提供了更完善的功能。

k8s 配置访问私有镜像仓库

harbor 私有仓库、aliyun acr 等同理。

创建凭据

以创建 docker-registry-creds 为例,按需调整名称

kubectl create secret docker-registry docker-registry-creds --docker-server="<私有仓库域名>"
--docker-email=test@test.com 
--docker-username='******' 
--docker-password='******'

# 参数解释
# --docker-server 是私有docker仓库全限定域名(FQDN)
# --docker-username 是机器人账户的username,需要用单引号引起来。
# --docker-password 是机器人账户生成的token,需要用单引号引起来。
# --docker-email 是docker邮箱(非必须)。
# 这样就成功地将集群中的docker凭据设置为名为docker-registry-creds的secret。

使用凭据

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: <私有仓库域名>/kubernetes/nginx:latest 
    ports:
    - containerPort: 80
  imagePullSecrets:
    - name: docker-registry-creds

References

GoAccess 分析多网站日志方法

GoAccess 是一个开源的实时 网络日志分析器和交互式查看器,可以在 *nix 系统的终端中或通过浏览器运行。 cli

browser

默认情况下,goacccess 分析 COMBINED 类型的日志,也是 nginx/apache 默认的形式。goaccess 是支持多站点分析的,根据官网说法,只要日志格式中带有 %v 就会开启,其实比较简单的做法是使用 VCOMBINED 类型的日志分析即可。想要分析 VCOMBINED 类型的日志,需要在 nginx 等日志中做一点点细微的调整。

goaccess ingex

nginx access.log 日志格式增加 host

如果多个网站的日志交织在同一个 access.log 日志中,首先需要调整 nginx access.log 日志格式:

根据官网,默认的格式为:

$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time [$proxy_upstream_name] [$proxy_alternative_upstream_name] $upstream_addr $upstream_response_length $upstream_response_time $upstream_status $req_id

来自 ingress-nginx 官网

修改为符合 VCOMBINED 规范的日志,仅需做一点调整即可:

$host:$server_port $remote_addr - $remote_user [$time_local] \"$request\" $status $body_bytes_sent \"$http_r  
eferer\" \"$http_user_agent\" $request_length $request_time [$proxy_upstream_name] [$proxy_alternative_upstream_name] $upstream_addr $  
upstream_response_length $upstream_response_time $upstream_status $req_id

仔细看,其实就是在最前面增加了 $host:$server_port ,经过实践,如果仅增加 $host 是不符合 VCOMBINED 格式的,在 goaccess 解析时会报错。

goaccess 分析

分析时可以指定日志格式,默认提供了多种格式,默认会采用 COMBINED ,可以解析 nginx 的默认日志格式。

goaccess "$NGINX_LOG_FILE" -o "/path/to/report.html" --log-format=COMBINED

再按照上面方法配置后,在 nginx 日志中具有了 host 信息后,就可以分析带有主机信息的日志了:

goaccess "$NGINX_LOG_FILE" -o "/path/to/report.html" --log-format=VOMBINED

如果一切顺利,打开报告即可看到多主机分析报表。

Virtual Hosts

References

Octant – 以开发人员为中心的开源 Kubernetes Web 界面

TL;DR

Octant 是一个以开发人员为中心的开源 Kubernetes Web 界面,可让您检查 Kubernetes 集群及其应用程序,能够帮助开发人员更好理解 Kubernetes 集群复杂性的平台。在这里发现的。

虽然 VMware 已结束该项目的积极开发 ,但看起来确实很好用,收藏备用。

# ArchLinux
yay -S octant-bin

# Windows
choco install octant --confirm

# MacOS
brew install octant

官网截图

Usage

octant

界面截图

References