将 Nagios 对象定义从整体配置文件提取到单个文件

Extract Nagios object definitions from a monolithic configuration file to individual files

我正在将一些旧的 Nagios 配置数据从 Nagios Core 移植到 Nagios XI。这项工作的一部分意味着我需要提取一些对象定义并将它们放入由主机名命名的单个文件中(下面的示例)。我可以看到很多方法可以做到这一点,可能是通过编写脚本(Perl/Python/PHP - Nagios XI 脚本似乎都在 PHP 中完成)。但是我想知道是否有更简单的方法可以做到这一点,也许在命令行上使用 awk 或类似的?我觉得 awk 可以很容易地提取两个定界模式之间的文本行(例如 /define host \{//\}/),但我需要将输出分成由 host_name 的内容命名的单独文件场.

最好的方法是什么?我最好写一个脚本,还是有一个简洁的 awk 命令(或类似命令)可以是 运行 来自 Nagios XI 机器上的 bash shell?

示例单片文件:

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
}

期望的输出:

# 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
 }

例如,现在我可以 运行 这样的命令,它似乎相当广泛地用于行提取:

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

这切断了 define host} 但这是一个相对容易的修复 - 但是它将数据作为一个流输出到 shell.

我是否可以实施一些巧妙的技巧来完成所有这些工作,包括从 shell 上的一个衬里拆分成单独的配置文件,或者我应该编写一个脚本吗?

热烈欢迎来到 Stack overflow 网站,希望您能在这里享受学习和分享知识的乐趣,请尝试关注并告诉我是否对您有帮助。

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

编辑: 现在也添加非单线形式的解决方案。

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=[=11=];                 ##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=".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 [=11=] > 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.

使用 awk:

单行

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

说明

awk '
      /^define host/{                # look for line start with define host
                      f=1            # set variable f to 1
                      str=[=11=]         # 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 [=11=]  # 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

测试结果

Input:

$ 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
}

Execution:

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

Files generated:

$ 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
}

在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