如何在PowerShell的WinSCP SSH脚本中实现双凭证自动重试登录?
实现方案
核心逻辑为预先定义两组账号凭证,通过循环遍历优先使用第一组账号发起连接,捕获认证失败异常后自动切换第二组重试,SSH和WinSCP复用同一组验证通过的凭证,避免两次连接使用不同账号的冲突问题。
修改后的完整代码
if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { $arguments = "& '" +$myinvocation.mycommand.definition + "'" Start-Process powershell -Verb runAs -ArgumentList $arguments Break } Add-Type -Path "C:\Program Files (x86)\WinSCP\WinSCPnet.dll" $db = import-csv -Path "C:\Program Files (x86)\WinSCP\db.csv" $inputID = Read-Host -Prompt "ID" $entry = $db | where-Object {$_.HostName -eq $inputID} if ($inputID -eq $entry.HostName){ "$inputID Ok!" } else{ "$inputID nu exista in baza de date!" $title = 'Title' $question = 'Doriti sa introduceti un ID nou in Baza de Date?' $choices = '&Yes', '&No' $decision = $Host.UI.PromptForChoice($title, $question, $choices, 1) if ($decision -eq 0) { Write-Host 'confirmed' $ID = Read-Host -Prompt "Introduceti ID" $IP = Read-Host -Prompt "Introduceti IP" $wrapper = New-Object PSObject -Property @{ HostName = $ID; IP = $IP } Export-Csv -Append -InputObject $wrapper -Path "C:\Program Files (x86)\WinSCP\db.csv" -NoTypeInformation -Force $dbTrimmer = Get-Content -Path "C:\Program Files (x86)\WinSCP\db.csv" $dbTrimmer.Replace('","',',').TrimStart('"').TrimEnd('"') | Out-File "C:\Program Files (x86)\WinSCP\db.csv" -Force -Confirm:$false Exit } else{ Write-Host 'No' Exit } } Write-Host "IP:" $entry.IP # 配置双组账号凭证,第一组优先使用,请替换为实际账号密码 $credPairs = @( @{ User = "user1"; Password = "pass1" }, @{ User = "user2"; Password = "pass2" } ) $validCred = $null $sessionID = $null $Command = "C:\Info.exe" # 遍历两组凭证尝试SSH连接 foreach ($pair in $credPairs) { $secpasswd = ConvertTo-SecureString $pair.Password -AsPlainText -Force $Credentials = New-Object System.Management.Automation.PSCredential($pair.User, $secpasswd) try { Get-SSHTrustedHost | Remove-SSHTrustedHost -ErrorAction SilentlyContinue $sessionID = New-SSHSession -ComputerName $entry.IP -Credential $Credentials -AcceptKey:$true -ErrorAction Stop $validCred = $pair Write-Host "使用账号$($pair.User) SSH连接成功" break } catch { Write-Host "使用账号$($pair.User) SSH连接失败:$_" } } # 两组账号均认证失败直接终止脚本 if (-not $validCred) { Write-Host "两组账号均认证失败,脚本终止运行" Exit 1 } Invoke-SSHCommand -Index $sessionid.sessionid -Command $Command # Set up session options $sessionOptions = New-Object WinSCP.SessionOptions -Property @{ Protocol = [WinSCP.Protocol]::Sftp HostName = $entry.IP UserName = $validCred.User Password = $validCred.Password GiveUpSecurityAndAcceptAnySshHostKey = "true" } $session = New-Object WinSCP.Session $file = "Dev.log", "Info.dat" $localPath = "E:\Arhive\*" $remotePath = "/C:/Program Files/Dev.log", "/C:/Program File/Info.dat" try { # Connect $session.Open($sessionOptions) # Check exists files foreach ($remotePath in $remotePath) { if ($session.FileExists($remotePath)) { Write-Host "Fisierul $remotePath exista" # Transfer files $session.GetFiles($remotePath, $localPath).Check() } else { Write-Host "Fisierul $remotePath NU exista" } } } finally { $session.Dispose() } foreach ($file in "E:\loguri\Dev.log", "E:\loguri\Info.dat") { if (Test-Path $file) { Compress-Archive $file -DestinationPath "E:\Arhive\$inputID.zip" -Update Remove-Item $file } } # Stergere fisiere din Arhive mai vechi de 60 minute $Files = get-childitem 'E:\Arhive' | Where-Object PSIsContainer -eq $false $LimitTime = (Get-Date).AddMinutes(-60) $Files | ForEach-Object { if ($_.CreationTime -lt $LimitTime -and $_.LastWriteTime -lt $LimitTime) { Remove-Item -Path $_.FullName -Force Write-Host "Am sters $Files pentru ca sunt mai vechi de $LimitTime !" } }
注意事项
- 请提前替换代码中
$credPairs里的两组账号密码为实际业务值 - 原代码中SFTP拉取路径
/C:/Program File/Info.dat存在拼写缺漏,建议根据实际路径修正 - 若需要对非认证类异常(如IP不可达、端口未开放)也增加重试逻辑,可自行调整异常判断规则
内容的提问来源于stack exchange,提问作者user12428212
相关产品推荐
相关产品推荐

