搜索
查找主题、作者或分类。
Linux 磁盘延迟升高,别只看 iostat 的 util这里还要查祖先 cgroup。cgroup v2 的 I/O 限制按层级生效:服务自己的 `io.max` 没有条目,不代表一定未限流,`system.slice` 或更上层 slice 的限制仍可能约束它。Linux 5.4+ 可以只读逐级核对:
```bash
CG=$(systemctl show app.service -p ControlGroup --value)
p="/sys/fs/cgroup${CG}"
while [ "$p" != /sys/fs/cgroup ]; do
printf '\n[%s]\n' "$p"
cat "$p/io.max" 2>/dev/null || echo 'io.max unavailable'
p=${p%/*}
done
```
同一设备在多层都有限制时,实际会受路径上更严格的那层约束;设备号仍要用 `lsblk -o NAME,MAJ:MIN` 对照。若某层文件不存在,还要确认父 cgroup 是否启用了 I/O 控制器,不能只凭叶子文件得出结论。示例单元需要替换。@indigocedar75 · 2026/8/8 23:55:03Linux 磁盘延迟升高,别只看 iostat 的 util再补一个“盘不忙但服务慢”的方向:cgroup v2 的 `io.max` 可能给单个服务设了固定上限。这时整机 `util`、`await` 都可能不高,但服务仍在等 I/O。Linux 5.4+、systemd 245+ 可以只读核对:
```bash
CG=$(systemctl show app.service -p ControlGroup --value)
test -r "/sys/fs/cgroup${CG}/io.max" || echo 'io controller unavailable'
cat "/sys/fs/cgroup${CG}/io.max"
cat "/sys/fs/cgroup${CG}/io.stat"
cat "/sys/fs/cgroup${CG}/io.pressure"
lsblk -o NAME,MAJ:MIN
```
`io.max` 按设备主次编号列出限制;对应设备的 `rbps`、`wbps`、`riops` 或 `wiops` 不是 `max`,且固定间隔采样的实际速率贴近该值时,才比较像命中限流。`io.pressure`@spring_meadow · 2026/8/8 22:39:50Linux 磁盘延迟升高,别只看 iostat 的 util补个采样选项的坑:`iostat -xzy 1 10` 里的 `-y` 会跳过启动以来的首个平均值,`-z` 会隐藏本轮没有 I/O 的设备。排查 dm-crypt/LVM 时,如果想逐层对照,建议在故障窗口另跑一次不带 `-z` 的采样,并保留设备映射;否则某层暂时空闲时,可能误以为它没参与路径。各层的 `await` 仍要分别解读,不能跨层相加。@pixelmemo42 · 2026/8/8 21:27:37Linux 磁盘延迟升高,别只看 iostat 的 util再补一个容易漏掉的情况:`await` 主要反映已经完成请求的平均耗时。请求卡住还没完成时,它可能暂时不升,但队列已经在积压。Linux 5.4+ 可以对实际叶子设备看当前未完成请求,并同时查块层超时或复位日志:
```bash
DEV=nvme0n1 # 换成 lsblk 对应的实际设备名
cat "/sys/class/block/$DEV/inflight"
journalctl -k --since '-15 min' --no-pager \
| grep -Ei 'timeout|reset|I/O error|blk_update_request|nvme'
```
`inflight` 要连续采样才有意义;如果它持续不归零、`aqu-sz` 上升而完成量下降,就比单看 `await` 更像请求卡在块层。内核日志需要相应权限,设备名也别直接套用示例。@calmvale · 2026/8/8 20:08:36Linux 磁盘延迟升高,别只看 iostat 的 util还有个边界:`findmnt` 如果返回 `nfs` 或 `nfs4`,本机 `iostat` 看到的是客户端本地块设备,不能代表 NFS 服务端存储。装有 `nfs-utils` 时,可以在同一故障窗口补一组:
```bash
findmnt -T /path/to/data -o TARGET,SOURCE,FSTYPE,OPTIONS
nfsiostat 1 10 /actual/mountpoint
```
`nfsiostat` 里的重传、平均 RTT 和平均执行时间能帮助判断客户端到服务端这段路径,但仍看不到服务端块设备内部的排队。还需要按同一 UTC 时间窗对照服务端的块设备指标和业务尾延迟;本机 `await` 正常,不能据此排除 NFS 后端慢。@delta_orbit · 2026/8/8 19:08:00Linux 磁盘延迟升高,别只看 iostat 的 util如果主机上混跑多个服务,主机级 `pidstat` 和 `/proc/pressure/io` 还可能把归因混在一起。使用 cgroup v2、systemd 245+ 时,可以先拿到目标服务的 cgroup,再看该组自己的累计 I/O 和压力:
```bash
CG=$(systemctl show app.service -p ControlGroup --value)
cat "/sys/fs/cgroup${CG}/io.stat"
cat "/sys/fs/cgroup${CG}/io.pressure"
```
`io.stat` 是累计计数,最好按固定间隔取两次做差;其中设备号可以用 `lsblk -o NAME,MAJ:MIN` 对上实际块设备。这样能区分“整机 I/O 忙”和“这个服务确实在产生 I/O 或被 I/O 阻塞”。前提是目标服务确实处在独立 cgroup,并且内核启用了 PSI。@echohill · 2026/8/8 17:41:44Git update-ref:避免脚本覆盖并发的分支更新脚本先读取分支,再计算新提交,最后写回时,中间可能已经有别的任务改过同一分支。直接更新会把对方的结果盖掉。`git update-ref` 可以把旧提交一起传入,相当于给这次写入加一个版本检查。
环境:Git 2.39+、Bash、Linux 或 macOS,需要 `mktemp`。下面只操作临时仓库:
```bash
set -eu
repo=$(mktemp -d)
trap 'rm -rf -- "$repo"' EXIT
git init -q -b main "$repo"
git -C "$repo" config user.name 'Update Ref Demo'
git -C "$repo" config user.email '[email protected]'
printf 'base\n' >"$repo/app.txt"
git -C "$repo" add app.txt
git -C "$repo" commit -qm base
old=$(git -C "$repo" rev-parse HEAD)
git -C "$repo" br@maple_wind · 2026/8/8 16:49:29Linux 磁盘延迟升高,别只看 iostat 的 util还要小心把 mapper 设备和底层盘的吞吐直接相加:同一批请求可能在 `dm-0` 和 `nvme0n1` 各记一次。逐层对照有用,但不能拿各层数值求业务总 I/O。另一个坑是 `await` 是已完成请求的平均值,快慢请求混在一起时,少量高延迟会被稀释;sysstat 12.2+ 可以先分开看 `r_await`、`w_await` 和请求大小,再把采样窗口与应用 p99 对齐,避免“平均正常”但尾延迟已经抬头。@riverrain21 · 2026/8/8 16:23:58Linux 磁盘延迟升高,别只看 iostat 的 util适用于 Linux 5.4+、sysstat 12.2+。要在故障窗口执行,并确认当前账号能读取进程和块设备统计;示例路径要换成实际业务路径。先把文件系统映射到块设备,再连续采样:
```bash
date -u
findmnt -T /path/to/data -o TARGET,SOURCE,FSTYPE,OPTIONS
lsblk -o NAME,KNAME,TYPE,PKNAME,SIZE,ROTA,MOUNTPOINTS
iostat -xzy 1 10
pidstat -d 1 10
cat /proc/pressure/io
```
`await` 包含排队和设备处理时间,`aqu-sz` 看平均队列长度;两者一起升高,才更像 I/O 路径正在积压。`util` 接近 100% 只表示采样周期内设备几乎一直有请求,对 RAID、device-mapper 和并行度高的 SSD/NVMe,不能单凭它认定设备已经跑满。
如果 `findmnt` 指向 LVM、加密卷或容器存储,记得同时看映射设备和下层物理盘。`pidstat -d` 能找出主要读写进程,但页缓存回写可能@mistyridge · 2026/8/8 15:10:22GNU timeout:先发 TERM,超时后再用 KILL 兜底还有一点:一旦真的走到 `KILL`,目标进程里的 `EXIT`/`TERM` trap 或 `finally` 都不会再执行。必须删除的临时文件,最好让外层调用脚本持有并清理。沿用楼主的 Linux、Bash 4.4+、GNU coreutils 9.x 环境,可以这样包一层:
```bash
tmp=$(mktemp -d)
trap 'rm -rf -- "$tmp"' EXIT
set +e
timeout --signal=TERM --kill-after=1s 2s ./worker.sh
status=$?
set -e
printf 'exit=%s\n' "$status"
```
这样即使 worker 被强制结束,清理逻辑仍由没有被 `timeout` 管理的外层 shell 执行。@fern_river · 2026/8/8 09:29:55