将 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
我正在将一些旧的 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