Когда-то давно мною был написан vbs-скрипт, сейчас он попался под руку и я решил его опубликовать. Чтоб не затерялся в недрах винчестеров.
Скрипт архивирует файлы (по маске), которые не модифицировались по прошествии указанного количества дней/месяцев. С помощью этого скрипта можно автоматизировать процесс архивирования лог-файлов, которые накапливаются в служебных папках, - экономия занятого пространства, да и папка при открытии не будет тормозить если в ней не находятся тысячи или десятки тысяч файлов. Файлы архивируются с помощью архиватора 7zip (7-zip.org), который сохранен на доступном для всех серверов сетевом диске, там же сохранены и сами скрипты.
Сейчас просматривая этот скрипт я вижу где и что можно было бы оптимизировать, но помня поговорку "Не надо трогать то, что хорошо работает", решил ничего не менять.
Итак, скрипт отвечающий за архивацию:
'данный скрипт delmask.vbs удаляет в директории все файлы, у которых 'дата последней модификации старше определенного количества дней 'синтаксис таков 'delmask.vbs /a:<address with mask> /d:<days> /r /l:<File Name> /e:<File Name> /7z '/a:<address with mask> - адрес папки с маской файла '/d:<number> - указывает старше скольки дней файлы будут удаляться '/m:<number> - указывает старше скольки месяцев файлы будут удаляться '/r - использовать рекурсию ВНИМАНИЕ! значительно замедляется работа скрипта '/l:<File Name> - ведение лога '/e:<File Name> - закидывать удаляемые файлы в архив, по умолчанию тип - zip '/7z - архивироватся будет в формате 7zip, использовать параметрв вместе с /e:<File Name> 'например 'delmask.vbs /a:c:\0\*.txt /d:8 /r /l:C:\log.log /e:archive.zip 'Отмечу также, что если параметры содержат пробелы, 'в нашем случае это может быть путь к папке, то его надо 'брать в кавычки 'обьявление обьектов set objNamedArgs=Wscript.Arguments.Named Set objDateTime = CreateObject("WbemScripting.SWbemDateTime") Set objService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\CIMV2") Set FSO = CreateObject("Scripting.FileSystemObject") Set WshShell = CreateObject("Wscript.Shell") 'справка if (objNamedArgs.Exists("?")) then WScript.Echo "данный скрипт удаляет в директории все файлы, у которых" WScript.Echo "дата последней модификации старше определенного количества дней" WScript.Echo "синтаксис таков" WScript.Echo "del.vbs /a:<address with mask> /d:<days> /r /l:<File Name> /e:<File Name>" WScript.Echo "/a:<address with mask> - адрес папки с маской файла" WScript.Echo "/d:<number> - указывает старше скольки дней файлы будут удаляться" WScript.Echo "/m:<number> - указывает старше скольки месяцев файлы будут удаляться" кот WScript.Echo "/r - использовать рекурсию ВНИМАНИЕ! значительно замедляется работа скрипта" WScript.Echo "/l:<File Name> - ведение лога" WScript.Echo "/e:<File Name> - закидывать удаляемые файлы в архив" WScript.Echo "например" WScript.Echo "del.vbs /a:c:\0\*.txt /d:8 /r /l:C:\log.log /e:archive.zip" WScript.Echo "Отмечу также, что если параметры содержат пробелы, " WScript.Echo "в нашем случае это может быть путь к папке, то его надо " WScript.Echo "брать в кавычки" WScript.Quit end if RetCode = 0 drive = "" FileName = "" Extension = "" LogFile = "" ArchivatorPath = Chr(34) & "\\networkdisk\Scripts\7-Zip\7z" & Chr(34) ArchiveFile = "" ArchiveType = "-tzip " zip7 = "" strdate = Year(date) if Month(date) < 10 then strdate = strdate & "0" & Month(date) else strdate = strdate & Month(date) end if if Day(date) < 10 then strdate = strdate & "0" & Day(date) else strdate = strdate & Day(date) end if 'вычисляем время последней модификации if (objNamedArgs.Exists("d")) then killdate=DateAdd("d",-objNamedArgs.item("d"),date) end if if (objNamedArgs.Exists("m")) then killdate=DateAdd("m",-objNamedArgs.item("m"),date) end if path=objNamedArgs.item("a") LogFile = objNamedArgs.item("l") if (objNamedArgs.Exists("e")) then ArchiveFile = Chr(34) & objNamedArgs.item("e") & strdate & Chr(34) end if if (objNamedArgs.Exists("7z")) then if not(objNamedArgs.Exists("e")) then WScript.Echo "Вы не указали имя архива, используйте параметр /e" WScript.Quit end if ArchiveType = "-t7z " end if objDateTime.SetVarDate killdate if killdate = "" then WScript.Echo "Вы не указали время" WScript.Quit else WScript.Echo "Будут удалены файлы, которые созданы до " & killdate end if 'коректировка sql запроса path=Replace(path, "*", "%") path=Replace(path, "?", "_") 'разделение адреса на диск, папку, имя-маску, раширение-маску файла slash = InStrRev(path,"\") FileName = Mid(path,slash+1) tochka = InStrRev(FileName,".") drive=Left(path,2) path = Left(path,slash) path=Mid(path,3) path_work = drive & path if tochka <> 0 then Extension = Mid(FileName,tochka+1) FileName = Mid(FileName,1,tochka-1) end if listfile = path_work & "listfile.txt" if ( drive = "" ) or ( FileName = "" ) then WScript.Echo "неверно введенная маска!" WScript.Quit end if 'заменяем все одинарные слешы на двойные path=Replace(path, "\", "\\") 'проверяем надо ли рекурсию if (objNamedArgs.Exists("r")) then podzapros = "Path Like'" & path & "%'" else podzapros = "Path = '" & path & "'" end if zapros = "SELECT Name, LastModified FROM CIM_DataFile WHERE Drive = '" & drive & "' AND " & podzapros & " AND FileName Like '" & FileName & "' AND LastModified <= '" & objDateTime.value & "'" 'Смотрим если в маске файла расширение if Extension <> "" then zapros = zapros & " AND Extension Like '" & Extension & "'" end if On Error Resume Next If Err.Number <> 0 Then WScript.Echo Err.Number & ": " & Err.Description WScript.Quit End If 'выполняем запрос Set colFiles = objService.ExecQuery(zapros) 'если запрос выдал не нулевой результат if colFiles.Count <> 0 then 'если надо архивировать - архивируем if ( ArchiveFile <> "" ) then Set TextStream = FSO.CreateTextFile(listfile,1) For Each objFile In colFiles TextStream.WriteLine Chr(34) & objFile.Name & Chr(34) Next TextStream.Close comand = "cmd /c " & Chr(34) & ArchivatorPath & " a " & ArchiveType & ArchiveFile & " @" & Chr(34) & listfile & Chr(34) & " -scsWIN -mx9 -w" & Chr(34) & path_work & Chr(34) if LogFile <> "" then comand = comand & " >> " & Chr(34) & LogFile & Chr(34) end if comand = comand & Chr(34) RetCode = WshShell.Run(comand, 0, True) FSO.DeleteFile(listfile) end if 'если архивирование успешно - удаляем файлы и записуем это в лог if RetCode = 0 then Set TextStream = FSO.OpenTextFile(LogFile,8,1) For Each objFile In colFiles WScript.Echo objFile.Name objDateTime.Value = objFile.LastModified TextStream.WriteLine "Delete File " & Now() & " " & objFile.Name & " " & objDateTime.GetVarDate FSO.DeleteFile(objFile.Name) Next WScript.Echo "Завершено успешно! Всего файлов: " & colFiles.Count 'если архивирование не успешно - выдаем ошибку else Select Case RetCode Case "1" WScript.Echo "ошибка при архивации! Warning (Non fatal error(s)). For example, some files were locked by other application during compressing. So they were not compressed." Case "2" WScript.Echo "ошибка при архивации! Fatal error" Case "7" WScript.Echo "ошибка при архивации! Command line error" Case "8" WScript.Echo "ошибка при архивации! Not enough memory for operation" Case "255" WScript.Echo "ошибка при архивации! User stopped the process" End Select end if TextStream.Close else WScript.Echo "files with specified mask is not found!" end if
Запуск этого скрипта я совершаю из скрипта №2:
Set WSHShell = CreateObject("WScript.Shell") Set WshSysEnv = WshShell.Environment("Process") Set FSO = CreateObject("Scripting.FileSystemObject") strdate = Year(date) if Month(date) < 10 then strdate = strdate & "0" & Month(date) else strdate = strdate & Month(date) end if if Day(date) < 10 then strdate = strdate & "0" & Day(date) else strdate = strdate & Day(date) end if if WshSysEnv("ComputerName") = "NAME_OF_SERVER" then comand = "cscript \\networkdisk\Scripts\delmask.vbs /a:" & Chr(34) & "C:\Program Files\Microsoft Forefront Threat Management Gateway\Logs\*.w3c" & Chr(34) & " /m:1 /e:" & Chr(34) & "C:\Program Files\Microsoft Forefront Threat Management Gateway\Logs\Archive\archive" & Chr(34) & " /l:" & Chr(34) & "C:\Program Files\Microsoft Forefront Threat Management Gateway\Logs\Archive\log.log" & Chr(34) RetCode = WshShell.Run(comand, 0, True) FSO.CopyFile "C:\Program Files\Microsoft Forefront Threat Management Gateway\Logs\Archive\archive" & strdate & ".zip", "\\networkdisk\Public\Backup\NameOfServer\Logs\" FSO.CopyFile "C:\Program Files\Microsoft Forefront Threat Management Gateway\Logs\Archive\log.log", "\\networkdisk\Public\Backup\NameOfServer\Logs\" end if
Сама суть автоматизации такова: в скрипте №2 (который сохранен на сетевом диске) я описываю для каждого сервера какие папки и файлы необходимо архивировать (а значит с какими параметрами необходимо запустить скрипт №1). После этого в планировщике задач каждого сервера добавляю задачу с запуском скрипта №2. Если мне нужно архивировать файлы которые старше 3-х месяцев, то и задача эта выполняется раз в три месяца.
С помощью условий
if WshSysEnv("ComputerName") = "NAME_OF_SERVER" then
скрипт узнает на каком сервере он запущен и дает команду скрипту №1 на архивацию тех или иных папок.
Таким образом в одном файле-скрипте перечислены все папки логов всех серверов в нашей сети - удобно для анализа архивируемых папок, редактирования скрипта и добавления одной универсальной команды в планировщики задач всех серверов.