1

我正在尝试构建一个 nagios 检查以检查 mongoDB 已使用 fsyncLock() 锁定多长时间以用于备份目的(例如,如果 iSCSI 快照脚本崩溃并且 mongo 未解锁)

我正在考虑使用一个简单的

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

但似乎 run_command() 还不支持 currentOp。(在那里看到:https ://github.com/MLstate/opalang/blob/master/lib/stdlib/apis/mongo/commands.opa )

Woudl 有人对如何检查 mongo 是否被 perl 脚本锁定有建议吗?如果没有,我想我会去参加一些狂欢。我正在考虑使用 db.eval('db.currentOp()') 但我有点迷路了。

谢谢!

4

2 回答 2

2

你是对的,run_command不支持currentOp直接做a。但是,如果我们查看 shell 中的实现db.currentOpmongo我们可以看到它在幕后是如何工作的:

> 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);
}

因此,我们可以在 Perl 端查询特殊集合$cmd.sys.inprog,以获取inprog将在 shell 中返回的相同数组。

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;

当服务器锁定时,它将返回一个$current_op如下所示的结构:

{
      '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'
                  }
                ]
    };

在 an 期间fsyncLock(),您将获得一个空inprog数组,但您将拥有一个有用的info字段和预期的fsyncLock布尔值:

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

所以,把它们放在一起,我们得到:

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";
}
于 2013-02-08T05:07:01.657 回答
2

我实际上决定切换到 bash 中的解决方案(以后我想对数据做的事情更容易):

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

然后某种grep -Po '"fsyncLock" : \d'

不过感谢 Perl 的见解,它运行良好

于 2013-02-08T17:39:39.250 回答