15.07.2026: Среда доработки
Нейроразминка
Снилась дичь. Запомнилось, как общался с колонкой Алиса (от Яндекса). При том, мысленно. Это было бы очень странно, если бы не вчерашний пост. А так… Так это больше похоже на отсылку.
Кстати об Алисе. Сегодня она заявила, что середина лета приходится на 21 июня. Ну либо на 14-15 июля. В веб-версии, куда я перезашёл после ответа умной колонки, она эту мысль вполне обосновывает. Так что сие не какая-то там придурь или глюк.
А я считаю просто.
- Беру количество дней календарного лета 30+31+31 = 92.
- Делю это число пополам 92/2 = 46. Вот 46-день лета и будет его серединой.
- А дата… 46-30 = 16.
Для меня середина лета это 16 июля. Т.е. завтра. Сегодня я всё ещё нахожусь в первой половине нынешнего лета.

Что на это скажет DeepSeek?
Погоди-погоди! Серьёзно? А если спросим ChatGPT?

…по традиции астрономии, астрономическое лето — период между летним солнцестоянием и осенним равноденствием. В Северном полушарии оно продолжается с 21 (20) июня по 23 (22) сентября. В Южном полушарии астрономическое лето продолжается с 21 (22) декабря по 20 (21) марта[4][неавторитетный источник]. В разные годы (на Земле) эти астрономические отрезки приходятся на разное время (в пределах указанных суток).
Т.е. Алиса, называя 21 июня серединой лета, мягко говоря, наврала? Или нет? Давай глянем что есть такое Мидсаммер, на который она ссылается?
Мидсаммер или Мидсоммар (Шведский: [ˈmɪˌsmːar] или [ˈmǐːdˌsmːar]) — это праздник лета, который отмечается в день летнего солнцестояния в Северном полушарии или незадолго до него, в самый длинный день в году. Название «середина лета» в основном относится к праздникам летнего солнцестояния европейского происхождения. В этих культурах традиционно считается, что это середина лета, а сезон начинается 1 мая.[9] Хотя в Северном полушарии летнее солнцестояние приходится на 20, 21 или 22 июня, в большей части Европы его традиционно отмечали 23–24 июня. Эти даты были христианизированы и стали кануном и днём святого Иоанна. Обычно его отмечают гуляньями на свежем воздухе, которые включают костры, танцы вокруг майского дерева и застолья.
Вот хоть смейся, хоть плач. Формально, Алиса оказалась права. У шведов середина лета, по каким-то их традициям, и правда приходится на день летнего солнцестояния.
Но есть одна маленькая неувязочка. Я как бы не швед. И не астроном. И даже не агроном. Я программист, тестировщик, обыватель, сотрудник на сорокачасовой рабочей неделе, блогер и т.д. Логично, что в моём контексте правильным ответом было бы 16-е июля. Ну или более близкое, округлённое нежеланием вдаваться в математику, 15-е июля.

А давай проверим! DeepSeek выдал именно тот ответ, который я ожидал. Спросим у остальных, дав им контекст.
Вот что ответил ChatGPT.

А вот что ответила Алиса.
Всё не влезло в скрин, но изначальный вопрос звучал как и у остальных: «Привет. Какого числа середина лета?».
Ну что же. Благодаря этому простому эксперименту я изменил мнение на счёт нейроимплантов. Всё-таки современные ИИ волне годятся, при условии что они погружены в мой контекст, и что туда не попадёт Алиса (от Яндекса), в её теперешнем виде.

Хоть ГигаЧат и прогнал дичи (я о 24 июня), но его основной ответ получился таким как у ChatGPT.

Мечты-мечты, туды-сюды… Для работы Дипсика нужна коробка, размером с небольшой сейф и по цене небольшого автомобиля. При этом греться она будет как масляный радиатор. Увы, но в ближайшее время рассчитывать на то, что такая хренотень безопасно разместится в черепе можно только в мире, где давно и стабильно освоили пространственную магию, да и то с некоторыми оговорками.
Впрочем, на моей книжной полке стоит книга — Программирование на ЭЦВМ «Минск-2» и «Минск-22». С её издания прошло 55 лет.
Компьютер «Минск-22» (1965)
- Занимал площадь 50 м²
- Тактовая частота: 0,25 МГц
- Операций в секунду: ~6 000
- Оперативная память: 38 КБ
Микроконтроллер ESP32-C3 (2021)
- Размером с почтовую марку
- Тактовая частота: 160 МГц
- Операций в секунду: до 160 000 000
- Оперативная память: 400 КБ

Доживём — увидим.
Итак, утро началось не только с кофе. Впрочем, сразу после того как убрал ESP32-C3 и отнёс спичечный коробок на кухню, стартовал рабочий день.

Ну и раз такое дело, то решил ударными темпами выполнить всю недельную норму, скажем, к середине четверга. Вот только один из руководителей смежного отдела решил попробовать свои силы в автоматизации API-тестов.

В результате, днём сервер помер. Отказала база данных. Чинили её до семи вечера. Ну а я накодил кое-как вслепую, ибо не проверить, да и выкинул из головы всю эту чушь. Пусть сами разбираются, что, почему, у кого и откуда руки растут….
Ну а я, вместе с Эль, отправился в лес погуляти.

Подкроватный сервер и вокальный угар
Есть у меня маленький домашний серверочек, собранный на устаревшем (а потому сильно подешевевшем «железе»). В этом году менял на нём SSD.
Поскольку монитор к нему не подключен, а каждый раз вползать туда по SSH мне лениво, давно сделал для него пингач. Достаточно сказать колонке: «Алиса, пингани сервер», — и из-под стола доносится бодрое «Сервер функционирует, пинг получен».

Сегодня, совершенно случайно, выяснил, что сервер заткнулся и не отвечает, хотя работает. Вроде…
Полез внутрь, ну и заодно, пока не разогнулся, решил допилить нормальный синтез речи, который недоделал несколько лет тому… Разбирался вместе с одним продвинутым ИИ. И вот тут начался спектакль в девяти актах с прологом и хэппи-эндом.
Акт 1: «А он и не был недоделан»
Моя версия: синтез речи я когда-то начал прикручивать, но недокрутил. Там внутри демон на Silero — я его прозвал вокабулятором. Я честно пытался его настроить по разным гайдам, но не преуспел.
Ассистент полез в старый лог демона и вернулся с фактами: 66 принятых соединений, каждое закрыто штатным «Иду на новый круг», плюс 42 записи от torch о реальном прогоне модели. Ни одной ошибки.
То есть вокабулятор был доделан. Работал. Говорил. Просто я этого не заметил почему-то.

Акт 2: Сервер, которого больше нет
Дальше выяснилась деталь, которая объяснила вообще всё. В апреле я переустановил сервер с нуля (когда менял SSD). Данные уцелели: код на месте, mp3 на месте, 60 мегабайт модели Silero на месте. Всё выглядит живым.

И вот в чём коварство. PHP вызывает mpg123 через exec(). Программы нет — exec() молча возвращает «command not found». Никакой ошибки, никакого лога. Просто тишина. Код на диске выглядит идеально рабочим и врёт мне в лицо.

Акт 3: Самострел
Копнули глубже — и стало ещё веселее. Мой старый код проигрывал звук так:
pulseaudio -D && mpg123 -o pulse файл && pulseaudio -k
Видите последнее? Каждый пинг ПОДНИМАЛ PulseAudio, играл, а потом УБИВАЛ его. Тот самый PulseAudio, через который вокабулятор держал звуковой поток. То есть каждое «Пинг получен» ломало синтез речи. Годами. Но регулярно.

Перешли на ALSA напрямую. Заодно оказалось, что пользователь веб-сервера вообще не состоял в группе audio — то есть до звуковой карты не дотягивался в принципе. Бедняга даже не знал, что у него есть динамик.
Акт 4: Сервис-призрак
Почему демон не переживал перезагрузки? Я был уверен, что сделал systemd-сервис. У меня даже readme лежит с командами:
systemctl enable vocabulater.service systemctl start vocabulater.service
А сервиса не существовало. Никогда. Это была не документация, а список намерений. Я написал себе инструкцию и не выполнил её. Демон запускался руками и умирал с каждым ребутом, а я каждый раз думал, что «что-то опять отвалилось».
В общем, сделали сервис. Перезагрузил сервер. И через минуту он сам, без единой команды, сказал в темноту: «Стартую вокабулятор».

Интерлюдия: Ударение
Первая же фраза прозвучала с ударением «проверка связИ», и где-то в закоулках моей души шевельнулся… француз. Оказалось, Silero умеет в ударения — знаком «+» перед ударной гласной. Написал «св+язи», и говорилка исправилась.

Акт 5: Кроличья нора
Звук починили. Пинг работает. Локально. А из Home Assistant — нет. Потому что он ходит по HTTPS, а у меня истекли сертификаты. Все одиннадцать. В один день.

Оказалось — не совпадение: их выпустили пачкой при апрельской переустановке, Let’s Encrypt живёт 90 дней. Так общий день рождения дал общий день смерти. Помянем.
Почему не продлились? А потому что в коде панели управления сервером (не надо на меня так смотреть, это другие разрабы постарались) была синтаксическая ошибка. Крон исправно запускался каждую ночь в три часа, падал на импорте и умирал. Три месяца. Каждую ночь. В три часа. А сообщения об ошибках он отправлял письмами локальному root — в почтовый ящик, которого нет.

Ошибку я поправил. Однако, сертификаты не выпустились. Здравствуй, акт шестой.
Акт 6: Шесть версий, шесть промахов
Дальше был час, за который ассистент выдвинул и похоронил шесть гипотез:
- Гипотеза: Крон не работает. Оказалось: работает, задача на месте
- Гипотеза: Порт 80 закрыт снаружи. Оказалось: открыт, 12 стран из 12 достучались
- Гипотеза: Мёртвый домен топит пачку. Оказалось: все домены смотрят куда надо
- Гипотеза: fail2ban банит проверяющих. Оказалось: ни одного бана, там одни боты с /wp-admin/
- Гипотеза: Проблема в IPv6. Оказалось: нет никаких IPv6-записей
- Гипотеза: Асимметричная маршрутизация. Оказалось: это противоречит настройкам роутера
Отдельно отмечу лучший момент. Ассистент бодро заявил: «Порт 80 открыт снаружи, проверено!» — а проверял он с моего же компьютера. Из моей же локальной сети. Запрос развернулся на роутере и наружу вообще не вышел. Он это сам поймал и честно признал. Уважаю. Но осадочек остался.

Акт 7: Роутер ни у чём не виноват
Настоящая причина оказалась красивой. У меня на роутере был поднят КВН, но для конкретных адресов — прописан списком статических маршрутов. Сервер при этом честно сидит на политике «Прямое подключение», а потому КВН к нему никак не относится.

Статические маршруты в роутере оказались… глобальными. Они кроют политики приоритетов подключений, как… Впрочем, не будем о животноводстве. Приоритеты подключений задают, каким каналом устройство ВЫХОДИТ в интернет. А маршрут — правило уровнем ниже, и оно срабатывает первым.
И вот что происходит. Проверяющий Let’s Encrypt стучится ко мне на порт 80. Доходит. Сервер отвечает. Роутер смотрит на пакет и видит только «куда» — адрес получателя. А тот случайно попал в мой КВН-список. Для роутера нет разницы между «я иду на этот адрес» и «я отвечаю на входящий с этого адреса». Ответ уходит в туннель и вылезает наружу совсем с другого IP. Проверяющий ждёт ответ от одного адреса, получает от другого, крути пальцем у виска и пишет: «Timeout during connect».
Доказали трассировкой: для одних адресов второй хоп — мой провайдер, 0.6 мс. Для других — приватный адрес и скачок задержки до 89 мс. Туннель.

Акт 8: Мина
Выключил КВН, пошли выпускать сертификаты. Выпустились. А сайты по HTTPS всё равно отдают чужую просрочку.
Полезли смотреть, почему nginx не подхватил новые файлы. И нашли вот это:
include /www/server/panel/vhost/nginx/*.conf; } ← закрылся блок http listen [::]:80 ipv6only=off; ← а это висит снаружи, вне каких-либо блоков.

Одна лишняя строка. Панель дописала директиву не туда. Конфиг не проходил проверку. Работающий nginx жил на СТАРОМ конфиге, загруженном в память при последнем запуске. Перечитать себя он не мог. А значит: новые сертификаты не применялись, панель молча откатывала правки.
Это к тому, что при первой же перезагрузке сервера, nginx бы просто НЕ ПОДНЯЛСЯ. А с ним полегли бы и все одиннадцать сайтов. Разом. Без предупреждения.

Удалили строку. Проверка прошла. Сертификаты применились. Семнадцать доменов (нашлись ещё и кириллические, о которых я забыл) получили новенькие сертификаты до октября. И сервер, наконец, сказал «Пинг получен» в ответ на запрос из Home Assistant. Через HTTPS. Как и было задумано в 2023 году.
Акт 9: Сторож, который говорит
Раз уж сервер теперь умеет говорить — пусть говорит по делу. Попросил у ИИ помочь написать скрипт, который раз в день проверяет сертификаты и, если что-то не так, объявит вслух, какие домены пострадали.
Ещё одно применение вокабулятора для дела. Взрослеем. Умнеем.

Первая версия проверяла файлы на диске. Отрапортовала: всё годно. А один сайт при этом не работал. Потому что годный файл на диске ничего не значит, если он не прописан в конфиге. nginx в таком случае молча берёт сертификат от первого попавшегося соседа. Браузер получает подлинный пропуск, но на чужое имя. Это как предъявить настоящий паспорт, но не свой.
Переписали: теперь скрипт спрашивает у nginx, что тот РЕАЛЬНО отдаёт в эфир для каждого домена, и сверяет имя. Первый же запуск новой версии обнаружил проблему и торжественно сообщил вслух:
«Внимание. Проблема с сертификатами. Пострадал 1 домен. 127 точка 0 точка 0 точка 1 — чужой сертификат»

Сторож поправил очки, покряхтел, но согласился.
Что в итоге
Сервер говорит. Сам поднимается после перезагрузки. Произносит любой текст живым голосом, с ударениями. Пинг из Home Assistant отвечает быстро. Сторож следит за сертификатами и докладывает голосом. Сертификаты можно не трогать до октября.
Корневую причину — маршруты на роутере — я тупо вырубил.

Вот так оно и бывает. Исходная задача звучит как «научить сервер говорить». Потом выясняется, что он как бы умел, всё это время, но не мог. А потому что в апреле, по ходу замены SSD, из под него вынесло всё, на чём он стоял, а я потом удивлялся тишине, когда заметил, спустя 3 месяца.
Что я запомнил
- exec() молчит, когда программы нет. Тишина — это тоже ошибка.
- Код на диске не доказывает, что оно работает. Проверяй пакеты.
- Readme с командами — это не «сделано». Это может оказаться список намерений, или вовсе мечты-мечты.
- Проверять внешнюю доступность изнутри своей сети — всё равно что закрыть глаза ладошками, и думать, что «сделал темно» всему миру.
- Шесть красивых гипотез не стоят одной трассировки.
- Мониторинг, проверяющий файл вместо реального результата, врёт, но врёт успокаивающе.
- Если что-то падает каждую ночь в три часа и никто не жалуется — возможно, жалобы уходят в почтовый ящик, которого нет.
- Иногда чинишь одно, а находишь мину под другим. Это и есть лучшая часть. Так что поосторожнее с минами.
Тем временем вечер закончился. И это было даже весело. Словно смотрел черно-белый детектив из 60-х.
Напишите комментарий