jbbarth's

Là où je bosse, on a la chance (?) de disposer d’un SAN, c’est-à-dire d’un réseau dédié au stockage. En l’occurence c’est un réseau fibre, et tous les flux passent par deux switches fibre McData Sphereon 4500… qu’il faut surveiller d’une manière ou d’une autre.

En l’occurrence on surveille tout ça par Nagios. L’ancien script (qui doit faire partie des nagios plugins du site officiel ?) vérifiait les interfaces une par une, ce qui est gênant dans un environnement évolutif (oubli d’interfaces non surveillées!). Il faisait d’autres choses (check trafic rx/tx, errors) que mon script ne fait pas, mais il ne demande qu’à être amélioré ;-)

Voici donc un script de remplacement qui check toutes les interfaces d’un coup. Gros avantage : on passe les ports non branchés en exception, mais si un port est vu “up” et qu’il est en exception le script sort en Critical. Cela force à maintenir la liste des exceptions à jour ;-)

PS: Il faut bien sûr que ruby soit installé sur votre serveur de supervision.

#!/usr/bin/ruby

# Dernière modif: 19/11/2008
# Script de test des ports pour les switches fibre
# Jean-Baptiste BARTH <jeanbaptiste.barth@gmail.com>

# Remonter les infos à la main (sous l'user "nagios")
# $ snmpwalk -c public -v 2c switch_san_a .1.3.6.1.4.1.289.2.1.1.2.3.1.1.2
#       SNMPv2-SMI::enterprises.289.2.1.1.2.3.1.1.2.1 = INTEGER: 2
#       SNMPv2-SMI::enterprises.289.2.1.1.2.3.1.1.2.2 = INTEGER: 2
# ...
# => 2 = OK, 6 = down, 13 = info not available

unless ARGV.length >= 2 && ARGV.length <= 3
  puts "Mauvais format :"
  puts "\t./check_fc_setra.rb HOST COMMUNITY [EXCLUSIONS]"
  puts "Les ports exclus évitent des remontées d'alertes pour les ports non branchés."
  puts "Exemple: ./check_fc_setra.rb switch_san_a public 1,4,9"
  exit 2
end

# Valeurs prises dans utils.sh
STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
STATE_UNKNOWN=3
STATE_DEPENDENT=4

# Parsing arguments
host = ARGV.shift
community = ARGV.shift
exclusions = (ARGV.shift || "none").split(",")

# Passage de la commande
command = `snmpwalk -c #{community} -v 2c #{host} .1.3.6.1.4.1.289.2.1.1.2.3.1.1.2`
result = []
command.each do |line|
  #puts "DEBUG snmpwalk: "+line
  matches = line.match /\.(\d+) = INTEGER: (\d+)/
  result.push [matches[1], matches[2]]
end

# Traitement de la sortie
not_ignored = result.select{|x| !exclusions.include? x[0]}
interfaces_down = not_ignored.select{|v| v[1] == "6"}.map{|x| x[0]}
interfaces_ok = not_ignored.select{|v| v[1] == "2"}.map{|x| x[0]}
interfaces_unknown = not_ignored.map{|x| x[0]} - interfaces_ok - interfaces_down
interfaces_ok_not_normal = (result - not_ignored).select{|v| v[1] == "2"}.map{|x| x[0]}
# Output
puts "Link DOWN on interfaces : "+interfaces_down.join(",") unless interfaces_down.empty?
puts "Link UP on IGNORED interfaces : "+interfaces_ok_not_normal.join(",")+"\n!!!CHANGE THE SERVICE CONFIG!!!" unless interfaces_ok_not_normal.empty?
puts "State UNKNOWN : "+interfaces_unknown.join(",") unless interfaces_unknown.empty?
puts "Link UP on interfaces : "+interfaces_ok.join(",") unless interfaces_ok.empty?
puts "Ignored: "+exclusions.join(",")
if !interfaces_down.empty? || !interfaces_ok_not_normal.empty?
  exit STATE_CRITICAL
elsif !interfaces_unknown.empty?
  exit STATE_UNKNOWN
else
  exit STATE_OK
end

J’avais évoqué ici la synchronisation de dépôts Git (en l’occurrence Github mais ça n’a pas d’importance).

Mais voilà, ça ne fonctionnait plus tout à fait après migration de serveur, et ce n’était pas très clair pour moi honnêtement. Alors j’ai de nouveau regardé sur le wiki de Redmine et trouvé cet article qui décrit les choses très bien.

Seule différence, j’utilise les branches sous Git, et ce mode ne synchronise que la branche principale (“master”, ce que l’on appellerait le “trunk” sous subversion).

Initialisation de mon dépôt:

cd /var/redmine/git_repositories/
git clone —bare git@github.com:jbbarth/project.git project
cd project
git remote add origin git@github.com:jbbarth/project.git
git fetch -v

Ajout de ceci en CRON:

#sync of my github repos for redmine
*/10 * * * * /var/redmine/git_repositories/sync_repositories.sh >/dev/null

Et le petit script qui va bien:

#!/bin/sh

base=$(dirname $0)
[ "$base" == "." ] && base=$(pwd)

cd $base
for repo in $(ls -F |fgrep "/"); do
  cd $base/$repo
  git fetch origin
  for branch in $(ls refs/remotes/origin/); do
    git reset —soft refs/remotes/origin/$branch
  done
done

Youpi!

Dans 4 jours, je vais me faire massacrer tenter un examen interne au boulot, censé valider mes aptitudes de “programmeur système”. Cet examen comporte une épreuve de développement (sur papier, faut pas déconner), que la plupart des gens vont passer en Java ou C/C++. Mais très peu pour moi, j’attaque en Ruby !

Je lis donc des bouquins, qui présentent un squelette de shell en C. Et en Ruby ? Eh bien en fait, contre toute attente, c’est super simple, voici un squelette fonctionnel :

#!/usr/bin/ruby

require 'readline'
require 'open3'

class Rshell
  def initialize
    loop do
      cmd = Readline.readline("$ ")
      exit if cmd.nil? or cmd == "exit"
      Open3.popen3(cmd) do |stdin,stdout,stderr|
        STDOUT.print stdout.read
        STDERR.print stderr.read
      end
    end
  end
end

Rshell.new

Il ne faut pas s’attendre à des miracles, aucun builtin, pas de gestion du PATH, mais on peut passer des commandes, différencier éventuellement STDOUT/STDERR pour le futur.

Ca me donne l’occasion de parler d’un vrai shell en Ruby, utilisé chez Heroku, Rush. J’en reparlerai dès que j’aurai testé ça au quotidien au boulot :)

Note pour moi-même:

wget --mirror -p --html-extension --base=./ -k -P ./ http://www.example.net/

Utile par exemple pour récupérer la doc de Vagrant en local (source).