From b17ad6d8aaf15a3cb51a2a38755609a8307746be Mon Sep 17 00:00:00 2001 From: zuevav Date: Mon, 5 Oct 2026 21:16:24 +0300 Subject: [PATCH] =?UTF-8?q?=D0=AD=D0=BA=D1=80=D0=B0=D0=BD=20=D1=83=D1=81?= =?UTF-8?q?=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D0=BA=D0=B8=20=D1=81=D0=B8=D1=81?= =?UTF-8?q?=D1=82=D0=B5=D0=BC=D1=8B:=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D0=BA=D0=B8=20=D1=8D?= =?UTF-8?q?=D0=BA=D1=80=D0=B0=D0=BD=D0=B0=20=D1=83=D1=81=D1=82=D0=B0=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D1=89=D0=B8=D0=BA=D0=B0=20Ubuntu=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=BD=D1=81=D0=BE=D0=BB=D1=8C=20=C2=AB=D0=B2=D0=B5=D1=88=D0=B0?= =?UTF-8?q?=D0=B5=D1=82=D1=81=D1=8F=C2=BB=20(vhangup)=20=D0=B8=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=BF=D0=B8=D1=81=D1=8C=20=D0=B2=20=D0=BF=D1=80=D0=B5?= =?UTF-8?q?=D0=B6=D0=BD=D0=B8=D0=B9=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=20?= =?UTF-8?q?=D0=B4=D0=B0=D1=91=D1=82=20EIO=20=E2=80=94=20=D1=8D=D0=BA=D1=80?= =?UTF-8?q?=D0=B0=D0=BD=20=D0=BF=D0=B0=D0=B4=D0=B0=D0=BB=20=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B2=D0=BE=D0=BC=20=D0=BA=D0=B0=D0=B4=D1=80?= =?UTF-8?q?=D0=B5=20(=D0=B6=D1=83=D1=80=D0=BD=D0=B0=D0=BB=20=D1=83=D1=81?= =?UTF-8?q?=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D0=BA=D0=B8=20.28);=20=D1=82?= =?UTF-8?q?=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20=D0=BA=D0=BE=D0=BD=D1=81=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=20=D0=BE=D1=82=D0=BA=D1=80=D1=8B=D0=B2=D0=B0=D0=B5?= =?UTF-8?q?=D1=82=D1=81=D1=8F=20=D0=B7=D0=B0=D0=BD=D0=BE=D0=B2=D0=BE,=20?= =?UTF-8?q?=D1=88=D1=80=D0=B8=D1=84=D1=82=20=D1=81=D1=82=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=81=D1=8F=20=D1=8F=D0=B2=D0=BD=D0=BE=20=D0=BD=D0=B0=20?= =?UTF-8?q?tty1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi --- deploy/iso/bj-install-progress | 53 +++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/deploy/iso/bj-install-progress b/deploy/iso/bj-install-progress index e272166..70a14e8 100644 --- a/deploy/iso/bj-install-progress +++ b/deploy/iso/bj-install-progress @@ -231,6 +231,46 @@ def demo(path, html_out): LIVE = "BJ_PROGRESS_STATE" not in os.environ # настоящая установка (не проверка) +TTY = "/dev/tty1" + + +class Console: + """Вывод на первую консоль. Экран установщика Ubuntu при остановке «вешает» консоль (vhangup): открытый + до этого вывод отвечает EIO (так упал первый вариант экрана) — тогда консоль открывается заново.""" + + def __init__(self): + self.f = None + + def _open(self): + if not LIVE: + return sys.stdout + return open(TTY, "w", encoding="utf-8", errors="replace") + + def write(self, s): + for _ in range(5): + try: + if self.f is None: + self.f = self._open() + self.f.write(s) + self.f.flush() + return + except OSError: + if self.f is not None and self.f is not sys.stdout: + try: + self.f.close() + except OSError: + pass + self.f = None + time.sleep(0.3) + + def size(self): + try: + return os.get_terminal_size(self.f.fileno()) if self.f is not None else os.get_terminal_size(sys.stdout.fileno()) + except OSError: + return os.terminal_size((100, 37)) + + +OUT = Console() PSF = "/snap/subiquity/current/subiquity.psf" # шрифт консоли установщика: кириллица и рамки @@ -244,7 +284,7 @@ def hold_console(state, font_set): subprocess.call(["systemctl", "stop", "--no-block", CLIENT_UNIT], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) sys.stderr.write("bj-install-progress: экран установщика Ubuntu остановлен\n") if not font_set and os.path.exists(PSF): - font_set = subprocess.call(["setfont", PSF], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0 + font_set = subprocess.call(["setfont", "-C", TTY, PSF], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0 return font_set @@ -263,7 +303,7 @@ def main(): def run(): sys.stderr.write("bj-install-progress: экран установки запущен\n") font_set = hold_console(read_state(), False) - sys.stdout.write("\033[?25l") # без мигающего курсора + OUT.write("\033[?25l") # без мигающего курсора p = Progress() j = subprocess.Popen(["journalctl", "-b", "-o", "json", "-f", "-n", "all", "-q", "SUBIQUITY_EVENT_TYPE=start", "SUBIQUITY_EVENT_TYPE=finish", "SUBIQUITY_EVENT_TYPE=error"], @@ -287,17 +327,16 @@ def run(): font_set = hold_console(p.state, font_set) if p.state == "NEEDS_CONFIRMATION": # установщик ждёт подтверждения — это делает его экран j.terminate() - sys.stdout.write("\033[?25h\033[H\033[2J") + OUT.write("\033[?25h\033[H\033[2J") return 3 - cols, rows = shutil.get_terminal_size((100, 37)) - sys.stdout.write(to_ansi(frame(p, cols, rows))) - sys.stdout.flush() + cols, rows = OUT.size() + OUT.write(to_ansi(frame(p, cols, rows))) if p.error: if not error_at: error_at = time.time() elif time.time() - error_at > 6: j.terminate() - sys.stdout.write("\033[?25h\033[H\033[2J") + OUT.write("\033[?25h\033[H\033[2J") return 2 # обёртка запустит экран установщика Ubuntu: подробности и командная строка