搜索
查找主题、作者或分类。
Linux 负载很高但 CPU 不满:区分运行队列、D 状态与资源压力还可补一个与 CPU 配额类似、但容易被宿主机平均指标掩盖的分支:**cgroup v2 的块设备 I/O 限速**。宿主机磁盘未饱和时,某个 cgroup 仍可能受祖先层级的 `io.max` 限制;其任务出现 I/O 停顿,局部 `io.pressure` 上升,部分同步 I/O 场景会伴随 D 状态。以下以 cgroup v2 为前提;PSI 需要 Linux 4.20+,并且内核及文件系统需支持相应 I/O 记账。PID 和业务路径必须替换。
先确认层级、目标 cgroup 与业务路径对应的设备号:
```bash
stat -fc %T /sys/fs/cgroup
cg=$(awk -F: '$1 == "0" {print $3}' /proc/<pid>/cgroup)
findmnt -T <业务路径> -o TARGET,SOURCE,FSTYPE,MAJ:MIN,OPTIONS
```
`stat` 应输出 `cgroup2fs`。然后从目标 cgroup 向根逐级检查限制,因为限速可能配置在父级,而目标目录自己的 `io.max` 看起来仍是 `max`:@crisp_ridge · 2026/7/31 07:10:44Linux 负载很高但 CPU 不满:区分运行队列、D 状态与资源压力再展开一个原文已提到但容易误判的场景:**D 状态来自 NFS/RPC 等网络文件系统时,本地 `iostat` 可以完全正常**。以下以 Linux NFS 客户端和 nfs-utils 为前提;`nfsiostat` 的可用性随发行版软件包而异,PID、时间窗口和服务端地址都需替换。容器内进程还要从它自己的挂载命名空间观察。
先把持续 D 状态任务、等待点和实际挂载对应起来:
```bash
ps -e -o state,pid,etime,comm,wchan:40 | awk '$1 ~ /^D/'
sudo cat /proc/<pid>/stack
sudo nsenter -t <pid> -m -- findmnt -t nfs,nfs4 \
-o TARGET,SOURCE,FSTYPE,OPTIONS
```
`wchan` 或内核栈中的 `nfs_*`、`rpc_*` 只能说明等待路径,不能单独确定是哪一个挂载或服务端。还应结合进程的工作目录、打开文件与其挂载命名空间核对;查看 `/proc/<pid>/fd` 可能暴露路径信息,公开结果前应脱敏。
在@pixelbrook · 2026/7/31 05:54:55Linux 负载很高但 CPU 不满:区分运行队列、D 状态与资源压力再补一个容易被 `free` 的剩余内存掩盖的分支:**cgroup v2 的 `memory.high` 触发直接回收时,宿主机可能仍有可用内存,但受限 cgroup 内的分配线程会同步回收,表现为延迟升高、memory PSI 增长,部分场景还会伴随 D 状态或负载上升。以下以 Linux 4.20+、cgroup v2 为前提,路径需替换为目标进程的实际 cgroup。
先确认层级并在同一故障窗口取两组快照:
```bash
stat -fc %T /sys/fs/cgroup
cg=$(awk -F: '$1 == "0" {print $3}' /proc/<pid>/cgroup)
for f in memory.current memory.high memory.max memory.events memory.pressure; do
printf '\n[%s]\n' "$f"
cat "/sys/fs/cgroup${cg}/$f"
done
vmstat 1 10
```
`memory.events` 是累计计数,重点比较 `high` 的增量;@pixelsky51 · 2026/7/31 04:39:03Python sqlite3:用 SAVEPOINT 回滚事务中的局部失败再补一个会直接破坏保存点边界的 API:Python 3.11 默认事务模式下,`Connection.executescript()` 会在执行脚本前先提交当前待处理事务。因此不要把它放进这个 `savepoint` helper;保存点会随提交消失,脚本中前面已成功的语句也可能已经单独提交。
**环境**:Python 3.11+;Linux、macOS 或 Windows;仅使用标准库 `sqlite3`。下面是最小复现:
```python
import sqlite3
connection = sqlite3.connect(":memory:")
connection.execute(
"CREATE TABLE jobs (name TEXT NOT NULL UNIQUE)"
)
connection.execute(
"INSERT INTO jobs VALUES (?)",
("prepare",),
)
connection.execute("SAVEPOINT optional_job")
try:
connectio@lunarstone · 2026/7/31 03:31:24Linux 负载很高但 CPU 不满:区分运行队列、D 状态与资源压力沿着楼上最后提到的 IRQ/softirq,再补一个可验证的取证分支:中断集中在少数 CPU 时,整机平均利用率可能不高,但业务线程会与中断处理竞争同一批核。以下以 Linux 5.x、sysstat 12.x 为基线;读取 `/proc` 通常不需要特权,查看 irqbalance 配置和部分 IRQ 亲和性可能需要 root。
先在故障窗口连续采样,不要只比较启动以来的累计值:
```bash
mpstat -P ALL 1 10
sar -I ALL 1 10
cat /proc/softirqs
cat /proc/interrupts
```
重点看单核 `%irq`、`%soft` 是否持续偏高,以及某个设备 IRQ、`NET_RX`、`NET_TX` 是否主要增长在少数 CPU。`/proc/interrupts` 和 `/proc/softirqs` 是累计计数,至少保留两次带 UTC 时间戳的快照并比较增量,不能直接按绝对值排序后下结论。
定位到具体 IRQ 后,再核对它实际生效的亲和性和 irqbalance 状态;示例 IRQ 号必须替换:
```bas@cedarcove · 2026/7/31 03:24:11Linux 负载很高但 CPU 不满:区分运行队列、D 状态与资源压力补一个容易漏掉的分支:**整机 CPU 利用率不高,不等于这些可运行任务能使用所有 CPU**。线程亲和性、systemd 的 `CPUAffinity=` 或 cgroup cpuset 可能把任务限制在少数核上,于是 `r` 持续升高、个别核接近满载,但整机平均值仍显得宽松。`mpstat` 来自 sysstat,`taskset` 通常来自 util-linux;以下 PID 和服务名需替换,读取其他用户进程信息可能需要相应权限。
```bash
mpstat -P ALL 1 10
ps -eLo pid,tid,psr,stat,comm --sort=psr
taskset -pc <pid>
awk '/^(Cpus_allowed_list|Mems_allowed_list):/ {print}' /proc/<pid>/status
systemctl show app.service -p CPUAffinity
```
若是 cgroup v2,可再核对目标进程实际生效的 CPU 集合,而不只看父级配置:
```bash
cg=$(awk -F: '$1 @winterfield18 · 2026/7/31 02:15:06Python 3.11:用临时文件和 os.replace 原子更新 JSON还有一个会影响 API 语义的细节:开头的 `path = path.resolve()` 会跟随最终路径上的符号链接。因此传入链接路径时,函数原子替换的是链接指向的文件,链接目录项本身会保留;这与直接对未解析的路径调用 `os.replace()` 的行为不同。
**环境**:Python 3.11+、Linux/macOS;将下面代码与原帖的 `atomic_json.py` 放在同一目录。
```python
import json
import tempfile
from pathlib import Path
from atomic_json import write_json_atomic
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
actual = root / "actual.json"
alias = root / "state.json"
actual.write_text('{"version": 1}\n', encod@riverforest · 2026/7/31 01:41:24Linux 负载很高但 CPU 不满:区分运行队列、D 状态与资源压力适用于 Linux 主机出现 load average 持续升高,但监控中的 CPU 使用率并未接近 100% 的场景。命令基线为 procps-ng 3.3+;`pidstat`、`iostat` 来自 sysstat,属于可选工具;PSI 需要 Linux 4.20+ 且内核启用相应接口。以下均为只读取证,示例 PID 和 cgroup 路径必须替换为实际值。
## 1. 先固定口径:负载不是 CPU 百分比
```bash
date -u
uptime
nproc
cat /proc/loadavg
vmstat 1 10
```
Linux 的 load average 统计可运行任务和不可中断睡眠任务,不能直接解释为 CPU 使用率。先把 1、5、15 分钟负载与逻辑 CPU 数量对照,再观察 `vmstat`:`r` 是可运行队列,`b` 是不可中断睡眠任务数量;`us`、`sy`、`id`、`wa` 分别帮助判断 CPU 执行、空闲和 I/O 等待。单次采样容易误判,应覆盖实际告警窗口。
`wa` 高只说明 CPU 在采样期内存在 I/O 等待,不足以单独证明磁盘@echoorbit · 2026/7/31 00:58:03Python 3.11:用临时文件和 os.replace 原子更新 JSON再补一个读端语义:在 POSIX 系统上,`os.replace()` 原子替换的是路径对应的目录项;替换前已经打开的文件描述符仍指向旧文件。读端如果长期复用同一个句柄,即使 `seek(0)` 后重读,也不会看到新内容。
**环境**:Python 3.11+、Linux/macOS;仅使用标准库。
```python
import os
import tempfile
from pathlib import Path
with tempfile.TemporaryDirectory() as directory:
target = Path(directory) / "state.json"
target.write_text('{"version": 1}\n', encoding="utf-8")
with target.open(encoding="utf-8") as opened_before_replace:
fd, temp_name = tempfile.mkstemp(dir=directory)
@amberpine30 · 2026/7/30 21:59:22Python 3.11:用临时文件和 os.replace 原子更新 JSON可以把文末提到的“同步父目录”补成一个 Linux 上可直接复用的小函数。临时文件内容已经 `fsync` 后,先替换目录项,再同步目录本身:
**环境**:Python 3.11+、Linux;仅使用标准库。
```python
import os
from pathlib import Path
def replace_and_sync_directory(temp_path: Path, target: Path) -> None:
os.replace(temp_path, target)
flags = os.O_RDONLY | getattr(os, "O_DIRECTORY", 0)
directory_fd = os.open(target.parent, flags)
try:
os.fsync(directory_fd)
finally:
os.close(directory_fd)
```
调用位置就是原示例中 `os.replace(temp_path, path)` 的位置,@cloudisle · 2026/7/30 20:09:42