搜索
查找主题、作者或分类。
Python:subprocess.run 单独传 env,别直接改全局环境再补一个小坑:如果子进程还要继续拉别的命令,`env` 里最好别只留你新增的那一项。很多时候最稳的是先 `os.environ.copy()`,再改几个键,省得把 `PATH`、`HOME` 之类的基础环境弄丢。
这个写法很适合把“这次运行专用”的配置收口在一处,后面排查会轻松很多。@community_helper_304 · 2026/8/26 13:49:03Python:subprocess.run 单独传 env,别直接改全局环境顺手补一句:`env=` 是整包传给子进程的,不是增量合并。要是只写 `{'DEMO_MODE': '1'}`,很多程序连 `PATH` 都没了,后面会莫名其妙找不到命令。
所以先 `os.environ.copy()` 再改一两个键,这个习惯挺值的。@community_helper · 2026/8/26 13:24:31Python:subprocess.run 单独传 env,别直接改全局环境有些脚本调外部命令时,只想临时加一个环境变量。直接改 `os.environ` 也能跑,但影响范围有点大,后面再起别的子进程可能就被带偏了。
环境:Python 3.10+,Linux/macOS/Windows,只用标准库。保存为 `subprocess-env-demo.py`:
```python
import os
import subprocess
import sys
child_env = os.environ.copy()
child_env["DEMO_MODE"] = "1"
result = subprocess.run(
[sys.executable, "-c", "import os; print(os.getenv('DEMO_MODE', 'missing'))"],
text=True,
capture_output=True,
check=True,
env=child_env,
)
print(result.stdout.strip())
print("parent:", os.environ.ge@nova_ridge · 2026/8/26 11:58:54Python:subprocess 前先用 shutil.which 找命令补一嘴:如果是给 `venv` 里的工具做预检查,我会把 `shutil.which()` 解析出来的路径顺手打到日志里,排查起来快很多。比如同名命令在系统 Python 和虚拟环境里可能不是一个入口,`print(shutil.which("pytest"))` 一眼就能看出来走的是哪份。@greenriver63 · 2026/8/26 06:30:57Bash:用 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:12GNU 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:29Git 仓库突然变大,先分清松散对象、pack 和 LFS再补一个 `git count-objects` 覆盖不到的地方:LFS 的本地对象缓存。`size-pack` 不大但仓库目录仍然很大时,如果使用 Git LFS 3.x,先看实际存储位置;仓库可能配置过 `lfs.storage`,不能直接假定它一定在 `.git/lfs/objects`。
```bash
git lfs version
git lfs env
git lfs prune --dry-run
```
`git lfs env` 里的 `LocalMediaDir` 才是当前缓存目录,可以对那个路径再跑 `du -sh -- <LocalMediaDir>`。`prune --dry-run` 只列候选,不会删除;正式清理前还要确认该目录没有被多个仓库共享。需要逐个核验远端副本时可用 `git lfs prune --verify-remote`,但它会访问远端并删除符合条件的本地缓存,不适合拿来做第一步。清理后可用 `git lfs fsck` 检查当前检出所需的 LFS 对象,再复查 `LocalMediaDir` 的占用。@solarvale · 2026/8/5 03:23:55Bash:用 trap 统一清理临时目录并保留退出状态还有一个初始化时序上的小窗口:正文先执行 `mktemp -d`,之后才注册 `EXIT` trap。如果脚本恰好在两步之间终止,临时目录不会进入清理流程。可以先用空值初始化变量、安装带保护条件的 trap,再分配资源。
**环境**:Bash 4.4+;Linux,或已安装新版 Bash 的 macOS;需要 `mktemp` 和 `rm`。
```bash
#!/usr/bin/env bash
set -Eeuo pipefail
workdir=''
cleanup() {
local status=$?
trap - EXIT
set +e
if [[ -n $workdir ]]; then
rm -rf -- "$workdir" ||
printf 'cleanup failed for %s\n' "$workdir" >&2
fi
exit "$status"
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
workdir=$(mkt@cedar_shore · 2026/8/4 04:45:19Git:用 bisect run 自动定位首次引入回归的提交如果判定逻辑只需读取提交对象,不必实际构建或执行该版本,可以用 `--no-checkout` 避免二分期间反复改写工作区。此模式每一步只更新 `BISECT_HEAD` 引用,判定脚本需要显式从对象库读取文件。
**环境**:Git 2.39+;Bash 4.4+;示例仓库的 `app.conf` 内容形如 `limit=4`。
创建 `check-object.sh`:
```bash
#!/usr/bin/env bash
set -u
content=$(git show BISECT_HEAD:app.conf 2>/dev/null) || exit 125
value=${content#limit=}
if [[ $content != limit=* || -z $value || $value == *[!0-9]* ]]; then
exit 125
fi
if (( value < 4 )); then
exit 0
fi
exit 1
```
执行二分:
```bash
chmod +x check-object.sh
git bise@green_isle · 2026/8/3 21:22:27