FreeBSD 中文社区 2025 第二季度问卷调查
FreeBSD 中文社区(CFC)
VitePress 镜像站QQ 群 787969044视频教程Ⅰ视频教程Ⅱ
  • FreeBSD 从入门到追忆
  • 中文期刊
  • 状态报告
  • 发行说明
  • 手册
  • 网络文章集锦
  • 笔记本支持报告
  • Port 开发者手册
  • 架构手册
  • 开发者手册
  • 中文 man 手册
  • 文章
  • 书籍
  • FreeBSD 中文期刊
  • 编辑日志
  • 2025-123 下游项目
    • FreeBSD 发布工程:新主管上任
    • GhostBSD:从易用到挣扎与重生
    • BSD Now 与将来
    • 字符设备驱动教程(第三部分)
    • 学会走路——连接 GPIO 系统
    • FreeBSD 中对 SYN 段的处理
    • FreeBSD 2024 年秋季峰会
  • 2024-1112 虚拟化
    • 字符设备驱动程序教程(第二部分)
    • 面向 Linux 和 Windows 用户的 bhyve
    • Xen 与 FreeBSD
    • Wifibox:一种嵌入式虚拟化无线路由器
    • 嵌入式 FreeBSD:Fabric——起步阶段
    • DGP:一种新的数据包控制方法
    • 会议报告:我在都柏林的 EuroBSDCon 体验
  • 2024-0910 内核开发
    • 字符设备驱动程序教程
    • VPP 移植到了 FreeBSD:基础用法
    • 利用 Kyua 的 Jail 功能提升 FreeBSD 测试套件的并行效率
    • FreeBSD 上的 Valgrind
    • 嵌入式 FreeBSD:探索 bhyve
    • TCP/IP 历险记:FreeBSD TCP 协议栈中的 Pacing
    • 实用软件:实现无纸化(Paperless)
  • 2024-0708 存储与文件系统
    • FreeBSD 中的 NVMe-oF
    • FreeBSD iSCSI 入门
    • 使用 ZFS 原生加密保护数据
    • 嵌入式 FreeBSD:打造自己的镜像
    • TCP LRO 简介
    • 基于 Samba 的时间机器备份
  • 2024-0506 配置管理对决
    • 基本系统中的 mfsBSD
    • rdist
    • Hashicorp Vault
    • 在 GitHub 上向 FreeBSD 提交 PR
    • 悼念 Mike Karels
    • 2024 年 5-6 月来信
    • 嵌入式 FreeBSD 面包板
    • TCP/IP 历险记:TCP BBLog
    • 实用软件:开发定制 Ansible 模块
  • 2024-0304 开发工作流与集成
    • FreeBSD 内核开发工作流程
    • FreeBSD 与 KDE 持续集成(CI)
    • 更现代的内核调试工具
    • 从零开始的 ZFS 镜像及 makefs -t zfs
    • 提升 Git 使用体验
  • 2024-0102 网络(十周年)
    • FreeBSD 中的 RACK 栈和替代 TCP 栈
    • FreeBSD 14 中有关 TCP 的更新
    • if_ovpn 还是 OpenVPN
    • SR-IOV 已成为 FreeBSD 的重要功能
    • FreeBSD 接口 API(IfAPI)
    • BATMAN:更优的可移动热点网络方式
    • 配置自己的 VPN——基于 FreeBSD、Wireguard、IPv6 和广告拦截
    • 实用软件:使用 Zabbix 监控主机
  • 2023-1112 FreeBSD 14.0
    • LinuxBoot:从 Linux 启动 FreeBSD
    • FreeBSD 容器镜像
    • 现在用 Webhook 触发我
    • 新的 Ports 提交者:oel Bodenmann (jbo@freebsd.org)
  • 2023-0910 Port 与软件包
    • 回忆录:与 Warner Losh(@imp)的访谈
    • 在你自己的仓库中定制 Poudriere 源
    • Wazuh 和 MITRE Caldera 在 FreeBSD Jail 中的使用
    • PEP 517
    • CCCamp 2023 旅行报告
  • 2023-0708 容器与云
    • 在 Firecracker 上的 FreeBSD
    • 使用 pot 和 nomad 管理 Jail
    • 会议报告:C 与 BSD 正如拉丁语与我们——一位神学家的旅程
    • 抒怀之旅:与 Doug Rabson 的访谈
    • 基于 Jail 的广告拦截教程
    • 我们收到的来信
  • 2023-0506 FreeBSD 三十周年纪念特刊
    • CheriBSD 近十多年的历程
    • AArch64:成为 FreeBSD 新的一级架构
    • 岁月如梭:我个人的时间线
    • 安装 FreeBSD 1.0:回顾 30 年前
    • ZFS 是如何进入 FreeBSD 的呢?
    • 我不是来自约克郡的,我保证!
    • 回忆录:采访 David Greenman Lawrence
    • FreeBSD 和早期的 Unix 社区
    • 早期的 FreeBSD 移植
    • FreeBSD 30 周年:成功的秘诀
    • FreeBSD 在日本:回忆之旅与今日之实
  • 2023-0304 嵌入式
    • CheriBSD port 和软件包
    • 让我们来试试 ChatGPT
    • GPU 直通
  • 2023-0102 构建 FreEBSD Web 服务器
    • ZFS 的原子 I/O 与 PostgreSQL
    • 虚拟实验室——BSD 编程研讨会
    • ZFS 简介
    • 会议报告:落基山庆祝女性计算机科学家
    • 进行中的工作/征求反馈:数据包批处理
    • 基金会与 FreeBSD 桌面
  • 2022-1112 可观测性和衡量标准
    • 在 FreeBSD 的 DDB 内核调试器中编写自定义命令
    • DTrace:老式跟踪系统的新扩展
    • 基于证书的 Icinga 监控
    • 活动监控脚本(activitymonitor.sh)
    • 实用 IPv6(第四部分)
    • EuroBSDCon 会议报道
    • 实用 Port:Prometheus 的安装与配置
    • 书评:《用火解决问题:管理老化的计算机系统(并为现代系统保驾护航)》Kill It with Fire: Manage Aging Computer Systems (and Future Proof Modern Ones)
  • 2022-0910 安全性
    • CARP 简介
    • 重构内核加密服务框架
    • PAM 小窍门
    • SSH 小窍门
    • 实用 IPv6(第三部分)
    • 书评:Understanding Software Dynamics(深入理解软件性能——一种动态视角)—— Richard L. Sites 著
    • 访谈:保障 FreeBSD 安全性
    • MCH 2022 会议报告
  • 2022-0708 科研、系统与 FreeBSD
    • 在 FreeBSD 上构建 Loom 框架
    • 教授本科生 Unix 课程
    • FreeBSD 入门研讨会
    • 实用 IPv6(第二部分)
    • 在 2022 年及以后推广 FreeBSD
    • 进行中的工作/征求反馈:Socket 缓冲区
    • FreeBSD 开发者峰会报告
    • 支持 Electromagnetic Field 2022
  • 2022-0506 灾难恢复
    • 使用 FreeBSD 构建高弹性的私有云
    • LLDB 14 —— FreeBSD 新调试器
    • 实用 IPv6(第一部分)
    • 利用 netdump(4) 进行事后内核调试
    • 进行中的工作/征求反馈:FreeBSD 启动性能
    • 实用 Port:在 OpenZFS 上设置 NFSv4 文件服务器
  • 2022-0304 ARM64 是一级架构
    • FreeBSD/ARM64 上的数据科学
    • Pinebook Pro 上的 FreeBSD
    • 嵌入式控制器的 ACPI 支持
    • 进行中的工作/征求反馈:Lumina 桌面征集开发人员
    • 实用 Port:如何设置 Apple 时间机器
  • 2022-0102 软件与系统管理
    • 为 FreeBSD Ports 做贡献
    • 使用 Git 贡献到 FreeBSD Ports
    • CBSD:第一部分——生产环境
    • 将 OpenBSD 的 pf syncookie 代码移植到 FreeBSD 的 pf
    • 进行中的工作/征求反馈:mkjail
    • 《编程智慧:编程鬼才的经验和思考》(The Kollected Kode Vicious)书评
    • 会议报告:EuroBSDCon 2021 我的第一次 EuroBSDCon:一位新组织者的视角
  • 2021-1112 存储
    • 开放通道 SSD
    • 构建 FreeBSD 社区
    • 与完美操作系统同行 27 年
    • 进行中的工作/征求反馈:OccamBSD
    • 通过 iSCSI 导入 ZFS ZIL——不要在工作中这样做——就像我做的那样
  • 2021-0910 FreeBSD 开发
    • FreeBSD 代码审查与 git-arc
    • 如何为 FreeBSD 实现简单的 USB 驱动程序
    • 内核开发技巧
    • 程序员编程杂谈
  • 2021-0708 桌面/无线网
    • 通往 FreeBSD 桌面的直线路径
    • FreeBSD 13 中的人机接口设备 (HID) 支持
    • Panfrost 驱动程序
    • 用 Git 更新 FreeBSD
    • FreeBSD 的新面孔
    • 想给你的桌面加点佐料?
  • 2021-0506 安全
    • 七种提升新安装 FreeBSD 安全性的方法
    • copyinout 框架
    • 使用 TLS 改善 NFS 安全性
    • Capsicum 案例研究:Got
    • 对 Jail 进行安全扫描
  • 2021-0304 FreeBSD 13.0
    • 展望未来
    • FreeBSD 13.0 工具链
    • FreeBSD 13.0 中有新加载器吗?
    • TCP Cubic 准备起飞
    • OpenZFS 中的 Zstandard 压缩
    • 会议报告:FreeBSD 供应商峰会
    • Git 不够吗?
  • 2021-0102 案例研究
    • Tarsnap 的 FreeBSD 集群
    • BALLY WULFF
    • Netflix Open Connect
    • FreeBSD 的新面孔
    • 写作学者的 FreeBSD
    • 在世界之巅
  • 2020-1112 工作流/持续集成(CI)
    • FreeBSD Git 快速入门
    • 使用 syzkaller 进行内核 Fuzzing
    • Mastering Vim Quickly 书评
    • 线上会议实用技巧
    • 在控制台上进行网络监控
  • 2020-0910 贡献与入门
    • 采访:Warner Losh,第 2 部分
    • 代码审查
    • 撰写良好的提交消息
    • 如何在不是程序员的情况下做出贡献——成为 FreeBSD 译者
    • 如何成为文档提交者
    • 谷歌编程之夏
    • 为 FreeBSD 期刊撰写文章
    • 你为什么使用 FreeBSD
    • FreeBSD 的新面孔
  • 2020-0708 基准测试/调优
    • FreeBSD Friday
    • 采访:Warner Losh,第 1 部分
    • 构建和运行开源社区
    • 在 FreeBSD 上轻松搭建我的世界(Minecraft)服务器
    • FreeBSD 的新面孔
  • 2020-0506 网络性能
    • 内核中的 TLS 卸载
    • 访谈:Michael W Lucas
    • FreeBSD 桌面发行版
    • 使用 Poudriere 进行 Port 批量管理
    • FreeBSD 的新面孔
由 GitBook 提供支持
LogoLogo

FreeBSD 中文社区(CFC) 2025

在本页
  • top 如何估算 CPU 利用率?
  • 绘图
  • activitymonitor.sh
  • 一个小脚本
  • 基本网页
  • 一些 JavaScript
  • 这是个坏主意
在GitHub上编辑
导出为 PDF
  1. 2022-1112 可观测性和衡量标准

活动监控脚本(activitymonitor.sh)

上一页基于证书的 Icinga 监控下一页实用 IPv6(第四部分)

最后更新于1个月前

  • 原文链接:

  • 作者:TOM JONES

在今年的维也纳 EuroBSDCon 上,我讲述了我在 FreeBSD 和 Linux 上研究 QUIC 性能的工作。

我的测量方法的核心部分是网络传输期间 CPU 饱和,利用所有可用的 CPU 周期进行发送。我通过两种方式使用 CPU 饱和度,第一种是检测 CPU 是否是系统中的瓶颈。如果它不是瓶颈,那么我需要确认网络是否是瓶颈,而不是我没有尝试测量的其他组件。其次,待我控制了 CPU 饱和度并确保没有其他瓶颈在起作用,我就可以利用实际的 CPU 使用率来估算系统如果能够饱和网络卡的 UDP,发送速度能有多快。这非常有用,因为在所有测量中,我的网络接口在任何操作系统上都只能处理大约 6Gbit/s 的 UDP 流量。但这并不会饱和 CPU,CPU 的利用率大约为 70%。通过良好的 CPU 测量,我可以发明一个指标,乐观地预测如果网络接口不成为障碍,处理器能做到的速度。

我的 EuroBSDCon 演讲基于尚未发布的学术工作,似乎是一个好主意,通过一个经过深思熟虑的方法来查看网络测试期间的 CPU 性能。我的一些测试灵感来自 Fastly 的工作,Fastly 比较了 QUIC 和 TCP 的计算效率。尽管 Fastly 似乎建立了一个很好的测试平台,但我从他们的写作中能理解到的唯一机制是"凭眼睛看" top。

这对于发布结果或准确评估数千个测试结果来说并不足够好。如果仅仅看 top 不够,那我是否可以去了解 top 是如何查看的,并重新实现它呢?

top 如何估算 CPU 利用率?

top 可能是我们在想知道系统上发生了什么时,首先使用的工具。尽管它非常实用,top 其实是个非常简单的程序,它能够在屏幕上漂亮地显示信息,并且在机器上做了一些抽象层处理,使得代码更加可移植。CPU 利用率接口由 FreeBSD 提供,以两个 sysctl 节点的形式呈现:

$ sysctl hw.ncpu
4
$ sysctl kern.cp_time
kern.cp_time: 3832370 11408 3650627 44926 2061043745
$ sysctl kern.cp_times
kern.cp_times: 1080959 3035 954019 4354 515101995 1062132 2823 815176 1143
515263088 960320 3419 980090 37760 515162773 728956 2131 901334 1668 515510273

第一个节点 kern.cp_times 返回处理器的五个值,报告自启动以来在用户、优先级、系统、中断和空闲状态下花费的总时间。kern.cp_times 报告系统中每个处理器的这五个值。通过使用 kern.cp_times 和 hw.ncpu,我们可以细分这个列表。通过这两个 sysctl,我们可以获得自启动以来的系统总时间使用情况以及每个处理器的时间使用情况。自启动以来的使用情况对于理解机器的工作状态很有帮助,并且对于观察系统使用情况在短时间内如何变化也很有用。top 启动时显示系统的总时间分解,但待刷新(默认每秒刷新一次),它将显示这些字段在这一秒内的变化。

绘图

通过非常容易复现 top 的功能,我想知道是否可以定期抓取系统 CPU 使用率并将其绘制出来。我想我可以将这些绘图与吞吐量图并排显示,以展示在测试之间,主机几乎完全空闲,并且在测试运行时,单核 CPU 达到了饱和。

多年来,我在绘图时使用过不同的工具,但在这项工作中,我对定制工具感到厌倦,想要简洁些。我本可以使用最简单的方法——电子表格来绘制利用率,但我觉得能给我更多控制的东西会更好。在其他近期的工作中,我使用了基于 Web 的绘图工具。c3js 库提供了很好的交互式图表,但当数据点数量过多时(超过几万)会有些力不从心。考虑到我还要查看网络使用情况,数据量在一分钟的录制中会非常大。当我在考虑工具时,我想起了我为 Klara Systems 撰写的关于 inetd 的一篇文章。在写这篇文章时,我创建了一个自己的简单 inetd 服务,通过 shell 脚本实现了日期时间服务。难道我可以通过 inetd 从主机实时提供 CPU 使用信息吗?

activitymonitor.sh

这将我们引向 activitymonitor.sh,一个不按常规出牌的创作,违背了所有良好的规范,却能在网页浏览器中提供简单的图表。activitymonitor.sh 是个单一的 shell 脚本,包含三个部分: • 由 inetd 运行的脚本。 • 一个基本的 HTML 页面。 • 一些 JavaScript 用于更新实时页面。

inetd 是一个互联网服务启动程序。inetd 的历史和功能略微超出了本文的范围,但它用于在主机过于小而无法保持等待服务时按需启动应用程序。inetd 负责监听流量。当接收到连接或数据报(对于基于 UDP 的协议)时,inetd 启动内建处理程序或指定的程序。该程序从网络连接的标准输入读取。所有写入标准输出的内容将通过网络发送。这是一个非常简单的接口,但足够强大,可以实现纯文本的服务器协议。

一个小脚本

这个小脚本非常简单。它有两个主要组件,然后是附加的网页和 JavaScript 数据。首先,shell 脚本处理作为 inetd 的客户并解析 HTTP 头部。脚本的输入将是客户端在发出请求时发送的 HTTP 头部。

# 读取客户端头信息,我们只关心其中是否有 data.json。
h=""
while read -t 1 h
do
 log $h

 if echo $h | grep -q "data.json";
 then
 page="data.json"
 contenttype="application/json"
 else
 fi
done
echo "HTTP/1.0 200 OK"
echo "Content-Type: $contenttype"
echo

该脚本使用带有超时的 read 内建命令,这意味着脚本会消耗套接字上的所有输入,直到输入行之间出现 1 秒的间隔才会继续执行。这个 read 超时是限速机制。然后检查 HTTP 头部,查看是否正在请求数据 URL,如果不是,则返回基础的 HTML 页面。

脚本的 data url 路径是我们收集关于主机的有趣数据的地方。activitymonitor.sh 实现了 top 的大部分默认接口。为了做到这一点,它使用 FreeBSD 的基础命令收集所需的信息,并将其编码为 JSON 格式的 blob 返回给请求者。

if["$contenttype" == "text/html" ]
then
 indexstart=$((cat -n $0 | grep -e 'INDEX START'\
 | awk '{print $1}' | tail -n 1+1))
 sed -n"$indexstart"',$p' $0
elif["$contenttype" == "application/json" ]
then
 psout=$(ps -ax -o \
 "user,pid,%cpu,cpu %mem,vsz,rss,state,command"\
 --libxo json)
 vmstatout=$(vmstat –libxo json)
 netstatout=$(netstat -bi –libxo json)
 # kern.cp_time(s) gives us 5 numbers for the system:
 # user nice system interrupt idle
 # kern.cp_times gives us hw.ncpu entries for those 5 values
 totalcputime=$(sysctl -n kern.cp_time)
 percputime=$(sysctl -n kern.cp_times)
 ncpu=$(sysctl -n hw.ncpu)
 loadavg=$(sysctl -n vm.loadavg)
 lastpid=$(sysctl -n kern.lastpid)
 hostname=$(sysctl -n kern.hostname)
 system=$(printf ‘{"hostname":"%s",
 "cp_time":"%s", "cp_times":"%s", "ncpu":"%s",
 "loadavg":"%s", "lastpid":"%s"}’ "$hostname"
 "$totalcputime" "$percputime" "$ncpu"
 "$loadavg" "$lastpid")
 log $system
 physmem=$(sysctl -n hw.physmem)
 pagesize=$(sysctl -n hw.pagesize)
pagecount=$(sysctl -n vm.stats.vm.v_page_count)
 wirecount=$(sysctl -n vm.stats.vm.v_wire_count)
 activecout=$(sysctl -n vm.stats.vm.v_active_count)
 inactivecount=$(sysctl -n vm.stats.vm.v_inactive_count)
 cachecount=$(sysctl -n vm.stats.vm.v_cache_count)
 freecount=$(sysctl -n vm.stats.vm.v_free_count)
 memory=$(printf '{"physmem":"%s", "pagesize":"%s",
 "pagecount":"%s", "wirecount":"%s",
 "activecout":"%s", "inactivecount":"%s",
 "cachecount":"%s", "freecount":"%s" }’
 "$physmem" "$pagesize" "$pagecount"
 "$wirecount" "$activecout" "$inactivecount"
 "$cachecount" "$freecount")
 log $totalcputime
 # deliver the data json
 printf '{"system":%s, "memory":%s, "ps":%s,
 "vmstat":%s, "netstat":%s}'"$system"
 "$memory" "$psout" "$vmstatout" "$netstatout"
fi
exit # 不要继续进入网页

脚本收集的第一组信息来自于支持 libxo 的 FreeBSD 工具。Libxo 是 FreeBSD 的一个非常强大的特性——支持的基础工具可以本地输出 JSON 格式的数据。我们获取了 ps、vmstat 和 netstat 的输出。这使我们能够显示进程、虚拟内存系统信息以及网络统计信息,如接口速率。脚本中的第二组信息直接来自 sysctl 接口。目前,我们获取了 kern.cp_time(s)、CPU 数量、主机名、负载平均值和关于内存的基础统计信息。每个信息都必须通过 printf 手动打包成 JSON 对象。所有这些信息最终被构建成一个 JSON 对象,并在简单的响应头之后由脚本打印出来。inetd 然后将其反馈到连接的套接字,并作为 HTTP 响应的主体返回给客户端。

基本网页

activitymonitor.sh 脚本在内部嵌入了一个小型网页,当没有请求数据 URL 时,它会返回这个页面。页面包含一个头部、一些画布用于让 JavaScript 绘制图表,以及一个用于显示 top 风格进程列表的 pre 块。它还嵌入了让所有功能得以实现的 JavaScript。HTML 页面(和 JavaScript)被追加到脚本的末尾,并用 'INDEX START' 标签标记。activitymonitor.sh 在自身中搜索该标签,并将标签后的所有内容作为要交付的内容,使用 sed 进行切割。

一些 JavaScript

JavaScript 执行所有繁重的任务,包括从数据中解析信息并提供用户界面。它提取并处理 kern.cp_times 的值,并计算绘制图表所需的增量。除了绘制之外,主要的功能是从 activitymonitor.sh 的数据端请求数据。当基本网页加载完成后,脚本会启动一个任务来获取 /data.json 链接。当数据成功到达时,它会从 JSON 结果中提取所需字段,并合并新数据以计算应该显示的内容。最后,它再次调用 getdata 开始此任务。由于 activitymonitor.sh 中的读取超时,这将在结果之间有 1 秒的间隔发生。

这是个坏主意

activitymonitor.sh 是一个有趣的小项目,最终几乎成为了一个可用的工具。CPU 绘图帮助我理解了 FreeBSD 调度器如何非常积极地在 CPU 之间移动进程,并帮助我制定了一个测量策略来考虑这一点。尽管是一个有趣的项目,但它并不适合在现实世界中使用。相反,它展示了 FreeBSD 基本系统中工具的组合能力。除了 sysctl,我们使用的所有工具本地都输出 JSON 格式,并且可以被强大的用户界面语言使用。这种原生对 JSON 的支持使得消费标准工具的输出变得容易,并且让自动化可以与人类消费的数据一起进行。它赋予我们用机器可读的方式构建系统的能力,使用的是我们在屏幕上读取的相同数据。这是超越传统 UNIX 接口的一项小增强,但却是非常强大的。

可在此获取 activitymonitor.sh 。需要类似以下的 inetd 配置:

http-alt stream tcp nowait tj /home/tj/code/activitymonitor.sh
activitymonitor.sh

TOM JONES 希望基于 FreeBSD 的项目能够获得应有的关注。他住在苏格兰东北部,并提供 FreeBSD 咨询服务。

Tom Once Again, Does Stupid Things with a Computer: activitymonitor.sh