Skip to content

Commit 4925824

Browse files
committed
Replace bare /dev/tty reads with prompt_confirm
Headless/unattended runs (cron, PHS_SILENT=1) have no /dev/tty, causing bare `read … </dev/tty` calls to fail with a device error or spin forever. Replace all such reads in network_check, pkg_update mirror fallback, check_container_resources, and check_container_storage with prompt_confirm (which respects is_unattended) and add clearer messages when a prompt is skipped automatically.
1 parent a4a1289 commit 4925824

3 files changed

Lines changed: 32 additions & 19 deletions

File tree

‎lxc/alpine-install.func‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,8 @@ network_check() {
129129
fi
130130

131131
if [[ $ipv4_connected == false ]]; then
132-
read -r -p "No Internet detected, would you like to continue anyway? <y/N> " prompt </dev/tty
133-
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
132+
# See lxc/install.func: a bare read from /dev/tty kills a headless install.
133+
if prompt_confirm "No Internet detected, would you like to continue anyway?" "n"; then
134134
echo -e "${INFO}${RD}Expect Issues Without Internet${CL}"
135135
else
136136
echo -e "${NETWORK}Check Network Settings"

‎lxc/install.func‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -518,8 +518,12 @@ pkg_update() {
518518
else
519519
msg_warn "Find Debian mirrors at: https://www.debian.org/mirror/list"
520520
fi
521-
while true; do
522-
read -rp " Enter a mirror hostname (or 'skip' to abort): " custom_mirror </dev/tty
521+
# Only ask when there is someone to answer. Headless, /dev/tty does not
522+
# exist, the read fails instantly, custom_mirror stays empty and the
523+
# `continue` below spins the loop forever instead of prompting. Falling
524+
# through leaves apt_ok=false, which the caller reports properly.
525+
while ! is_unattended; do
526+
read -rp " Enter a mirror hostname (or 'skip' to abort): " custom_mirror </dev/tty || break
523527
[[ -z "$custom_mirror" ]] && continue
524528
[[ "$custom_mirror" == "skip" ]] && break
525529
[[ ! "$custom_mirror" =~ ^[a-zA-Z0-9._-]+$ ]] && {
@@ -1162,8 +1166,10 @@ network_check() {
11621166

11631167
# If both IPv4 and IPv6 checks fail, prompt the user
11641168
if [[ $ipv4_connected == false && $ipv6_connected == false ]]; then
1165-
read -r -p "No Internet detected, would you like to continue anyway? <y/N> " prompt </dev/tty
1166-
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
1169+
# prompt_confirm, not a bare read from /dev/tty: an install driven from cron
1170+
# or any other headless context has no /dev/tty, and reading from it there
1171+
# aborted with a device error instead of answering the question.
1172+
if prompt_confirm "No Internet detected, would you like to continue anyway?" "n"; then
11671173
echo -e "${INFO}${RD}Expect Issues Without Internet${CL}"
11681174
else
11691175
echo -e "${NETWORK}Check Network Settings"

‎ui/menu.func‎

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -423,10 +423,17 @@ check_container_resources() {
423423
if [[ "$current_ram" -lt "$var_ram" ]] || [[ "$current_cpu" -lt "$var_cpu" ]]; then
424424
echo -e "\n${INFO}${HOLD} ${GN}Required: ${var_cpu} CPU, ${var_ram}MB RAM ${CL}| ${RD}Current: ${current_cpu} CPU, ${current_ram}MB RAM${CL}"
425425
echo -e "${YWB}Please ensure that the ${APP} LXC is configured with at least ${var_cpu} vCPU and ${var_ram} MB RAM for the build process.${CL}\n"
426-
echo -ne "${INFO}${HOLD} May cause data loss! ${INFO} Continue update with under-provisioned LXC? <yes/No> "
427-
read -r prompt </dev/tty
428-
if [[ ! ${prompt,,} =~ ^(yes)$ ]]; then
429-
echo -e "${CROSS}${HOLD} ${YWB}Exiting based on user input.${CL}"
426+
# prompt_confirm, not a bare read from /dev/tty. update-apps.sh exports
427+
# PHS_SILENT=1 for unattended runs and cron has no /dev/tty at all, so the
428+
# read failed the whole update with a device error instead of answering the
429+
# question it was asked.
430+
echo -e "${INFO}${HOLD} ${RD}May cause data loss!${CL}"
431+
if ! prompt_confirm "Continue update with under-provisioned LXC?" "n"; then
432+
if is_unattended; then
433+
echo -e "${CROSS}${HOLD} ${YWB}Not continuing: LXC is under-provisioned and there is nobody to ask.${CL}"
434+
else
435+
echo -e "${CROSS}${HOLD} ${YWB}Exiting based on user input.${CL}"
436+
fi
430437
exit 113 # user aborted an under-provisioned update
431438
fi
432439
else
@@ -450,16 +457,16 @@ check_container_storage() {
450457

451458
if [ "$usage" -gt 80 ]; then
452459
echo -e "${INFO}${HOLD}${YWB}Warning: Storage is dangerously low (${usage}%).${CL}"
453-
printf "Continue anyway? <y/N> "
454-
read -r prompt </dev/tty
455-
456-
case "$prompt" in
457-
[yY][eE][sS] | [yY]) ;;
458-
*)
459-
echo -e "${CROSS}${HOLD}${YWB}Exiting based on user input.${CL}"
460+
# See check_container_resources above for why this is not a bare read.
461+
if ! prompt_confirm "Continue anyway?" "n"; then
462+
if is_unattended; then
463+
echo -e "${CROSS}${HOLD}${YWB}Not continuing: only $((100 - usage))% of / is free and there is nobody to ask.${CL}"
464+
echo -e "${TAB}${YWB}An upgrade that runs out of disk mid-dpkg leaves the container broken.${CL}"
465+
else
466+
echo -e "${CROSS}${HOLD}${YWB}Exiting based on user input.${CL}"
467+
fi
460468
exit 114 # user aborted with storage too low
461-
;;
462-
esac
469+
fi
463470
fi
464471
}
465472

0 commit comments

Comments
 (0)