0

I have a configuration file (from Nagios) with the following structure:

define service{
    use                     pruebaspre-service,srv-pnp
    host_name               server1.es
    servicegroups           pruebasdatasourcesoaspre-servicegroup,pruebaspre-servicegroup
    service_description     Estado DataSource - cfio  JUVEPoolDSPoolDS
    check_command           check_ds_oas!cfio!JUVEPoolDSPoolDS!/opt/oracle/ias10g/10.1.2!1!0
}


define service{
    use                     pruebaspre-service,srv-pnp
    host_name               server1.es
    servicegroups           pruebasdatasourcesoaspre-servicegroup,pruebaspre-servicegroup
    service_description     Estado DataSource - cfio  REMEPoolDS
    check_command           check_ds_oas!cfio!REMEPoolDS!/opt/oracle/ias10g/10.1.2!1!0
}


define service{
    use                     pruebaspre-service,srv-pnp
    host_name               server2.es
    servicegroups           pruebasdatasourcesoaspre-servicegroup,pruebaspre-servicegroup
    service_description     Estado DataSource - cfio  iris_usr_irisPoolDS
    check_command           check_ds_oas!cfio!iris_usr_irisPoolDS!/opt/oracle/ias10g/10.1.3!1!0
}


define service{
    use                     pruebaspre-service,srv-pnp
    host_name               server2.es
    servicegroups           pruebasdatasourcesoaspre-servicegroup,pruebaspre-servicegroup
    service_description     Estado DataSource - cfio  REMEPoolDS
    check_command           check_ds_oas!cfio!REMEPoolDS!/opt/oracle/ias10g/10.1.2!1!0
}

define service{
    use                     pruebaspre-service,srv-pnp
    host_name               server2.es
    servicegroups           pruebasdatasourcesoaspre-servicegroup,pruebaspre-servicegroup
    service_description     Estado DataSource - cfio  redt2_usr_redt2PoolDS
    check_command           check_ds_oas!cfio!redt2_usr_redt2PoolDS!/opt/oracle/ias10g/10.1.3!1!0
}

To register a new service in this file, I need to first find if the service exists, for this I must find that for a check_command the host_name is not registered.

For example, I want to register:

define service {
     use pre-service tests, srv-pnp
     host_name server1.es
     servicegroups testsdatasourcesoaspre-servicegroup, pre-servicegroup tests
     service_description DataSource Status - cfio REMEPoolDS
     check_command check_ds_oas! cfio! REMEPoolDS! /opt/oracle/ias10g/10.1.2! 1! 0
}

so in the file I should look for it does not exist.

I tried it with a while loop that reads the file and when it finds

check_command check_ds_oas! Cfio! REMEPoolDS! /Opt/oracle/ias10g/10.1.2! 1! 0

it looks for the next one not to be

host_name server1.es
V_NAGIOS_COMMAND=check_ds_oas!cfio!REMEPoolDS!/opt/oracle/ias10g/10.1.2!1!0
if [ `grep ${V_NAGIOS_COMMAND} --count $V_FILE_NAGIOS` -ge 1 ] ; then
    while read LINEA_CONFIG
    do
        V_DIRECTIVA=`echo $LINEA_CONFIG| awk '{print $1} '`
        V_VALOR_DIRECTIVA=`echo $LINEA_CONFIG| awk '{print $2} '`
        if [ $V_DIRECTIVA = check_command ]&&[ $V_VALOR_DIRECTIVA = $V_NAGIOS_COMMAND ]; then
            V_COMANDO_ENCONTRADO=1
        elif [ $V_DIRECTIVA = host_name ]&& [ $V_COMANDO_ENCONTRADO = 1 ] ; then
            if [ $V_VALOR_DIRECTIVA = $V_MAQUINA ] ; then
                ((V_EXISTEN_DATOS++))
                return 1
            else
                V_COMANDO_ENCONTRADO=0
            fi
        fi
    done < <(tac $V_FILE_NAGIOS| grep -vE "^#|^$")
fi

but it is very slow.

  • Change while read LINEA_CONFIG to while read V_DIRECTIVA V_VALOR_DIRECTIVA and remove the two awk lines, that will help a lot. – wurtel Jul 16 at 8:37
0

If I understood well your requirements, this looks like a job that sed can do well thanks to its ability to delimit "sub-streams" within its input stream.

This should be POSIX:

sed -n "/^define service/,/^}/{/^[[:blank:]]\\{1,\}host_name[[:blank:]]\\{1,\\}${V_MAQUINA}/,/^}/{\\%^[[:blank:]]\\{1,\\}check_command[[:blank:]]\\{1,\\}${V_NAGIOS_COMMAND}%{p;q}}}" file

or, if you can do with GNU sed, for a bit less escaping in string:

sed -En "/^define service/,/^\\}/{/^[[:blank:]]+host_name[[:blank:]]+${V_MAQUINA}/,/^\\}/{\\%^[[:blank:]]+check_command[[:blank:]]+${V_NAGIOS_COMMAND}%{p;q}}}" file

Explained:

sed -En  # use Extended Regular Expressions, and don't print by default

# main `sed` script for entire stream
/^define service/,/^\\}/  # between 'define service' and '}'
{  # sub-stream: between specified 'host_name' and '}'
/^[[:blank:]]+host_name[[:blank:]]+${V_MAQUINA}/,/^\\}/
{  # look for specified 'check_command', using '%' because '/' can be in command
\\%^[[:blank:]]+check_command[[:blank:]]+${V_NAGIOS_COMMAND}%
{p;q}  # if found, print line and quit `sed`
}
}

This prints the check_command line if found within the file's "snippet" delimited by the regexps, or nothing at all if not found.

You can therefore just check for presence or absence of a returned string.

Don't check for exit status because sed exits 0 also when nothing is printed.

A few additional notes:

  • we need \\ to express one \ because we are inside shell's double-quotes
  • we use double-quotes to be able to use your shell's variables $V_MAQUINA and $V_NAGIOS_COMMAND
  • I chose % as regexp delimiter in last regexp, but you are free to choose any character that won't be present in your $V_NAGIOS_COMMAND variable
0

In awk:

/^define service/{

    found_command=0
    found_host=0

    while (getline && $0 !~ "^}") {

        # test host
        if($1 == "host_name") {
            if ($2 == new_host) {
                found_host=1
            }else{
                next
            }
        }

        # test check_command
        if($1 == "check_command"){
            cmd = gensub(/^\s*check_command\s*/, "", 1)
            if (cmd == new_command) {
                found_command=1
            }else{
                next
            }
        }
    }

    if (found_command && found_host)
        exit 1
}

can be used like this:

new_host='...'
new_command='...'
if awk -v new_host="$new_host" -v new_command="$new_command" -f script.awk cfg_file ; then
    echo "you can register it now"
fi

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.