求助:PowerShell结合WinSCP比较目录文件时间戳及密钥算法错误
WinSCP文件时间戳对比脚本及密钥兼容问题解决
问题描述
我是PowerShell脚本开发新手,需要实现通过WinSCP对比本地与远程SFTP服务器目录中文件时间戳的功能,具体需求:
- 获取用户输入的本地文件路径、远程服务器文件路径
- 获取用户输入的待比较文件名
- 对比两者的时间戳并输出结果
尝试编写连接脚本时遇到主机密钥算法不兼容错误,提示:
Couldn't agree a key host algorithm (available rsa-sha2-512, rsa-sha2-256)
WinSCP版本为6.3.1,附尝试的代码:
try { # Load WinSCP .NET assembly Add-Type -Path "WinSCPnet.dll" # Setup session options $sessionOptions = New-Object WinSCP.SessionOptions -Property @{ Protocol = [WinSCP.Protocol]::Sftp HostName = "example.com" UserName = "user" Password = "mypassword" SshHostKeyFingerprint = "ssh-rsa 2048 xxxxxxxxxxx..." } $session = New-Object WinSCP.Session try { # Connect $session.Open($sessionOptions) # code for comparing timestamp } finally { # Disconnect, clean up $session.Dispose() } exit 0 } catch { Write-Host "Error: $($_.Exception.Message)" exit 1 }
一、主机密钥算法不兼容问题解决
错误原因是指定的SshHostKeyFingerprint使用旧版ssh-rsa算法指纹,但服务器仅支持rsa-sha2-512或rsa-sha2-256这两种SHA2-based的RSA算法。解决步骤:
- 获取正确的主机密钥指纹:
- 打开WinSCP图形客户端,手动连接目标SFTP服务器,在弹出的主机密钥确认窗口中,复制
rsa-sha2-256或rsa-sha2-512算法的指纹(格式类似ssh-rsa-sha2-256 256 xx:xx:...) - 或用WinSCP命令行获取:
执行后输出会显示服务器提供的密钥指纹,复制对应算法的即可。winscp.com /command "open sftp://user:password@example.com" "exit"
- 打开WinSCP图形客户端,手动连接目标SFTP服务器,在弹出的主机密钥确认窗口中,复制
- 修改脚本配置:
将SshHostKeyFingerprint的值替换为新获取的指纹,示例:SshHostKeyFingerprint = "ssh-rsa-sha2-256 256 AA:BB:CC:DD:EE:...",
二、完整的文件时间戳比较脚本
以下是实现需求的完整PowerShell脚本,包含用户输入、SFTP连接、时间戳对比逻辑:
try { # 加载WinSCP .NET组件 Add-Type -Path "WinSCPnet.dll" # 获取用户输入 $localPath = Read-Host "请输入本地文件目录路径" $remotePath = Read-Host "请输入远程服务器文件目录路径" $fileName = Read-Host "请输入待比较的文件名" # 拼接完整文件路径 $localFullPath = Join-Path -Path $localPath -ChildPath $fileName $remoteFullPath = Join-Path -Path $remotePath -ChildPath $fileName # 配置SFTP会话选项 $sessionOptions = New-Object WinSCP.SessionOptions -Property @{ Protocol = [WinSCP.Protocol]::Sftp HostName = "example.com" UserName = "user" Password = "mypassword" # 替换为你获取的新主机密钥指纹 SshHostKeyFingerprint = "ssh-rsa-sha2-256 256 AA:BB:CC:DD:EE:...", } $session = New-Object WinSCP.Session try { # 连接SFTP服务器 $session.Open($sessionOptions) # 检查本地文件是否存在 if (-not (Test-Path -Path $localFullPath -PathType Leaf)) { Write-Host "错误:本地文件 $localFullPath 不存在" exit 1 } # 检查远程文件是否存在 if (-not $session.FileExists($remoteFullPath)) { Write-Host "错误:远程文件 $remoteFullPath 不存在" exit 1 } # 获取本地文件时间戳(最后修改时间,UTC) $localFileTime = (Get-Item -Path $localFullPath).LastWriteTimeUtc # 获取远程文件时间戳(最后修改时间,UTC) $remoteFileInfo = $session.GetFileInfo($remoteFullPath) $remoteFileTime = $remoteFileInfo.LastWriteTime # 对比时间戳并输出结果 Write-Host "=== 文件时间戳对比结果 ===" Write-Host "本地文件:$localFullPath" Write-Host "最后修改时间:$localFileTime" Write-Host "远程文件:$remoteFullPath" Write-Host "最后修改时间:$remoteFileTime" if ($localFileTime -eq $remoteFileTime) { Write-Host "* 时间戳一致" } elseif ($localFileTime -gt $remoteFileTime) { Write-Host "* 本地文件更新" } else { Write-Host "* 远程文件更新" } } finally { # 释放会话资源 $session.Dispose() } exit 0 } catch { Write-Host "执行错误:$($_.Exception.Message)" exit 1 }
脚本说明
- 先校验本地和远程文件是否存在,避免无效对比
- 统一使用UTC时间对比,消除时区差异导致的误差
- 清晰输出对比结果,明确标注哪个文件更新
内容的提问来源于stack exchange,提问作者Killua11
相关产品推荐
相关产品推荐

