2013-02-08 4 views
1

J'essaye de construire une vérification de nagios pour vérifier pendant combien de temps un mongoDB a été verrouillé en utilisant fsyncLock() à des fins de sauvegarde (si le script snapshoting iSCSI explose et que le mongo n'est pas déverrouillé par exemple)Récupérer l'état fsynclock d'un mongo db en perl

Je pensais à l'aide d'un simple

$currentLock->run_command({currentOp => 1}) 
    $isLocked = $currentLock->{fsyncLock} 

Mais il semble que run_command() ne supporte pas currentOp encore. (Comme on le voit là:)

Quelqu'un aurait-il un conseil sur la façon de vérifier si un mongo est verrouillé avec un script Perl? Sinon, je suppose que je vais aller pour un peu de bash. Je pensais utiliser un db.eval ('db.currentOp()') mais je me perds un peu.

Merci!

Répondre

2

Vous avez raison de dire que run_command ne supporte pas de faire un currentOp directement. Cependant, si nous regardons la mise en œuvre de db.currentOp dans la coquille mongo, nous pouvons voir comment il fonctionne sous le capot:

> db.currentOp 
function (arg) { 
    var q = {}; 
    if (arg) { 
     if (typeof arg == "object") { 
      Object.extend(q, arg); 
     } else if (arg) { 
      q.$all = true; 
     } 
    } 
    return this.$cmd.sys.inprog.findOne(q); 
} 

On peut donc interroger la collection spéciale $cmd.sys.inprog sur le côté Perl pour obtenir le même tableau inprog cela serait retourné dans la coquille.

use strict; 
use warnings; 

use MongoDB; 

my $db = MongoDB::MongoClient->new->get_database('test'); 
my $current_op = $db->get_collection('$cmd.sys.inprog')->find_one; 

Lorsque le serveur est pas verrouillé, il retournera une structure $current_op qui ressemble à ceci:

{ 
     'inprog' => [ 
        { 
        'connectionId' => 53, 
        'insert' => {}, 
        'active' => bless(do{\(my $o = 0)}, 'boolean'), 
        'lockStats' => { 
            'timeAcquiringMicros' => { 
                  'w' => 1, 
                  'r' => 0 
                  }, 
            'timeLockedMicros' => { 
                 'w' => 9, 
                 'r' => 0 
                 } 
           }, 
        'numYields' => 0, 
        'locks' => { 
           '^' => 'w', 
           '^test' => 'W' 
          }, 
        'waitingForLock' => $VAR1->{'inprog'}[0]{'active'}, 
        'ns' => 'test.fnoof', 
        'client' => '127.0.0.1:50186', 
        'threadId' => '0x105a81000', 
        'desc' => 'conn53', 
        'opid' => 7152352, 
        'op' => 'insert' 
        } 
       ] 
    }; 

Au cours d'une fsyncLock(), vous obtiendrez un tableau inprog vide mais vous aura un champ utile info et le fsyncLock booléen attendu:

{ 
     'info' => 'use db.fsyncUnlock() to terminate the fsync write/snapshot lock', 
     'fsyncLock' => bless(do{\(my $o = 1)}, 'boolean'), # <--- that's true 
     'inprog' => [] 
    }; 

Donc, mettre tous ensemble, nous obtenons:

use strict; 
use warnings; 

use MongoDB; 

my $db = MongoDB::MongoClient->new->get_database('fnarf'); 
my $current_op = $db->get_collection('$cmd.sys.inprog')->find_one; 

if ($current_op->{fsyncLock}) { 
    print "fsync lock is currently ON\n"; 
} else { 
    print "fsync lock is currently OFF\n"; 
} 
+1

Eh bien, c'est une réponse étonnamment précis qui fonctionne comme un charme. Merci beaucoup! –

1

En fait, je décidé de passer d'une solution dans bash (plus facile pour ce que je veux faire avec les données plus tard):

currentOp=`mongo --port $port --host $host --eval "printjson(db.currentOp())"` 

puis une sorte de grep -Po '"fsyncLock" : \d'

Merci pour l'aperçu Perl cependant, il a parfaitement fonctionné