2017-09-13 7 views
-1

Je transfère certaines anciennes données de configuration Nagios de Nagios Core à Nagios XI. Une partie de ce travail signifie que j'ai besoin d'extraire certaines définitions d'objets et de les placer dans des fichiers individuels nommés par nom d'hôte (exemple à suivre). Je peux voir un certain nombre de façons de le faire, éventuellement en écrivant un script (Perl/Python/PHP - le script Nagios XI semble être fait en PHP). Cependant, je me demandais s'il y avait une façon plus simple de le faire, peut-être sur la ligne de commande en utilisant awk ou similaire? Il me semble que awk peut facilement extraire des lignes de texte entre deux motifs de délimitation (par exemple, /define host \{/ et /\}/) mais j'ai besoin que la sortie se sépare en fichiers individuels nommés par le contenu du champ nom_hôte.Extraction des définitions d'objets Nagios d'un fichier de configuration monolithique vers des fichiers individuels

Quelle est la meilleure approche pour cela? Est-ce que je préfère écrire un script, ou est-ce qu'il y a une commande awk (ou similaire) qui peut être exécutée à partir du shell bash sur les machines Nagios XI?

Exemple de fichier monolithique:

define host { 
    host_name testhost1 
    use    hosttemplate1 
    address     10.0.0.1 
    host_groups      +linux,all 
    contact_groups   +servicedesk 
    alias   testhost1 
    icon_image  redhat_icon.png 
} 
define service { 
    use  servtemplate1 
    host_name testhost1 
    service_groups +All 
    service_description A Test Service 
} 
define host { 
    host_name testhost2 
    use    hosttemplate2 
    address     10.0.0.2 
    host_groups      +linux,all 
    contact_groups   +servicedesk 
    alias   testhost2 
    icon_image  redhat_icon.png 
} 

sortie souhaitée:

# cat testhost1.cfg 
define host { 
    host_name testhost1 
    use    hosttemplate1 
    address     10.0.0.1 
    host_groups      +linux,all 
    contact_groups   +servicedesk 
    alias   testhost1 
    icon_image  redhat_icon.png 
} 
# cat testhost2.cfg 
define host { 
    host_name testhost2 
    use    hosttemplate2 
    address     10.0.0.2 
    host_groups      +linux,all 
    contact_groups   +servicedesk 
    alias   testhost2 
    icon_image  redhat_icon.png 
} 

Maintenant, par exemple, je peux exécuter une commande comme celui-ci qui semble utilisé assez largement pour l'extraction de la ligne:

# gawk ' /define host/{flag=1;next} /}/{flag=0} flag { print }' example.cfg 

Cela coupe le define host et } mais c'est une solution relativement facile - cependant, elle produit les données sous la forme d'un flux dans le shell.

Y at-il un truc intelligent que je peux mettre en œuvre pour faire tout cela, y compris la division en fichiers de configuration individuels à partir d'un seul revêtement sur le shell, ou devrais-je écrire un script?

+0

Curieux de savoir pourquoi ma question downvoted que je suis nouveau ici - les solutions semblent avoir aidé d'autres au-delà de moi-même que le fait de façon pas en soi faire de la question de la valeur ? Si je comprends la raison alors je ferai en sorte que les futures questions soient meilleures. Je vous remercie! –

Répondre

1

En utilisant awk:

One-liner

awk '/^define host/{f=1;str=$0;next}/host_name/{h=$NF".cfg"}f{str=str ORS $0}f && /^\}/{print "#"h>h; print str>h; f=""; close(h)}' file 

Explication

awk ' 
     /^define host/{    # look for line start with define host 
         f=1   # set variable f to 1 
         str=$0   # set variable str = current line/row/record 
         next   # go to next line 
     } 
     /host_name/{     # look for line with hostname 
        h=$NF".cfg"  # set variable h with last field value plus ".cfg" 
     } 
     f{        # if f was true or 1 then 
        str=str ORS $0 # concatenate variable str with current record 
     } 
     f && /^\}/{     # if f is true and line starts with } then 
        print "#"h > h # write # hostname to file 
        print str > h # write the content of variable str to file 
        f=""   # nullify variable 
        close(h)  # close file 
     } 
    ' file 

Résultats du test

Entrée:

$ cat file 
define host { 
    host_name testhost1 
    use    hosttemplate1 
    address     10.0.0.1 
    host_groups      +linux,all 
    contact_groups   +servicedesk 
    alias   testhost1 
    icon_image  redhat_icon.png 
} 
define service { 
    use  servtemplate1 
    host_name testhost1 
    service_groups +All 
    service_description A Test Service 
} 
define host { 
    host_name testhost2 
    use    hosttemplate2 
    address     10.0.0.2 
    host_groups      +linux,all 
    contact_groups   +servicedesk 
    alias   testhost2 
    icon_image  redhat_icon.png 
} 

Exécution:

$ awk '/^define host/{f=1;str=$0;next}/host_name/{h=$NF".cfg"}f{str=str ORS $0}f && /^\}/{print "#"h>h; print str>h; f=""; close(h)}' file 

fichiers générés:

$ cat *.cfg 
#testhost1.cfg 
define host { 
    host_name testhost1 
    use    hosttemplate1 
    address     10.0.0.1 
    host_groups      +linux,all 
    contact_groups   +servicedesk 
    alias   testhost1 
    icon_image  redhat_icon.png 
} 
#testhost2.cfg 
define host { 
    host_name testhost2 
    use    hosttemplate2 
    address     10.0.0.2 
    host_groups      +linux,all 
    contact_groups   +servicedesk 
    alias   testhost2 
    icon_image  redhat_icon.png 
} 

En PHP

$ cat test.php 
<?php 
preg_match_all('~define host\s+?{[^}]*}~', file_get_contents('file'), $match); 
foreach($match[0] as $config) 
{ 
    if(preg_match('~host_name\s+([^\s]*)~', $config, $host)) 
    { 
     $file = $host[1].".cfg"; 
     file_put_contents($file, '#'.$file.PHP_EOL.$config.PHP_EOL); 
    } 
} 
?> 

$ php test.php 
$ ls *.cfg 
testhost1.cfg testhost2.cfg 
+1

Salut @ akshay-hegde! Script utile, je l'ai emballé et téléchargé sur SparrowHub afin que tout le monde puisse le réutiliser (et ajouté quelques paramètres et documentation) - https://sparrowhub.org/info/nagios-split-host –

+0

@AlexeyMelezhik: vous êtes les bienvenus –

+0

@AlexeyMelezhik: vous pouvez aussi utiliser php ... –

0

Un accueil chaleureux sur Stack site de débordement, j'espère que vous apprécierez apprendre et partager des connaissances ici, pourriez-vous s'il vous plaît essayer de suivre et laissez-moi savoir si cela vous aide.

awk '/^}$/ && flag{print > file;flag="";close(file);next} /define host/{flag=1;val=$0;next} flag && /host_name/{file=$2".cfg";print val ORS $0 > file;next} flag{print > file}' Input_file 

EDIT: Ajout d'une forme de ligne non une solution de trop maintenant.

awk ' 
/^}$/ && flag{    ##Looking for a line which starts from } and ends with same only + checking if variable flag is NOT null. 
    print > file;   ##printing the current line to variable file(which will be having values like testhost1, testhost2.cfg etc etc 
    flag="";    ##Nullifying the variable flag here. 
    close(file)    ##Closing the file because in case of Input_file is huge so in backend these files(testconfig1 etc etc) could be opened and which may cause issues in case they all are opened, so it is good practice to close them. 
    next     ##Using next keyword of awk will skip all the further statements for the current line. 
} 
/define host/{    ##Searching for a line which has string define_host in it. 
    flag=1;     ##Making variable flag value to TRUE now, to keep track that we have seen string define_host in Input_file. 
    val=$0;     ##Storing this current line to a variable named val now. 
    next     ##Using next keyword will skip all further statements for the current line. 
} 
flag && /host_name/{  ##Checking if flag is TRUE and current line has string host_name in it then do following. 
    file=$2".cfg";   ##Creating a variable named file who has value of 2nd field and string .cfg, this is actually the file names where we will save the contents 
    print val ORS $0 > file;##printing variable named val then output record separator and current line and redirecting them to variable file which will make sure it should be saved in file named testhost etc etc .cfg. 
    next     ##As mentioned before too, next will skip all further statements. 
} 
flag{      ##Checking if variable flag is TRUE or NOT NULL here. 
    print > file   ##Printing the current line into the file then. 
} 
' Input_file    ##Mentioning the Input_file here. 
+0

Merci beaucoup pour votre aide - l'ajout de commentaires m'a vraiment aidé à améliorer mes connaissances sur awk et à résoudre mon problème en même temps. –