def Main(): '''The main program function. Returns: bool: True if successful or False if not. ''' description = ( 'UnifiedLogReader is a tool to read macOS Unified Logging tracev3 files.\n' 'This is version {0:s} tested on macOS 10.12.5 - 10.15 and iOS 12.\n\n' 'Notes:\n-----\n' 'If you have a .logarchive, then point uuidtext_path to the .logarchive folder, \n' 'the timesync folder is within the logarchive folder').format(UnifiedLog.__version__) arg_parser = argparse.ArgumentParser( description=description, formatter_class=argparse.RawTextHelpFormatter) arg_parser.add_argument('uuidtext_path', help='Path to uuidtext folder (/var/db/uuidtext)') arg_parser.add_argument('timesync_path', help='Path to timesync folder (/var/db/diagnostics/timesync)') arg_parser.add_argument('tracev3_path', help='Path to either tracev3 file or folder to recurse (/var/db/diagnostics)') arg_parser.add_argument('output_path', help='An existing folder where output will be saved') arg_parser.add_argument( '-f', '--output_format', action='store', choices=( 'SQLITE', 'TSV_ALL', 'LOG_DEFAULT'), metavar='FORMAT', default='LOG_DEFAULT', help=( 'Output format: SQLITE, TSV_ALL, LOG_DEFAULT (Default is LOG_DEFAULT)'), type=str.upper) arg_parser.add_argument('-l', '--log_level', help='Log levels: INFO, DEBUG, WARNING, ERROR (Default is INFO)') args = arg_parser.parse_args() output_path = args.output_path.rstrip('\\/') uuidtext_folder_path = args.uuidtext_path.rstrip('\\/') timesync_folder_path = args.timesync_path.rstrip('\\/') tracev3_path = args.tracev3_path.rstrip('\\/') if not os.path.exists(uuidtext_folder_path): print('Exiting..UUIDTEXT Path not found {}'.format(uuidtext_folder_path)) return if not os.path.exists(timesync_folder_path): print('Exiting..TIMESYNC Path not found {}'.format(timesync_folder_path)) return if not os.path.exists(tracev3_path): print('Exiting..traceV3 Path not found {}'.format(tracev3_path)) return if not os.path.exists(output_path): print ('Creating output folder {}'.format(output_path)) os.makedirs(output_path) log_file_path = os.path.join(output_path, "Log." + time.strftime("%Y%m%d-%H%M%S") + ".txt") # log if args.log_level: args.log_level = args.log_level.upper() if not args.log_level in ['INFO','DEBUG','WARNING','ERROR','CRITICAL']: print("Invalid input type for log level. Valid values are INFO, DEBUG, WARNING, ERROR") return else: if args.log_level == "INFO": args.log_level = logging.INFO elif args.log_level == "DEBUG": args.log_level = logging.DEBUG elif args.log_level == "WARNING": args.log_level = logging.WARNING elif args.log_level == "ERROR": args.log_level = logging.ERROR elif args.log_level == "CRITICAL": args.log_level = logging.CRITICAL else: args.log_level = logging.INFO log_level = args.log_level #logging.DEBUG log_console_handler = logging.StreamHandler() log_console_handler.setLevel(log_level) log_console_format = logging.Formatter('%(levelname)s - %(message)s') log_console_handler.setFormatter(log_console_format) logger.addHandler(log_console_handler) #log file log_file_handler = logging.FileHandler(log_file_path) log_file_handler.setFormatter(log_console_format) logger.addHandler(log_file_handler) logger.setLevel(log_level) unified_log_reader = UnifiedLogReader() if not unified_log_reader.ReadTimesyncFolder(timesync_folder_path): logger.error('Failed to get any timesync entries') return False if args.output_format == 'SQLITE': database_path = os.path.join(output_path, 'unifiedlogs.sqlite') output_writer = SQLiteDatabaseOutputWriter(database_path) elif args.output_format in ('TSV_ALL', 'LOG_DEFAULT'): file_path = os.path.join(output_path, 'logs.txt') output_writer = FileOutputWriter( file_path, mode=args.output_format) if not output_writer.Open(): return False time_processing_started = time.time() logger.info('Started processing') unified_log_reader.ReadDscFiles(uuidtext_folder_path) unified_log_reader.ReadTraceV3Files(tracev3_path, output_writer) output_writer.Close() time_processing_ended = time.time() run_time = time_processing_ended - time_processing_started logger.info("Finished in time = {}".format(time.strftime('%H:%M:%S', time.gmtime(run_time)))) logger.info("{} Logs processed".format(unified_log_reader.total_logs_processed)) logger.info("Review the Log file and report any ERRORs or EXCEPTIONS to the developers") return True
def Main(): description = ( 'UnifiedLogReader is a tool to read macOS Unified Logging tracev3 files.\n' 'This is version {0:s} tested on macOS 10.12.5 - 10.15 and iOS 12.\n\n' 'Notes:\n-----\n' 'If you have a .logarchive, then point uuidtext_path to the .logarchive folder, \n' 'the timesync folder is within the logarchive folder').format( UnifiedLog.__version__) arg_parser = argparse.ArgumentParser( description=description, formatter_class=argparse.RawTextHelpFormatter) arg_parser.add_argument('logarchive_path', help='Path to logarchive folder') arg_parser.add_argument( '--log', help='An existing folder where output will be saved', required=False) args = arg_parser.parse_args() # print(vars(args)) logarchive_path = args.logarchive_path output_path = args.log if not os.path.exists(logarchive_path): print('Exiting..LogArchive Path not found {}'.format(logarchive_path)) timesync_folder_path = os.path.join(logarchive_path, "timesync") if not os.path.exists(timesync_folder_path): print( 'Exiting..Timesync Path not found {}'.format(timesync_folder_path)) tracev3_path = os.path.join(logarchive_path, "Persist") if not os.path.exists(timesync_folder_path): tracev3_path = logarchive_path log_file_path = None if bool(output_path) and os.path.exists(output_path): # print ('Creating output folder {}'.format(output_path)) # os.makedirs(output_path) log_file_path = os.path.join( output_path, "Log." + time.strftime("%Y%m%d-%H%M%S") + ".txt") # log_level = logging.INFO # log_console_handler = logging.StreamHandler() # log_console_handler.setLevel(log_level) # log_console_format = logging.Formatter('%(levelname)s - %(message)s') # log_console_handler.setFormatter(log_console_format) # logger.addHandler(log_console_handler) #log file if bool(log_file_path): log_file_handler = logging.FileHandler(log_file_path) log_file_handler.setFormatter( logging.Formatter('%(levelname)s - %(message)s')) logger.addHandler(log_file_handler) logger.setLevel(logging.INFO) unified_log_reader = UnifiedLogReader() if not unified_log_reader.ReadTimesyncFolder(timesync_folder_path): logger.error('Failed to get any timesync entries') return False output_writer = None if bool(output_path) and os.path.exists(output_path): file_path = os.path.join(output_path, 'logs.txt') output_writer = FileOutputWriter(file_path) if not output_writer.Open(): return False time_processing_started = time.time() logger.info('Started processing') unified_log_reader.ReadDscFiles(logarchive_path) unified_log_reader.ReadTraceV3Files(tracev3_path, output_writer) if bool(output_path): output_writer.Close() time_processing_ended = time.time() run_time = time_processing_ended - time_processing_started logger.info("Finished in time = {}".format( time.strftime('%H:%M:%S', time.gmtime(run_time)))) logger.info("{} Logs processed".format( unified_log_reader.total_logs_processed)) logger.info( "Review the Log file and report any ERRORs or EXCEPTIONS to the developers" ) return True