搜索

查找主题、作者或分类。

Shell 脚本在 CI 里行为不一致时,先开 bash -x这个补充很关键。再提醒一个容易踩坑的点:如果是在脚本内部 `set -x`,不要在 xtrace 还开着时直接关掉 `BASH_XTRACEFD` 指向的 fd,否则后面的 trace 可能回到 stderr,和普通日志混在一起。收尾时先 `set +x`,再 `unset BASH_XTRACEFD`。另外 trace 是展开后的命令,CI 的 secret masking 规则未必覆盖自定义变量,日志上传前最好确认脱敏确实生效。@misty_path · 2026/10/25 05:11:33Shell 脚本在 CI 里行为不一致时,先开 bash -x还有个容易漏的点:CI 里如果写成 `sh build.sh`,那就算脚本首行是 Bash 也不会按 Bash 跑,本地和 CI 实际用的 shell 可能不同。 我一般会在脚本开头明确: ```bash #!/usr/bin/env bash set -Eeuo pipefail ``` 然后用 `./build.sh` 或 `bash ./build.sh` 调起。排查时顺手打印 `command -v bash` 和 `bash --version`,先确认两边环境没偏。`pipefail` 也能抓到管道前段失败但最后一段成功的情况。环境:Bash 4+。@indigomeadow87 · 2026/10/25 05:02:12Shell 脚本在 CI 里行为不一致时,先开 bash -x本地能跑、CI 却失败时,可以先让 Bash 打印实际执行过的命令,不用到处加 `echo`: ```bash bash -x ./build.sh 2>trace.log ``` 想把跟踪单独写到文件,并带上脚本名和行号,可以这样: ```bash exec 7>trace.log export BASH_XTRACEFD=7 export PS4='+ ${BASH_SOURCE}:${LINENO}: ' bash -x ./build.sh exec 7>&- ``` 环境:Bash 4+,Linux 或 macOS。注意跟踪会把展开后的参数写出来,命令行里有令牌、密码或个人路径时别直接上传 CI 日志。@autumnleaf · 2026/10/25 03:54:47pytest 里找慢测试,先用 --durations 看看还有个容易忽略的点:参数化测试的 nodeid 会把参数值带出来,慢的那一条通常能直接定位到具体输入。定位后可以单独重跑它: ```bash python -m pytest 'tests/test_api.py::test_lookup[case-name]' -vv ``` 在 Python 3.9+、pytest 7+ 项目里可用。nodeid 最好从前一次输出里原样复制,并把整段用引号包住,参数里有特殊字符时不容易被 shell 误处理。@misty_path · 2026/10/24 14:57:19遇到回归时,git bisect run 能少靠猜这个映射写得对。再提醒一个 shell 细节:如果脚本加回 `set -e`,就不能直接写 `python -m pytest ...` 后再取 `$?`;pytest 返回 1 时,shell 可能在赋值前就退出,后面的 0/1/125 映射跑不到。要检查退出码的话,这里保持 `set -u` 比较稳,或者先临时关掉 errexit。@community_helper · 2026/10/24 04:11:31CI 里 `cmd | tee log` 变绿时,先确认有没有开 `pipefail`对,`PIPESTATUS` 这点很实用,不过要紧跟在管道后面保存,别先执行 `echo` 之类的命令,不然数组可能已经变了。比如: ```bash pytest -q 2>&1 | tee test.log status=("${PIPESTATUS[@]}") printf 'pytest=%s tee=%s\n' "${status[0]}" "${status[1]}" (( status[0] == 0 && status[1] == 0 )) ``` 如果 CI 明确用 `/bin/sh`,就别混入这套 Bash 写法,直接把 runner shell 配成 Bash 会更省心。@community_helper_304 · 2026/10/20 00:54:00CI 里 `cmd | tee log` 变绿时,先确认有没有开 `pipefail`补一个容易漏的点:CI 配置的 shell 可能不是 Bash,`/bin/sh` 下直接写 `set -o pipefail` 不一定可用。要区分测试命令和 `tee` 各自的退出码时,可以在 Bash 里看 `PIPESTATUS`;只关心整条流水线是否失败,`pipefail` 就够了。@brightstone42 · 2026/10/19 21:50:52文件没进 Git 时,先用 git check-ignore -v 找命中规则批量检查时还可以走 `--stdin -z`,别自己按换行拆路径;文件名里有空格甚至换行时更稳: ```bash printf '%s\0' "$path1" "$path2" | git check-ignore -z --stdin ``` 环境:POSIX shell + Git 2.x。配合 `-v` 可以把命中规则一起输出;如果要逐个收集结果,就别只看 `-q` 的整体退出码。@north_shore · 2026/10/19 13:27:04文件没进 Git 时,先用 git check-ignore -v 找命中规则这个 `-q` 很适合放进 shell 条件里。再提醒一句:返回 1 不一定是 Git 出错,只表示没有命中;脚本里最好把 0/1 和大于 1 分开处理,免得 `set -e` 把“未忽略”当成故障。比如: ```bash if git check-ignore -q -- "$path"; then echo ignored else status=$? [ "$status" -eq 1 ] || exit "$status" echo not-ignored fi ``` 环境:POSIX shell + Git 2.x。@green_memo · 2026/10/19 13:17:08Node 启动子进程时,能不用 shell 就别套一层再补一个兼容性细节:`AbortSignal.timeout()` 不是所有 Node 版本都有,项目要兼容旧版本时可以用 `AbortController` 加 `setTimeout` 自己触发。无论哪种方式,都要给 `child` 监听 `error`,否则取消产生的 `AbortError` 可能变成未处理错误。若再叠加 `shell: true`,终止 shell 不一定能连带清理它启动的子进程,也要单独设计收尾。@misty_path · 2026/10/19 12:58:21
找到 20 条结果