python parsing nagios

python - Cómo analizar el archivo nagios status.dat?



parsing (7)

No conozco nagios y su archivo de configuración, pero la estructura parece bastante simple:

# comment identifier { attribute= attribute=value }

que simplemente se puede traducir a

<identifier> <attribute name="attribute-name">attribute-value</attribute> </identifier>

todo contenido dentro de una etiqueta de nivel de raíz <nagios>.

No veo saltos de línea en los valores. ¿Los nagios tienen valores de varias líneas?

Debe tener en cuenta los signos iguales dentro de los valores de los atributos, por lo que debe configurar su expresión regular como no codicioso.

Me gustaría analizar el archivo status.dat para nagios3 y salir como xml con una secuencia de comandos python. La parte xml es la más fácil, pero ¿cómo hago para analizar el archivo? Usa expresiones regulares multilínea? Es posible que el archivo sea grande ya que se monitorean muchos servidores y servicios, ¿será prudente cargar todo el archivo en la memoria?
Solo necesito extraer servicios que tengan un estado crítico y un host al que pertenezcan.

Cualquier ayuda y apuntar en la dirección correcta será muy apreciada.

LE Así es como se ve el archivo:

######################################## # NAGIOS STATUS FILE # # THIS FILE IS AUTOMATICALLY GENERATED # BY NAGIOS. DO NOT MODIFY THIS FILE! ######################################## info { created=1233491098 version=2.11 } program { modified_host_attributes=0 modified_service_attributes=0 nagios_pid=15015 daemon_mode=1 program_start=1233490393 last_command_check=0 last_log_rotation=0 enable_notifications=1 active_service_checks_enabled=1 passive_service_checks_enabled=1 active_host_checks_enabled=1 passive_host_checks_enabled=1 enable_event_handlers=1 obsess_over_services=0 obsess_over_hosts=0 check_service_freshness=1 check_host_freshness=0 enable_flap_detection=0 enable_failure_prediction=1 process_performance_data=0 global_host_event_handler= global_service_event_handler= total_external_command_buffer_slots=4096 used_external_command_buffer_slots=0 high_external_command_buffer_slots=0 total_check_result_buffer_slots=4096 used_check_result_buffer_slots=0 high_check_result_buffer_slots=2 } host { host_name=localhost modified_attributes=0 check_command=check-host-alive event_handler= has_been_checked=1 should_be_scheduled=0 check_execution_time=0.019 check_latency=0.000 check_type=0 current_state=0 last_hard_state=0 plugin_output=PING OK - Packet loss = 0%, RTA = 3.57 ms performance_data= last_check=1233490883 next_check=0 current_attempt=1 max_attempts=10 state_type=1 last_state_change=1233489475 last_hard_state_change=1233489475 last_time_up=1233490883 last_time_down=0 last_time_unreachable=0 last_notification=0 next_notification=0 no_more_notifications=0 current_notification_number=0 notifications_enabled=1 problem_has_been_acknowledged=0 acknowledgement_type=0 active_checks_enabled=1 passive_checks_enabled=1 event_handler_enabled=1 flap_detection_enabled=1 failure_prediction_enabled=1 process_performance_data=1 obsess_over_host=1 last_update=1233491098 is_flapping=0 percent_state_change=0.00 scheduled_downtime_depth=0 } service { host_name=gateway service_description=PING modified_attributes=0 check_command=check_ping!100.0,20%!500.0,60% event_handler= has_been_checked=1 should_be_scheduled=1 check_execution_time=4.017 check_latency=0.210 check_type=0 current_state=0 last_hard_state=0 current_attempt=1 max_attempts=4 state_type=1 last_state_change=1233489432 last_hard_state_change=1233489432 last_time_ok=1233491078 last_time_warning=0 last_time_unknown=0 last_time_critical=0 plugin_output=PING OK - Packet loss = 0%, RTA = 2.98 ms performance_data= last_check=1233491078 next_check=1233491378 current_notification_number=0 last_notification=0 next_notification=0 no_more_notifications=0 notifications_enabled=1 active_checks_enabled=1 passive_checks_enabled=1 event_handler_enabled=1 problem_has_been_acknowledged=0 acknowledgement_type=0 flap_detection_enabled=1 failure_prediction_enabled=1 process_performance_data=1 obsess_over_service=1 last_update=1233491098 is_flapping=0 percent_state_change=0.00 scheduled_downtime_depth=0 }

Puede tener cualquier número de hosts y un host puede tener cualquier cantidad de servicios.


Puedes hacer algo como esto:

def parseConf(filename): conf = [] with open(filename, ''r'') as f: for i in f.readlines(): if i[0] == ''#'': continue matchID = re.search(r"([/w]+) {", i) matchAttr = re.search(r"[ ]*([/w]+)=([/w/d]*)", i) matchEndID = re.search(r"[ ]*}", i) if matchID: identifier = matchID.group(1) cur = [identifier, {}] elif matchAttr: attribute = matchAttr.group(1) value = matchAttr.group(2) cur[1][attribute] = value elif matchEndID: conf.append(cur) return conf def conf2xml(filename): conf = parseConf(filename) xml = '''' for ID in conf: xml += ''<%s>/n'' % ID[0] for attr in ID[1]: xml += ''/t<attribute name="%s">%s</attribute>/n'' % / (attr, ID[1][attr]) xml += ''</%s>/n'' % ID[0] return xml

Luego intenta hacer:

print conf2xml(''conf.dat'')



Si modifica ligeramente la solución de Andrea, puede usar ese código para analizar tanto el estado.dat como los objetos.caché

def parseConf(source): conf = [] for line in source.splitlines(): line=line.strip() matchID = re.match(r"(?:/s*define)?/s*(/w+)/s+{", line) matchAttr = re.match(r"/s*(/w+)(?:=|/s+)(.*)", line) matchEndID = re.match(r"/s*}", line) if len(line) == 0 or line[0]==''#'': pass elif matchID: identifier = matchID.group(1) cur = [identifier, {}] elif matchAttr: attribute = matchAttr.group(1) value = matchAttr.group(2).strip() cur[1][attribute] = value elif matchEndID and cur: conf.append(cur) del cur return conf

Es un poco desconcertante por qué Nagios eligió utilizar dos formatos diferentes para estos archivos, pero una vez que los hayas analizado en algunos objetos python utilizables, puedes hacer un poco de magia a través del archivo de comandos externo.

Si alguien tiene una solución para convertir esto en una dom xml real, sería increíble.


Durante los últimos meses, he escrito y publicado una herramienta que analiza Nagios status.dat y objects.cache y crea un modelo que permite una manipulación realmente útil de los datos de Nagios. Lo usamos para manejar un tablero de operaciones interno que es un ''mini'' Nagios simplificado. Está en desarrollo continuo y he descuidado las pruebas y la documentación, pero el código no es demasiado loco y me siento bastante fácil de seguir.

Déjame saber lo que piensas ... https://github.com/zebpalmer/NagParser


Habiendo robado desvergonzadamente de los ejemplos anteriores, Aquí hay una versión compilada para Python 2.4 que devuelve un dict que contiene matrices de secciones de Nagios.

def parseConf(source): conf = {} patID=re.compile(r"(?:/s*define)?/s*(/w+)/s+{") patAttr=re.compile(r"/s*(/w+)(?:=|/s+)(.*)") patEndID=re.compile(r"/s*}") for line in source.splitlines(): line=line.strip() matchID = patID.match(line) matchAttr = patAttr.match(line) matchEndID = patEndID.match( line) if len(line) == 0 or line[0]==''#'': pass elif matchID: identifier = matchID.group(1) cur = [identifier, {}] elif matchAttr: attribute = matchAttr.group(1) value = matchAttr.group(2).strip() cur[1][attribute] = value elif matchEndID and cur: conf.setdefault(cur[0],[]).append(cur[1]) del cur return conf

Para obtener todos los nombres de su host que tienen grupos de contactos que comienzan con ''devops'':

nagcfg=parseConf(stringcontaingcompleteconfig) hostlist=[host[''host_name''] for host in nagcfg[''host''] if host[''contact_groups''].startswith(''devops'')]