#!/usr/bin/env bash # Установщик воркера распознавания для Mac и Linux. Одна команда: # # curl -fsSL https://asr.unitcode.dev/install.sh | bash # # Что делает: кладёт файлы воркера в ~/asr-worker, спрашивает ваш токен GitLab, # записывает .env и запускает воркер. На Mac — как службу launchd (переживает # перезагрузку), на Linux — контейнером Docker с автозапуском. # Ничего, кроме ~/asr-worker и (на Mac) одного файла в ~/Library/LaunchAgents, # не трогает. Повторный запуск — обновляет файлы и перезапускает. set -euo pipefail BASE="${ASR_QUEUE_URL:-https://asr.unitcode.dev}" DIR="${ASR_WORKER_DIR:-$HOME/asr-worker}" OS="$(uname -s)"; ARCH="$(uname -m)" say() { printf '\n\033[1m%s\033[0m\n' "$*"; } die() { printf '\n\033[31m%s\033[0m\n' "$*" >&2; exit 1; } say "Воркер распознавания планёрок → $DIR" mkdir -p "$DIR"; cd "$DIR" for f in worker.py run-mac.sh docker-compose.yml docker-compose.cpu.yml .env.example; do curl -fsSL "$BASE/get/$f" -o "$f" || die "не скачать $f с $BASE" done chmod +x run-mac.sh # --- токен --------------------------------------------------------------- if [ -f .env ] && grep -q '^ASR_WORKER_TOKEN=.\+' .env; then say "Токен уже есть в .env — оставляю." else cat </dev/null | head -c 20 || true) [ -n "$WHO" ] || die "очередь не приняла токен. Проверьте, что это токен GitLab с галкой read_api и вы состоите в проекте planerka." cp .env.example .env sed -i.bak "s|^ASR_WORKER_TOKEN=.*|ASR_WORKER_TOKEN=$TOKEN|" .env && rm -f .env.bak sed -i.bak "s|^WORKER_NAME=.*|WORKER_NAME=$(hostname -s)|" .env && rm -f .env.bak chmod 600 .env say "Токен принят." fi set -a; . ./.env; set +a # --- Mac ----------------------------------------------------------------- if [ "$OS" = "Darwin" ]; then [ "$ARCH" = "arm64" ] || die "Mac на Intel не подходит: нужен чип Apple (M1 и новее)." command -v brew >/dev/null || die "Нет Homebrew. Поставьте с https://brew.sh и запустите установщик снова." for t in uv ffmpeg; do command -v "$t" >/dev/null || { say "Ставлю $t…"; brew install "$t"; }; done say "Ставлю окружение и модель (первый раз — несколько минут)…" ./run-mac.sh --install PLIST="$HOME/Library/LaunchAgents/ru.unitcode.asr-worker.plist" mkdir -p "$HOME/Library/LaunchAgents" cat > "$PLIST" < Labelru.unitcode.asr-worker ProgramArguments$DIR/run-mac.sh WorkingDirectory$DIR EnvironmentVariablesPATH/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin RunAtLoad KeepAlive StandardOutPath$DIR/worker.log StandardErrorPath$DIR/worker.log PL launchctl bootout "gui/$(id -u)/ru.unitcode.asr-worker" 2>/dev/null || true launchctl bootstrap "gui/$(id -u)" "$PLIST" say "Готово. Воркер запущен как служба и будет стартовать при входе в систему." echo "Журнал: tail -f $DIR/worker.log" echo "Остановить: launchctl bootout gui/$(id -u)/ru.unitcode.asr-worker" echo "Запустить: launchctl bootstrap gui/$(id -u) $PLIST" exit 0 fi # --- Linux --------------------------------------------------------------- command -v docker >/dev/null || die "Нет Docker. Поставьте: curl -fsSL https://get.docker.com | sudo sh (и добавьте себя в группу docker)" docker info >/dev/null 2>&1 || die "Docker не отвечает. Запущен ли он, и вы в группе docker?" COMPOSE=docker-compose.yml # Toolkit в режиме CDI: устройства идут через OCI-спеку, и cgroup выставляет сам # runc. В legacy-режиме на cgroup v2 контейнер видит /dev/nvidia-uvm, но # открыть не может (14.09, Arch) — nvidia-smi работает, CUDA нет. if command -v nvidia-ctk >/dev/null && ! nvidia-ctk config 2>/dev/null | grep -q '^mode = "cdi"'; then say "Перевожу nvidia-container-toolkit в режим CDI (спросит пароль sudo)." sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml >/dev/null \ && sudo nvidia-ctk config --set nvidia-container-runtime.mode=cdi --in-place \ && sudo nvidia-ctk runtime configure --runtime=docker --cdi.enabled >/dev/null \ && sudo systemctl restart docker \ || say "Не вышло включить CDI — продолжаю как есть." fi if docker run --rm --gpus all nvidia/cuda:12.6.3-base-ubuntu24.04 nvidia-smi >/dev/null 2>&1; then say "Видеокарта NVIDIA видна из Docker." else say "Docker не видит видеокарту NVIDIA (нет драйвера или nvidia-container-toolkit)." echo "Запущу воркер на процессоре — для проверки связи; для настоящей работы поставьте" echo "nvidia-container-toolkit и запустите установщик снова." COMPOSE=docker-compose.cpu.yml fi # Реестр GitLab принимает тот же токен как пароль; имя пользователя узнаём у GitLab. GL_USER=$(curl -fsS -H "PRIVATE-TOKEN: $ASR_WORKER_TOKEN" https://gitlab.unitcode.ru/api/v4/user | sed -n 's/.*"username":"\([^"]*\)".*/\1/p') [ -n "$GL_USER" ] || die "не узнать имя пользователя GitLab по токену" echo "$ASR_WORKER_TOKEN" | docker login registry.gitlab.unitcode.ru -u "$GL_USER" --password-stdin >/dev/null say "Скачиваю образ и запускаю (первый раз — несколько минут)…" docker compose -f "$COMPOSE" pull -q docker compose -f "$COMPOSE" up -d # Служба пользователя: при загрузке пересоздаёт контейнер (docker сам поднял бы # старый — со старыми правами на устройства, и после ребута карта «пропадает», # 14.09), а раз в сутки тянет свежий образ. Без root: юнит в ~/.config/systemd, # linger — чтобы работало и без входа в систему. if command -v systemctl >/dev/null && systemctl --user show-environment >/dev/null 2>&1; then UNITS="$HOME/.config/systemd/user"; mkdir -p "$UNITS" cat > "$UNITS/asr-worker.service" </dev/null 2>&1 && break; sleep 2; done; docker compose -f $COMPOSE pull -q || true; docker compose -f $COMPOSE up -d --force-recreate' [Install] WantedBy=default.target UNIT cat > "$UNITS/asr-worker.timer" </dev/null || true systemctl --user start asr-worker.timer 2>/dev/null || true loginctl enable-linger "$USER" 2>/dev/null || say "Не вышло включить linger — после перезагрузки воркер поднимется при входе в систему." say "Готово. Воркер запущен; при загрузке пересоздаётся, образ обновляется сам каждую ночь." else say "Готово. Воркер запущен и будет стартовать вместе с Docker." echo "Обновлять — запуском установщика снова." fi echo "Журнал: docker compose -f $DIR/$COMPOSE logs -f" echo "Остановить: docker compose -f $DIR/$COMPOSE stop"