From 983a2c2f0207d576804457ba44d307fe856ae11f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=80=A7=E9=A9=8A?= Date: Tue, 10 Nov 2026 14:32:56 +0800 Subject: [PATCH] install.sh: stop dying on macOS at the compile step MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "$RUST_HOST;" is one variable name to macOS /bin/sh (bash 3.2): it swallows the first byte of the full-width punctuation, so with set -u a plain \`sh install.sh app\` aborted at [3/4] with "RUST_HOST\*: unbound variable". Four such lines in install.sh, one in the server setup. Brace them, add make lint-sh (sh -n for every shipped script plus a check for this pattern) so it stays fixed. --- Makefile | 6 +++++- deploy/ci/lint-sh.sh | 44 ++++++++++++++++++++++++++++++++++++++++++ deploy/server/setup.sh | 2 +- install.sh | 8 ++++---- 4 files changed, 54 insertions(+), 6 deletions(-) create mode 100755 deploy/ci/lint-sh.sh diff --git a/Makefile b/Makefile index 46debdb..0bda545 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ APPDIR ?= $(HOME)/Applications BIN := $(TARGET)/release/anybot RELAY := $(if $(CARGO_TARGET_DIR),$(CARGO_TARGET_DIR),relay/target)/release/anybot-relay -.PHONY: all build app relay run serve setup relay-run test deps doctor install uninstall hands server dist clean help check-rust +.PHONY: all build app relay run serve setup relay-run test deps doctor install uninstall hands server dist clean help check-rust lint-sh all: build @@ -34,6 +34,7 @@ help: @echo " make deps 裝好建置需要的東西:系統套件和 Rust(Linux 會問 sudo 密碼)" @echo " make doctor 檢查這台缺什麼" @echo " make test 跑測試" + @echo " make lint-sh 檢查 shell 腳本(語法、中文標點黏變數)" @echo "" @echo " make serve 不開視窗執行(伺服器、一直開著的電腦)" @echo " make setup 把這台接到你的 AnyBot(終端機裡的引導畫面)" @@ -72,6 +73,9 @@ test: check-rust $(CARGO) test --bin anybot cd relay && $(CARGO) test +lint-sh: + @sh deploy/ci/lint-sh.sh + deps: sh ./install.sh deps diff --git a/deploy/ci/lint-sh.sh b/deploy/ci/lint-sh.sh new file mode 100755 index 0000000..abb990a --- /dev/null +++ b/deploy/ci/lint-sh.sh @@ -0,0 +1,44 @@ +#!/bin/sh +# Shell lint for the install scripts. Two checks: +# 1. POSIX syntax (sh -n) for every .sh we ship. +# 2. $VAR or ${VAR} glued to a non-ASCII character, which macOS's /bin/sh +# (bash 3.2) reads as part of the variable name: "($X;…" is an unbound +# variable there even when X is set, and install.sh runs with set -u. +# Write ${X}與… — braces fix it. +# Run: make lint-sh +set -u +cd "$(dirname "$0")/../.." || exit 1 +fail=0 + +for f in install.sh $(find deploy -name '*.sh' | sort); do + if sh -n "$f" 2>/tmp/anybot-sh-lint.log; then + printf ' ✓ %s\n' "$f" + else + printf ' ✗ %s\n' "$f"; sed 's/^/ /' /tmp/anybot-sh-lint.log; fail=1 + fi +done + +printf '\n' +python3 - <<'PY' || fail=1 +import glob, re, os, sys +pat = re.compile(r'(?/dev/null 2>&1 \ || die "安裝 Rust 失敗。" "手動:curl --proto '=https' -sSf https://sh.rustup.rs | sh" . "$HOME/.cargo/env" fi # 有人用 Rosetta 或跨架構:確保這個目標有標準庫。 if ! rustup target list --installed 2>/dev/null | grep -q "^${RUST_HOST}$"; then - rustup target add "$RUST_HOST" >/dev/null 2>&1 || warn "沒能加上 Rust 目標 $RUST_HOST,仍用 rustup 預設的主機目標試試" + rustup target add "$RUST_HOST" >/dev/null 2>&1 || warn "沒能加上 Rust 目標 ${RUST_HOST},仍用 rustup 預設的主機目標試試" fi rust_ok || die "Rust 還是太舊:$(rustc --version 2>/dev/null)" "執行 rustup update stable,或移除系統的 rustc/cargo 套件。" ok "Rust $(rustc --version | cut -d' ' -f2)" @@ -535,7 +535,7 @@ build_jobs() { build() { jobs=$(build_jobs) - info "編譯中,第一次約 5–15 分鐘($RUST_HOST;之後更新只重編改過的部分)…" + info "編譯中,第一次約 5–15 分鐘(${RUST_HOST};之後更新只重編改過的部分)…" log="$SRC/target/install-build.log"; mkdir -p "$SRC/target" if (cd "$SRC" && cargo build --release --bin anybot ${jobs:+-j "$jobs"}) >"$log" 2>&1; then ok "編譯完成"