File: //usr/libexec/pcp/bin/pmlogconf-setup
#!/bin/sh
#
# pmlogconf-setup - parse and process a group file to produce an
# initial configuration file control line
#
# Copyright (c) 2014,2017 Red Hat.
# Copyright (c) 2010 Ken McDonell. All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# Get standard environment
. $PCP_DIR/etc/pcp.env
status=1
tmp=`mktemp -d /tmp/pcp.XXXXXXXXX` || exit 1
trap "rm -rf $tmp; exit \$status" 0 1 2 3 15
#debug# tmp=`pwd`/tmp-setup
prog=`basename $0`
cat > $tmp/usage << EOF
# Usage: [options] file
Options:
--host
-t
-v,--verbose increase diagnostic verbosity
--help
EOF
_usage()
{
pmgetopt --progname=$prog --config=$tmp/usage --usage
exit 1
}
HOST=local:
verbose=false
probelist=''
ARGS=`pmgetopt --progname=$prog --config=$tmp/usage -- "$@"`
[ $? != 0 ] && exit 1
eval set -- "$ARGS"
while [ $# -gt 0 ]
do
case "$1"
in
-h) # host to contact for "probe" tests
HOST="$2"
shift
;;
-v) # verbose
verbose=true
;;
-t) #list from pmprobe
probelist="$2"
shift
;;
--) shift
break
;;
-\?) # eh?
_usage
# NOTREACHED
;;
esac
shift
done
[ $# -eq 1 ] || _usage
# find "probe metric [condition] [state_rule]" line to determine action
# or
# find "force state" line
#
metric=''
options=''
force=''
eval `sed -n <"$1" \
-e '/^#/d' \
-e 's/?/"\\\\?"/g' \
-e 's/\*/"\\\\*"/g' \
-e 's/\[/"\\\\["/g' \
-e '/^probe[ ]/{
s/^probe[ ]*/metric="/
s/$/ /
s/[ ]/" options="/
s/ *$/"/
p
q
}' \
-e '/^force[ ]/{
s/^force[ ]*/force='"'"'/
s/ *$/'"'"'/
p
}'`
$verbose && $PCP_ECHO_PROG "$1: " >&2
if [ -n "$force" -a -n "$metric" ]
then
$PCP_ECHO_PROG "$1: Warning: \"probe\" and \"force\" control lines ... ignoring \"force\"" >&2
force=''
fi
if [ -z "$force" -a -z "$metric" ]
then
$PCP_ECHO_PROG "$1: Warning: neither \"probe\" nor \"force\" control lines ... use \"force available\"" >&2
force=available
fi
$verbose && [ -n "$metric" ] && $PCP_ECHO_PROG $PCP_ECHO_N "probe $metric $options""$PCP_ECHO_C" >&2
$verbose && [ -n "$force" ] && $PCP_ECHO_PROG $PCP_ECHO_N "force $force""$PCP_ECHO_C" >&2
rm -f $tmp/err
if [ -n "$metric" ]
then
# probe
echo "$options"
if [ -s "$probelist" ]
then
echo "data `grep "^$metric" "$probelist"`"
else
echo "data `pmprobe -h $HOST -v $metric`"
fi
# need to handle these variants of pmprobe output
# sample.string.hullo 1 "hullo world!"
# sample.colour 3 101 202 303
#
else
# force
$PCP_ECHO_PROG "force $force"
# the '^G' character is used as a field separator in awk
fi \
| sed \
-e '/^data /!{
s/ //g
}' \
-e '/^data [^"]*$/{
s/^data //
s/ //g
}' \
-e '/^data .*"/{
s/^data //
s/ "//
s/" "//g
s/"$//
s/ //
}' \
| $PCP_AWK_PROG -F '
BEGIN { # conditions
i = 0
exists = ++i; condition[exists] = "exists"
values = ++i; condition[values] = "values"
force = ++i; conditon[force] = "-"
regexp = ++i; condition[regexp] = "~"
notregexp = ++i; condition[notregexp] = "!~"
gt = ++i; condition[gt] = ">";
ge = ++i; condition[ge] = ">=";
eq = ++i; condition[eq] = "==";
neq = ++i; condition[neq] = "!=";
le = ++i; condition[le] = "<=";
lt = ++i; condition[lt] = "<";
# states
include = 100; state[include] = "include"
exclude = 101; state[exclude] = "exclude"
available = 102; state[available] = "available"
}
NR == 1 && $1 == "force" && NF == 2 {
# force variant
action = -1
for (i in state) {
if ($2 == state[i]) {
action = i
break
}
}
if (action == -1) {
print "force state \"" $2 "\" not recognized" >"'$tmp/err'"
exit
}
printf "probe=1 action=%d\n",action >>"'$tmp/out'"
exit
}
NR == 1 {
op = exists # default predicate
yes = available # default success action
no = exclude # default failure action
if (NF > 0) {
have_condition = 0
for (i in condition) {
if ($1 == condition[i]) {
have_condition = 1
op = i
yes = available # default success action
no = exclude # default failure action
break
}
}
if (have_condition == 0 && $1 != "?") {
print "condition operator \"" $1 "\" not recognized" >"'$tmp/err'"
exit
}
if (op == exists || op == values) {
if (have_condition)
actarg = 2
else
actarg = 1
}
else {
if (NF < 2) {
print "missing condition operand after " condition[op] " operator" >"'$tmp/err'"
exit
}
oprnd = $2
actarg = 3
}
if (NF < actarg) next
str = $actarg
for (i = actarg+1; i <= NF; i++) {
str = str " " $i
}
if (NF >= actarg && $actarg != "?") {
print "expected \"?\" after condition, found \"" str "\"" >"'$tmp/err'"
exit
}
if (NF >= actarg && NF < actarg+3) {
print "missing state rule components: \"" str "\"" >"'$tmp/err'"
exit
}
if (NF >= actarg && NF > actarg+3) {
print "extra state rule components: \"" str "\"" >"'$tmp/err'"
exit
}
actarg++
yes = -1
for (i in state) {
if ($actarg == state[i]) {
yes = i
break
}
}
if (yes == -1) {
print "sucess state \"" $actarg "\" not recognized" >"'$tmp/err'"
exit
}
actarg++
if ($actarg != ":") {
print "expected \":\" in state rule, found \"" $actarg "\"" >"'$tmp/err'"
exit
}
actarg++
no = -1
for (i in state) {
if ($actarg == state[i]) {
no = i
break
}
}
if (no == -1) {
print "failure state \"" $actarg "\" not recognized" >"'$tmp/err'"
exit
}
}
}
NR == 2 {
#debug# printf "op: %d %s pmprobe: %s",op, condition[op],$0
probe = 0
if ($2 < 0) {
# error from pmprobe
;
}
else {
if (op == exists) {
probe = 1
}
else if (op == values) {
if ($2 > 0) probe = 1
}
else if (op == regexp) {
for (i = 3; i <= NF; i++) {
if ($i ~ oprnd) {
probe = 1
break
}
}
}
else if (op == notregexp) {
for (i = 3; i <= NF; i++) {
if ($i !~ oprnd) {
probe = 1
break
}
}
}
else if (op == gt) {
for (i = 3; i <= NF; i++) {
if ($i > oprnd) {
probe = 1
break
}
}
}
else if (op == ge) {
for (i = 3; i <= NF; i++) {
if ($i >= oprnd) {
probe = 1
break
}
}
}
else if (op == eq) {
for (i = 3; i <= NF; i++) {
if ($i == oprnd) {
probe = 1
break
}
}
}
else if (op == neq) {
for (i = 3; i <= NF; i++) {
if ($i != oprnd) {
probe = 1
break
}
}
}
else if (op == le) {
for (i = 3; i <= NF; i++) {
if ($i <= oprnd) {
probe = 1
break
}
}
}
else if (op == lt) {
for (i = 3; i <= NF; i++) {
if ($i < oprnd) {
probe = 1
break
}
}
}
}
if (probe == 1)
action = yes
else
action = no
printf "probe=%d action=%d\n",probe,action >>"'$tmp/out'"
}'
if [ -f $tmp/err ]
then
$verbose && $PCP_ECHO_PROG >&2
$PCP_ECHO_PROG "$1: Error: `cat $tmp/err`" >&2
elif [ -f $tmp/out ]
then
probe=''
action=''
eval `cat $tmp/out`
if $verbose
then
case $probe
in
0)
probe_s="failure"
;;
1)
probe_s="success"
;;
*)
probe_s="unknown ($probe)"
;;
esac
case $action
in
100)
action_s="include"
;;
101)
action_s="exclude"
;;
102)
action_s="available"
;;
*)
action_s="unknown ($action)"
;;
esac
$PCP_ECHO_PROG " -> probe=$probe_s action=$action_s" >&2
fi
if [ $action = 100 -o $action = 102 ]
then
mode='n'
[ $action = 100 ] && mode='y'
delta=`sed -n <"$1" -e /'^delta[ ]/s/delta[ ]*//p'`
[ -z "$delta" ] && delta='default'
echo "#+ $1:$mode:$delta:"
else
echo "#+ $1:x::"
fi
status=0
else
$verbose && $PCP_ECHO_PROG >&2
$PCP_ECHO_PROG "$1: Botch: no errors and no probe results ... try verbose mode" >&2
fi
exit