# deploy-adb.ps1 — заливает бандл на голое устройство и разворачивает (Windows-хост). # # powershell -ExecutionPolicy Bypass -File deploy-adb.ps1 ` # -Bundle buttontask-deploy-2.1.tgz # # Сценарий: подключил по USB -> нашлось adb-устройство -> отработал -> ребут -> работает. param( [string]$Bundle, [string]$Adb, [switch]$ResetConfig ) # native-команды adb пишут в stderr (adb root, прогресс push); Stop делает это фатальным $ErrorActionPreference = 'Continue' $Here = Split-Path -Parent $MyInvocation.MyCommand.Path function Log($m) { Write-Host "[deploy] $m" -ForegroundColor Green } function Warn($m) { Write-Host "[warn] $m" -ForegroundColor Yellow } function Die($m) { Write-Host "[error] $m" -ForegroundColor Red; Read-Host 'Нажмите Enter'; exit 1 } function AdbOut($arglist) { (& $Adb @arglist | Out-String) } # adb по умолчанию из .\bin\adb.exe рядом со скриптом, иначе из PATH if (-not $Adb) { $cand = Join-Path $Here 'bin\adb.exe' $Adb = if (Test-Path $cand) { $cand } else { 'adb' } } if (-not (Get-Command $Adb -ErrorAction SilentlyContinue)) { Die "не найден adb. Положите adb.exe в .\bin\ рядом со скриптом." } # бандл: если не задан — берём единственный *.tgz рядом со скриптом if (-not $Bundle) { $found = @(Get-ChildItem $Here -Filter '*.tgz' -File) if ($found.Count -eq 1) { $Bundle = $found[0].FullName } elseif ($found.Count -eq 0) { Die "рядом нет ни одного .tgz — положите бандл сюда" } else { Die "рядом несколько .tgz — укажите нужный: -Bundle <имя>" } } if (-not (Test-Path $Bundle)) { Die "не найден бандл: $Bundle" } Log "бандл: $(Split-Path -Leaf $Bundle)" # 1. ждём ровно одно устройство (до 60 c) — дружелюбно для не-специалиста & $Adb start-server 2>$null | Out-Null Write-Host '[deploy] Подключите устройство по USB...' -ForegroundColor Cyan $n = 0 for ($i = 0; $i -lt 60; $i++) { $n = (& $Adb devices | Select-Object -Skip 1 | Where-Object { $_ -match '\sdevice$' }).Count if ($n -eq 1) { break } Start-Sleep -Seconds 1 } if ($n -ne 1) { Die "не вижу ровно одно adb-устройство (найдено: $n). Проверьте USB-кабель и порт." } # 2. пробуем root & $Adb root 2>$null | Out-Null & $Adb wait-for-device $uid = (AdbOut @('shell', 'id -u')).Trim() if ($uid -eq '0') { $sudo = ''; Log 'adb shell работает как root' } else { $sudo = 'sudo'; Warn "adb shell не root (uid=$uid) — установка через sudo" } # 3. архитектура $arch = (AdbOut @('shell', 'dpkg --print-architecture')).Trim() Log "архитектура устройства: $arch" if ($arch -ne 'arm64') { Warn 'не arm64 — убедитесь, что бандл собран под эту арх' } # 4. заливаем и распаковываем Log 'заливаю бандл...' & $Adb shell 'rm -rf /tmp/btdeploy /tmp/btdeploy.tgz && mkdir -p /tmp/btdeploy' | Out-Null & $Adb push $Bundle /tmp/btdeploy.tgz | Out-Null & $Adb shell 'cd /tmp/btdeploy && tar xzf /tmp/btdeploy.tgz' | Out-Null # 5. установка, ловим INSTALL-OK Log 'разворачиваю на устройстве...' if ($ResetConfig) { Log 'полный сброс config.json и .master из бандла' if ($sudo) { $cmd = "$sudo env BUTTONTASK_RESET_CONFIG=1 bash /tmp/btdeploy/device-install.sh" } else { $cmd = 'env BUTTONTASK_RESET_CONFIG=1 bash /tmp/btdeploy/device-install.sh' } } else { $cmd = ("$sudo bash /tmp/btdeploy/device-install.sh").Trim() } $output = & $Adb shell $cmd 2>&1 | Out-String Write-Host ($output -replace "`r", '') if ($output -notmatch 'INSTALL-OK') { Die 'установка завершилась без INSTALL-OK (см. вывод выше)' } & $Adb shell 'rm -rf /tmp/btdeploy /tmp/btdeploy.tgz' 2>$null | Out-Null # 6. ребут + проверка Log 'перезагрузка устройства...' & $Adb reboot & $Adb wait-for-device Log 'жду подъёма сервисов...' Start-Sleep -Seconds 10 $status = (AdbOut @('shell', 'systemctl is-active buttontask buttontask-web')) -replace "`r", '' -replace "`n", ' ' Log "статус сервисов: $($status.Trim())" if ($status -match 'active\s+active') { Write-Host '' Write-Host ' ==============================' -ForegroundColor Green Write-Host ' ГОТОВО. Устройство настроено.' -ForegroundColor Green Write-Host ' ==============================' -ForegroundColor Green } else { Warn 'сервисы ещё не active; проверьте: adb shell journalctl -u buttontask -b' } Write-Host '' Read-Host 'Можно отключать устройство. Нажмите Enter для выхода'