ODT Export
 
#!/bin/bash
 
# a script to check Zabbix database for inconsistencies and problems
# it is attempted to keep each actual check contained in sql only
# currently mysql specific - help to make this db agnostic appreciated
# bash specific - no plans to change that
 
# performs checks, then allows user to choose category to explain errors found
# other actions are planned, like fixing the problem (by dropping erroneous records, for example)
 
# current checks:
#    1. graph items that reference non-existent items;
#    2. items that reference non-existent host;
#    3. items without description;
#    4. triggers without function references;
#    5. actions with zero eventid;
#    6. functions that refer non-existent items;
#    7. duplicate host-group relationship records
 
DB=${1:-zabbix}
MYSQL="mysql -N"
#DBUSER=zabbix
# note ! passing password on the commandline is not safe
#DBPASSWORD=zabbix
 
echo "performing tests on database $DB"
IFS=" " # needed so that 'read' can read line containing tabs
 
[[ "$DBUSER" ]] && USERNAME="-u $DBUSER"
[[ "$DBPASSWORD" ]] && PASSWORD="-p$DBPASSWORD"
 
# -------------------------- checks
 
# *** 1
graphitems() {
    while read i; do
        ((GRAPHBADITEMS++))
        GRAPHITEM_gitemid[$GRAPHBADITEMS]=$(echo $i | awk -F"\t" '{print $1}')
        GRAPHITEM_graphid[$GRAPHBADITEMS]=$(echo $i | awk -F"\t" '{print $2}')
        GRAPHITEM_itemid[$GRAPHBADITEMS]=$(echo $i | awk -F"\t" '{print $3}')
    done < <(echo "select gitemid,graphid,graphs_items.itemid from graphs_items\
 left join items on graphs_items.itemid=items.itemid where items.itemid is null;" | $MYSQL $USERNAME $PASSWORD $DB)
}
 
# *** 2
itemswithouthost() {
    while read i; do
        ((ITEMSWITHOUTHOST++))
        ITEMWITHOUTHOST_itemid[$ITEMSWITHOUTHOST]=$(echo $i | awk -F"\t" '{print $1}')
        ITEMWITHOUTHOST_key_[$ITEMSWITHOUTHOST]=$(echo $i | awk -F"\t" '{print $2}')
        ITEMWITHOUTHOST_hostid[$ITEMSWITHOUTHOST]=$(echo $i | awk -F"\t" '{print $3}')
        ITEMWITHOUTHOST_host[$ITEMSWITHOUTHOST]=$(echo $i | awk -F"\t" '{print $4}')
    done < <(echo "select itemid,key_,items.hostid,host from items left join hosts on items.hostid=hosts.hostid\
 where hosts.hostid is null;" | $MYSQL $USERNAME $PASSWORD $DB)
}
 
# *** 3
itemswithoutdescription() {
    while read i; do
        ((ITEMSWITHOUTDESCR++))
        ITEMWITHOUTDESCR_itemid[$ITEMSWITHOUTDESCR]=$(echo $i | awk -F"\t" '{print $1}')
        ITEMWITHOUTDESCR_key_[$ITEMSWITHOUTDESCR]=$(echo $i | awk -F"\t" '{print $2}')
        ITEMWITHOUTDESCR_hostid[$ITEMSWITHOUTDESCR]=$(echo $i | awk -F"\t" '{print $3}')
        ITEMWITHOUTDESCR_host[$ITEMSWITHOUTDESCR]=$(echo $i | awk -F"\t" '{print $4}')
    done < <(echo "select itemid,key_,items.hostid,hosts.host from items left join hosts on items.hostid=hosts.hostid\
 where description='';" | $MYSQL $USERNAME $PASSWORD $DB)
}
 
# *** 4
triggerswithoutfunctionreference() {
    while read i; do
        ((TRIGGERSWOFUNCREF++))
        TRIGGERWOFUNCREF_triggerid[$TRIGGERSWOFUNCREF]=$(echo $i | awk -F"\t" '{print $1}')
        TRIGGERWOFUNCREF_expression[$TRIGGERSWOFUNCREF]=$(echo $i | awk -F"\t" '{print $2}')
        TRIGGERWOFUNCREF_description[$TRIGGERSWOFUNCREF]=$(echo $i | awk -F"\t" '{print $3}')
    done < <(echo "select triggerid,expression,description from triggers where expression\
 not regexp '.*{[0-9]*}.*';" | $MYSQL $USERNAME $PASSWORD $DB)
}
 
# *** 5
actionswithzeroeventid() {
    while read i; do
        ((ACTIONSWITHZEROID++))
        ACTIONWITHZEROID_alertid[$ACTIONSWITHZEROID]=$(echo $i | awk -F"\t" '{print $1}')
        ACTIONWITHZEROID_alias[$ACTIONSWITHZEROID]=$(echo $i | awk -F"\t" '{print $2}')
        ACTIONWITHZEROID_sendto[$ACTIONSWITHZEROID]=$(echo $i | awk -F"\t" '{print $3}')
    done < <(echo "select alertid,alias,sendto from alerts left join users on alerts.userid=users.userid\
 where eventid=0;" | $MYSQL $USERNAME $PASSWORD $DB)
}
 
# *** 6
functionswithbaditems() {
    while read i; do
        ((FUNCTIONSWITHBADITEMS++))
        FUNCTIONWITHBADITEMS_functionid[$FUNCTIONSWITHBADITEMS]=$(echo $i | awk -F"\t" '{print $1}')
        FUNCTIONWITHBADITEMS_itemid[$FUNCTIONSWITHBADITEMS]=$(echo $i | awk -F"\t" '{print $2}')
        FUNCTIONWITHBADITEMS_trigger_description[$FUNCTIONSWITHBADITEMS]=$(echo $i | awk -F"\t" '{print $3}')
    done < <(echo "select functionid,functions.itemid,triggers.description from functions left join\
 items on functions.itemid=items.itemid left join triggers on functions.triggerid=triggers.triggerid\
 where items.itemid is null;" | $MYSQL $USERNAME $PASSWORD $DB)
}
 
# *** 7
 
dupehostgroups() {
    while read i; do
        ((DUPEHOSTGROUPS++))
        DUPEHOSTGROUPS_amount[$DUPEHOSTGROUPS]=$(echo $i | awk -F"\t" '{print $1}')
        DUPEHOSTGROUPS_hostid[$DUPEHOSTGROUPS]=$(echo $i | awk -F"\t" '{print $2}')
        DUPEHOSTGROUPS_groupid[$DUPEHOSTGROUPS]=$(echo $i | awk -F"\t" '{print $3}')
    done < <(echo "SELECT COUNT(*) as qty,hostid,groupid FROM hosts_groups GROUP BY hostid,groupid\
 HAVING qty > 1;" | $MYSQL $USERNAME $PASSWORD $DB)
}
 
# -------------------------- check explanations
 
explaingraphitems() {
    echo "this check finds graph items that reference non-existent items. graph items found :"
    ( echo -e "gitemid\tgraphid\titemid"
    for ((count=1;count<=$GRAPHBADITEMS;count++)); do
        echo -e "${GRAPHITEM_gitemid[$count]}\t${GRAPHITEM_graphid[$count]}\t${GRAPHITEM_itemid[$count]}"
    done ) | column -t -s$'\t'
}
 
explainitemswithouthost() {
    echo "this check finds items that reference non-existent hosts. items found :"
    ( echo -e "itemid\tkey_\thostid\thost"
    for ((count=1;count<=$ITEMSWITHOUTHOST;count++)); do
        echo -e "${ITEMWITHOUTHOST_itemid[$count]}\t${ITEMWITHOUTHOST_key_[$count]}\t${ITEMWITHOUTHOST_hostid[$count]}\t${ITEMWITHOUTHOST_host[$count]}"
    done ) | column -t -s$'\t'
}
 
explainitemswithoutdescription() {
    echo "this check finds items with empty description. items found :"
    ( echo -e "itemid\tkey_\thostid\thost"
    for ((count=1;count<=$ITEMSWITHOUTDESCR;count++)); do
        echo -e "${ITEMWITHOUTDESCR_itemid[$count]}\t${ITEMWITHOUTDESCR_key_[$count]}\t${ITEMWITHOUTDESCR_hostid[$count]}\t${ITEMWITHOUTDESCR_host[$count]}"
    done ) | column -t -s$'\t'
}
 
explaintriggerswithoutfunctionreference() {
    echo "this check finds triggers that do not reference any function. triggers found :"
    ( echo -e "triggerid\texpression\tdescription"
    for ((count=1;count<=$TRIGGERSWOFUNCREF;count++)); do
        echo -e "${TRIGGERWOFUNCREF_triggerid[$count]}\t${TRIGGERWOFUNCREF_expression[$count]}\t${TRIGGERWOFUNCREF_description[$count]}"
    done ) | column -t -s$'\t'
}
 
explainactionswithzeroeventid() {
    echo "this check finds actions (alerts, notifications) that have zero eventid. such entries could occur if migration has happened from version 1.4 to 1.6 before 1.6.3 or .4. actions like that do not appear in the frontend. actions found :"
    ( echo -e "alertid\talias\tsendto"
    for ((count=1;count<=$ACTIONSWITHZEROID;count++)); do
        echo -e "${ACTIONWITHZEROID_alertid[$count]}\t${ACTIONWITHZEROID_alias[$count]}\t${ACTIONWITHZEROID_sendto[$count]}"
    done ) | column -t -s$'\t'
}
 
explainfunctionswithbaditems() {
    echo "this check finds functions that reference non-existent items. functions found :"
    ( echo -e "functionid\titemid\ttrigger_description"
    for ((count=1;count<=$FUNCTIONSWITHBADITEMS;count++)); do
        echo -e\
 "${FUNCTIONWITHBADITEMS_functionid[$count]}\t${FUNCTIONWITHBADITEMS_itemid[$count]}\t${FUNCTIONWITHBADITEMS_trigger_description[$count]}"
    done ) | column -t -s$'\t'
}
 
explaindupehostgroups() {
    echo "this check finds duplicate entries for host-group linking. duplicates found :"
    ( echo -e "amount\tgroupid\thostid"
    for ((count=1;count<=$DUPEHOSTGROUPS;count++)); do
        echo -e\
 "${DUPEHOSTGROUPS_amount[$count]}\t${DUPEHOSTGROUPS_groupid[$count]}\t${DUPEHOSTGROUPS_hostid[$count]}"
    done ) | column -t -s$'\t'
}
 
# --------------------------
 
finaloutput() {
    echo "----------------------------------------"
    echo "problems in $PROBLEMCATEGORIES categories found:"
    echo -e $INFOSTRING
    echo "enter category number for actions for that category, 'a' for all categories and 'q' to quit"
}
#
for i in graphitems itemswithouthost itemswithoutdescription triggerswithoutfunctionreference\
 actionswithzeroeventid functionswithbaditems dupehostgroups; do
    echo -n "running check $i... "
    $i
done
echo
 
[[ "$GRAPHBADITEMS" ]] && {
    ((PROBLEMCATEGORIES++))
    PROBLEMCATEGORY[$PROBLEMCATEGORIES]=graphitems
    INFOSTRING="$INFOSTRING\n${PROBLEMCATEGORIES}. $GRAPHBADITEMS bad graph items found"
}
 
[[ "$ITEMSWITHOUTHOST" ]] && {
    ((PROBLEMCATEGORIES++))
    PROBLEMCATEGORY[$PROBLEMCATEGORIES]=itemswithouthost
    INFOSTRING="$INFOSTRING\n${PROBLEMCATEGORIES}. $ITEMSWITHOUTHOST items without host found"
}
 
[[ "$ITEMSWITHOUTDESCR" ]] && {
    ((PROBLEMCATEGORIES++))
    PROBLEMCATEGORY[$PROBLEMCATEGORIES]=itemswithoutdescription
    INFOSTRING="$INFOSTRING\n${PROBLEMCATEGORIES}. $ITEMSWITHOUTDESCR items without description found"
}
 
[[ "$TRIGGERSWOFUNCREF" ]] && {
    ((PROBLEMCATEGORIES++))
    PROBLEMCATEGORY[$PROBLEMCATEGORIES]=triggerswithoutfunctionreference
    INFOSTRING="$INFOSTRING\n${PROBLEMCATEGORIES}. $TRIGGERSWOFUNCREF triggers that do not reference any function found"
}
 
[[ "$ACTIONSWITHZEROID" ]] && {
    ((PROBLEMCATEGORIES++))
    PROBLEMCATEGORY[$PROBLEMCATEGORIES]=actionswithzeroeventid
    INFOSTRING="$INFOSTRING\n${PROBLEMCATEGORIES}. $ACTIONSWITHZEROID actions with zero eventid found"
}
 
[[ "$FUNCTIONSWITHBADITEMS" ]] && {
    ((PROBLEMCATEGORIES++))
    PROBLEMCATEGORY[$PROBLEMCATEGORIES]=functionswithbaditems
    INFOSTRING="$INFOSTRING\n${PROBLEMCATEGORIES}. $FUNCTIONSWITHBADITEMS functions that reference non-existent items found"
}
 
[[ "$DUPEHOSTGROUPS" ]] && {
    ((PROBLEMCATEGORIES++))
    PROBLEMCATEGORY[$PROBLEMCATEGORIES]=dupehostgroups
    INFOSTRING="$INFOSTRING\n${PROBLEMCATEGORIES}. $DUPEHOSTGROUPS duplicate host-group links found"
}
 
 
chooseaction() {
    read -p "choose action ('e' for explain): " ACTION
    echo $ACTION
}
 
performaction() {
    case $1 in
        e)
            echo "----- explaining ${PROBLEMCATEGORY[$INPUT]} category -----"
            explain${PROBLEMCATEGORY[$INPUT]}
            echo
            ;;
        *)
            echo "no such action"
            performaction $(chooseaction)
            ;;
    esac
}
 
[[ "$INFOSTRING" ]] && {
    while true; do
        finaloutput
        read INPUT
        case $INPUT in
            [0-9]*)
                if [ "${PROBLEMCATEGORY[$INPUT]}" == "" ]; then
                    echo "no such category"
                else
                    performaction $(chooseaction)
                fi
                ;;
            a)
                ACTION=$(chooseaction)
                for ((i=1;i<=$PROBLEMCATEGORIES;i++)); do
                    INPUT=$i
                    performaction $ACTION
                done
                ;;
            q)
                exit
                ;;
            *)
                echo "invalid input"
                ;;
        esac
    done
}
 
scripts/db_consistency.sh.txt · Last modified: 2012/01/19 00:27 by zalex_ua
 
Except where otherwise noted, content on this wiki is licensed under the following license:CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki