Comment doit fonctionner un compteur 32 bits en script :

  • Le compteur est un entier modulo 2^32
  • Le compteur augmente uniquement de la différence de valeur entre deux requêtes
  • Le compteur doit être conservé entre deux requêtes

Pour implémenter le modulo, ce n'est pas très compliqué en bash/sh :

$(($count % 2**32))

J'ai choisi de stocker les données dans un tableau bash. Pour conserver les données entre 2 appels, je stocke directement le tableau dans un fichier sous la forme d'une définition de tableau bash. De cette façon, je peux inclure le fichier au début de mon script et j'évite d'avoir à lire un fichier de donnée. Les données que je conserve sont le résultat de ma dernière requête SQL, la différence entre la dernière requête et la précédente, et finalement mon compteur. Pourquoi conserver le dernier résultat ? Ca me permet au passage de choisir le comportement du compteur entre compteur 32 bits et donnée directe (gauge).
La requête SQL est tout simplement un count(*) sur une table, le nombre de lignes de cette table peut augmenter ou diminuer (si il ne faisait qu'augmenter, je pourrais directement prendre le count(*) modulo 2^32).

#!/bin/sh

counters='pgcount.txt'
# call the counters
if [ -f $counters ]; then
    . $counters
else
    # last count / last diff / counter
    count=(0 0 0)
fi

# adds 2 values
# return the sum modulo 2**32
counter() {
    counter=$(($1 + $2))
    echo -n $(($counter % 2**32))
}

# dumps the values as bash arrays
dump() {
    echo "count=(${count[@]})" > $counters
}

getdata() {
    count=($@)
    rows=$(getcount $table)
    if [ "${count[1]}" -ne "$count" ]; then
        count[1]=$(($rows - ${count[0]}))
        count[0]=$rows
        count[2]=$(counter ${count[2]} ${count[1]})
    fi
    # return needed values
    echo ${count[@]}
}

count=($(getdata ${count[@]}))
dump()

La fonction getcount() effectue le count(*) et retourne le nombre de lignes lues.

Ce script est lancé toutes les minutes car la requêtes peut parfois prendre du temps et provoquer un timeout snmp. Mon serveur net-snmp appelle donc un bête script qui inclut le fichier de sauvegarde et renvoit les données sauvées.

#!/bin/sh

counters='pgcount.txt'
# call the counters
if [ -f $counters ]; then
    . $counters
else
    # last count / last diff / counter
    count=(0 0 0)
fi

echo ${count[1]}
echo ${count[2]}

En sélectionnant la donnée que je veux dans mon chemin snmp je peux obtenir le nombre de lignes insérées sous forme de compteur 32 bits ou le nombre de lignes insérées entre deux exécutions du scipt. Cette dernière valeur est bancale puisqu'elle ne représente pas le nombre de lignes insérées entre deux consultations du compteur. Il serait possible de le faire fonctionner correctement si le script de lecture réécrivait le fichier de sauvegarde à chaque lecture pour signifier qu'il a été consulté. Il faudrait alors implémenter un verrou sur ce fichier pour éviter qu'il soit utilisé par les 2 scripts en même temps.

NB: Désolé pour le titre du post, je ne trouvais rien de plus inspiré mais un compteur 32bits c'est un peu comme Doris, au bout d'un certain temps, il revient à zero. Oui, je sais ...