VBS: автоматическая архивация логов

Когда-то давно мною был написан 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 на архивацию тех или иных папок.

Таким образом в одном файле-скрипте перечислены все папки логов всех серверов в нашей сети - удобно для анализа архивируемых папок, редактирования скрипта и добавления одной универсальной команды в планировщики задач всех серверов.

Понравилось? =) Поделись с друзьями:

Обсудить