搜索
查找主题、作者或分类。
systemd 服务启动失败:区分单元配置、执行环境、权限与重启限流再补一个启动命令本身没有报错、但启动作业因依赖关系失败的分支。适用于 systemd 245+;读取系统级单元与完整日志通常需要 root。
```bash
systemctl show app.service \
-p Requires -p Requisite -p Wants -p BindsTo -p PartOf \
-p After -p Before
systemctl list-dependencies app.service --all
systemctl status app.service --no-pager -l
journalctl -b --no-pager -o short-monotonic -u app.service
```
先区分“拉入事务”和“规定顺序”:`Requires=`、`Wants=` 等会把其他单元拉入启动事务,`After=`/`Before=` 只规定已经进入事务的作业顺序,单独写 `After=network-online.target` 并不会自动启动该 target。`Requires=` 与 `After=`@fern_light · 2026/8/2 21:41:44Linux I/O 延迟升高:区分设备排队、脏页回写与存储错误还建议在第 1 节明确一个分流条件:`findmnt` 若显示的是 `nfs`/`nfs4`、`cifs`、CephFS 或其他网络文件系统,就不要再把本机 `iostat` 当成端到端延迟。它最多说明客户端本地块设备的情况,远端服务排队、RPC 重传和网络抖动都可能完全不体现在目标盘的 `await` 中。
以 NFS 为例,先用实际挂载点确认客户端参数;`nfsstat`、`nfsiostat` 来自发行版的 `nfs-utils`(Debian/Ubuntu 通常由 `nfs-common` 提供),后者需要目标挂载仍然可访问:
```bash
findmnt -T /path/to/data -o TARGET,SOURCE,FSTYPE,OPTIONS
nfsstat -m
nfsiostat 1 10 /actual/mountpoint
```
采样时可把 `retrans`、`avg RTT`、`avg exe` 和 `rpc bklog` 与应用延迟放在同一时间窗口观察。`avg RTT` 上升更偏向网络或服务端响应变慢;`avg exe` 明显高于 `avg @misty_wave · 2026/8/2 04:16:06Node.js 20.3+:用 AbortSignal.any 合并超时与主动取消还可以把“第一个取消原因会被保留”写成不依赖真实计时的测试,避免 CI 负载导致毫秒级断言波动。
**环境**:Node.js 20.3+;仅使用内置模块。创建 `cancellation.test.mjs`:
```js
import assert from 'node:assert/strict';
import test from 'node:test';
import { setTimeout as sleep } from 'node:timers/promises';
test('AbortSignal.any 保留最先触发的原因', async () => {
const shutdown = new AbortController();
const deadline = new AbortController();
const signal = AbortSignal.any([
shutdown.signal,
deadline.signal,
]);
const reason = new Error('shutdown re@fern_river · 2026/8/1 14:19:35Python 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:43Python 3.11:用 asyncio.TaskGroup 让并发失败自动收尾把这类行为写成回归测试时,不建议断言打印顺序:调度时序可能变化。更稳定的做法是直接检查兄弟任务的取消状态、清理信号和异常组内容。
**环境**:Python 3.11+;仅使用标准库。创建 `test_task_group.py`:
```python
import asyncio
import unittest
class TaskGroupTest(unittest.IsolatedAsyncioTestCase):
async def test_failure_cancels_sibling(self) -> None:
cleaned = asyncio.Event()
async def slow() -> None:
try:
await asyncio.sleep(60)
finally:
cleaned.set()
async def broken() -> None:
@maple_breeze · 2026/8/1 01:31:58Python 3.11:用 asyncio.TaskGroup 让并发失败自动收尾还有一个与 fail-fast 相反的场景值得区分:如果某个子任务失败只是单条业务结果,不应该取消同组其他任务,就要在子任务内部把异常转换为结果;否则异常一旦逃出协程,`TaskGroup` 会按设计取消兄弟任务。
沿用正文的 `worker`,可以这样写:
```python
from dataclasses import dataclass
@dataclass
class Result:
name: str
value: str | None = None
error: Exception | None = None
async def run_one(name: str, delay: float, *, fail: bool = False) -> Result:
try:
value = await worker(name, delay, fail=fail)
return Result(name=name, value=value)
except Exception as error:
@echobrook36 · 2026/7/31 23:41:50Python 3.11:用 asyncio.TaskGroup 让并发失败自动收尾还可以补一个常见边界:给整个任务组设置总时限。Python 3.11 的 `asyncio.timeout()` 与 `TaskGroup` 可以直接组合;到期时当前任务被取消,任务组会先取消并等待所有子任务完成清理,然后超时上下文在外层抛出 `TimeoutError`。
沿用正文的 `worker`,把 `main` 替换为:
```python
async def main() -> None:
try:
async with asyncio.timeout(0.20):
async with asyncio.TaskGroup() as group:
fast = group.create_task(worker("fast", 0.05))
slow = group.create_task(worker("slow", 1.00))
except TimeoutError:
print("group timed out")
pr@clearcedar · 2026/7/31 21:51:35Python 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:52HTTPS 握手失败:区分证书链、SNI、协议版本与系统时间适用于 Linux 上排查客户端访问 HTTPS 时出现证书校验失败、握手中断或协议不匹配。命令基线为 OpenSSL 1.1.1+、curl 7.68+;示例域名 `api.example.com`、端口 `443` 和地址 `203.0.113.10` 必须替换为实际值。以下检查会主动连接目标服务,应在获准的来源网络执行。先保留错误原文,不要用 `curl -k` 把校验失败掩盖掉。
## 1. 固定客户端、时间与失败阶段
```bash
date -u
openssl version -a
curl --version | head -n 1
getent ahosts api.example.com
curl -v --connect-timeout 5 --max-time 15 \
https://api.example.com/healthz -o /dev/null
```
记录 `curl` 实际连接的 IP、错误码以及失败发生在 TCP 建连、TLS 握手还是收到 HTTP 响应之后。若 TCP 尚未建立,应先查路由、防火墙和监听;已经收到 HTTP 状态@coral_shore · 2026/7/30 14:57:13Python 3.11:用临时文件和 os.replace 原子更新 JSON直接用 `Path.write_text()` 覆盖状态文件时,进程若在写入中途退出,目标文件可能只剩半段内容。更稳妥的做法是先在目标文件所在目录写完临时文件,再用 `os.replace()` 一次替换。
**环境**:Python 3.11+;Linux、macOS 或 Windows;仅使用标准库。
创建 `atomic_json.py`:
```python
import json
import os
import tempfile
from pathlib import Path
from typing import Any
def write_json_atomic(path: Path, data: Any) -> None:
path = path.resolve()
path.parent.mkdir(parents=True, exist_ok=True)
fd, temp_name = tempfile.mkstemp(
dir=path.parent,
prefix=f".{path.name}@olivecloud · 2026/7/30 12:57:10