按每台机器实测推导的 TCP 调优工具. 不套用固定参数, 实测 BDP 与限速器拐点.
本脚本由 kylin010 编写和维护.
bash <(curl -fsSL https://raw.githubusercontent.com/Kylin010/tcpfit/main/tcpfit.sh)跑完直接出菜单, 选 1 全自动. 脚本会装到 /usr/local/bin/tcpfit, 以后敲 tcpfit 即可.
| 用法 | 命令 |
|---|---|
| 一键跑 | bash <(curl -fsSL .../main/tcpfit.sh) |
| 装好后 | tcpfit |
| 子命令 | tcpfit tune --role proxy --bw 500 |
菜单需要终端. 远程执行用 ssh -t <主机> tcpfit, 脚本里用子命令.
1. 一键调优 Auto-tune (recommended) ~10 min
2. 基础调优 Base tuning only ~1 min
3. 拐点测试 Policer sweep ~8 min
4. 加 swap Add swap (low-memory box)
────────────────────────────────────────────
5. 查看状态 Status
6. 端口验证 Verify port capability ~1 min
7. 回滚改动 Rollback all changes
8. 检查更新 Check for updates
9. 调优存档 Tuning archives
u. 卸载 tcpfit
脚本不会自动更新. 装好之后跑的一直是装的那一版, 想升级用菜单 8 或 tcpfit update ——
它只检查, 发现新版本会问你要不要更新.
一键调优只问三个问题: 带宽、测速对端、机器用途. 确认之后跑到底不再打断.
带宽那一问支持四种输入:
| 输入 | 行为 |
|---|---|
| 数字 | 按该带宽推导缓冲区, 然后实测拐点 |
| 回车 | 现场实测带宽, 然后实测拐点; 预计流量超过 50 GB 先问 |
m |
直接填限速值, 跳过拐点扫描 |
0 |
不做整形 |
tcpfit detect # 机器画像
tcpfit probe --peer <近处iperf3服务器> # 探测可用带宽
tcpfit tune --role proxy --bw 500 # 基础调优
tcpfit tune --role proxy --bw 500 --save 换机房前 # 调优并给存档命名
tcpfit sweep --peer <近处iperf3服务器> --nominal 500 # 扫拐点, 加 --yes 跳过流量确认
tcpfit shape --rate 510 # 应用整形
tcpfit shape --off # 移除整形, 保留基础调优
tcpfit harden --swap 2G # 加 swap
tcpfit verify --peer <近处iperf3服务器> # 测速验证
tcpfit status # 当前配置
tcpfit rollback # 回滚全部改动
tcpfit update # 检查更新
tcpfit archive list # 列出存档
tcpfit archive save "晚间配置" # 保存当前状态
tcpfit archive restore 0010 # 恢复第 10 份存档
tcpfit archive rename 0010 "备用配置" # 存档改名
tcpfit archive show 0010 # 查看某份存档的内容
tcpfit archive delete 0010 # 删除指定存档(别名 rm)
tcpfit uninstall --keep-archives # 卸载,保留存档和快照家宽 PPPoE、以及任何默认路由长这样的机器:
default dev ppp0 scope link # 点对点, 没有 via
0.5.8 起支持. 这类机器每次重拨都是新接口, qdisc 和路由窗口会跟着消失,
所以 tcpfit 会往 /etc/ppp/ip-up.d/50-tcpfit 放一个钩子, 让整形和 initcwnd
在拨通后自动回来. 钩子只对调优时那块网卡生效, 不会碰机器上别的 ppp 链路.
没有 /etc/ppp/ip-up.d 的机器不受影响, 不会被创建任何东西.
多机编排还没在真实环境验证过, 暂时不建议使用. 下面的用法仅供参考.
cp inventory/servers.example.yml inventory/servers.yml
chmod 600 inventory/servers.yml
vi inventory/servers.yml
python3 orchestrator/fleet.py detect
python3 orchestrator/fleet.py tune
python3 orchestrator/fleet.py sweep
python3 orchestrator/fleet.py shape --auto
python3 orchestrator/fleet.py verify选项: --only 机器名 --tag 标签 -j 并发数 --dry-run.
临时执行任意命令: fleet.py run -- uptime.
| 类别 | 参数 |
|---|---|
| 拥塞控制 | tcp_congestion_control=bbr + default_qdisc=fq |
| 缓冲区 | tcp_rmem / tcp_wmem / rmem_max / wmem_max / tcp_mem |
| 窗口 | tcp_window_scaling / tcp_moderate_rcvbuf / tcp_adv_win_scale |
| 队列 | netdev_max_backlog / netdev_budget / somaxconn 等 |
| 连接 | tcp_tw_reuse / tcp_fin_timeout / ip_local_port_range 等 |
| 起步 | tcp_slow_start_after_idle=0 / initcwnd 32 |
| 出向整形 | HTB 全局上限 + fq 叶子 pacing |
基础调优设 30 个 sysctl 参数, 加 swap 时再设 vm.swappiness. 缓冲区和整形值按每台机器实测推导, 不是固定值.
先不限速跑一次, 看有没有东西在打你:
| 结果 | 动作 |
|---|---|
| 丢包低 | 没有限速器, 不整形 |
| 丢包高 | 有限速器, 从实测吞吐往上扫找拐点 |
| 吞吐 > 10000 Mbit | 超出扫描上限, 不扫(可用 --cap 调整) |
扫描前按实测速率估流量. 超过 50 GB, 或明显超过开始前给你的预估时先问, 默认不扫.
拐点在"不限速吞吐"的上面 —— 打穿限速器会让吞吐掉下来, 所以往上找.
tcpfit rollback # 按快照逐项写回, 不是恢复默认
tcpfit rollback --purge-swap # 同时删掉 harden 建的 /swapfile
tcpfit shape --off # 只去掉整形首次改动前自动存快照到 /var/lib/tcpfit/pre-tune.snapshot, 记录全部 33 项参数的原始值.
0.5.7 起,原始快照同时保留为 0000 出厂状态,不可改名或单独删除。
archive restore 0000 与 rollback 使用同一回滚流程;“出厂状态”指首次调优前的快照。
普通存档位于 /var/lib/tcpfit/archives/。基础调优后自动保存,一键调优则在最终整形、验证完成后保存。
序号可以输入 10 或 0010;名字含空格时请加引号。
恢复普通存档会同步 sysctl 启动配置、整形服务和 initcwnd 持久化。路由只套用存档里的窗口值,不写回旧网关。 恢复失败可能已经应用部分设置,请按提示检查后重试。
tcpfit uninstall 默认删除存档;需要保留则加 --keep-archives。
若回滚失败,卸载会停止并保留存档。卸载不删除 swap、iperf3 或 ping。
swap 默认不动 —— 删掉正在用的 swap 可能让机器立刻 OOM, 要一并撤销得显式加 --purge-swap.
改动只落在这些文件, 不碰 /etc/sysctl.conf:
/etc/sysctl.d/99-tcpfit.conf
/etc/systemd/system/tcpfit-qdisc.service
/usr/local/sbin/tcpfit-qdisc.sh
/etc/modules-load.d/tcpfit-bbr.conf
/var/lib/tcpfit/
initcwnd 的开机持久化按机器只用其中一种:
/etc/ppp/ip-up.d/50-tcpfit
/etc/systemd/network/<网卡配置名>.network.d/50-tcpfit-initcwnd.conf
/etc/networkd-dispatcher/routable.d/50-tcpfit-initcwnd
/etc/systemd/system/tcpfit-initcwnd.service
/usr/local/sbin/tcpfit-initcwnd.sh
initcwnd 设在默认路由上, 网卡重连、网络服务重启都会把它冲掉. tcpfit 按机器选一种:
| 机器 | 做法 |
|---|---|
| PPP 拨号 | pppd 拨通后的钩子 |
| networkd 管的 DHCP 网卡, systemd 255+(Ubuntu 24.04 / Debian 13) | 写进 networkd 配置 |
| networkd 管的其他网卡(Ubuntu 22.04 等) | networkd-dispatcher 钩子 |
| 其他有 systemd 的机器 | 开机执行一次的单元 |
写进 networkd 配置时不重载网络, networkd 下次重启或开机后才完全生效. systemd 255 以下的机器, 网络服务重启后要等网卡重连或开机才补回.
用了 harden --swap 还会创建 /swapfile 并往 /etc/fstab 加一行 —— 这两个 rollback 默认不动,
要一并撤销加 --purge-swap. 缺 iperf3 时经你确认后会用包管理器安装它.
- 瓶颈在国际链路而非端口时, 整形不会带来提升, 但输出看起来一切正常
- 扫满区间仍没找到拐点时不会整形, 结果页会说明原因; 已知限速值的话用
m手动指定 - 需要 Linux + systemd + iproute2. OpenVZ/LXC 上
tc和initcwnd可能受限 sweep需要一台近处的 iperf3 对端
老机器上的产物文件名还是 nettune-*, 新版本会自动检测并搬迁, 快照和 rollback 都保留. 直接跑新版即可.