fix(deploy): 交互提示写不进终端导致静默退出——fd 3 必须用 <> 打开,不能只读
Ubuntu 24.04 实机定位:菜单打印完就退回 shell、退出码 1、没有任何提示(用户三次复现)。 根因是 `exec 3</dev/tty` 以**只读**方式打开 fd 3,而 read_prompt / read_secret 要往它**写**提示语: $ exec 3<file; printf x >&3 bash: printf: write error: Bad file descriptor # 退出码 1 在 set -e 下这一下就把脚本打死;错误信息还因为走 tee 管道、脚本退出时进程替换的子进程来不及 flush 而被吞掉 —— 于是表现成"菜单打完就默默消失"。 - install.sh 的 open_prompt_fd、classhelper 的 open_tty 都改成 `exec 3<>/dev/tty`(读写打开); - 提示语写失败改为显式降级(该项用默认值 + 打印一条提示),不再让整条命令消失; - classhelper 里是同一份实现,不修的话 Linux 上 `classhelper password` 会同样毫无提示地退出。 本地复现验证过三种情形:只读 fd 写 → Bad file descriptor / 退出码 1;`<>` 写 → 成功; `if printf … >&3; then` 里的失败不会被 set -e 打死(新加的护栏确实兜住了)。
This commit is contained in:
1 parent
f6edfa5ea1
commit
2be8d30376
2 files changed
+30
-11
No files matched your search
+12
-4
@@ -348,7 +348,11 @@ PROMPT_FD=""
|
||||
open_prompt_fd() {
|
||||
if [ -n "$PROMPT_FD" ]; then return 0; fi
|
||||
if [ "${CLASSHELPER_NO_TTY:-0}" = "1" ]; then return 1; fi
|
||||
if exec 3</dev/tty 2>/dev/null; then PROMPT_FD=3; return 0; fi
|
||||
# 必须用 `<>`(读写)打开,不能只用 `<`(只读):下面 read_prompt 要往 fd 3 **写**提示语,
|
||||
# 而往只读 fd 写会 EBADF("printf: write error: Bad file descriptor"),在 set -e 下
|
||||
# 直接把安装脚本打死 —— 现象是"菜单打印完就默默退回 shell",错误还被 tee 吞掉,极难查。
|
||||
# 2026-10-05 在 Ubuntu 24.04 上实测踩到并定位。
|
||||
if exec 3<>/dev/tty 2>/dev/null; then PROMPT_FD=3; return 0; fi
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -362,9 +366,13 @@ read_prompt() {
|
||||
local prompt="$1" var="$2" hidden="${3:-0}" value=""
|
||||
printf -v "$var" ''
|
||||
if open_prompt_fd; then
|
||||
printf '%s' "$prompt" >&3
|
||||
if [ "$hidden" = "1" ]; then IFS= read -r -s value <&3 || true; else IFS= read -r value <&3 || true; fi
|
||||
printf '\n' >&3
|
||||
# 提示语写不进去时**不能让它把脚本打死**:退化成"这一项用默认值",并且把这件事说出来
|
||||
if printf '%s' "$prompt" >&3 2>/dev/null; then
|
||||
if [ "$hidden" = "1" ]; then IFS= read -r -s value <&3 || true; else IFS= read -r value <&3 || true; fi
|
||||
printf '\n' >&3 2>/dev/null || true
|
||||
else
|
||||
fail_print "$(printf '%s[classhelper]%s 写不进终端(fd 3 不可写),这一项按默认值处理' "$C_YELLOW" "$C_RESET")"
|
||||
fi
|
||||
fi
|
||||
# 刻意**不**退回 stdin:`curl … | bash` 时 stdin 就是脚本内容本身,
|
||||
# 从 stdin 读会把脚本的下一行当成用户输入吃掉,表现为"脚本后半段莫名其妙乱套"。
|
||||
|
||||
Reference in new issue
Block a user