Пакетное изменение файлов с закачкой их по FTP (WSH инструменты вэб-мастера).
В этом топике я напомню о старинной скриптовой технологии WSH - которая не требует специфических навыков программирования и доступна каждому. У меня на сайте достаточно много старых топиков по простейшим скриптовым технологиям, не требущим знания программирования (в основном от 2002-го года - 2004-го года):
- Скрипты WSH
- Сценарии ADSI
- VBA - язык автоматизации Excel
- Управление ресурсами компьютера с помощью Windows WMI
- Thomas_Eck_ADSI_Lib - OpenSource библиотека ADSI-функций Томаса Еска на VB.NET
Итак, о возможностях этой технологии мы вспомним на примере простейшего скрипта web-мастера - cамая распространенная работа которого заключается во внесении изменений в некий набор файлов сайта и закачку каждого обработанного файла на web-сервер.
Для начала надо подготовить список обрабатываемых файлов (FileList.txt). Такие списки могут быть весьма большими. Например, на моем сайте votpusk.ru только в ОДНОМ поддомене лежит 623 тысячи файлов в 4260 каталогах). И для сайта с посещаемостью четверть миллиона человек в сутки никакая серверная технология не обеспечивает нужной производительности. Поэтому реклама и все необходимое заранее включается в html-файлы, которые потом без изменений 30 миллионов раз в месяц запрашиваются пользователями. Ну а когда рекламный блок меняется - проходит бот, меняет рекламный блок и новые измененные тысячи html-страничек отгружаются пользователям десятки миллионов раз без изменений (пока не потребуется внесения новых изменений). Вообще с нагруженными сайтами работают иначе, чем с обычными - многое описано у меня на сайте - например Выполнение периодических задач в ASP.NET. Но не будем отвлекатся на технологии веб-мастеров для нагруженных сайтов - надеюсь общий смысл работы веб-мастера вам понятен?
Вэб-мастеру важно не только внести требуемое изменение каждый файл на локальном кампутере, но не пропустить ни одного файла при закачке на веб-сервер. При этом в каждом каталоге могут быть многие тысячи файлов а нам нужно в каждом каталоге исправить ОДИН нужный файл и именно его закачать (не пропустив его и не закачав ничего лишнего и не изменив ничего лишнего). Поэтому, как вы понимаете, интерактивные решения типа моего SiteChecker - утилита оптимизации сайта - для решения такой задачи не подходят совершенно.
Итак, даже для моего скромного блога программиста vb-net.com за 10 лет скопилось более двухсот входных страниц.
1: D:\Job57\1C-Gateway\index.htm
2: D:\Job57\1U\index.htm
3: D:\Job57\2012\index.htm
4: D:\Job57\AbsoluteEvil\index.htm
5: D:\Job57\AIR\index.htm
6: D:\Job57\altova\index.htm
7: D:\Job57\AmnestyBusiness\index.htm
8: D:\Job57\Apache\index.htm
9: D:\Job57\asp2\1\index.htm
10: D:\Job57\asp2\10\index.htm
11: D:\Job57\asp2\11\index.htm
12: D:\Job57\asp2\13\index.htm
13: D:\Job57\asp2\14\index.htm
14: D:\Job57\asp2\15\index.htm
15: D:\Job57\asp2\16\index.htm
16: D:\Job57\asp2\17\index.htm
17: D:\Job57\asp2\18\index.htm
18: D:\Job57\asp2\19\index.htm
19: D:\Job57\asp2\2\index.htm
20: D:\Job57\asp2\21\index.htm
21: D:\Job57\asp2\22\index.htm
22: D:\Job57\asp2\23\index.htm
23: D:\Job57\asp2\24\index.htm
24: D:\Job57\asp2\25\index.htm
25: D:\Job57\asp2\26\index.htm
26: D:\Job57\asp2\27\index.htm
27: D:\Job57\asp2\28\index.htm
28: D:\Job57\asp2\3\index.htm
29: D:\Job57\asp2\30\index.htm
30: D:\Job57\asp2\31\index.htm
31: D:\Job57\asp2\32\index.htm
32: D:\Job57\asp2\33\index.htm
33: D:\Job57\asp2\34\index.htm
34: D:\Job57\asp2\35\index.htm
35: D:\Job57\asp2\36\index.htm
36: D:\Job57\asp2\37\index.htm
37: D:\Job57\asp2\38\index.htm
38: D:\Job57\asp2\39\index.htm
39: D:\Job57\asp2\4\index.htm
40: D:\Job57\asp2\40\index.htm
41: D:\Job57\asp2\41\index.htm
42: D:\Job57\asp2\42\index.htm
43: D:\Job57\asp2\43\index.htm
44: D:\Job57\asp2\44\index.htm
45: D:\Job57\asp2\45\index.htm
46: D:\Job57\asp2\5\index.htm
47: D:\Job57\asp2\6\index.htm
48: D:\Job57\asp2\8\index.htm
49: D:\Job57\asp2\9\index.htm
50: D:\Job57\AspNet_UserManager\index.htm
51: D:\Job57\AutoComplete\index.htm
52: D:\Job57\Barron\index.htm
53: D:\Job57\BasePage\index.htm
54: D:\Job57\Bike\index.htm
55: D:\Job57\Bug_Tracker\index.htm
56: D:\Job57\Calendar\index.htm
57: D:\Job57\card\index.htm
58: D:\Job57\ChoiceFotoCamera\index.htm
59: D:\Job57\ClientSSL\index.htm
60: D:\Job57\ComDetector\index.htm
61: D:\Job57\CompareSQLPerfomance\index.htm
62: D:\Job57\convert\index.htm
63: D:\Job57\convert\xslt\index.htm
64: D:\Job57\Counter\index.htm
65: D:\Job57\CreateUserProfile\index.htm
66: D:\Job57\criminal\index.htm
67: D:\Job57\criptopro\index.htm
68: D:\Job57\CSV_Spliter\index.htm
69: D:\Job57\Curs\index.htm
70: D:\Job57\Custom_VKP80\index.htm
71: D:\Job57\Dlink_VOIP_VLAN\physical-level.htm
72: D:\Job57\DomainDelegated\index.htm
73: D:\Job57\dotnet\tour13\index.htm
74: D:\Job57\dotnet\tour14\index.htm
75: D:\Job57\dotnet\tour15\index.htm
76: D:\Job57\dotnet\tour16\index.htm
77: D:\Job57\dotnet\tour17\index.htm
78: D:\Job57\dotnet\tour18\index.htm
79: D:\Job57\dotnet\tour21\index.htm
80: D:\Job57\dotnet\tour7\index.htm
81: D:\Job57\dotnet\tour9\index.htm
82: D:\Job57\dotnet\uml.htm
83: D:\Job57\DrawPolarGradientAtan\index.htm
84: D:\Job57\dvd\index.htm
85: D:\Job57\EnglishGrammar\index.htm
86: D:\Job57\EnglishIdioms\index.htm
87: D:\Job57\EnglishPhonetics\index.htm
88: D:\Job57\EnglishPhrase\index.htm
89: D:\Job57\EnglishProverbs\index.htm
90: D:\Job57\Excel\Report.htm
91: D:\Job57\ExcelPriceConverter\index.htm
92: D:\Job57\ExchangeLogAnalyzer\index.htm
93: D:\Job57\ExecMySQL_RDR\index.htm
94: D:\Job57\Firefox\index.htm
95: D:\Job57\Flash_BLUR\index.htm
96: D:\Job57\Flash_Professional\index.htm
97: D:\Job57\Flex_Diagram\index.htm
98: D:\Job57\Flex_Image_Slider\index.htm
99: D:\Job57\Flex_Panorama\index.htm
100: D:\Job57\Flex_Socket\index.htm
101: D:\Job57\Flex_StackViewTemplate\index.htm
102: D:\Job57\Flex_Video\index.htm
103: D:\Job57\Flex4_Welcome\index.htm
104: D:\Job57\FlexVideoPlayer\index.htm
105: D:\Job57\Flowers\index.htm
106: D:\Job57\Flowers\index.html
107: D:\Job57\Forest\index.htm
108: D:\Job57\Foto_Slider\index.htm
109: D:\Job57\freebsd\tour\graph.htm
110: D:\Job57\freebsd\tour\install.htm
111: D:\Job57\freebsd\tour\prepare.htm
112: D:\Job57\freebsd\tour\rus.htm
113: D:\Job57\Garmin-62s\index.htm
114: D:\Job57\GoogleTranslate\index.htm
115: D:\Job57\GraphFramework\index.htm
116: D:\Job57\hMailServer\index.htm
117: D:\Job57\hosting\forum\index.html
118: D:\Job57\hosting\index.htm
119: D:\Job57\hosting\php.htm
120: D:\Job57\hosting\php3\index.html
121: D:\Job57\hosting\qmail\index.htm
122: D:\Job57\Java-Welcome\index.htm
123: D:\Job57\jQuery_in_AIR\index.htm
124: D:\Job57\jQuery-UI-Dialog\index.htm
125: D:\Job57\Lamp\index.htm
126: D:\Job57\LinkedList\index.htm
127: D:\Job57\Linq\index.htm
128: D:\Job57\LiveCD\index.htm
129: D:\Job57\LowCostAspNet\index.htm
130: D:\Job57\Meteonova\index.htm
131: D:\Job57\MoscowFire\index.htm
132: D:\Job57\MoscowRiver\index.htm
133: D:\Job57\mvc_markup\index.htm
134: D:\Job57\MVC3_step_by_step\index.htm
135: D:\Job57\My_cisco\index.htm
136: D:\Job57\MySQL\index.htm
137: D:\Job57\MySQL_ASPNET_Users\index.htm
138: D:\Job57\Navalny\index.html
139: D:\Job57\NestedDatalist\index.htm
140: D:\Job57\NetStringObfuscatorHelper\index.htm
141: D:\Job57\ngins\index.htm
142: D:\Job57\Obfuscator\index.htm
143: D:\Job57\OpenSuse\index.htm
144: D:\Job57\PaperVision3D_CUBE\index.htm
145: D:\Job57\PaymentGateway\index.htm
146: D:\Job57\PeriodicAspNetJob\index.htm
147: D:\Job57\PHP\index.htm
148: D:\Job57\Plan-Gitler-Putin\index.htm
149: D:\Job57\PoE-Injector\index.htm
150: D:\Job57\Portability\index.htm
151: D:\Job57\Post1\index.htm
152: D:\Job57\PostgreSQL\BLL.htm
153: D:\Job57\PostgreSQL\index.htm
154: D:\Job57\PostgreSQL\xml.htm
155: D:\Job57\PostgreSQL_AspNet\index.htm
156: D:\Job57\PostgreSQL_defect\index.htm
157: D:\Job57\PostgreSQL_hierarchy\index.htm
158: D:\Job57\PostgreSQL_Object\index.htm
159: D:\Job57\RemoteSQLexecute\index.htm
160: D:\Job57\RemoveOldFile\index.htm
161: D:\Job57\router\index.htm
162: D:\Job57\router\ISA2006\index.htm
163: D:\Job57\sarotech\index.htm
164: D:\Job57\ScriptManager\index.htm
165: D:\Job57\SEO_SiteMap\index.htm
166: D:\Job57\Simple-Flex-Music-Player\index.htm
167: D:\Job57\SIP-GW3\index.htm
168: D:\Job57\SNMP_Tester\index.htm
169: D:\Job57\SoapWsdl_vs_XML\index.htm
170: D:\Job57\SoundCreator\index.htm
171: D:\Job57\SoundCreator2\index.htm
172: D:\Job57\sql\access\index.htm
173: D:\Job57\sql\msde.htm
174: D:\Job57\sql\MySQL.htm
175: D:\Job57\sql\perfomance\index.htm
176: D:\Job57\sql\replication.htm
177: D:\Job57\sql\stady.htm
178: D:\Job57\sql\syntax.htm
179: D:\Job57\SQL_CTE\index.htm
180: D:\Job57\sqlbackup\index.htm
181: D:\Job57\SqlClr_IndexCryptoProtector\index.htm
182: D:\Job57\SQLite\index.htm
183: D:\Job57\SqlJobTimeout\index.htm
184: D:\Job57\SqlServer\index.htm
185: D:\Job57\Sql-SOAP\index.htm
186: D:\Job57\standard\index.htm
187: D:\Job57\StelsChallenger\index.htm
188: D:\Job57\Supervisor\index.htm
189: D:\Job57\Surprise\index.htm
190: D:\Job57\Terminal\index.htm
191: D:\Job57\TerminalMonitoring\index.htm
192: D:\Job57\ThomasEckAdsiLibraryOnVBNet\index.htm
193: D:\Job57\TimeTable\index.htm
194: D:\Job57\Tomcat\index.htm
195: D:\Job57\TurnRowsIntoColumns\index.htm
196: D:\Job57\UIK1493\index.htm
197: D:\Job57\UrlRewrating\index.htm
198: D:\Job57\VideoConverter\index.htm
199: D:\Job57\VmWare\index.htm
200: D:\Job57\VS2010\index.htm
201: D:\Job57\vsftpd\index.htm
202: D:\Job57\VT6421L\index.htm
203: D:\Job57\wanted\asp2class\index.htm
204: D:\Job57\wanted\message\index.htm
205: D:\Job57\wanted\my\draganddrop.htm
206: D:\Job57\wanted\my\imagecombo.htm
207: D:\Job57\wanted\my\pj.htm
208: D:\Job57\wanted\my\plugin.htm
209: D:\Job57\wanted\my\sync.htm
210: D:\Job57\Watchdog\index.htm
211: D:\Job57\WCF_Client\index.htm
212: D:\Job57\WebActivator\index.htm
213: D:\Job57\WebDownloader_UltraLite\index.htm
214: D:\Job57\WebHandler\index.htm
215: D:\Job57\WebPerfomance\index.htm
216: D:\Job57\WebServer\index.htm
217: D:\Job57\windows\DirMSI\index.htm
218: D:\Job57\windows\Exchange\index.htm
219: D:\Job57\windows\Framework2007\index.htm
220: D:\Job57\windows\frx.htm
221: D:\Job57\windows\FTP\index.htm
222: D:\Job57\windows\Goodbye\index.htm
223: D:\Job57\windows\help\index.htm
224: D:\Job57\windows\Icon\index.htm
225: D:\Job57\windows\IE\index.htm
256: D:\Job57\windows\installer\index.htm
227: D:\Job57\windows\mobile\index.htm
228: D:\Job57\windows\Outline\index.htm
229: D:\Job57\windows\OutLook\index.htm
230: D:\Job57\windows\pe\index.htm
231: D:\Job57\windows\Regeidt.htm
232: D:\Job57\windows\round\index.htm
233: D:\Job57\windows\SiteChecker\index.htm
234: D:\Job57\windows\SQLBath\index.htm
235: D:\Job57\windows\stop\index.htm
236: D:\Job57\windows\WinDump\index.htm
237: D:\Job57\WSQL_SOAP_Service_for_FLEX\index.htm
238: D:\Job57\XLINQ-and-LINQ-to-SQL\index.htm
239: D:\Job57\Xping\index.htm
240: D:\Job57\xslt\index.htm
Как получить такой список файлов в огромной системе каталоги-подкаталоги? Для этого надо сделать простейший рекурсивный обход дерева каталогов. У меня на сайте лежит весятки вариантов кода для рекурсивного обхода чего угодно - например WinDump - фиксация состояния системы или Опыт видео-конвертации - останавливатся на этом не будем - я просто покажу как выглядит рекурсивный обход на WSH:
1: StartFolder = "D:\Job57"
2:
3: Set WshFSO = CreateObject("Scripting.FileSystemObject")
4: Set FileList = WshFSO.CreateTextFile("FileList3.txt", True)
5: GetDir WshFSO, FileList, StartFolder
6:
7: function GetDir(FSO, FileList, Dir)
8: Set Folders = FSO.GetFolder(Dir)
9: For each One in Folders.Files
10: Pos1 = InStr (One.Type, "HTML")
11: if Pos1>0 then
12: FileList.WriteLine Dir & "\" & One.Name
13: end if
14: next
15: For each One in Folders.Subfolders
16: if One.Name<>".svn" then
17: GetDir FSO, FileList, Dir & "\" & One.Name
18: end if
19: next
20: end function
Теперь, когда список файлов для определенной операции готов - сделаем цикл на WSH, который будет перебирать эти файлы по очереди, выполнять требуемую обработку и затем загружать обработанный файл по FTP. То что вы должны настроить в вашей среде - выделено красным.
1: LocalFolder = "D:\Job57"
2: RemoteFTPFolder = "/Job57"
3: i=0
4: Set WshFSO = CreateObject("Scripting.FileSystemObject")
5: Set WshShell = WScript.CreateObject("WScript.Shell")
6: Set MyFileList = WshFSO.OpenTextFile("FileList.txt",1)
7: Do Until MyFileList.AtEndOfStream
8: i=i+1
9: OneLine = MyFileList.ReadLine()
10: WshShell.Run "Notepad.exe " & OneLine, 3, true
11: RemoteDir = Replace(Replace(Replace(OneLine,LocalFolder,RemoteFTPFolder),"\","/"),WshFSO.GetFileName(OneLine),"")
12: Wscript.Echo i & ": UPLOAD " & OneLine & " => " & RemoteDir
13: WshShell.Run "FTP_UPLOAD.BAT " & RemoteDir & " " & OneLine, 0, true
14: Loop
15: MyFileList.Close
PacketChange.vbs - это собственно файл VBS - скрипn на бейсике, который выполняет перебор файлов, вызывает для этого примера просто NOTEPAD и затем другой вложенный скрипт FTP_UPLOAD.BAT
Вокруг файла VBS можно сделать WSH-обвязку WindowsScript1.wsf, которую удобно отлаживать, запускать по планировщику на ночь, делать скрипты из многих шагов и так далее:
1: <job id="main">
2: <script language="VBScript" src="PacketChange.vbs" />
3: </job>
И наконец, вызываемый выше скрипт FTP_UPLOAD.BAT закачки по FTP можно сделать в виде простого батничка, который на ходу создаст файлик ftpcmd.dat, заполнит его данными для коннекта по FTP (и режимом FTP-передачи ascii/bin) и скормит этот файлик микрософтовской утилитке FTP :
1: @echo off
2: echo user MYLOGIN> ftpcmd.dat
3: set pass=MYPASSWORD
4: echo %pass%>> ftpcmd.dat
5: echo ascii>> ftpcmd.dat
6: echo cd %1>> ftpcmd.dat
7: echo put %2>> ftpcmd.dat
8: echo quit>> ftpcmd.dat
9: ftp -n -s:ftpcmd.dat 192.168.0.153
10: del ftpcmd.dat
Теперь два слова, как надо создать и отлаживать WSH-скрипт.
Наиболее важным моментом являтся то, что для WSH-скриптов работает полноценный отладчик, котрый вы можете запустить (ключи -x -d) и изучить все методы скриптового вызова COM-объектов windows (и даже попробовать их вызвать с параметрами в окне отладчика).
|