Files
Button/winDeployScripts/collect-debs-ssh.ps1
T
2026-07-28 21:29:02 +03:00

152 lines
7.8 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# collect-debs-ssh.ps1 — как collect-debs.ps1, но по SSH (для устройства БЕЗ adbd).
# Windows-хост, без WSL: SSH/SCP делаются через plink.exe / pscp.exe (PuTTY tools).
#
# Шаг 1 — снять список установленных пакетов с устройства:
# powershell -ExecutionPolicy Bypass -File collect-debs-ssh.ps1 -Step target
# -> new-installed.txt
#
# Шаг 2 — сравнить с тем, что вам давали (файл target-installed.txt из старого workflow):
# powershell -ExecutionPolicy Bypass -File collect-debs-ssh.ps1 -Step diff
#
# Шаг 3 (опционально, как -Step fetch у adb-версии) — добрать недостающие .deb:
# powershell -ExecutionPolicy Bypass -File collect-debs-ssh.ps1 -Step fetch
# нужен рядом packages.list и collect-on-device.sh (тот же файл, без изменений).
#
# Параметры подключения (по умолчанию — как вы просили):
# -HostAddr 192.168.1.52 -User linaro -Pass linaro
#
# plink.exe / pscp.exe берутся из .\bin\ рядом со скриптом (как у вас adb.exe),
# иначе — из PATH. Если ни там ни там нет — скачайте с https://www.putty.org
#
# ВАЖНО про первое подключение: plink на первый коннект спросит про host key
# ("host key is not cached... store key?"). В batch-режиме он на это ответит
# отказом и упадёт. Поэтому один раз ПЕРЕД первым запуском примите ключ вручную:
# .\bin\plink.exe -ssh linaro@192.168.1.52
# (введите "y" на вопрос про ключ, затем можно Ctrl+C — ключ сохранится в реестр)
param(
[Parameter(Mandatory = $true)][ValidateSet('target', 'diff', 'fetch')][string]$Step,
[string]$HostAddr = '192.168.1.52',
[string]$User = 'linaro',
[string]$Pass = 'linaro',
[string]$SudoPass,
[string]$OldFile, # для -Step diff, по умолчанию target-installed.txt
[string]$NewFile, # для -Step diff, по умолчанию new-installed.txt
[string]$Plink,
[string]$Pscp
)
$ErrorActionPreference = 'Continue'
$Here = Split-Path -Parent $MyInvocation.MyCommand.Path
if (-not $SudoPass) { $SudoPass = $Pass }
function Log($m) { Write-Host "[collect] $m" -ForegroundColor Green }
function Warn($m) { Write-Host "[warn] $m" -ForegroundColor Yellow }
function Die($m) { Write-Host "[error] $m" -ForegroundColor Red; exit 1 }
# plink/pscp по умолчанию берём из .\bin\ рядом со скриптом, иначе из PATH
if (-not $Plink) {
$cand = Join-Path $Here 'bin\plink.exe'
$Plink = if (Test-Path $cand) { $cand } else { 'plink' }
}
if (-not $Pscp) {
$cand = Join-Path $Here 'bin\pscp.exe'
$Pscp = if (Test-Path $cand) { $cand } else { 'pscp' }
}
foreach ($exe in @($Plink, $Pscp)) {
if (-not (Get-Command $exe -ErrorAction SilentlyContinue)) {
Die "не найден '$exe'. Положите plink.exe/pscp.exe в .\bin\ или в PATH (https://www.putty.org)"
}
}
function Write-Lf($path, [string[]]$lines) {
$text = ($lines -join "`n") + "`n"
[System.IO.File]::WriteAllText($path, $text, (New-Object System.Text.UTF8Encoding($false)))
}
function Invoke-Remote([string]$cmd) {
# plink в batch-режиме: без интерактивных вопросов (host key должен быть уже принят заранее)
$out = & $Plink -ssh -batch -pw $Pass "$User@$HostAddr" $cmd 2>&1 | Out-String
return $out
}
function Push-File([string]$local, [string]$remote) {
& $Pscp -batch -pw $Pass $local "$User@${HostAddr}:$remote" 2>&1 | Out-Null
}
function Pull-Path([string]$remote, [string]$localDir) {
& $Pscp -batch -pw $Pass -r "$User@${HostAddr}:$remote" $localDir 2>&1 | Out-Null
}
# ---------------------------------------------------------------------------
if ($Step -eq 'target') {
Log "подключаюсь к $User@$HostAddr, снимаю список установленных пакетов..."
$raw = Invoke-Remote 'dpkg-query -W | cut -f1'
$pkgs = $raw -replace "`r", '' -split "`n" | Where-Object { $_ -ne '' } | Sort-Object -Unique
if ($pkgs.Count -eq 0) { Die "не получил список пакетов (проверьте SSH-доступ / что это Debian-rootfs). Вывод:`n$raw" }
$out = Join-Path $Here 'new-installed.txt'
Write-Lf $out $pkgs
Log "сохранено $($pkgs.Count) пакетов -> $out"
Log "теперь сравните: -Step diff"
exit 0
}
# ---------------------------------------------------------------------------
if ($Step -eq 'diff') {
$old = if ($OldFile) { $OldFile } else { Join-Path $Here 'target-installed.txt' }
$new = if ($NewFile) { $NewFile } else { Join-Path $Here 'new-installed.txt' }
foreach ($f in @($old, $new)) { if (-not (Test-Path $f)) { Die "нет файла: $f" } }
$oldSet = Get-Content $old | Where-Object { $_ -ne '' } | Sort-Object -Unique
$newSet = Get-Content $new | Where-Object { $_ -ne '' } | Sort-Object -Unique
$onlyOld = $oldSet | Where-Object { $newSet -notcontains $_ }
$onlyNew = $newSet | Where-Object { $oldSet -notcontains $_ }
Write-Host "=== Есть только на СТАРОМ устройстве (в новом отсутствует), $($onlyOld.Count) шт ===" -ForegroundColor Cyan
$onlyOld | ForEach-Object { Write-Host $_ }
Write-Host ""
Write-Host "=== Есть только на НОВОМ устройстве (на старом не было), $($onlyNew.Count) шт ===" -ForegroundColor Cyan
$onlyNew | ForEach-Object { Write-Host $_ }
if ($onlyOld.Count -eq 0 -and $onlyNew.Count -eq 0) { Log "списки пакетов идентичны." }
else { Warn "списки различаются (см. выше)." }
exit 0
}
# ---------------------------------------------------------------------------
# Step 'fetch'
$pkgsList = Join-Path $Here 'packages.list'
$helper = Join-Path $Here 'collect-on-device.sh'
$tgt = Join-Path $Here 'target-installed.txt'
foreach ($f in @($pkgsList, $helper)) { if (-not (Test-Path $f)) { Die "нет файла: $f" } }
Log "проверяю доступ по SSH..."
$idOut = (Invoke-Remote 'id -u').Trim()
if (-not $idOut) { Die "не удалось подключиться к $User@$HostAddr (проверьте host key: см. комментарий в начале файла)" }
$sudo = if ($idOut -eq '0') { '' } else { Warn "$User не root — иду через sudo"; 'sudo -S' }
Log "заливаю списки и хелпер на устройство..."
Invoke-Remote 'rm -rf /tmp/btcollect && mkdir -p /tmp/btcollect' | Out-Null
Push-File $pkgsList '/tmp/btcollect/packages.list'
Push-File $helper '/tmp/btcollect/collect-on-device.sh'
if (Test-Path $tgt) { Push-File $tgt '/tmp/btcollect/target-installed.txt' }
else { Warn "нет target-installed.txt — сначала лучше прогнать -Step target" }
# на случай CRLF после Windows
Invoke-Remote "sed -i 's/\r`$//' /tmp/btcollect/* 2>/dev/null; true" | Out-Null
Log "качаю зависимости на устройстве (нужен интернет на нём)..."
$cmd = if ($sudo -ne '') {
"echo '$SudoPass' | $sudo bash /tmp/btcollect/collect-on-device.sh"
} else {
"bash /tmp/btcollect/collect-on-device.sh"
}
$output = Invoke-Remote $cmd
Write-Host $output
if ($output -notmatch 'COLLECT-OK') { Die "сбор пакетов не дошёл до COLLECT-OK" }
Log "забираю .deb на хост..."
$debs = Join-Path $Here 'debs'
if (Test-Path $debs) { Remove-Item -Recurse -Force $debs }
Pull-Path '/tmp/btdebs' $Here
Rename-Item (Join-Path $Here 'btdebs') $debs
$n = (Get-ChildItem $debs -Filter *.deb).Count
Log "готово: $n .deb в $debs"