Назад | Перейти на главную страницу

Статус резервного копирования запроса Acronis после команды

Я хотел бы выполнить действие, когда резервное копирование завершится успешно (но не при сбое).

В настоящее время я использую уведомление по электронной почте, отправляя электронное письмо боту, который анализирует состояние резервного копирования из темы, а затем запускает команду, если резервное копирование было успешным.

Продукт: Acronis Backup & Recovery 10

Судя по тому, что я видел, нет простого пути.

Как и вы, я в настоящее время получаю электронное письмо о статусе выполнения задачи; однако я хотел бы получить часть этой информации в системе панелей управления. Я просто написал сценарий python (3.4) для извлечения информации из журналов Acronis и записи в файл журнала. Я также добавил возможность условного выполнения команд. (Я сделал эту часть в пакетном файле, но скрипт python можно было изменить для выполнения команд ... тем самым устраняя необходимость в пакетном файле.)

С небольшой модификацией / настройкой это должно сработать для вас.

Концепция

  • Посткомандное действие Acronis запускает командный файл.
  • ... который запускает скрипт Python
  • ... который анализирует журнал Acronis, определяет успех или неудачу (среди прочего) и возвращает код ошибки
  • ... который фиксируется командным файлом
  • ... который затем условно выполняет действие, основанное на успехе или неудаче

Предостережения

  • Сценарий python будет читать последний измененный файл журнала, поэтому параллельные операции Acronis могут быть рискованными.
  • Сценарий python читает только файлы журналов, имена файлов которых начинаются с дней недели. (т.е. он проигнорирует любые журналы console_xxxxx.log [и подобные]. Но это то, что мы хотим.)
  • Я разработчик по профессии, но это моя первая попытка освоить Python, так что это может быть не очень красиво.

Требования

  • Python 3.4 установлен в PATH среды и связан с файлами .py
  • В untangle установлен пакет python (pip install untangle)

Шаги

  1. Создайте следующий командный файл и сохраните его как acronis-last-log.cmd. Измените применимые команды для условного выполнения действий.

    @echo off
    REM Filename: acronis-last-log.cmd
    
    acronis-last-log.py
    
    if ERRORLEVEL 1 (
      echo This statement is executed whenever the Acronis task FAILS
      echo Insert any action here within the if-clause
    ) else (
      echo This statement is executed whenever the Acronis task SUCCEEDS
      echo Insert any action here within the else-clause
    )
    
  2. Создайте следующий скрипт python и сохраните его как acronis-last-log.py и поместите его в ту же папку, что и командный файл. Обязательно посетите CONFIGURATION VARIABLES раздел, чтобы изменить любые пути или параметры. Примечание. При этом создается файл журнала на основе имени задачи, который перезаписывается каждый раз при выполнении задачи Acronis. Чтобы отключить файл журнала, закомментируйте with open(...) as outFile и print(..., file=outFile) строк, не забывая при необходимости корректировать отступы кода. Чтобы изменить путь к журналу, отредактируйте outputPath переменная.

    # Filename:
    # acronis-last-log.py
    #
    # Description:
    # Process an Acronis log file and print out relevant output in a formatted string.
    # 
    # Rules:
    #   1. if any log entry is greater than ACRONIS_LOG_INFO, report that the task has failed.
    #      - This is how the Acronis emails work.  Warnings will cause the "failed" summary
    
    
    import glob
    import os
    import sys
    import textwrap
    import time
    import untangle    # to install: pip install untangle
    
    ########## CONSTANTS DECONSTRUCTED FROM ACRONIS LOGS ###########################
    
    # log module that provides the overall task status
    ACRONIS_STATUS_MODULE = 316
    
    # Acronis log error levels ("levels")
    # (0 and 1 are dummy entries that don't seem to exist within the logs)
    ACRONIS_LOG_DUMMY0  = 0
    ACRONIS_LOG_DUMMY1  = 1
    ACRONIS_LOG_INFO    = 2
    ACRONIS_LOG_WARNING = 3
    ACRONIS_LOG_ERROR   = 4
    
    
    # Error level descriptions
    # descriptions for printing, indexed by the above constants
    # padded to 7 characters long for alignment
    ERROR_LEVEL_DESCRIPTIONS = ["DUMMY0 ", "DUMMY1 ", "INFO   ", "WARNING", "ERROR  "]
    
    ########## CONFIGURATION VARIABLES #############################################
    
    # showSubMessages
    #   show auxiliary messages that meet the error level threshold (set below)
    #     True:  show subMessages
    #     False: only show the overall exit error level (module 316)
    showSubMessages = True
    
    # logPath
    #   path to Acronis log files (default: C:\ProgramData\Acronis\TrueImageHome\Logs)
    logPath = r'C:\ProgramData\Acronis\TrueImageHome\Logs'
    
    # outputPath
    #   path to where this script will output
    outputPath = r'.'
    
    # debug
    #   turn debugging on? (default: False)
    debug = False
    
    # minLevelToDisplay
    #   minimum error level to display (default: ACRONIS_LOG_WARNING)
    minLevelToDisplay = ACRONIS_LOG_WARNING
    
    # maxLevelToDisplay
    #   maximum error level to display (default: ACRONIS_LOG_ERROR)
    maxLevelToDisplay = ACRONIS_LOG_ERROR
    
    ########## HELPER FUNCTIONS ####################################################
    
    def logDescription(errorLevel):
      """Return a log description based on Acronis error level."""
      return ERROR_LEVEL_DESCRIPTIONS[errorLevel]
    
    ########## FUNCTIONS ###########################################################
    def process(logFile):
      """Process an Acronis log file and print out relevant output in a formatted string.
    
    
        with !showSubMessages, just a single line is printed:
    
        yyyy-mm-dd hh:mm:ss ERRORLEVEL [AcronisTask] Summary
        e.g.
        2014-12-25 14:16:40 WARNING [MyBackupTask] execution failed
    
    
        with showSubMessages, multiple will be printed:
    
        yyyy-mm-dd hh:mm:ss ERRORLEVEL [AcronisTask] Summary
                            ERRORLEVEL SubMessage 1
                            ERRORLEVEL SubMessage 2
                            ERRORLEVEL SubMessage n
        e.g.
        2014-12-25 14:16:40 ERROR [MyBackupTask] execution failed
                            ERROR   The quotas are violated.
                            ERROR   Cannot perform this operation in quiet mode. (0x103F1)     Tag = 0x1D8EAB676A3F6BAA Target drive is running out of space. (0x4001D)     Tag = 0x1D8EAB676A3F6BAB
                            WARNING Terminated by user.
                            WARNING Batch operation has been terminated by user.
    
    
        Note: the first ERRORLEVEL printed (the one between the timestamp and [AcronisTask])
              will be the highest error level in the log
      """
    
      # store the highest error level
      highestLevel = ACRONIS_LOG_DUMMY0
      subMessages = []
      success = False
      try:
        xmlDocument = untangle.parse(logFile)
    
        # read task_name
        taskName = xmlDocument.log['task_name']
    
        # open output file
        with open(outputPath + r"\acronis-" + taskName + ".log", 'w') as outFile:
    
          if debug:
            print("Debug mode enabled. Processing", logFile)
            print("Debug mode enabled. Processing", logFile, file=outFile)
    
          # for each log event
          for event in xmlDocument.log.event:
            # read attributes
            eventId = int(event['id'])
            eventLevel = int(event['level'])
            eventModule = int(event['module'])
            eventCode = int(event['code'])
            eventTime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(event['time'])))
            eventMessage = event['message']
    
            # strip unicode characters out (yes, it happens for some INFO messages annotating user responses)
            eventMessage = eventMessage.encode('ascii', 'ignore').decode('ascii', 'ignore')
    
            # set highestLevel
            if eventLevel > highestLevel:
              highestLevel = eventLevel
    
            # add subMessages, if they fit into the level threshold
            if (eventLevel >= minLevelToDisplay) and \
               (eventLevel <= maxLevelToDisplay):
              subMessages.append([logDescription(eventLevel), eventMessage])
    
          # create summary message for top line
          summary = "execution failed"
          # determine success
          if highestLevel <= ACRONIS_LOG_INFO:
            summary = "completed successfully"
            success = True
    
          # print the summary message
          if (highestLevel >= minLevelToDisplay) and \
             (highestLevel <= maxLevelToDisplay):
              print(eventTime, logDescription(highestLevel), "[" + taskName + "]", summary)
              print(eventTime, logDescription(highestLevel), "[" + taskName + "]", summary, file=outFile)
    
    
          # print subMessages, maybe
          if showSubMessages:
            for message in subMessages:
              # do some fancy textwrapping here, because sometimes there are really long messages that wrap in the wrong places
              # and a hanging indent is prettier
              print(' '*(len(eventTime)+1) + message[0], textwrap.fill(message[1], 160, subsequent_indent=' '*30)) #30 = len("YYYY-MM-DD HH:MM:SS ERRCODE ") + 2 for indenting
              print(' '*(len(eventTime)+1) + message[0], textwrap.fill(message[1], 160, subsequent_indent=' '*30), file=outFile) #30 = len("YYYY-MM-DD HH:MM:SS ERRCODE ") + 2 for indenting
      except:
          if debug:
            # probably want to catch the error in debug...
            raise
          else:
            print("Generic Error with file <" + logFile + ">.")
    
      # return success flag
      return success
    
    ########## ENTRY POINT #########################################################
    if __name__ == "__main__":
    
      # only grab files named with a day of week
      # so, ignore non-compliant (won't parse) logs
      #   - console*,
      #   - monitor.log,
      #   - afcdpsrv.log
      #   - NSB*.log (non-stop backup)
      logFiles = [f for f in glob.iglob(logPath + "\*.log") \
        if "Sunday"    in f or \
           "Monday"    in f or \
           "Tuesday"   in f or \
           "Wednesday" in f or \
           "Thursday"  in f or \
           "Friday"    in f or \
           "Saturday"  in f]
    
      # sort by modified date (descending)
      logFiles.sort(key=os.path.getmtime, reverse=True)
    
      # get the most recent
      newestFile = logFiles[0]
    
      # process newest file
      success = process(newestFile)
    
      # for testing purposes...
      # process all log files
      #for logFile in logFiles:
      #  process(logFile)
    
      # return with exit code 0 if success (no warnings or errors), otherwise 1
      sys.exit(0 if success else 1)
    
  3. Настройте Acronis для запуска командного файла (acronis.cmd) как пост-командное действие со следующими настройками диалогового окна:

    • Команда: C:/path/to/acronis.cmd
    • Рабочий каталог: C:/path/to (расположение командного файла)
    • Аргументы: (оставьте поле пустым)
    • [] Не выполнять операции до завершения выполнения команды.
    • [x] Прервать операцию, если пользовательская команда не удалась.

Редактировать: оставив флажок "Не выполнять операции ..." проверил может привести к ошибкам синтаксического анализа XML, поскольку файл журнала еще не был очищен.

  1. См. Всеобъемлющий ответ - этот маршрут я бы порекомендовал.

  2. До публикации Cyber ​​у меня был некоторый успех с LogParser, так как я хотел отслеживать 2 задания резервного копирования.

Предостережение это LogParser решение подвержено ложным срабатываниям (например, если одно задание выполнялось дважды, а другое не выполнялось, вы получите те же результаты, что и оба задания).

Acronis 10, похоже, не публикует достаточно подробностей в журналах Windows, чтобы можно было однозначно идентифицировать успешные или даже начинающиеся задания.

чек-acronis-backup.bat

"C:\Program Files (x86)\Log Parser 2.2\LogParser.exe" -i:evt file:check-acronis-backup.sql > check-acronis-backup.out
type check-acronis-backup.out
grep "Elements output:    2" check-acronis-backup.out
if %ERRORLEVEL%==0 goto ReportSuccess
GOTO End
:ReportSuccess
call report-success acronis
:End

проверьте-acronis-backup.sql

SELECT 
TOP 10 SourceName, TimeGenerated, EventCategory, Message
FROM Application
WHERE TimeGenerated > TO_TIMESTAMP(SUB(TO_INT(SYSTEM_TIMESTAMP()), 90000)) --90000 = 60*60*25
AND SourceName = 'Acronis Backup  Recovery 10'
AND EventCategory = 144
AND Message like '%Task _Full backup_ completed successfully.%'