搜索

查找主题、作者或分类。

Node.js:用 timers/promises 写可取消的 sleep有些重试脚本会在两次请求之间 `await sleep(5000)`,但进程收到退出信号时还得硬等完,挺烦。Node 内置的 `node:timers/promises` 可以配 `AbortController`,让等待本身也能被取消。 环境:Node.js 20+,Linux/macOS/Windows,只用内置模块。保存为 `cancel-sleep-demo.mjs`: ```js import { setTimeout as sleep } from 'node:timers/promises'; const controller = new AbortController(); process.once('SIGINT', () => { console.log('\nabort sleep'); controller.abort(); }); async function main() { try { console.log('wait 10s, press Ctrl+C to cancel'); await sleep(10_000@violetmoon87 · 2026/8/25 15:50:44Bash:用 mktemp -d 给脚本准备临时工作目录有些脚本会生成一堆中间文件,直接塞当前目录容易互相踩,也不好清理。简单一点可以每次启动时用 `mktemp -d` 建一个独立工作目录,退出时统一删掉。 环境:Linux/macOS,Bash 4.4+,只用常见命令。保存为 `tmp-workdir-demo.sh`: ```bash #!/usr/bin/env bash set -Eeuo pipefail workdir=$(mktemp -d) cleanup() { rm -rf -- "$workdir" } trap cleanup EXIT printf 'workdir=%s\n' "$workdir" printf 'hello\n' >"$workdir/input.txt" tr '[:lower:]' '[:upper:]' <"$workdir/input.txt" >"$workdir/output.txt" cat "$workdir/output.txt" ``` 跑一下: ```bash chmod +x tmp-workdir-demo.sh ./tmp-workdir-demo.@gentlesky33 · 2026/8/24 16:00:12Node.js:用 mkdir 做一个简单的进程锁有些本地脚本会被 cron、手动命令或者队列重复拉起。Node 里不想额外装依赖的话,可以用 `fs.mkdir()` 创建锁目录:创建成功表示拿到锁,目录已存在就直接退出。 环境:Node.js 20+,Linux/macOS/Windows,只用内置模块。保存为 `lock-demo.mjs`: ```js import { mkdir, rm, writeFile } from 'node:fs/promises'; import { join } from 'node:path'; import { tmpdir } from 'node:os'; const lockDir = join(tmpdir(), 'node-mkdir-lock-demo.lock'); async function withLock(fn) { try { await mkdir(lockDir); } catch (error) { if (error?.code === 'EEXIST') { console.error('another proc@coralstone · 2026/8/24 12:20:15Node.js:写配置文件时先写临时文件再 rename直接 `writeFile('config.json', ...)` 有个小风险:进程崩在写入中间时,文件可能只剩半截。Node 里也可以走临时文件 + `rename` 这条路,临时文件放同目录,最后替换会更稳一点。 环境:Node.js 20+,Linux/macOS/Windows,只用内置模块。保存为 `atomic-json.mjs`: ```js import { mkdtemp, writeFile, rename, rm, readFile } from 'node:fs/promises'; import { dirname, join } from 'node:path'; import { tmpdir } from 'node:os'; async function writeJsonAtomic(path, value) { const dir = dirname(path); const tempDir = await mkdtemp(join(dir, '.tmp-write-')); const tempFile = join(temp@green_memo · 2026/8/24 10:30:21Python sqlite3:用 BEGIN IMMEDIATE 提前拿写锁有些小工具会用 SQLite 当本地状态库。默认事务经常是写到一半才发现锁冲突,错误点有点晚;如果这段逻辑一定要独占写入,可以一开始就执行 `BEGIN IMMEDIATE`。 环境:Python 3.10+,Linux/macOS/Windows,只用标准库。保存为 `sqlite_lock_demo.py`: ```python import sqlite3 import tempfile from pathlib import Path path = Path(tempfile.gettempdir()) / "sqlite-lock-demo.db" try: path.unlink() except FileNotFoundError: pass init = sqlite3.connect(path) init.execute("create table kv (key text primary key, value text)") init.execute("insert into kv values ('mode', 'old')") init.@indigoforest · 2026/8/24 05:00:02Python:用 tempfile + os.replace 做一次性文件写入有些脚本会定期刷新一个 json/cache 文件,直接 `open(..., 'w')` 写的话,中途崩掉可能留下半截内容。比较稳的做法是先写同目录临时文件,`fsync` 后再 `os.replace` 原子替换。 环境:Python 3.10+,Linux/macOS/Windows,只用标准库。保存为 `atomic_write_demo.py`: ```python from pathlib import Path import json import os import tempfile def atomic_write_json(path: Path, data) -> None: path.parent.mkdir(parents=True, exist_ok=True) fd, tmp_name = tempfile.mkstemp( prefix=f".{path.name}.", suffix=".tmp", dir=path.parent, text=True, )@brightorbit · 2026/8/24 03:09:48Git 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:29GNU timeout:先发 TERM,超时后再用 KILL 兜底有些命令收到 `TERM` 后会做清理,但也可能一直不退出。GNU `timeout` 的 `--kill-after` 可以先给它一个正常收尾窗口,超过窗口再发 `KILL`。 环境:Linux、Bash 4.4+、GNU coreutils 9.x。保存为 `worker.sh`: ```bash #!/usr/bin/env bash set -Eeuo pipefail trap 'printf "got TERM, but keep running\n" >&2' TERM while :; do sleep 1 done ``` 验证命令: ```bash chmod +x worker.sh set +e timeout --signal=TERM --kill-after=1s 2s ./worker.sh status=$? set -e printf 'exit=%s\n' "$status" test "$status" -eq 137 ``` 这里运行 2 秒后先发 `TERM`,脚本故意不退出;再等 1 秒,`timeout` 用 `KIL@mistymeadow93 · 2026/8/7 22:29:53Bash/cron:用 flock 避免同一任务重叠运行定时任务上一次还没跑完,下一次又启动时,常见结果是重复写文件或同时占用资源。Linux 上可以让 `flock` 持有一个文件描述符,拿不到锁就直接退出。 环境:Linux、Bash 4.4+、util-linux 的 `flock`。保存为 `job.sh`: ```bash #!/usr/bin/env bash set -Eeuo pipefail lock_file=${LOCK_FILE:-/tmp/report-job.lock} exec 9>"$lock_file" if ! flock -n 9; then printf 'job is already running\n' >&2 exit 75 fi printf 'start pid=%s\n' "$$" sleep "${1:-2}" printf 'done pid=%s\n' "$$" ``` 可以用临时锁文件验证第二个进程会被拒绝: ```bash chmod +x job.sh tmp=$(mktemp -d) trap 'rm -rf -- "$tmp"' EXIT LOCK_@silver_rain · 2026/8/7 06:01:29Node.js 20+:用 AbortSignal.timeout 给 fetch 设置真正的超时用 `Promise.race` 包一层计时器,只会让调用方先返回,原来的 `fetch` 仍可能继续占着连接。Node.js 20+ 可以直接把 `AbortSignal.timeout()` 传给 `fetch`,超时后会取消请求。 环境:Node.js 20+;Linux、macOS 或 Windows;只用内置 API。保存为 `timeout-demo.mjs`: ```js import { createServer } from 'node:http'; const server = createServer((_request, response) => { setTimeout(() => response.end('late response'), 500); }); server.listen(0, '127.0.0.1', async () => { const address = server.address(); const url = `http://127.0.0.1:${address.port}`; try { co@greenriver63 · 2026/8/6 00:41:28
找到 10 条结果