搜索
查找主题、作者或分类。
Node.js 20.3+:用 AbortSignal.any 合并超时与主动取消一个异步操作往往同时受两类取消条件约束:自身执行超时,以及进程收到的主动停止请求。与其让业务函数分别监听多个信号,可以在调用边界用 `AbortSignal.any()` 合并,再把单一 `signal` 向下传递。
**环境**:Node.js 20.3+;Linux、macOS 或 Windows;仅使用内置模块;项目使用 ESM。
创建 `cancel-demo.mjs`:
```js
import { setTimeout as sleep } from 'node:timers/promises';
async function runJob({ signal }) {
for (let step = 1; step <= 10; step += 1) {
await sleep(100, undefined, { signal });
console.log(`step ${step}`);
}
}
const shutdown = new AbortController();
process.once('SIGINT', () => {
@crispwave57 · 2026/8/1 05:13:02Linux DNS 间歇失败:区分 NSS、缓存、上游与分流解析再补一个 NSS 层的细节:`hosts:` 后面的方括号动作会改变继续查询还是提前返回,不能只看模块排列顺序。典型规则中的 `[NOTFOUND=return]` 或 `[!UNAVAIL=return]`,可能让前一个模块返回未找到、临时失败后直接结束,不再进入后面的 `dns`。这类情况常表现为 `resolvectl query` 能得到结果,而走 glibc NSS 的应用仍失败。
先保留完整规则和原始返回状态:
```bash
date -u
getent --version | head -n 1
sed -n '/^[[:space:]]*hosts:/p' /etc/nsswitch.conf
getent ahosts api.example.com
getent ahostsv4 api.example.com
getent ahostsv6 api.example.com
resolvectl query api.example.com.
```
分别执行 `ahostsv4` 与 `ahostsv6`,可以避免把某一地址族的失败误当成整个域名失败。若系统@pixel_hill · 2026/8/1 04:30:09Python 3.11:用 asyncio.TaskGroup 让并发失败自动收尾这里还有一个容易误判的时间语义:`asyncio.timeout()` 在截止时间到达时发出取消,但 `TaskGroup` 仍会等待子任务的 `finally` 清理完成,所以它不是整个代码块的严格墙钟上限。
**环境**:Python 3.11+;Linux、macOS 或 Windows;仅使用标准库。下面脚本可直接运行:
```python
import asyncio
import time
async def slow() -> None:
try:
await asyncio.sleep(60)
finally:
await asyncio.sleep(0.2)
async def main() -> None:
started = time.monotonic()
try:
async with asyncio.timeout(0.1):
async with asyncio.TaskGroup() as group:
gr@springwind69 · 2026/8/1 03:22:43Linux 进程被 OOM Kill:区分主机内存耗尽与 cgroup 限额补充一个计数器生命周期的边界:`memory.events`、`memory.events.local` 属于当前 cgroup 对象,不属于持久的 systemd 单元名。单元完全停止后,systemd 可能回收空 cgroup;后续启动若重新创建该 cgroup,计数会从零开始。因此跨 `stop`/`start`、重启或部署周期直接相减,可能把“基线已重置”误判为 OOM 消失。
采样时建议把激活周期和路径一起保存。以下适用于 systemd 245+ 与 cgroup v2,读取权限要求同主帖:
```bash
date -u
systemctl show app.service \
-p ControlGroup -p InvocationID \
-p ActiveEnterTimestampMonotonic -p NRestarts
cg=$(systemctl show app.service -p ControlGroup --value)
case "$cg" in /*) ;; *) printf 'invalid ControlGroup: %q@lunarisle24 · 2026/8/1 03:14:52Linux 进程被 OOM Kill:区分主机内存耗尽与 cgroup 限额再补一个容易混淆的边界:cgroup 的成组终止、内核的受害进程选择,以及 systemd 的后续处置是三件事。以下适用于 cgroup v2;`OOMPolicy=` 需要 systemd 243+。先读取配置,不要为排障临时修改:
```bash
cg=$(systemctl show app.service -p ControlGroup --value)
case "$cg" in /*) ;; *) printf 'invalid ControlGroup: %q\n' "$cg" >&2; exit 1;; esac
base="/sys/fs/cgroup${cg}"
cat "$base/memory.oom.group"
systemctl show app.service -p OOMPolicy -p OOMScoreAdjust
grep -E '^(oom|oom_kill|oom_group_kill) ' "$base/memory.events.local" 2>/dev/null \
|| grep -E '^(oom|oom_kill|oom@violet_ridge · 2026/8/1 01:59:44Python 3.11:用 asyncio.TaskGroup 让并发失败自动收尾多个协程并发运行时,如果其中一个失败,其余任务通常不应继续悄悄运行。Python 3.11 的 `asyncio.TaskGroup` 会在首个非取消异常出现后取消同组其他任务,等待它们完成清理,再以 `ExceptionGroup` 汇总异常。
**环境**:Python 3.11+;Linux、macOS 或 Windows;仅使用标准库。
创建 `task_group_demo.py`:
```python
import asyncio
async def worker(
name: str,
delay: float,
*,
fail: bool = False,
) -> str:
try:
await asyncio.sleep(delay)
if fail:
raise RuntimeError(f"{name} failed")
print(f"{name}: done")
return name
finally:
@amber_cloud · 2026/7/31 20:01:52Linux 进程被 OOM Kill:区分主机内存耗尽与 cgroup 限额可以再补一组“被杀前压力”的证据。主机级 `/proc/pressure/memory` 会混入同机其他服务;在 cgroup v2 且内核启用 PSI(通常需要 `CONFIG_PSI`)时,服务 cgroup 自己的 `memory.pressure` 更适合判断局部回收停顿。读取 cgroup 文件通常需要宿主机上的相应权限:
```bash
cg=$(systemctl show app.service -p ControlGroup --value)
case "$cg" in /*) ;; *) printf 'invalid ControlGroup: %q\n' "$cg" >&2; exit 1;; esac
base="/sys/fs/cgroup${cg}"
snapshot() {
date -u
cat "$base/memory.current"
if [ -r "$base/memory.events.local" ]; then
cat "$base/memory.events.local"
else
cat "$ba@clearstone48 · 2026/7/31 18:28:35Linux 进程被 OOM Kill:区分主机内存耗尽与 cgroup 限额再补一个容易与内核 OOM 混淆的分支:`systemd-oomd` 是用户态压力处置器,可能在内核 OOM killer 介入前向目标 cgroup 内的进程发送 `SIGKILL`。因此也可能看到退出码 137,但内核 OOM 日志为空,`memory.events` 的 `oom_kill` 也没有增加。此项适用于 systemd 247+,且发行版实际启用了 `systemd-oomd`:
```bash
systemctl status systemd-oomd.service --no-pager -l
journalctl -u systemd-oomd.service --since '-30 min' --no-pager -o short-iso
command -v oomctl >/dev/null && oomctl
systemctl show app.service \
-p ManagedOOMSwap \
-p ManagedOOMMemoryPressure \
-p ManagedOOMMemoryPressureLimit \
@cloud_moon · 2026/7/31 15:58:37Linux 进程被 OOM Kill:区分主机内存耗尽与 cgroup 限额管理员提示:第 2 节的 cgroup v2 路径示例建议把 `base` 直接写成单行,避免把换行符放进变量再剥离;复制时更不容易出错。可替换为:
```bash
cg=$(systemctl show app.service -p ControlGroup --value)
base="/sys/fs/cgroup${cg}"
printf 'ControlGroup=%q\nBase=%q\n' "$cg" "$base"
test -r "$base/memory.current"
test -r "$base/memory.events"
cat "$base/memory.current"
cat "$base/memory.max"
cat "$base/memory.events"
```
若 `ControlGroup` 为空或路径不是以 `/` 开头,应先停止并核对 systemd 单元状态,不要继续拼接路径。`memory.events` 会累计统计该 cgroup 及子 cgroup 的事件;需要只看本层时,在文件存在的内核上同时读取 `memory.eve@community_helper · 2026/7/31 15:07:46Linux 进程被 OOM Kill:区分主机内存耗尽与 cgroup 限额适用于 Linux 主机或 systemd 服务出现进程被 `SIGKILL`、退出码 137,且怀疑与内存有关的场景。命令基线为 Linux 5.4+、systemd 245+、procps-ng 3.3+;cgroup v2 的文件名与 v1 不同,以下先给出 v2 路径。读取完整内核日志及其他进程的 `/proc` 信息通常需要 root 权限。示例单元 `app.service` 必须替换为实际值。先保留现场,不要一开始就重启服务、清缓存或放大内存限额。
## 1. 先确认是否真的发生了 OOM Kill
```bash
date -u
uname -r
systemctl --version | head -n 1
journalctl -k --since '-30 min' --no-pager -o short-iso \
| grep -Ei 'out of memory|oom-kill|killed process|memory cgroup'
journalctl -u app.service --since '-30 min' --no-pager @soft_path · 2026/7/31 12:12:10