Acronis 命令后查询备份状态

Acronis 命令后查询备份状态

我想在备份成功完成时执行一项操作(但不在备份失败时执行)。

  • 有没有办法将备份状态传递到备份后命令?
  • 或者我可以从后备份中查询环境变量?
  • 或者查询作业状态的简单方法(可能正在运行多个作业)。
  • 考虑登录事件日志并使用日志解析器搜索成功消息。

我目前正在使用电子邮件通知,将电子邮件发送给机器人,该机器人从主题中解析出备份状态,然后如果备份成功则运行命令。

产品:Acronis Backup & Recovery 10

答案1

据我所见,没有简单的方法。

像您一样,我目前会收到一封任务后状态电子邮件;但是,我想将该信息的子集放入仪表板系统中。我刚刚编写了一个 Python (3.4) 脚本,用于从 Acronis 日志中提取信息并写入日志文件。我还添加了有条件执行命令的功能。(我在批处理文件中完成了这部分工作,但可以修改 Python 脚本以执行命令……从而无需使用批处理文件。)

经过一些轻微的修改/定制,它应该适合您。

概念

  • Acronis 命令后操作启动批处理文件
  • ...启动一个 Python 脚本
  • ...解析 Acronis 日志,检测成功或失败(以及其他事项),并返回错误代码
  • ...由批处理文件捕获
  • ...然后根据成功或失败有条件地执行操作

注意事项

  • python 脚本将读取最后修改的日志文件,因此并发的 Acronis 操作可能会有危险。
  • python 脚本仅读取文件名以星期几开头的日志文件。(即它将忽略任何“console_xxxxx.log” [和类似的] 日志。但这正是我们想要的。)
  • 我是一名职业开发人员,但这是我第一次尝试使用 Python,所以它可能不是很漂亮。

要求

  • Python 3.4 已安装在环境 PATH 中,并与 .py 文件关联
  • pythonuntangle包已安装(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 outFileprint(..., 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 解析错误,因为日志文件可能尚未刷新。

答案2

  1. 请参阅 Cyber​​ 的综合回答- 这是我推荐的路线。

  2. 在 Cyber​​ 发帖之前,我确实取得了一些成功日志解析器,因为我想跟踪 2 个备份作业。

警告日志解析器解决方案容易受到误报的影响(例如,如果一项作业运行两次,而另一项作业没有运行,那么您将获得与两项作业都成功相同的结果)。

Acronis 10 似乎没有向 Windows 日志发布足够的详细信息,以便能够唯一地标识成功甚至启动的作业。

检查-acronis-备份.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-备份.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.%'

相关内容