<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet title="XSL formatting" type="text/xsl" href="http://www.bonz.org/tech/feed/rss2/xslt" ?><rss version="2.0"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
  <title>ZenTech - snmp</title>
  <link>http://www.bonz.org/tech/</link>
  <description>Om Mani Padme Hum</description>
  <language>fr</language>
  <pubDate>Mon, 10 Nov 2008 00:41:06 +0100</pubDate>
  <copyright></copyright>
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  <generator>Dotclear</generator>
  
    
  <item>
    <title>Booooooonjouuuuuuuuuuuur jeee m'aaaappeeeeeeeeeeeeelle Dooooooooriiiiiiiiiiiis</title>
    <link>http://www.bonz.org/tech/post/2008/03/12/Booooooonjouuuuuuuuuuuur-jeee-maaaappeeeeeeeeeeeeelle-Dooooooooriiiiiiiiiiiis</link>
    <guid isPermaLink="false">urn:md5:3b3acdda0ae236ebe8705160e7ffb8e8</guid>
    <pubDate>Thu, 13 Mar 2008 15:54:00 +0100</pubDate>
    <dc:creator>hr</dc:creator>
        <category>code</category>
        <category>bash</category><category>snmp</category>    
    <description>&lt;p&gt;Suite à la configuration de net-snmp pour &lt;a href=&quot;http://www.bonz.org/tech/post/2008/03/04/All-your-poll-are-belong-to-us&quot; hreflang=&quot;fr&quot;&gt;utiliser des scripts&lt;/a&gt;, il a bien fallu coder un compteur 32bits. Aimant les défis, je me suis décidé à écrire un compteur 32 bits en bash qui compte les entrées d'une base de donnée.&lt;/p&gt;    &lt;p&gt;Comment doit fonctionner un compteur 32 bits en script&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Le compteur est un entier modulo 2^32&lt;/li&gt;
&lt;li&gt;Le compteur augmente uniquement de la différence de valeur entre deux requêtes&lt;/li&gt;
&lt;li&gt;Le compteur doit être conservé entre deux requêtes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pour implémenter le modulo, ce n'est pas très compliqué en &lt;code&gt;bash/sh&lt;/code&gt;&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
$(($count % 2**32))
&lt;/pre&gt;

&lt;p&gt;J'ai choisi de stocker les données dans un &lt;a href=&quot;http://tldp.org/LDP/abs/html/arrays.html&quot; hreflang=&quot;en&quot;&gt;tableau bash&lt;/a&gt;. 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&amp;nbsp;? Ca me permet au passage de choisir le comportement du compteur entre compteur 32 bits et donnée directe (gauge).&lt;br /&gt;
La requête SQL est tout simplement un &lt;code&gt;count(*)&lt;/code&gt; 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 &lt;code&gt;count(*)&lt;/code&gt; modulo 2^32).&lt;/p&gt;
&lt;pre&gt;
#!/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 &amp;quot;count=(${count[@]})&amp;quot; &amp;gt; $counters
}

getdata() {
    count=($@)
    rows=$(getcount $table)
    if [ &amp;quot;${count[1]}&amp;quot; -ne &amp;quot;$count&amp;quot; ]; 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()
&lt;/pre&gt;

&lt;p&gt;La fonction &lt;code&gt;getcount()&lt;/code&gt; effectue le &lt;code&gt;count(*)&lt;/code&gt; et retourne le nombre de lignes lues.&lt;/p&gt;


&lt;p&gt;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.&lt;/p&gt;
&lt;pre&gt;
#!/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]}
&lt;/pre&gt;

&lt;p&gt;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.&lt;/p&gt;


&lt;p&gt;&lt;ins&gt;NB&lt;/ins&gt;: Désolé pour le titre du post, je ne trouvais rien de plus inspiré mais un compteur 32bits c'est un peu comme &lt;a href=&quot;http://fr.wikipedia.org/wiki/Le_Monde_de_Nemo&quot; hreflang=&quot;fr&quot;&gt;Doris&lt;/a&gt;, au bout d'un certain temps, il revient à zero. Oui, je sais ...&lt;/p&gt;</description>
    
    
    
      </item>
    
  <item>
    <title>All your poll are belong to us</title>
    <link>http://www.bonz.org/tech/post/2008/03/04/All-your-poll-are-belong-to-us</link>
    <guid isPermaLink="false">urn:md5:478d1667209ca96937554b17ebdbc7f8</guid>
    <pubDate>Wed, 05 Mar 2008 18:36:00 +0100</pubDate>
    <dc:creator>hr</dc:creator>
        <category>système</category>
        <category>debian</category><category>etch</category><category>net-snmp</category><category>snmp</category>    
    <description>&lt;p&gt;J'ai aujourd'hui besoin de tenir à l'oeil certaines valeurs sur un serveur, le plus simple semble d'utiliser &lt;a href=&quot;http://net-snmp.sourceforge.net/&quot; hreflang=&quot;en&quot;&gt;net-snmp&lt;/a&gt; et &lt;a href=&quot;http://oss.oetiker.ch/mrtg/&quot; hreflang=&quot;en&quot;&gt;mrtg&lt;/a&gt;. Ce serveur SNMP peut être très facilement étendu, mais est assez mal documenté à mon goût. Je vais donc faire un petit tour des méthodes simples d'utilisation de net-snmp pour récupérer des données non communes.&lt;/p&gt;    &lt;p&gt;Les versions de net-snmp et mrtg installées sur ma debian etch sont &lt;code&gt;snmpd (5.2.3-7etch2)&lt;/code&gt; et &lt;code&gt;mrtg (2.14.7-2)&lt;/code&gt;. Je suppose que vous êtes à l'aise avec le concept de SNMP et que net-snmp et mrtg sont configurés.&lt;br /&gt;
En faisant le tour du site web, du fichier de configuration par défaut et de goo^Winternet, j'ai pû lister les méthodes suivantes&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;exec&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;extend&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pass&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Je passe sur l'utilisation de &lt;a href=&quot;http://net-snmp.sourceforge.net/wiki/index.php/TUT:Writing_a_Subagent&quot; hreflang=&quot;en&quot;&gt;subagent&lt;/a&gt; qui est plus complexe.&lt;br /&gt;
Le script que je vais utiliser tient en 2 lignes et se trouve dans &lt;code&gt;/tmp/test_snmp&lt;/code&gt;&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;#!/bin/sh
echo 42
&lt;/pre&gt;

&lt;p&gt;Pour information, le fichier &lt;code&gt;/usr/share/snmp/mibs/UCD-SNMP-MIB.txt&lt;/code&gt; indique que l'OID 2021 correspond à &lt;code&gt;ucdavis&lt;/code&gt; et se trouve après le noeud &lt;code&gt;enterprise&lt;/code&gt; (ce qui donne &lt;code&gt;.1.3.6.1.4.1.2021&lt;/code&gt;). Cet OID sera utilisé pour ajouter de nouvelles données en test, en réalité il faudrait utiliser un OID correspondant à l'environnement d'utilisation (un OID d'entreprise délivré par &lt;a href=&quot;http://www.iana.org/assignments/enterprise-numbers&quot; hreflang=&quot;en&quot;&gt;IANA&lt;/a&gt; par exemple).&lt;/p&gt;


&lt;h2&gt;&lt;code&gt;exec&lt;/code&gt;&lt;/h2&gt;
&lt;pre&gt;
[...]
exec test1 /tmp/test_snmp
exec .1.3.6.1.4.1.2021.60 test2 /tmp/test_snmp
[...]
&lt;/pre&gt;

&lt;p&gt;Après redémarrage, on vérifie que les données sont bien accessibles en SNMP&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
$ snmpwalk -v 1 -c private localhost .1.3.6.1.4.1.2021
[...]
UCD-SNMP-MIB::extIndex.1 = INTEGER: 1
UCD-SNMP-MIB::extNames.1 = STRING: test_snmp
UCD-SNMP-MIB::extCommand.1 = STRING: /tmp/test_snmp
UCD-SNMP-MIB::extResult.1 = INTEGER: 0
UCD-SNMP-MIB::extOutput.1 = STRING: 42
UCD-SNMP-MIB::extErrFix.1 = INTEGER: 0
UCD-SNMP-MIB::extErrFixCmd.1 = STRING:
[...]
UCD-SNMP-MIB::ucdavis.60.1.1 = INTEGER: 1
UCD-SNMP-MIB::ucdavis.60.2.1 = STRING: &amp;quot;test_snmp&amp;quot;
UCD-SNMP-MIB::ucdavis.60.3.1 = STRING: &amp;quot;/tmp/test_snmp&amp;quot;
UCD-SNMP-MIB::ucdavis.60.100.1 = INTEGER: 0
UCD-SNMP-MIB::ucdavis.60.101.1 = STRING: &amp;quot;42&amp;quot;
UCD-SNMP-MIB::ucdavis.60.102.1 = INTEGER: 0
UCD-SNMP-MIB::ucdavis.60.103.1 = &amp;quot;&amp;quot;
[...]
&lt;/pre&gt;

&lt;p&gt;La première forme est plus explicite et la deuxième forme est mieux maitrisée puisqu'on choisit l'OID destination.&lt;/p&gt;


&lt;p&gt;Le problème est que le serveur snmp n'est pas très satisfait de l'utilisation de &lt;code&gt;exec&lt;/code&gt;&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
[...]
Mar  4 17:28:45 snmp.priv snmpd[8678]: /etc/snmp/snmpd.conf: line 363: Error: Warning: relocatable 'exec' format will change in a future release - See 'NET-SNMP-EXTEND-MIB' for an alternative
Mar  4 17:28:45 snmp.priv snmpd[8678]: net-snmp: 2 error(s) in config file(s)
&lt;/pre&gt;


&lt;h2&gt;&lt;code&gt;extend&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;L'uilisation de &lt;code&gt;extend&lt;/code&gt; se fait via une mib spéciale (&lt;code&gt;NET-SNMP-EXTEND-MIB.txt&lt;/code&gt;), sur une debian elle se trouve dans &lt;code&gt;/usr/share/snmp/mibs&lt;/code&gt;. L'utilisation de cette option permet de créer automatiquement des entrées sous l'OID &lt;code&gt;.1.3.6.1.4.1.8072&lt;/code&gt; par défaut.&lt;/p&gt;
&lt;pre&gt;
extend test_snmp /tmp/test_snmp
extend .1.3.6.1.4.1.2021.60 test_snmp /tmp/test_snmp
&lt;/pre&gt;

&lt;p&gt;Les résultats se trouvent aux 2 endroits suivants&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
$ snmpwalk -v 1 -c private localhost NET-SNMP-EXTEND-MIB::nsExtendObjects
[...]
NET-SNMP-EXTEND-MIB::nsExtendNumEntries.0 = INTEGER: 3
NET-SNMP-EXTEND-MIB::nsExtendCommand.&amp;quot;test_snmp&amp;quot; = STRING: /tmp/test_snmp
NET-SNMP-EXTEND-MIB::nsExtendArgs.&amp;quot;test_snmp&amp;quot; = STRING: 
NET-SNMP-EXTEND-MIB::nsExtendInput.&amp;quot;test_snmp&amp;quot; = STRING: 
NET-SNMP-EXTEND-MIB::nsExtendCacheTime.&amp;quot;test_snmp&amp;quot; = INTEGER: 5
NET-SNMP-EXTEND-MIB::nsExtendExecType.&amp;quot;test_snmp&amp;quot; = INTEGER: exec(1)
NET-SNMP-EXTEND-MIB::nsExtendRunType.&amp;quot;test_snmp&amp;quot; = INTEGER: run-on-read(1)
NET-SNMP-EXTEND-MIB::nsExtendStorage.&amp;quot;test_snmp&amp;quot; = INTEGER: permanent(4)
NET-SNMP-EXTEND-MIB::nsExtendStatus.&amp;quot;test_snmp&amp;quot; = INTEGER: active(1)
NET-SNMP-EXTEND-MIB::nsExtendOutput1Line.&amp;quot;test_snmp&amp;quot; = STRING: 42
NET-SNMP-EXTEND-MIB::nsExtendOutputFull.&amp;quot;test_snmp&amp;quot; = STRING: 42
NET-SNMP-EXTEND-MIB::nsExtendOutNumLines.&amp;quot;test_snmp&amp;quot; = INTEGER: 1
NET-SNMP-EXTEND-MIB::nsExtendResult.&amp;quot;test_snmp&amp;quot; = INTEGER: 0
NET-SNMP-EXTEND-MIB::nsExtendOutLine.&amp;quot;test_snmp&amp;quot;.1 = STRING: 42
[...]
$ snmpwalk -v 1 -c private localhost .1.3.6.1.4.1.2021.60
UCD-SNMP-MIB::ucdavis.60.1.0 = INTEGER: 1
UCD-SNMP-MIB::ucdavis.60.2.1.2.9.116.101.115.116.95.115.110.109.112 = STRING: &amp;quot;/tmp/test_snmp&amp;quot;
UCD-SNMP-MIB::ucdavis.60.2.1.3.9.116.101.115.116.95.115.110.109.112 = &amp;quot;&amp;quot;
UCD-SNMP-MIB::ucdavis.60.2.1.4.9.116.101.115.116.95.115.110.109.112 = &amp;quot;&amp;quot;
UCD-SNMP-MIB::ucdavis.60.2.1.5.9.116.101.115.116.95.115.110.109.112 = INTEGER: 5
UCD-SNMP-MIB::ucdavis.60.2.1.6.9.116.101.115.116.95.115.110.109.112 = INTEGER: 1
UCD-SNMP-MIB::ucdavis.60.2.1.7.9.116.101.115.116.95.115.110.109.112 = INTEGER: 1
UCD-SNMP-MIB::ucdavis.60.2.1.20.9.116.101.115.116.95.115.110.109.112 = INTEGER: 4
UCD-SNMP-MIB::ucdavis.60.2.1.21.9.116.101.115.116.95.115.110.109.112 = INTEGER: 1
UCD-SNMP-MIB::ucdavis.60.3.1.1.9.116.101.115.116.95.115.110.109.112 = STRING: &amp;quot;42&amp;quot;
UCD-SNMP-MIB::ucdavis.60.3.1.2.9.116.101.115.116.95.115.110.109.112 = STRING: &amp;quot;42&amp;quot;
UCD-SNMP-MIB::ucdavis.60.3.1.3.9.116.101.115.116.95.115.110.109.112 = INTEGER: 1
UCD-SNMP-MIB::ucdavis.60.3.1.4.9.116.101.115.116.95.115.110.109.112 = INTEGER: 0
UCD-SNMP-MIB::ucdavis.60.4.1.2.9.116.101.115.116.95.115.110.109.112.1 = STRING: &amp;quot;42&amp;quot;
&lt;/pre&gt;

&lt;p&gt;La deuxième forme revient à peu de choses près au résultat de la commande &lt;code&gt;exec&lt;/code&gt; avec utilisation d'un chemin.&lt;br /&gt;
La première forme permet d'obtenir beaucoup d'informations intéressantes comme le nombre d'éléments qui étendent la mib (&lt;code&gt;NET-SNMP-EXTEND-MIB::nsExtendNumEntries.0&lt;/code&gt; on remarque donc que j'ai nettoyé la réponse puisqu'il annonce 3 scripts d'extension). On peut récupérer la réponse complète &lt;code&gt;NET-SNMP-EXTEND-MIB::nsExtendOutputFull.&quot;test_snmp&quot;&lt;/code&gt; ou les lignes une à une &lt;code&gt;NET-SNMP-EXTEND-MIB::nsExtendOutLine.&quot;test_snmp&quot;.x&lt;/code&gt;.&lt;/p&gt;


&lt;p&gt;Le point faible de cette méthode subsiste dans le type de donnée renvoyé, notre script envoit un chiffre et il est considéré comme une chaine de caractère. De la même façon, si on veut générer un compteur sur 32 ou 64 bits, c'est impossible avec cette méthode.&lt;/p&gt;


&lt;h2&gt;&lt;code&gt;pass&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;L'utilisation de cette option de configuration oblige à choisir un OID en dessous duquel le script est entièrement maitre. Il faut donc avoir recours à un script plus complexe qui permet de donner le type de valeur et la valeur pour un OID donné. Le script &lt;code&gt;passtest&lt;/code&gt; donne une bonne idée d'un script basique permettant cette intégration. Je ne rentrerai pas dans les détails.&lt;/p&gt;
&lt;pre&gt;
pass .1.3.6.1.4.1.2021.60 /tmp/test_snmp
&lt;/pre&gt;

&lt;p&gt;Dans l'idée, le script est appelé avec les arguments &lt;code&gt;&amp;lt;reqtype&amp;gt;&lt;/code&gt; &lt;code&gt;&amp;lt;miboid&amp;gt;&lt;/code&gt;. Avec &lt;code&gt;reqtype&lt;/code&gt; qui correspond à &lt;code&gt;-g&lt;/code&gt; pour une requête &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;-n&lt;/code&gt; pour un &lt;code&gt;GETNEXT&lt;/code&gt; et un &lt;code&gt;-s&lt;/code&gt; pour un &lt;code&gt;SET&lt;/code&gt;. le chemin OID est donné par &lt;code&gt;miboid&lt;/code&gt;.&lt;br /&gt;
Dans le cas des commandes &lt;code&gt;GET&lt;/code&gt; et &lt;code&gt;GETNEXT&lt;/code&gt;, la réponse est constituée de 3 lignes&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;l'OID de réponse;&lt;/li&gt;
&lt;li&gt;le type de la valeur retournée, au choix dans integer, gauge, counter, timeticks, ipaddress, objectid, ou string;&lt;/li&gt;
&lt;li&gt;la valeur.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dans le cas de la commande &lt;code&gt;SET&lt;/code&gt;, le script ne doit rien retourner.&lt;/p&gt;


&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Il faut bien en finir avec tout ce bazar, il est intéressant de jeter un coup d'oeil du côté de &lt;code&gt;snmpd.conf(5)&lt;/code&gt; pour les détails, d'autres options de configuration comme &lt;code&gt;pass_persist&lt;/code&gt; peuvent être utilisées. Personnellement, j'utilise la solution &lt;code&gt;extend&lt;/code&gt; qui me semble raisonnablement simple à mettre en place et à utiliser.&lt;/p&gt;</description>
    
    
    
      </item>
    
</channel>
</rss>