From b7dc9e90e6db182cfb69565bb2478efd81d99493 Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Tue, 15 Sep 2026 10:27:20 +0800 Subject: [PATCH] =?UTF-8?q?fix(deploy):=20=E6=9D=83=E9=99=90=E6=94=BF?= =?UTF-8?q?=E7=AD=96=E6=8C=89**=E6=96=87=E4=BB=B6=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E5=88=86=E5=B2=94**=E5=BC=80=E8=8D=AF=E6=96=B9=20=E2=80=94?= =?UTF-8?q?=E2=80=94=20=E6=88=91=E4=B8=8A=E4=B8=80=E7=89=88=E6=8A=8A=20rel?= =?UTF-8?q?ease-linux.sh=20=E7=9A=84=E6=89=A7=E8=A1=8C=E4=BD=8D=E6=94=B9?= =?UTF-8?q?=E6=8E=89=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 我在上一个提交里弄坏了一个脚本 `client/electron/scripts/release-linux.sh` 原本是 **711**: group/other 读位缺失 ⇒ 本判据判红(**判得对**),但我给的药方是无脑 `chmod 644` ⇒ **去掉执行位** —— 把"读位缺失"换成"不能执行",**比原来更坏**, 而判据随后报"通过",工作区显示这个文件被改(`M`)。是我在提交前扫 `git status` 时 看见那一行 `M client/electron/scripts/release-linux.sh` 才发现的 —— **不是判据发现的**。 已恢复 755(`git diff` 干净,因为它 git 记录是 100755)。 ★ 教训:**一条判据说"这个文件被改错了"时,药方必须按文件类型分岔**; 只有一个药方(`chmod 644`)就会把另一类文件改坏,而它同样报"已修好"。 这与"判据的适用范围没写出来"同族,只是这次代价落在了**修的动作**上,不是读的动作上。 ## 改法 可执行与否按 **git 记录的那个位**(`git ls-files -s` 的 `100755`)判, 不按当前文件系统权限 —— 否则"执行位被谁弄丢了"会被这条判据**追认**成正常。 三条区分力实测(都当场恢复 + `cmp` 校验): 1. 非可执行文件改 0600 ⇒ 红,文案"权限过严"; 2. 可执行文件丢掉执行位 ⇒ 红,文案"**注意别去掉执行位**"; 3. 可执行文件 711(= `release-linux.sh` 原来的形态)⇒ 红 —— 即**最初那次判红是对的**, 错的是药方。 另外把计数循环改成读 `git ls-files -s` 一次(不再在循环里对每个文件调 `git ls-files --error-unmatch`,也不再让计数落在管道子 shell 里)。 验证:`check-file-modes.sh` 正常态 exit 0;三条变异行为如上; `git status` 只剩本文件本身的改动。 --- deploy/check-file-modes.sh | 52 +++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/deploy/check-file-modes.sh b/deploy/check-file-modes.sh index 9a4be3b..c72812a 100755 --- a/deploy/check-file-modes.sh +++ b/deploy/check-file-modes.sh @@ -33,34 +33,56 @@ cd "$REPO" # 允许的最严权限:0644。比它更严(组/其他读位缺失)即判红。 # 例外:**可执行**脚本的 0755 不是"更严",它多了执行位、读位齐全,属正常。 +# 允许的最严权限:0644(非可执行)/ 0755(可执行)。 +# +# ★ 可执行与否按 **git 记录的那个位**判(`git ls-files -s` 的 100755),不按当前文件系统权限 +# —— 否则"执行位被谁弄丢了"会被这条判据**追认**成正常。 +# +# ★ 这条我第一版写错了,代价是**真的弄坏了一个脚本**:`client/electron/scripts/release-linux.sh` +# 原本是 **711**(group/other 读位缺失 ⇒ 本判据判红,判得对),但我给的药方是无脑 +# `chmod 644` —— 那是**去掉执行位**,等于把"读位缺失"换成"不能执行",比原来更坏, +# 而判据随后报"通过"。⇒ 一条判据说"这个文件被改错了"时,**药方必须按文件类型分岔**; +# 只有一个药方就会把另一类文件改坏,且同样显示"已修好"。 fail=0 worst="" count=0 -while IFS= read -r f; do +while IFS= read -r line; do + gmode="${line%% *}" + f="${line##* }" [ -n "$f" ] || continue - # 只判 git 已跟踪的文件(未跟踪的构建产物不在这条政策范围内) - git ls-files --error-unmatch "$f" >/dev/null 2>&1 || continue [ -f "$f" ] || continue mode="$(stat -c '%a' "$f" 2>/dev/null)" || continue - # 取八进制后三位 m="${mode: -3}" - o="${m: -1}" # other 位 - g="${m:1:1}" # group 位 - # other 与 group 都必须有读位(4 及以上);否则这条政策判红 - if [ "$(( o & 4 ))" -eq 0 ] || [ "$(( g & 4 ))" -eq 0 ]; then - count=$((count + 1)) - [ -z "$worst" ] && worst="$f" + o="${m: -1}"; g="${m:1:1}"; u="${m:0:1}" + bad=0 + # group 与 other 必须有读位 + [ "$(( o & 4 ))" -eq 0 ] && bad=1 + [ "$(( g & 4 ))" -eq 0 ] && bad=1 + # git 记为可执行的,三处执行位都要在 + if [ "$gmode" = "100755" ]; then + [ "$(( u & 1 ))" -eq 0 ] && bad=1 + [ "$(( g & 1 ))" -eq 0 ] && bad=1 + [ "$(( o & 1 ))" -eq 0 ] && bad=1 + fi + [ "$bad" -eq 0 ] && continue + count=$((count + 1)) + [ -z "$worst" ] && worst="$f" + if [ "$gmode" = "100755" ]; then + printf ' [FAIL] 权限不对:%s 是 %s(git 记为可执行 ⇒ 应为 0755,注意别去掉执行位)\n' "$f" "$mode" >&2 + else printf ' [FAIL] 权限过严:%s 是 %s(政策要求不严于 0644)\n' "$f" "$mode" >&2 fi -done < <(git ls-files) +done < <(git ls-files -s | awk '{print $1" "$4}') if [ "$count" -gt 0 ]; then - printf '\n 共 %d 个源文件比 0644 更严(首个:%s)。\n' "$count" "$worst" >&2 - printf ' 药方:chmod 644 <文件>。原因:写文件的工具不理会 umask,而 `cp -a` 会把这个\n' >&2 - printf ' 权限位带进生产快照,且 `cmp`/漂移判据都看不见它。\n' >&2 + printf '\n 共 %d 个源文件权限不对(首个:%s)。\n' "$count" "$worst" >&2 + printf ' 药方(**按类型分岔**):非可执行文件补齐到 644;git 记为 100755 的补齐到 755。\n' >&2 + printf ' 原因:写文件的工具不理会 umask,而 `cp -a` 会把这个权限位带进生产快照,\n' >&2 + printf ' 且 `cmp` / ① 内容判据都看不见它。\n' >&2 printf ' 这是**政策问题**(源文件应当可被构建/测试/部署以不同身份读),不是代码问题。\n' >&2 exit 1 fi -printf ' 源文件权限政策:通过(没有任何已跟踪文件比 0644 更严)\n' +printf ' 源文件权限政策:通过(已跟踪文件都够读;git 记为可执行的都保留了执行位)\n' exit 0 +