diff --git a/scripts/install.sh b/scripts/install.sh index a1ba1cc..37179bb 100644 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -3,6 +3,7 @@ # 用法: # curl -fsSL https://git.bz121.com/dekun/LocalNav/raw/main/scripts/install.sh | bash # bash install.sh +# curl -fsSL .../install.sh | bash -s -- install -y set -euo pipefail DEFAULT_REPO="https://git.bz121.com/dekun/LocalNav.git" @@ -15,20 +16,42 @@ need_cmd() { } } +run_navctl() { + local navctl_py="$1" + shift + # curl | bash 时 stdin 是管道,无法交互;改从终端设备读取 + if [ ! -t 0 ]; then + if [ ! -r /dev/tty ]; then + echo "[FAIL] 当前为非交互环境且无法打开 /dev/tty" >&2 + echo "请改用: curl -fsSL .../install.sh -o install.sh && bash install.sh" >&2 + echo "或非交互安装: curl -fsSL .../install.sh | bash -s -- install -y" >&2 + exit 1 + fi + exec python3 "$navctl_py" "$@" /dev/null && pwd || true)" -NAVCTL_PY="${SCRIPT_DIR}/navctl.py" - -if [ ! -f "$NAVCTL_PY" ]; then - TMP_DIR="$(mktemp -d)" - trap 'rm -rf "$TMP_DIR"' EXIT - echo "[OK] 正在下载部署管理脚本..." - curl -fsSL "${RAW_BASE}/navctl.py" -o "${TMP_DIR}/navctl.py" - curl -fsSL "${RAW_BASE}/nav_common.py" -o "${TMP_DIR}/nav_common.py" - export PYTHONPATH="${TMP_DIR}:${PYTHONPATH:-}" - exec python3 "${TMP_DIR}/navctl.py" "$@" +# curl | bash 时 BASH_SOURCE 可能未设置;仅当脚本为真实文件时才走本地路径 +script_path="${BASH_SOURCE[0]:-}" +if [[ -n "$script_path" && -f "$script_path" ]]; then + script_dir="$(cd "$(dirname "$script_path")" && pwd)" + if [[ -f "${script_dir}/navctl.py" ]]; then + run_navctl "${script_dir}/navctl.py" "$@" + fi fi -cd "$(dirname "$NAVCTL_PY")" -exec python3 "$NAVCTL_PY" "$@" +download_and_run "$@" diff --git a/scripts/navctl.py b/scripts/navctl.py index 86db196..a2ec49e 100644 --- a/scripts/navctl.py +++ b/scripts/navctl.py @@ -41,12 +41,25 @@ def _fail(msg: str) -> None: def _pause() -> None: + if not sys.stdin.isatty(): + return try: input("\n按回车返回菜单...") except (EOFError, KeyboardInterrupt): print() +def _require_tty(action: str) -> None: + if sys.stdin.isatty(): + return + print(f"[FAIL] 当前环境无法交互式{action}(stdin 不是终端)", file=sys.stderr) + print("请使用以下方式之一:", file=sys.stderr) + print(" bash scripts/install.sh", file=sys.stderr) + print(" python3 scripts/navctl.py install -y", file=sys.stderr) + print(" curl -fsSL .../install.sh | bash -s -- install -y", file=sys.stderr) + sys.exit(1) + + def prompt_value(label: str, default: str) -> str: try: raw = input(f"{label} [{default}]: ").strip() @@ -118,6 +131,8 @@ def run_deploy(project_dir: Path, py_exe: str) -> None: def action_install(*, repo: str = "", dest: str = "", yes: bool = False) -> None: + if not yes: + _require_tty("安装") print() print("=" * 50) print(" 一键部署安装") @@ -168,6 +183,7 @@ def action_update(*, dest: str = "") -> None: def action_uninstall(*, dest: str = "") -> None: + _require_tty("卸载") print() print("=" * 50) print(" 一键卸载") @@ -249,6 +265,7 @@ def render_menu(project_dir: Path | None) -> None: def interactive_menu() -> None: + _require_tty("打开菜单") print(f"LocalNav 部署管理 · {platform.system()} {platform.release()}") while True: project_dir = resolve_project_dir() @@ -259,6 +276,11 @@ def interactive_menu() -> None: print("\n再见。") return + if not choice: + _warn("请输入 0-3") + _pause() + continue + if choice == "1": try: action_install()