# 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"