Перейти к содержанию

Отключение обновлений на Станции 1

Рецепт останавливает службу обновлений Алисы, если колонка с root по кругу пытается поставить обязательное обновление, а Алиса отвечает с ошибками.

Проверено на: Яндекс Станция 1 (tulip), прошивка 2.369.5.46, root через AliceBridge, SSH (Dropbear) в /data/dropbear. На других моделях и прошивках не проверялось.

Колонка перестанет получать обновления и может потерять доступ к Алисе

Исправления ошибок и безопасности больше не придут. Если Яндекс перестанет обслуживать старую прошивку, Алиса может замолчать совсем.

Для моделей на Linux (Лайт, Мини и др.) обновления отключаются скриптом yandex-noupdate.sh из шага 2. На Станции 1 (Android) он не подходит: рецепт ниже только замораживает службу обновлений и ничего не меняет в /system.

Признаки

  • В /sensors_cache/logs/updatesd.log каждые ~40 секунд повторяется одна и та же пара строк: Has update: version: ... и Executing OTA script ....
  • На часть запросов Алиса не отвечает: подсветка переливается и гаснет. В /sensors_cache/logs/maind.log при этом видно onRequestError: ... error=ErrorDeviceNotReady, errorText=Настройте станцию заново.
  • Каждые ~30 секунд перезапускается локальный сервер на порту 1961: в maind.log повторяется Restarting WS server due to new auth data. Приложения на телефоне не могут подключиться.

Шаги

  1. Скопируйте contrib/station1-freeze-updatesd.sh на колонку (из клона репозитория):

    ssh root@<STATION_IP> 'cat > /data/dropbear/freeze_updatesd.sh' < contrib/station1-freeze-updatesd.sh
    
  2. Проверьте синтаксис:

    /sbin/busybox sh -n /data/dropbear/freeze_updatesd.sh && echo OK
    
  3. Добавьте запуск в /data/dropbear/start.sh сразу после строки #!/system/bin/sh:

    /sbin/busybox sed -i '1a /sbin/busybox setsid /sbin/busybox sh /data/dropbear/freeze_updatesd.sh </dev/null >>/data/dropbear/freeze.log 2>\&1 \&' /data/dropbear/start.sh
    
  4. Перезагрузите колонку:

    sync; reboot
    
  5. После загрузки убедитесь, что служба заморожена:

    cat /data/dropbear/freeze.log
    for p in /proc/[0-9]*; do
        case "$(tr '\0' ' ' < $p/cmdline 2>/dev/null)" in
            maind\ --updatesd*|*/maind\ --updatesd*) grep State $p/status;;
        esac
    done
    

    В журнале должны появиться строки freeze started и froze <pid>, а состояние процесса должно быть T (stopped). Нового updatesd.log в этой загрузке не появляется.

Переустановка SSH перезаписывает start.sh

После переустановки SSH через AliceBridge шаг 3 нужно повторить.

Откат

  1. Удалите строку с freeze_updatesd.sh из /data/dropbear/start.sh:

    /sbin/busybox sed -i '/freeze_updatesd/d' /data/dropbear/start.sh
    
  2. Перезагрузите колонку. Служба обновлений запустится как обычно.

Как это работает

  • Службы Алисы запускает quasar_launcher2 по списку из /system/vendor/quasar/launch.json. Обновлениями занимается задача updatesd (maind --updatesd). Если её завершить, лаунчер перезапускает её.
  • AliceBridge подменяет /system/vendor/quasar/device_ota_update.sh заглушкой, которая возвращает exit 1. Если сервер требует обязательное обновление (при регистрации отвечает "hasCriticalUpdate":true), updatesd бесконечно повторяет проверку файла и запуск установки. Именно в это время Алиса отвечает с ошибками.
  • Сигнал SIGSTOP оставляет процесс живым, но он ничего не делает. Лаунчер видит, что процесс есть, и не перезапускает его.
  • Шаблон в скрипте привязан к argv[0] (maind --updatesd* или */maind --updatesd*). Это важно: по подстроке без привязки под SIGSTOP попадает любой процесс, в чьей командной строке просто упоминается maind --updatesd — в том числе ваша же SSH-сессия, если выполнить в ней проверочную команду из шага 5. Тогда зависнет сессия, а не служба обновлений.
  • Скрипт работает в фоне и проверяет процессы раз в 3 секунды. Это нужно, потому что время запуска start.sh после загрузки меняется: наблюдалось и 28 секунд (раньше updatesd, который стартует примерно на 37-й секунде), и около 10 минут.
  • Подменить launch.json через mount -o bind из start.sh нельзя: лаунчер читает его на ~34-й секунде загрузки, и start.sh может запуститься позже.
  • Через системный /system/bin/sh фоновый скрипт после загрузки не оставался работать, а через /sbin/busybox sh работает. Причина не выяснена; похоже на то, что mksh из Android при выходе рассылает сигнал SIGHUP своей группе процессов, а busybox ash — нет (вывод, не проверялось). Именно поэтому в шаге 3 запуск идёт через setsid и с отсоединённым вводом-выводом: так процесс уходит в свою сессию и переживает выход родителя независимо от выбранной оболочки.

Ограничения

  • Между загрузкой и запуском start.sh служба обновлений успевает поработать. Если start.sh запускается поздно, Алиса может ненадолго уйти в режим обновления. Поставить прошивку служба всё равно не может: установка заблокирована заглушкой AliceBridge.
  • Сервер Яндекса уже знает, что колонке нужно обновление. После остановки updatesd Алиса отвечала нормально, но это проверено только на одной колонке, и поведение сервера может измениться.