前言:
公司有幾百臺windows服務器,每次程序更新,如果是一臺臺拷數據,只怕安排十個人,一天都不一定做得完,所以就必須研究個全自動更新方案來,于是就想到了FTP,做個主FTP站,在幾百臺客戶機上啟動BAT腳本,每30秒檢測一次,如果主站有更新程序,就自動下載更新,幾分鐘內,上400臺windows服務器,都可以全自動更新程序完畢,相當實用,現把當初研究BAT的腳本思路貼出來,希望對大批量運維人員一個方向。當然,批量更新服務器,每個公司有它自己的解決辦法,這個BAT的方式不是最優的,可以用shell,可以用perl,也可以用python等腳本解決。
一、FTP命令說明
1、在windows系統中因為FTP是一個程序,如果在bat腳本中直接調用FTP的命令,在執行時總會彈出命令行窗口,循環在>FTP光標這,所以要換種方式,利用-S:filename,更多的命令請輸入-h查看。

2、FTP登錄成功后,需要下載遠程單個文件時,使用get命令,如果下載多個文件時,用mget,它支持通配符,在使用mget時,需要對每一個文件都進行選擇Y/N,如果想不交互的下載全部的文件,可以輸入一次prompt命令關閉交互方式。
Mput和mget命令要注意兩個問題:
Ⅰ、不能對目標文件指定命字,在命令行上所有的文件都視做源文件
Ⅱ、mput,mget兩個命令不能對目錄進行上傳與下載,只能對文件
Ⅲ、Prompt:每次執行一個這個命令,就在on ,off之間循環,ftp腳本開始時,prompt默認為on,所以一般在上傳、下載文件時,執行一次prompt,把交互式的on關掉,變為off。
3、文件的傳輸方式:
Binary ,二進制傳輸
Ascii ,ascII傳輸
在FTP文件傳輸過程中,ASCII傳輸HTML和文本編寫的文件,而二進制碼傳輸可以傳送文本和非文本(執行文件,壓縮文件,圖片等),具有通用性,二進制碼傳輸速度比ASCII傳輸要快,所以在建立bat腳本時,一般輸入bin命令,啟用二進制傳輸。如果用ASCII模式傳輸非文本文件,可能會顯示一堆亂碼,如果是上傳一些CGI腳本,有可能將無法運行這類腳本,而在瀏覽器上看到server 500 error的錯誤。
Ascii和binary模式的區別是回車換行的處理。binary模式不對數據進行任何處理,asci模式將回車換行轉換為本機的回車字符,比如Unix下是\n,Windows下是\r\n,Mac下是\r。unix系統下行結束符是一個字節,即十六進制的0A,而ms的系統是兩個字節,即十六進制的0D0A。
所以當你用ascii方式從unix的ftp server下載文件時(不管是二進制或者文本文件,redhat的 vsftp默認是binary,ascii默認關閉),每檢測到一個字節是0A,就會自動插入一個0D,所以如果你的文件是二進制文件比如可執行文件、壓縮包什么的,就肯定不能用了。如果你的文件就是unix下的文本文件,你用 ascii模式是正確的,要是誤用了binary模式,你在windows上看這個文件是沒有換行的,里面是一個個的黑方塊。
在用FTP客戶端傳輸文件時,因為這些軟件都做得比較智能化,它可以根據后綴,自動啟用傳輸模式,所以不用擔心出問題。
二、實例求證:
環境說明:192.168.133.34上有一FTP服務器端(windows版),FTP用戶名為lgh,密碼為www.jb51.net。該用戶的根目錄為D:\lgh。里面文件見下圖。sql.rar是sql.bat的壓縮文件,大家注意看圖,我等下會在后面的實例中引用這個文件,把mget,get,prompt,bin,ascii等ftp命令詮釋得一清二白。

實例一:直接BAT調用FTP命令
ftpbat.bat內容
(***大家建立bat文件不要命名為ftp.bat,執行時會有問題***)
復制代碼 代碼如下:
ftp
open 192.168.133.34
lgh
www.jb51.net
get sql.rar
bye

從圖上的結果看,bat腳本直接調用xp的FTP命令是不行的,執行時H:\&;ftp會一直死循環。我這里的XP系統是SP3的,其它版本的,我沒有作測試。如果有不同,歡迎大家留言告之。
實例二:用put,get上傳,下載單個文件
把XP機器上H:\js目錄下文件flower.zip上傳到FTP服務器
把FTP服務器中的sql.rar文件下載到XP機器上的H:\JS目錄
ftp-get-put.bat內容如下:
復制代碼 代碼如下:
@echo off
set ftpfilename=autoftp.cfg
echo open 192.168.133.34 >"%ftpfilename%"
echo lgh >>"%ftpfilename%"
echo www.liuguohua.com >>"%ftpfilename%"
echo bin >>"%ftpfilename%"
echo lcd h:\js >>"%ftpfilename%"
echo get sql.rar >>"%ftpfilename%"
echo put flower.zip >>"%ftpfilename%"
echo bye >>"%ftpfilename%"
ftp -s:"%ftpfilename%"
del "%ftpfilename%"

我們來看看結果,見下面兩張圖。從XP系統上看,H盤的JS目錄,多了個sql.rar,FTP服務器上的根目錄多了個flower.zip,這說明,剛才的腳本完成正常的執行了,達到了預期的目的。


實例三:用put,get上傳,下載多個文件
在XP機器上把flower.zip復制一次,改名為flower2.zip
在XP機器上把把第二次實例下載的sql.rar文件刪除,以免影響到本次操作
在FTP服務器上把第二次實例上傳的flower.zip文件刪除,以免影響到本次操作
把XP機器上H:\js目錄下文件flower.zip 和flower2.zip上傳到FTP服務器
ftp-get-put-many.bat內容如下:
復制代碼 代碼如下:
@echo off
set ftpfilename=autoftp.cfg
echo open 192.168.133.34 >"%ftpfilename%"
echo lgh >>"%ftpfilename%"
echo www.liuguohua.com >>"%ftpfilename%"
echo bin >>"%ftpfilename%"
echo lcd h:\js >>"%ftpfilename%"
echo put flower.zip flower2.zip>>"%ftpfilename%"
echo bye >>"%ftpfilename%"
ftp -s:"%ftpfilename%"
del "%ftpfilename%"

到FTP服務器上查看根目錄,看flower.zip與flower2.zip是否已成功上傳。從圖上看,只成功上傳了flower2.zip文件。

剛那個ftp-get-put-many.bat腳本里
echo put flower.zip flower2.zip>>"%ftpfilename%"
flower2.zip是傳輸的最后一個文件,是不是用put時,意味著bat在處理上傳時,只認最后一個文件呢。我們再多加個文件flower3.zip,來驗證。
在XP機器上把flower.zip復制一次,改名為flower3.zip
在FTP服務器上把第二次實例上傳的flower2.zip文件刪除,以免影響到本次操作
ftp-get-put-many.bat內容修改如下:
復制代碼 代碼如下:
@echo off
set ftpfilename=autoftp.cfg
echo open 192.168.133.34 >"%ftpfilename%"
echo lgh >>"%ftpfilename%"
echo www.liuguohua.com >>"%ftpfilename%"
echo bin >>"%ftpfilename%"
echo lcd h:\js >>"%ftpfilename%"
echo put flower.zip flower2.zip flower3.zip>>"%ftpfilename%"
echo bye >>"%ftpfilename%"
ftp -s:"%ftpfilename%"
del "%ftpfilename%"

結果,還是只成功上傳了flower2.zip,因bat雙擊時,執行過程會一閃而過,我們看不到執行過程,到命令行去執行下,看到底出了什么問題。
命令行,執行ftp-get-put-many.bat腳本,從執行情況看,flower.zip三個文件都是put的,但在傳輸時,卻只傳了flower2.zip,真不解,有知道的朋友嗎?給點方向

再換個方式,用通配符*,試試。
ftp-get-put-many.bat內容修改如下:
復制代碼 代碼如下:
@echo off
set ftpfilename=autoftp.cfg
echo open 192.168.133.34 >"%ftpfilename%"
echo lgh >>"%ftpfilename%"
echo www.liuguohua.com >>"%ftpfilename%"
echo bin >>"%ftpfilename%"
echo lcd h:\js >>"%ftpfilename%"
echo put flower*.zip >>"%ftpfilename%"
echo bye >>"%ftpfilename%"
ftp -s:"%ftpfilename%"
del "%ftpfilename%"
在FTP服務器上把上傳的flower文件全部刪除,以免影響到本次操作
執行ftp-get-put-many.bat,結果只有flower.zip文件上傳成功了。呵,flower3.zip文件,怎么都不能上傳。???

其實用put傳輸多個文件,完全可用重復的方式取代,比如:ftp-get-put-many.bat內容修改如下:
復制代碼 代碼如下:
@echo off
set ftpfilename=autoftp.cfg
echo open 192.168.133.34 >"%ftpfilename%"
echo lgh >>"%ftpfilename%"
echo www.liuguohua.com >>"%ftpfilename%"
echo bin >>"%ftpfilename%"
echo lcd h:\js >>"%ftpfilename%"
echo put flower.zip >>"%ftpfilename%"
echo put flower2.zip >>"%ftpfilename%"
echo put flower3.zip >>"%ftpfilename%"
echo bye >>"%ftpfilename%"
ftp -s:"%ftpfilename%"
del "%ftpfilename%"
實例四:用mput,mget上傳,下載多個文件
在FTP服務器上刪除有關flower的文件
ftp-mget-mput-many.bat內容如下:
復制代碼 代碼如下:
@echo off
set ftpfilename=autoftp.cfg
echo open 192.168.133.34 >"%ftpfilename%"
echo lgh >>"%ftpfilename%"
echo www.liuguohua.com >>"%ftpfilename%"
echo bin >>"%ftpfilename%"
echo lcd h:\js >>"%ftpfilename%"
echo mput flower.zip flower2.zip flower3.zip>>"%ftpfilename%"
echo bye >>"%ftpfilename%"
ftp -s:"%ftpfilename%"
del "%ftpfilename%"
雙擊ftp-mget-mput-many.bat后,發現系統彈出一窗口后,就卡住了,停止不前

原因是用了mput命令,但沒有用Prompt關閉交互
ftp-mget-mput-many.bat內容修改如下:
復制代碼 代碼如下:
@echo off
set ftpfilename=autoftp.cfg
echo open 192.168.133.34 >"%ftpfilename%"
echo lgh >>"%ftpfilename%"
echo www.liuguohua.com >>"%ftpfilename%"
echo Prompt >>"%ftpfilename%"
echo bin >>"%ftpfilename%"
echo lcd h:\js >>"%ftpfilename%"
echo mput flower.zip flower2.zip flower3.zip>>"%ftpfilename%"
echo bye >>"%ftpfilename%"
ftp -s:"%ftpfilename%"
del "%ftpfilename%"
再次執行ftp-mget-mput-many.bat,結果見下圖:

用通配符*試試
在FTP服務器上刪除有關flower的文件
ftp-mget-mput-many.bat內容修改如下:
復制代碼 代碼如下:
@echo off
set ftpfilename=autoftp.cfg
echo open 192.168.133.34 >"%ftpfilename%"
echo lgh >>"%ftpfilename%"
echo www.liuguohua.com >>"%ftpfilename%"
echo Prompt >>"%ftpfilename%"
echo bin >>"%ftpfilename%"
echo lcd h:\js >>"%ftpfilename%"
echo mput flower*.zip >>"%ftpfilename%"
echo bye >>"%ftpfilename%"
ftp -s:"%ftpfilename%"
del "%ftpfilename%"
照樣成功上傳有關flower*.zip文件。因為結果與上一步是一樣的,所以就不抓圖了。
實例五:用ascii在windows系統間傳輸非文本文件
把XP電腦上的rmb.jpg通過ascii傳到FTP服務器的根目錄。

ftp-get-ascii.bat內容修改如下:
復制代碼 代碼如下:
@echo off
set ftpfilename=autoftp.cfg
echo open 192.168.133.34 >"%ftpfilename%"
echo lgh >>"%ftpfilename%"
echo www.liuguohua.com >>"%ftpfilename%"
echo ascii >>"%ftpfilename%"
echo lcd h:\js >>"%ftpfilename%"
echo put rmb.jpg>>"%ftpfilename%"
echo bye >>"%ftpfilename%"
ftp -s:"%ftpfilename%"
del "%ftpfilename%"
執行ftp-get-ascii.bat后,發現rmb.jpg可以正常上傳,并且可以正常打開,那,這個現象與前面所以的ascii不能傳輸非文本東西有出入,這是怎么回會事呢。
這是因為,FTP服務器是WINDOWS系統,XP電腦上的bat腳本也是在windows系統上運行的,所以bat在windows系統里用FTP傳輸文件,不管是用ascii,還是用binary,都是可以的。接下來我們再做一個實驗,FTP服務器選centos,再測下ascii傳輸非文本文件問題。

實例六:用ascii在windows系統與linux系統間傳輸非文本文件
在RHEL 5.4 64位系統上建立一vsftpd服務器
上面說過redhat默認啟用二進制傳輸,關閉了ascii碼傳輸,所以我們還要修改一下vsftpd的配置文件,修改/etc/vsftpd/vsftpd.conf文件,允許客戶端進行ascii傳輸,并重啟vsftpd

把rmb.jpg放到FTP服務器,大家注意下H:\js目錄下只有ftp-getascii.bat文件

ftp-getascii.bat文件內容修改如下:
復制代碼 代碼如下:
@echo off
set ftpfilename=autoftp.cfg
echo open 192.168.145.226 >"%ftpfilename%"
echo ftp1 >>"%ftpfilename%"
echo redhat >>"%ftpfilename%"
echo asc >>"%ftpfilename%"
echo lcd h:\js >>"%ftpfilename%"
echo get rmb.jpg >>"%ftpfilename%"
echo bye >>"%ftpfilename%"
ftp -s:"%ftpfilename%"
del "%ftpfilename%"
執行ftp-getascii.bat,看結果,rmb.jpg文件有下載到XP電腦里,雙擊這個文件,發現圖像亂碼,文件被破壞了,都是ascii碼傳輸惹的禍。
換bin傳輸,測試一下
在XP電腦上刪除rmb.jpg文件,再雙擊ftp-getascii.bat文件,去從LINUX的FTP服務器下載一個rmb.jpg文件。

修改ftp-getascii.bat,把ascii改給二進制傳輸
復制代碼 代碼如下:
@echo off
set ftpfilename=autoftp.cfg
echo open 192.168.145.226 >"%ftpfilename%"
echo ftp1 >>"%ftpfilename%"
echo redhat >>"%ftpfilename%"
echo bin >>"%ftpfilename%"
echo lcd h:\js >>"%ftpfilename%"
echo get rmb.jpg >>"%ftpfilename%"
echo bye >>"%ftpfilename%"
ftp -s:"%ftpfilename%"
del "%ftpfilename%"
結果,文件正常下載,圖像也顯示正常。
擴展閱讀:
ftp使用的內部命令如下(中括號表示可選項):
1.![cmd[args]]:在本地機中執行交互shell,exit回到ftp環境,如:!ls*.zip.
2.$ macro-ame[args]:執行宏定義macro-name.
3.account[password]:提供登錄遠程系統成功后訪問系統資源所需的補充口令。
4.append local-file[remote-file]:將本地文件追加到遠程系統主機,若未指定遠程系統文件名,則使用本地文件名。
5.ascii:使用ascii類型傳輸方式。
6.bell:每個命令執行完畢后計算機響鈴一次。
7.bin:使用二進制文件傳輸方式。
8.bye:退出ftp會話過程。
9.case:在使用mget時,將遠程主機文件名中的大寫轉為小寫字母。
10.cd remote-dir:進入遠程主機目錄。
11.cdup:進入遠程主機目錄的父目錄。
12.chmod mode file-name:將遠程主機文件file-name的存取方式設置為mode,如: chmod 777 a.out 。
13.close:中斷與遠程服務器的ftp會話(與open對應)。
14.cr:使用asscii方式傳輸文件時,將回車換行轉換為回行。
15.delete remote-file:刪除遠程主機文件。
16.debug[debug-value]:設置調試方式, 顯示發送至遠程主機的每條命令,如: deb up 3,若設為0,表示取消debug。
17.dir[remote-dir][local-file]:顯示遠程主機目錄,并將結果存入本地文件local-file。
18.disconnection:同close。
19.form format:將文件傳輸方式設置為format,缺省為file方式。
20.get remote-file[local-file]: 將遠程主機的文件remote-file傳至本地硬盤的local-file。
21.glob:設置mdelete,mget,mput的文件名擴展,缺省時不擴展文件名,同命令行的-g參數。
22.hash:每傳輸1024字節,顯示一個hash符號(#)。
23.help[cmd]:顯示ftp內部命令cmd的幫助信息,如:help get。
24.idle[seconds]:將遠程服務器的休眠計時器設為[seconds]秒。
25.image:設置二進制傳輸方式(同binary)。
26.lcd[dir]:將本地工作目錄切換至dir。
27.ls[remote-dir][local-file]:顯示遠程目錄remote-dir, 并存入本地文件local-file。
28.macdef macro-name:定義一個宏,遇到macdef下的空行時,宏定義結束。
29.mdelete[remote-file]:刪除遠程主機文件。
30.mdir remote-files local-file:與dir類似,但可指定多個遠程文件,如: mdir *.o.*.zipoutfile 。
31.mget remote-files:傳輸多個遠程文件。
32.mkdir dir-name:在遠程主機中建一目錄。
33.mls remote-file local-file:同nlist,但可指定多個文件名。
34.mode[modename]:將文件傳輸方式設置為modename, 缺省為stream方式。
35.modtime file-name:顯示遠程主機文件的最后修改時間。
36.mput local-file:將多個文件傳輸至遠程主機。
37.newer file-name: 如果遠程機中file-name的修改時間比本地硬盤同名文件的時間更近,則重傳該文件。
38.nlist[remote-dir][local-file]:顯示遠程主機目錄的文件清單,并存入本地硬盤的local-file。
39.nmap[inpattern outpattern]:設置文件名映射機制, 使得文件傳輸時,文件中的某些字符相互轉換,如:nmap $1.$2.$3[$1,$2].[$2,$3],則傳輸文件a1.a2.a3時,文件名變為a1,a2。該命令特別適用于遠程主機為非UNIX
機的情況。
40.ntrans[inchars[outchars]]:設置文件名字符的翻譯機制,如ntrans1R,則文件名LLL將變為RRR。
41.open host[port]:建立指定ftp服務器連接,可指定連接端口。
42.passive:進入被動傳輸方式。
43.prompt:設置多個文件傳輸時的交互提示。
44.proxy ftp-cmd:在次要控制連接中,執行一條ftp命令, 該命令允許連接兩個ftp服務器,以在兩個服務器間傳輸文件。第一條ftp命令必須為open,以首先建立兩個服務器間的連接。
45.put local-file[remote-file]:將本地文件local-file傳送至遠程主機。
46.pwd:顯示遠程主機的當前工作目錄。
47.quit:同bye,退出ftp會話。
48.quote arg1,arg2...:將參數逐字發至遠程ftp服務器,如:quote syst.
49.recv remote-file[local-file]:同get。
50.reget remote-file[local-file]:類似于get,但若local-file存在,則從上次傳輸中斷處續傳。
51.rhelp[cmd-name]:請求獲得遠程主機的幫助。
52.rstatus[file-name]:若未指定文件名,則顯示遠程主機的狀態,否則顯示文件狀態。
53.rename[from][to]:更改遠程主機文件名。
54.reset:清除回答隊列。
55.restart marker:從指定的標志marker處,重新開始get或put,如:restart 130。
56.rmdir dir-name:刪除遠程主機目錄。
57.runique:設置文件名唯一性存儲,若文件存在,則在原文件后加后綴..1,.2等。
58.send local-file[remote-file]:同put。
59.sendport:設置PORT命令的使用。
60.site arg1,arg2...:將參數作為SITE命令逐字發送至遠程ftp主機。
61.size file-name:顯示遠程主機文件大小,如:site idle 7200。
62.status:顯示當前ftp狀態。
63.struct[struct-name]:將文件傳輸結構設置為struct-name, 缺省時使用stream結構。
64.sunique:將遠程主機文件名存儲設置為唯一(與runique對應)。
65.system:顯示遠程主機的操作系統類型。
66.tenex:將文件傳輸類型設置為TENEX機的所需的類型。
67.tick:設置傳輸時的字節計數器。
68.trace:設置包跟蹤。
69.type[type-name]:設置文件傳輸類型為type-name,缺省為ascii,如:type binary,設置二進制傳輸方式。
70.umask[newmask]:將遠程服務器的缺省umask設置為newmask,如:umask 3。
71.user user-name[password][account]:向遠程主機表明自己的身份,需要口令時,必須輸入口令,如:user anonymous my@email。
72.verbose:同命令行的-v參數,即設置詳盡報告方式,ftp服務器的所有響應都將顯示給用戶,缺省為on.
73.?[cmd]:同help.
您可能感興趣的文章:- 實現自動上傳文件到ftp服務器的BAT腳本分享
- 批處理bat下載FTP服務器上某個目錄下的文件
- 批處理bat下載FTP服務器上指定天數之前的文件
- 備份文件并上傳至FTP服務器的bat代碼
- linux和windows下的自動ftp腳本(shell bat)
- 使用FTP下載目錄,即FTP命令批量自動下載的bat文件
- windows下定時利用bat腳本實現ftp上傳下載