
简介一份聚焦 Windows 与 UNIX 环境下 FTP 自动传输实现思路的 doc 技术文档面向需要定时备份、批量收发文件的系统管理员与运维初学者。全文以批处理命令配合系统「任务计划」为主线讲清如何用 ftp 命令脚本组织 open、user、cd、bin、prompt、mget、mput 等指令完成登录与批量收发再由批处理通过 ftp -n -s 调用执行并说明二进制与 ASCII 传输方式的取舍、Windows 之间互传时省略 bin 行的差异同时给出 UNIX 下编写可执行 shell 脚本调用 ftp 的等价做法以及银行网络设备管理中每日异地备份的落地案例。整包仅 1 个 doc 文件约 44KB篇幅精炼、步骤完整可直接当作脚本模板对照改写。已有 2121 人学习适合作为 FTP 自动化与定时任务配置的入门实操参考。1. 从一台老服务器每天凌晨的传输说起批处理命令配FTP脚本到底还值不值得用常见的一类夜间传输场景是一台 Windows 机器每天凌晨要把C:\datatran里的文件送到另一台机器的data目录值班的人最怕的不是不会敲 ftp而是每天重复登录、切目录、敲mget漏一次就要翻日志。用批处理命令配合 FTP 脚本把登录、目录、传输模式、通配符固定下来再挂到 Windows 任务计划机器就能按周期自己收发文件。这套做法适合内网、老系统、没有额外客户端、只需要定时搬文件的场景不适合需要断点续传、传输加密、复杂任务编排的场景。下面按脚本拆解、任务计划、模式选择、排错和可验证几块落地参数都能直接替换。2. 把登录过程写进 1.ftp批处理命令调用 FTP 脚本的参数、目录与命令顺序2.1 为什么用 ftp -n -s而不是在 bat 里逐行 echo批处理命令本身不处理 FTP 协议它只负责调用 Windows 自带的ftp.exe。真正让传输稳定下来的是把 FTP 命令集中写进一个后缀为.ftp的脚本文件再用ftp -n -s:路径一次性喂给客户端。-n的作用是禁止自动登录避免客户端在脚本执行前尝试用当前用户身份连接-s指定脚本文件登录用户名、口令、远端目录、传输模式和mget都在脚本里按顺序执行。这样做比在 bat 里用echo拼管道可读得多账号、目录、通配符也能单独改不用动批处理主体。常见的参数和误用可以对照下表。-i和多文件传输交互提示有关等价于脚本里写prompt off但脚本里写更直观-v会抑制远端响应显示日志会干净一些-d是调试开关排错时临时打开能看到更多命令细节。参数作用常见误用-n禁止自动登录必须由脚本里的user登录漏写后客户端可能先尝试匿名或当前用户-s:C:\1.ftp指定 FTP 命令脚本写成相对路径任务计划启动后找不到文件-i关闭多文件传输时的交互确认只写-i但脚本里又打开prompt-v抑制远端响应显示排错时关掉日志里看不到服务端返回码-d打开调试信息长期开着导致日志膨胀还有一个经常被忽略的点ftp.exe的退出码只代表客户端进程有没有正常结束不代表每个文件都传成功。后面第 4 章和第 5 章会反复用到日志里的226、250、550、530这些返回码因为只看errorlevel容易得到一个“任务成功但文件没到”的假象。提示.ftp文件里是明文口令文件权限要收紧不要放在共享目录里也不要用业务账号的弱口令做示例值。2.2 一份能直接替换参数的 1.ftp 模板下面这份模板对应“从对方机器下载文件到本机”的方向。地址、用户名、口令、远端目录、通配符都可以按实际环境替换。open负责连接user负责登录cd切到远端目录binary指定二进制传输prompt off关闭多文件逐个确认mget拉取匹配文件bye结束会话。open 10.30.15.3 user anonymous 123456 cd data binary prompt off mget *.* bye逻辑说明命令按从上到下的顺序执行open失败后面不会继续user把用户名和口令写在同一行比“用户名一行、口令一行”更稳能避开脚本空行和编码带来的密码错位cd data进入远端接收目录binary必须放在mget之前prompt off也必须放在多文件命令之前否则mget会逐个询问是否传输任务计划里就表现为“任务一直不结束”。参数说明10.30.15.3换成对方 FTP 地址anonymous和123456换成实际账号口令data换成远端目录*.*换成业务文件匹配规则比如*.csv、*.dat、*.zip。如果方向反过来是本机往对方上传把mget改成mput并把cd data换成远端接收目录同时在脚本里用lcd指定本地目录。需要传无扩展名文件时*.*在 UNIX 侧不一定匹配按业务后缀写多个mget更稳比如mget *.dat和mget *.txt分开写。如果要传的是纯文本且确实需要换行转换可以把binary换成ascii但压缩包、可执行文件、数据库导出文件、图片这类内容必须用binary。Windows 与 Windows 之间传文本时原文里提到可以去掉bin一行我的习惯是默认保留binary只有确认是纯文本且对换行格式有要求时才切ascii这样少一次“文件大小变了、内容打不开”的翻车。注意脚本文件建议保存为 ANSI 或 UTF-8 无 BOM。带 BOM 的文本在第一行open前可能多出不可见字符表现为“手工能登录脚本一跑就报连接失败”。2.3 对应的 1.bat 与目录切换.ftp只负责协议动作.bat负责把工作目录切过去、调用客户端、留日志、把退出码传给任务计划。任务计划启动程序时的工作目录不一定是脚本所在目录所以 bat 里必须用cd /d显式切换盘符和路径。echo off setlocal cd /d C:\datatran ftp -n -s:C:\1.ftp C:\datatran\ftp_run.log 21 if errorlevel 1 ( echo [%date% %time%] FTP command failed C:\datatran\ftp_error.log exit /b 1 ) echo [%date% %time%] FTP command finished C:\datatran\ftp_run.log exit /b 0逻辑说明cd /d同时处理盘符和目录避免任务计划在C:\Windows\System32下启动时找不到相对路径ftp -n -s:C:\1.ftp用绝对路径调用脚本覆盖本次运行日志21把错误输出也送进同一个文件if errorlevel 1判断ftp.exe的进程退出码失败时追加错误日志并返回 1成功时返回 0任务计划的“上次运行结果”才有意义。参数说明C:\datatran换成本机接收目录C:\1.ftp换成脚本实际路径日志路径建议放在有写权限的目录不要放在需要管理员权限才能写的根目录。%date%和%time%的格式受系统区域设置影响如果日志名要用日期拼接先执行echo %date%看格式或者干脆用固定日志名加追加写入避免日期变量里出现空格和斜杠导致路径非法。ftp.exe一般位于%SystemRoot%\System32如果任务计划里提示找不到命令可以在 bat 里写完整路径%SystemRoot%\System32\ftp.exe。这套组合的关键不是命令多而是路径全部绝对化、日志落在固定位置、退出码能回传。后面挂任务计划时任何一项缺失都会变成“手工跑得好好的计划任务一跑就没文件”。3. 让 1.bat 自己跑起来Windows 任务计划的账户、路径与日志三件事3.1 任务计划到底替我们做了什么任务计划解决的是“到点触发”和“以哪个身份触发”。触发器决定每天几点跑、隔多久跑操作决定启动哪个 bat条件决定是否只在空闲、是否只在交流电源、网络可用时才跑账户决定脚本运行时有没有权限访问本地目录和网络资源。很多人只填了触发器和 bat 路径结果任务计划显示已运行文件却没动问题往往出在账户和工作目录上。账户选择要分情况。用SYSTEM账户跑不需要保存密码权限也高但它没有普通用户的网络映射和用户配置文件FTP 脚本里如果依赖用户级配置就会出偏差。用具体本机账户跑需要保存密码密码过期或被改掉后任务会失败表现是“上次运行结果 0x1”。我的习惯是纯内网、脚本里自带 FTP 账号口令、只读写本地固定目录可以用SYSTEM需要访问用户级路径或网络共享就用专门的服务账户并把密码到期时间单独管理。工作目录是另一个高频坑。任务计划启动 bat 时默认工作目录不是 bat 所在目录ftp -s:1.ftp这种相对路径会找不到脚本。解决办法不是依赖任务计划里的“起始于”而是在 bat 里永远写cd /d和绝对路径。任务计划里的“起始于”可以填C:\datatran但它不能替代 bat 内部的路径处理。3.2 用 schtasks 建一个每天凌晨 2 点的任务图形界面能建任务命令行更适合复现和批量部署。下面这条命令创建一个名为DailyFtpPull的任务每天 02:00 运行C:\scripts\1.bat以SYSTEM账户执行/F表示同名任务存在时覆盖。schtasks /Create /TN DailyFtpPull /TR C:\scripts\1.bat /SC DAILY /MO 1 /ST 02:00 /RU SYSTEM /F逻辑说明/TN是任务名排错时用同一个名字查询/TR指向 bat 的绝对路径/SC DAILY表示按天调度/MO 1表示每 1 天一次/ST 02:00是开始时间/RU SYSTEM指定运行账户/F覆盖同名任务方便反复调试。如果换成具体账户命令里可以加/RU 账户名执行时会提示输入密码或者用/RP传密码但密码会留在命令历史里不如交互式输入稳妥。参数说明/ST用 24 小时制/SC还可以用HOURLY、WEEKLY、ONLOGON文件传输一般用DAILY或HOURLY/TR路径里有空格时要用引号包住。任务建好后不要只看“已创建成功”要立刻手动运行一次确认日志里有226 Transfer complete或至少能看到文件落盘。schtasks /Run /TN DailyFtpPull逻辑说明/Run立即触发一次不用等到凌晨运行后马上去看 bat 里写的日志和接收目录。参数说明任务名必须和创建时一致如果提示找不到任务先用/Query查名字注意引号和大小写。3.3 任务计划里必须复核的四个参数任务计划建完只是开始下面四个位置要逐项复核。表格里列的是常见默认值和推荐处理方式照着改能减少大部分“计划任务不执行”的问题。复核项常见默认值推荐处理原因起始于空或System32填 bat 所在目录bat 内仍写cd /d相对路径找不到脚本运行账户当前用户固定服务账户或SYSTEM单独管理密码密码过期导致 0x1条件仅交流电源、网络可用才运行按实际取消不必要的限制笔记本或网络状态导致跳过历史记录未启用启用任务历史记录失败时能看到触发和返回码查询任务详情用下面这条命令重点看“上次运行结果”“上次运行时间”“要运行的任务”和“登录模式”。上次运行结果是0x0只代表 bat 返回了 0不代表每个文件都成功如果是0x1先看 bat 日志里ftp那一段有没有输出。schtasks /Query /TN DailyFtpPull /V /FO LIST逻辑说明/Query查询任务/V输出详细字段/FO LIST用列表格式比表格好读。参数说明任务名要和创建时一致如果字段太多可以把输出重定向到文件再搜“上次运行结果”。任务计划历史记录在图形界面的“启用所有任务历史记录”里打开排查“到底有没有触发”时很有用。4. 二进制还是 ASCIImget/mput、prompt 与通配符的边界4.1 binary 与 ascii 的适用边界FTP 传输模式选错是文件损坏类问题里最隐蔽的一种。ascii会做换行转换Windows 的 CRLF 和 UNIX 的 LF 之间来回转纯文本看起来正常但压缩包、可执行文件、数据库导出文件一旦走ascii字节内容被改写传过去就打不开。binary不做转换按字节搬运适合绝大多数业务文件。我的默认选择是binary只有确认是纯文本且确实需要换行转换时才用ascii。文件类型推荐模式说明.txt、.csv、.xmlascii或binary纯文本可用ascii但跨系统编码复杂时binary更稳.zip、.exe、.dmpbinary必须按字节传输不能做换行转换图片、音视频binary任何转换都会破坏文件无扩展名业务文件binary先按二进制传再在业务侧校验下面这段脚本把binary放在所有传输命令之前并按后缀分开拉取。分开写的好处是某个后缀没有匹配文件时不会影响其他后缀日志里也更容易看出是哪一类文件出的问题。open 10.30.15.3 user anonymous 123456 cd data binary prompt off mget *.csv mget *.dat mget *.zip bye逻辑说明binary设置传输类型prompt off关闭多文件确认三个mget按业务后缀分别匹配。参数说明*.csv等通配符匹配的是远端当前目录不是本地目录UNIX 侧区分大小写*.CSV和*.csv不是一回事如果远端文件没有扩展名*.*可能匹配不到需要单独写mget 文件名或用更宽的通配符并在日志里确认。4.2 mget/mput、prompt 与通配符的坑上传方向的脚本要把mget换成mput同时用lcd指定本地目录用cd指定远端目录。lcd只影响本地路径cd只影响远端路径两个都写清楚避免把文件传到错误目录。open 10.30.15.3 user anonymous 123456 lcd C:\datatran\out cd incoming binary prompt off mput *.dat bye逻辑说明lcd切本地目录cd切远端目录binary设置二进制prompt off关闭确认mput上传匹配文件。参数说明C:\datatran\out换成实际上传目录incoming换成远端接收目录*.dat换成业务后缀。路径里尽量不要有空格FTP 命令对含空格路径的处理不如 Windows 命令行友好如果必须有空格先在小范围测试确认客户端能正确识别。prompt的位置很关键。它必须放在mget或mput之前放在后面等于没关。多文件传输时如果没关客户端会逐个询问任务计划里没有人工输入就会卡住。另一个常见误用是通配符写得太宽mput *可能把临时文件、日志文件一起传上去按业务后缀写多个mput比一个宽通配符更可控。4.3 用 hash、verbose 和日志确认传输结果排错时不要只盯着 bat 的返回码。ftp.exe的进程退出码可能为 0但日志里已经有550文件不可用也可能部分文件失败后继续执行后面的命令。打开hash和verbose能让日志更有信息量hash显示传输进度verbose显示服务端响应配合重定向就能留下黑匣子。open 10.30.15.3 user anonymous 123456 cd data binary hash on verbose on prompt off mget *.dat bye逻辑说明hash on在传输时输出进度标记verbose on显示服务端返回prompt off关闭确认mget拉取文件。参数说明hash和verbose会增加日志体积长期运行可以只保留verbose排错时再打开hash日志里可能出现账号信息交付前要脱敏。日志落到文件后用findstr抓关键返回码。226表示传输完成250表示命令成功550表示文件不可用或权限不足530表示登录失败。下面这条命令把命中的行留在日志里方便判断是登录问题、目录问题还是文件问题。findstr /I /C:226 /C:250 /C:550 /C:530 C:\datatran\ftp_run.log逻辑说明/I忽略大小写/C:指定多个搜索字符串多个/C:之间是“或”的关系。参数说明日志路径换成实际文件如果日志是追加写入先清空或按日期分文件避免把历史成功记录混进本次判断。findstr找到内容返回 0找不到返回 1可以接在 bat 里做简单校验但不要只用它判断成功还要结合接收目录的文件数量和时间戳。5. 传输失败但任务显示成功五类常见翻车现场与排查顺序5.1 现象与根因对照表任务计划显示0x0、接收目录却没文件这类问题比直接报错更难查。下面五类现象是按排查顺序排的先看路径再看登录再看交互卡住再看模式损坏最后看部分失败。每一类都对应一个可验证的动作不要一上来就重装客户端或改网络。现象常见根因先看哪里任务显示成功文件没到bat 工作目录不对相对路径找不到脚本bat 日志里CD和ftp输出手工能登录脚本报 530.ftp编码带 BOM、user分行、口令错位脚本第一行和user行任务一直运行不结束没写prompt off或位置在mget之后日志停在mget附近压缩包传过去打不开用了ascii传二进制文件脚本里binary/ascii位置部分文件失败但返回 0ftp.exe对单个文件失败不返回非零日志里的550和文件数量5.2 逐条修复与验证第一条任务成功但文件没到。现象是任务计划“上次运行结果”为0x0C:\datatran下没有新文件。原因多半是任务计划在System32下启动bat 里用了ftp -s:1.ftp这种相对路径客户端找不到脚本或者脚本找到了但cd没切到接收目录。解决是把所有路径写成绝对路径并在 bat 里先打印当前目录和文件列表再调用 ftp。echo off cd /d C:\datatran echo [%date% %time%] CWD%CD% C:\datatran\ftp_run.log dir C:\datatran C:\datatran\ftp_run.log ftp -n -s:C:\1.ftp C:\datatran\ftp_run.log 21逻辑说明cd /d固定工作目录echo CWD把当前目录写进日志dir记录传输前本地文件情况ftp追加日志。参数说明日志路径和脚本路径换成实际值dir只列本地目录用来确认 bat 是不是在预期位置执行如果日志里CWD不是C:\datatran说明cd /d没生效或被前面的命令改掉了。第二条手工能登录脚本报530。现象是命令行里输入账号口令能进脚本一跑就提示登录失败。原因常见有三种.ftp文件保存成了带 BOM 的 UTF-8第一行open前面多了不可见字符user和口令分成两行中间有空行或行尾符不一致口令被当成下一条命令脚本里用了中文标点或全角空格。解决是把user写成一行脚本另存为 ANSI 或无 BOM 的 UTF-8删掉空行。open 10.30.15.3 user anonymous 123456 cd data binary prompt off mget *.dat bye逻辑说明user一行写完用户名和口令减少分行等待open是第一行前面不能有空白行cd和mget按顺序执行。参数说明anonymous和123456换成实际账号如果口令里包含空格或特殊字符先确认客户端是否支持必要时改用更简单的服务账号做验证再逐步加回特殊字符。第三条任务一直运行不结束。现象是任务计划里状态一直是“正在运行”日志停在mget后面没有bye。原因通常是没写prompt off或者写在了mget之后客户端在等人工输入y/n。解决是把prompt off放到所有mget/mput之前并在任务计划里设置“如果任务运行时间超过”一个合理值后停止避免卡死占用下一次触发。prompt off mget *.dat mget *.txt bye逻辑说明prompt off必须在多文件命令前多个mget共享这个设置bye结束会话。参数说明如果只传一个文件prompt不影响但保留它能让脚本以后加多文件时不踩坑任务计划的超时设置是兜底不是替代prompt off。第四条压缩包传过去打不开。现象是.zip或.exe文件大小和源文件不一致解压报错。原因是脚本用了ascii或者在binary之前就执行了mget。解决是把binary放到传输命令之前并检查日志里传输模式Windows 之间传纯文本可以去掉bin但二进制文件必须保留。open 10.30.15.3 user anonymous 123456 cd data binary prompt off mget *.zip bye逻辑说明binary在mget前设置prompt off关闭确认mget只拉压缩包。参数说明*.zip换成实际后缀如果同一个脚本既传文本又传二进制按文件类型分段写每段前明确设置模式不要依赖上一次会话的默认值。第五条部分文件失败但任务返回 0。现象是日志里有550但任务计划显示成功接收目录少文件。原因是ftp.exe对单个文件失败不一定返回非零mget遇到一个不可用文件后可能继续执行后面的命令。解决是日志解析加文件数量校验发现550或Not connected就把 bat 返回码改成非零让任务计划标红。findstr /I /C:550 /C:Not connected C:\datatran\ftp_run.log if not errorlevel 1 ( echo [%date% %time%] FTP partial failure C:\datatran\ftp_error.log exit /b 2 )逻辑说明findstr找到关键字时返回 0if not errorlevel 1表示“找到了”此时写错误日志并返回 2没找到就继续。参数说明550和Not connected是常见失败关键字可以按实际服务端返回补充返回码 2 和前面的 1 区分开任务计划历史里能看出是“部分失败”还是“进程失败”。更稳的做法是传输前后各统计一次文件数量数量对不上就报警不要只依赖文本搜索。6. 从能跑到可验证日志、重试与过期文件清理的进阶做法脚本能跑通只是第一步真正省心的是让失败可见、可重试、可清理。我的习惯是给 bat 加三样东西带时间戳的日志、有限次重试、传输后的文件校验。重试不要无限循环三次足够每次间隔一分钟避免网络抖动时把对端打满。echo off setlocal set LOGC:\datatran\ftp_run.log for /L %%i in (1,1,3) do ( ftp -n -s:C:\1.ftp %LOG% 21 if not errorlevel 1 goto :ok echo [%date% %time%] retry %%i failed %LOG% timeout /t 60 /nobreak nul ) exit /b 1 :ok exit /b 0逻辑说明for /L从 1 到 3 循环每次调用 ftp 后判断退出码成功就goto :ok跳出失败写重试日志并等待 60 秒。参数说明%%i是循环变量bat 文件里要双百分号timeout /t 60在任务计划里可用老系统没有timeout时可以换成ping -n 61 127.0.0.1 nul返回码 1 表示三次都失败任务计划会标红。清理过期文件可以用forfiles按修改时间删除两天前的文件适合接收目录只保留最近几天数据的场景。/D -2表示两天前/S递归子目录/C里path是匹配到的文件路径。执行前先用echo打印一遍确认范围没错再换成del。forfiles /P C:\datatran\archive /S /M *.* /D -2 /C cmd /c echo path forfiles /P C:\datatran\archive /S /M *.* /D -2 /C cmd /c del path p a hrefhttps://download.csdn.net/download/andysong163/1807019 stylecolor:#ec7500;font-size:14px; 本文还有配套的精品资源点击获取 /a img altmenu-r.4af5f7ec.gif srchttps://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif stylewidth:16px;margin-left:4px;vertical-align:text-bottom;cursor:text; /p