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'')
Nagiosity hace exactamente lo que quieres:
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'')]
Pfft, hazte mk_livestatus. http://mathias-kettner.de/checkmk_livestatus.html