Ansible从SFTP服务器下载文件遇错:Windows主机适配方案求助
Ansible Windows主机SFTP下载文件失败问题
环境信息
- Ansible控制节点:Linux,版本
ansible 2.10.8 - 目标主机:Windows
尝试的任务
尝试用win_get_url模块从SFTP下载文件,任务代码如下(存在拼写错误):
- name: Download from SFTP win_get_url: url: "sftp://ftp.mycompany.com/path/someFile.exe" dest: "C:\\temp" url_username: "myUser" utl_password: "myPw123" # 此处拼写错误,应为url_password,但不影响核心问题
错误信息
执行任务后报错:
TASK [downloader : Download sftp://ftp.kmhapub.com/devops/exa-3rdparty/7z/7z2107-x64.exe] ************************************************* task path: /path/exa-playbooks/roles/downloader/tasks/download.yml:2 redirecting (type: modules) ansible.builtin.win_get_url to ansible.windows.win_get_url Using module file /usr/local/Cellar/ansible/3.3.0/libexec/lib/python3.9/site-packages/ansible_collections/ansible/windows/plugins/modules/win_get_url.ps1 Pipelining is enabled. <10.227.x.x> ESTABLISH WINRM CONNECTION FOR USER: Administrator on PORT 5986 TO 10.227.x.x EXEC (via pipeline wrapper) The full traceback is: Exception calling "Create" with "1" argument(s): "The URI prefix is not recognized." At line:213 char:20 + ... $web_request = Get-AnsibleWindowsWebRequest -Uri $Uri -Module $Module + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [Get-AnsibleWindowsWebRequest], MethodInvocationException + FullyQualifiedErrorId : NotSupportedException,Get-AnsibleWindowsWebRequest ScriptStackTrace: at Get-AnsibleWindowsWebRequest, <No file>: line 211 at Invoke-DownloadFile, <No file>: line 213 at <ScriptBlock>, <No file>: line 265 System.Management.Automation.MethodInvocationException: Exception calling "Create" with "1" argument(s): "The URI prefix is not recognized." ---> System.NotSupportedException: The URI prefix is not recognized. at System.Net.WebRequest.Create(Uri requestUri, Boolean useUriBase) at CallSite.Target(Closure , CallSite , Type , Object ) --- End of inner exception stack trace --- at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception) at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.Interpreter.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.LightLambda.RunVoid1[T0](T0 arg0) at System.Management.Automation.PSScriptCmdlet.RunClause(Action`1 clause, Object dollarUnderbar, Object inputToProcess) at System.Management.Automation.PSScriptCmdlet.DoEndProcessing() at System.Management.Automation.CommandProcessorBase.Complete() fatal: [10.227.x.x]: FAILED! => { "changed": false, "msg": "Unhandled exception while executing module: Exception calling \"Create\" with \"1\" argument(s): \"The URI prefix is not recognized.\"" } PLAY RECAP ****************************************************************************************************************************** 10.227.x.x : ok=5 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
问题解答
错误含义
win_get_url模块依赖Windows的System.Net.WebRequest组件,该组件不支持SFTP协议,因此当传入sftp://前缀的URL时,会抛出"The URI prefix is not recognized"错误,明确表明无法识别SFTP的URI格式。
修复方案及替代模块
因为win_get_url不支持SFTP,可采用以下几种替代方案:
方案1:使用Windows OpenSSH客户端(推荐,无需额外安装模块)
前提是Windows目标主机已安装OpenSSH Client(Windows 10 1809+/Server 2019+默认可选安装),直接调用sftp命令行:
- name: 从SFTP下载文件(OpenSSH方式) win_shell: | sftp -o PasswordAuthentication=yes myUser@ftp.mycompany.com:/path/someFile.exe C:\temp\someFile.exe args: creates: C:\temp\someFile.exe # 文件已存在则跳过任务 no_log: true # 避免日志泄露敏感信息
注意:若需要自动输入密码,可结合
sshpass(需在Windows主机安装)或使用密钥认证更安全。
方案2:使用Posh-SSH PowerShell模块
先安装Posh-SSH模块,再通过PowerShell命令操作SFTP:
- name: 安装Posh-SSH模块 win_psmodule: name: Posh-SSH state: present - name: 从SFTP下载文件(Posh-SSH方式) win_shell: | $cred = New-Object System.Management.Automation.PSCredential('myUser', (ConvertTo-SecureString 'myPw123' -AsPlainText -Force)) $session = New-SFTPSession -ComputerName ftp.mycompany.com -Credential $cred Get-SFTPFile -SessionId $session.SessionId -RemoteFile '/path/someFile.exe' -LocalPath 'C:\temp\someFile.exe' Remove-SFTPSession -SessionId $session.SessionId no_log: true
方案3:通过Ansible控制节点中转下载
利用ansible.posix.synchronize模块,先从SFTP下载到控制节点,再同步到Windows主机(需控制节点能访问SFTP服务器):
- name: 从SFTP下载到控制节点 ansible.posix.synchronize: src: "sftp://myUser:myPw123@ftp.mycompany.com/path/someFile.exe" dest: "/tmp/someFile.exe" mode: pull - name: 同步文件到Windows主机 win_copy: src: "/tmp/someFile.exe" dest: "C:\\temp\\someFile.exe"
注意:此方案会在控制节点留下临时文件,任务完成后可添加删除步骤;密码直接写在URL中存在安全风险,建议使用Ansible Vault加密。
内容的提问来源于stack exchange,提问作者Chris F
相关产品推荐
相关产品推荐

