Checking system uptime on FreeBSD

We usually check "sysctl:kernel.boottime" to get uptime on freebsd, but it does not work for version 6 and above. Be obtained by reading the source code uptime the system call,and then through the python to obtain accurate uptime.

#!/usr/bin/env python

# NOTE: ctypes require python 2.5
import os, sys, datetime
from optparse import OptionParser

EX_WARN = 1
EX_CRIT = 2
EX_UNKN = 3

try:
    import ctypes
except ImportError:
    print "UPTIME CRITICAL: Python ctypes required (Python 2.5 or greater)"
    sys.exit(EX_CRIT)

class timespec(ctypes.Structure):
    _fields_ = [
        ('tv_sec', ctypes.c_long),
        ('tv_nsec', ctypes.c_long)
        ]

if sys.platform.startswith('freebsd'):
    CLOCK_MONOTONIC = 4 # see <time.h>
    dylib = 'libc.so'
elif sys.platform.startswith('linux'):
    CLOCK_MONOTONIC = 1 # see <linux/time.h>
    dylib = 'librt.so.1'
else:
    print >> sys.stderr, "Unsupported platform"
    exit(1)

syslib = ctypes.CDLL(dylib, use_errno=True)
clock_gettime = syslib.clock_gettime
clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(timespec)]

def monotonic_time():
    t = timespec()
    if clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(t)) != 0:
        errno_ = ctypes.get_errno()
        raise OSError(errno_, os.strerror(errno_))
    return t.tv_sec + t.tv_nsec * 1e-9

def human_readable(seconds):
    delta = datetime.timedelta(seconds=seconds)

    # divide and modilus to get hours, minutes, seconds
    (minutes, seconds) = divmod(delta.seconds, 60)
    (hours, minutes) = divmod(minutes, 60)

    data = []

    if delta.days > 0:
        data.append('%d %s' % (delta.days, ('days','day')[delta.days > 1]))
    if hours > 0:
        data.append('%02dh:%02dm:%02ds' % (hours, minutes, seconds))
    else:
        data.append('%02dm:%02ds' % (minutes, seconds))

    return ", ".join(data)

def perf_data(time, warn, crit):
    return "uptime=%ds;0s:%ds;0s:%ds;null;null" % (time, warn, crit)

if __name__ == "__main__":
    p = OptionParser()
    p.add_option('-c', '--critical',
                 dest='critical',
                 help='Critical threshold in seconds (default: 12h)',
                 metavar='NUM',
                 type='int',
                 default=(3600 * 12))
    p.add_option('-w', '--warning',
                 dest='warning',
                 help='Warning threshold in seconds (default 24h)',
                 metavar='NUM',
                 type='int',
                 default=(3600 * 24))

    (options, args) = p.parse_args()

    time = monotonic_time()
    if time <= options.critical:
        print "UPTIME CRITICAL: Uptime is %s (critical threshold: %s) | %s" % (human_readable(time), human_readable(options.critical), perf_data(time, options.warning, options.critical))
        sys.exit(EX_CRIT)
    elif time <= options.warning:
        print "UPTIME WARNING: Uptime is %s (warning treshold: %s) | %s" % (human_readable(time), human_readable(options.warning), perf_data(time, options.warning, options.critical))
        sys.exit(EX_WARN)
    else:
        print "UPTIME OK: Uptime is %s | %s" % (human_readable(time), perf_data(time, options.warning, options.critical))

NOTE:In the freebsd 10, these codes should be revised.

if sys.platform.startswith('freebsd'):
    CLOCK_MONOTONIC = 4 # see 
    dylib = '/lib/libc.so.7'
elif sys.platform.startswith('linux'):
    CLOCK_MONOTONIC = 1 # see <linux/time.h>
    dylib = 'librt.so.1'
else:
    print >> sys.stderr, "Unsupported platform"
    exit(1)

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: