Azure DevOps中FtpUpload@2任务间歇性失败的原因及解决咨询
Azure DevOps FTP上传管道间歇性失败及文件占用问题排查
问题背景
我有一个周一至周五运行的Azure DevOps管道,正常情况下可更新Web应用,但每周约出现1次失败,报错如下:
##[warning]FTPError: 550 Access is denied. connecting to: ftp.mywebsite.site:21 connected: 220 Microsoft FTP Service ##[error]FTPError: 550 Access is denied.
对应的YAML配置:
- task: FtpUpload@2 displayName: 'FTP Upload Test Site' inputs: credentialsOption: inputs serverUrl: $(ftpServerSite) username: $(ftpUser) password: $(ftpPassword) rootDirectory: '$(build.artifactstagingdirectory)/$(subFolder)' remoteDirectory: $(remoteDirSite) clean: true cleanContents: true preservePaths: true trustSSL: true
代码与变量未变更却间歇性失败,尝试将clean改为false并注释cleanContents: true后,出现新错误:
/home/vsts/work/1/a/spicetheworld/Microsoft.IdentityModel.Tokens.dll to: /mywebsite/Microsoft.IdentityModel.Tokens.dll ##[warning]FTPError: 550 The process cannot access the file because it is being used by another process.
一、原始550权限拒绝错误的原因及解决
原因分析
- 当
clean: true和cleanContents: true时,FTP任务会先尝试删除远程目录下的所有内容。如果此时Web应用正处于运行状态,部分被进程锁定的文件无法被删除,FTP服务器会返回权限拒绝(本质是文件被占用导致删除操作失败,服务器返回550错误)。 - 少数情况可能是FTP账号权限存在间歇性验证波动,但结合后续改参数后的错误,文件占用是核心诱因。
解决建议
- 避免直接在运行中的Web应用目录执行全量删除操作。可以先将文件上传到远程临时目录,再通过服务器端脚本(如PowerShell、批处理)在应用空闲时段切换目录,或者先停止Web应用池再执行删除和上传。
- 检查FTP账号是否拥有远程目录的删除、修改权限,确认服务器端没有定时变更权限策略的配置。
二、修改参数后出现的文件占用错误原因及解决
原因分析
将clean设为false后,任务改为直接覆盖现有文件,但目标文件Microsoft.IdentityModel.Tokens.dll正被Web应用进程(如w3wp.exe)占用,导致无法覆盖,触发“文件被其他进程使用”的550错误。
解决建议
方案一:部署前停止Web应用池
在FTP上传任务前,添加PowerShell远程执行任务,连接到Web服务器停止目标应用池,上传完成后再启动。示例脚本(需服务器开启WinRM并配置对应权限):# 停止应用池 Stop-WebAppPool -Name "YourAppPoolName" # 等待几秒确保进程释放文件锁 Start-Sleep -Seconds 5上传完成后添加启动脚本:
Start-WebAppPool -Name "YourAppPoolName"方案二:临时目录切换部署
- 将文件上传到远程服务器的临时目录(如
/mywebsite_temp) - 执行服务器端脚本:先停止应用池,备份原目录内容,将临时目录的文件移动到目标目录,最后启动应用池。
- 将文件上传到远程服务器的临时目录(如
方案三:替换为Azure原生部署任务
如果部署目标是Azure App Service,建议使用AzureRmWebAppDeployment@4任务替代FTP上传。该任务支持部署槽、自动停止应用、智能文件替换等功能,稳定性远高于FTP,能自动处理文件占用问题。
内容的提问来源于stack exchange,提问作者Kev
相关产品推荐
相关产品推荐

