[Git][NTPsec/ntpsec][master] 4 commits: temp-log.py: keep logs forever.

Gary E. Miller gitlab at mg.gitlab.com
Fri Jan 27 03:55:59 UTC 2017


Gary E. Miller pushed to branch master at NTPsec / ntpsec


Commits:
2044d511 by Gary E. Miller at 2017-01-26T18:05:31-08:00
temp-log.py: keep logs forever.

- - - - -
774baf9b by Gary E. Miller at 2017-01-26T18:11:34-08:00
temp-log.py: simplify smartctl drive detection

- - - - -
517b704e by Gary E. Miller at 2017-01-26T18:32:55-08:00
temp-log.py: improve comments.

- - - - -
4f9623ac by Gary E. Miller at 2017-01-26T19:54:39-08:00
temp-log.py: remove subprocess.check_output() for Python 2.6 compatibility

Move all the system call stuff into one function.

- - - - -


1 changed file:

- contrib/temp-log.py


Changes:

=====================================
contrib/temp-log.py
=====================================
--- a/contrib/temp-log.py
+++ b/contrib/temp-log.py
@@ -1,11 +1,24 @@
 #!/usr/bin/env python
-# temp-log.py: A script that will be run eventually as a daemon
-#              to log temperatures of a system
-# Usage:
-# temp-log.py [-h] [-q] [-v] [-V] [-l LOGFILE]
-# Requires root to run
+"""\
+usage: temp-log.py [-h] [-l LOGFILE] [-o] [-q] [-v] [-w WAIT] [-V]
+
+Program to log system temperatures
+
+optional arguments:
+  -h, --help            show this help message and exit
+  -l LOGFILE, --logfile LOGFILE
+                        append log data to LOGFILE instead of stdout
+  -o, --once            Run the output once and exit
+  -q, --quiet           be quite
+  -v, --verbose         be verbose
+  -w WAIT, --wait WAIT  Set delay time in seconds, default is 60
+  -V, --version         show program's version number and exit
+
+See the manual page for details.
+"""
 
 import argparse
+import glob
 import logging
 import logging.handlers
 import os
@@ -22,37 +35,57 @@ except ImportError as e:
     sys.exit(1)
 
 
+def run_binary(cmd):
+    """\
+Run a binary
+Return output if good, None if bad
+"""
+
+    try:
+        # sadly subprocess.check_output() is not in Python 2.6
+        # so use Popen()
+        # this throws an exception if not found
+        proc = subprocess.Popen( cmd,
+                                stdout=subprocess.PIPE,
+                                stderr=subprocess.STDOUT,
+                                universal_newlines=True)
+        output = proc.communicate()[0]
+
+        if proc.returncode:
+            # non-zero return code, fail
+            return None
+
+    except:
+        if args.verbose:
+            sys.stderr.write("Unable to run %s binary\n" % cmd[0])
+        # throws exceptoin
+        return None
+    return output
+
 class CpuTemp:
     "Sensors on the CPU Core"
-    no_sensors = False
+    has_sensors = False
 
     def __init__(self):
         # check for sensors binary
-        try:
-            # sadly subprocess.check_output() is not in Python 2.6
-            subprocess.check_output(["which", "sensors"],
-                                    stderr=subprocess.STDOUT,)
-        except:
-            # skip sensors, many systems can not use sensors
-            self.no_sensors = True
-            if args.verbose:
-                sys.stderr.write("Unable to find sensors binary")
+        ret = run_binary(["sensors", "-h"])
+        if ret is not None:
+            self.has_sensors = True
 
         # pattern that matches the string that has the cpu temp
         self._pattern = re.compile('^\s+temp\d+_input:\s+([\d\.]+).*$')
 
     def get_data(self):
         "Collects the data and return the output as an array"
-        if self.no_sensors:
+        if not self.has_sensors:
             return None
 
         _index = 0
         _data = []
         # grab the needed output
-        # sadly subprocess.check_output() is not in Python 2.6
-        _output = subprocess.check_output(['sensors', "-u"],
-                                          universal_newlines=True).split('\n')
-        for record in _output:
+        output = run_binary(["sensors", "-u"])
+
+        for record in output.split("\n"):
             match = self._pattern.match(record)
             if match and match.group(1):
                 _now = int(time.time())
@@ -66,34 +99,37 @@ class CpuTemp:
 class SmartCtl:
     "Sensor on the Hard Drive"
     _drives = []
+    has_smartctl = False
 
     def __init__(self):
-        if os.getuid() != 0:
-            raise IOError("You must be root!")
-        # Which drive to watch
-        for child in os.listdir('/dev/'):
-            if re.compile('sd[a-z]$').match(child):
-                self._drives.append("/dev/"+str(child))
-        self._drives = sorted(self._drives)
+        ret = run_binary(["smartctl", "-h"])
+        if ret is not None:
+            self.has_smartctl = True
+
+        if self.has_smartctl:
+            # Which drive to watch
+            for child in glob.glob('/dev/sd?'):
+                self._drives.append(child)
+            self._drives = sorted(self._drives)
 
     def get_data(self):
         "Collects the data and return the output as an array"
+        if not self.has_smartctl:
+            return None
+
         data = []
         for _device in self._drives[:]:
-            try:
-                # sadly subprocess.check_output() is not in Python 2.6
-                _output = subprocess.check_output(["smartctl", "-A",
-                                                  _device],
-                                                  universal_newlines=True
-                                                  ).split('\n')
-                for line in _output:
+            output = run_binary(["smartctl", "-A", _device])
+
+            if output is None:
+                # do not keep trying on failure
+                self._drives.remove(_device)
+            else:
+                for line in output.split("\n"):
                     if line.startswith('194 '):
                         now = int(time.time())
                         temp = line.split()[9]
                         data.append('%d %s %s' % (now, _device, temp))
-            except:
-                # do not keep trying on failure
-                self._drives.remove(_device)
         return data
 
 
@@ -105,42 +141,31 @@ class Temper:
     plugged in, and the temper-python package must be installed and configured.
     See their documentation for that procedure.
 """
-    no_temper = False
+    has_temper = False
 
     def __init__(self):
-        # check for temper-poll binary
-        try:
-            # sadly subprocess.check_output() is not in Python 2.6
-            subprocess.check_output(["which", "temper-poll"],
-                                    stderr=subprocess.STDOUT,)
-        except:
-            # skip temper, many systems do not have it
-            self.no_temper = True
-            if args.verbose:
-                sys.stderr.write("Unable to find temper-poll binary")
+        # check for sensors binary
+        ret = run_binary(["temper-poll", "-h"])
+        if ret is not None:
+            self.has_temper = True
 
     def get_data(self):
         "Collects the data and return the output as an array"
-        if self.no_temper:
+        if not self.has_temper:
             return None
 
         data = []
         _device = 'TEMPER0'
         # grab the needed output
-        # sadly subprocess.check_output() is not in Python 2.6
+        output = run_binary(["temper-poll", "-c"])
         try:
-            proc = subprocess.Popen(["temper-poll", "-c"],
-                                    stdout=subprocess.PIPE,
-                                    stderr=subprocess.STDOUT,
-                                    universal_newlines=True)
-            temp = proc.communicate()[0]
             # make sure it is a temperature
-            temp = float(temp)
+            temp = float(output)
             now = int(time.time())
             data.append('%d %s %s' % (now, _device, temp))
         except:
-            # bad data, ignore it
-            self.no_temper = True
+            # bad data, ignore it, forever
+            self.has_temper = False
         return data
 
 
@@ -188,15 +213,15 @@ parser.add_argument('-v', '--verbose',
                     action="store_true",
                     dest='verbose',
                     help="be verbose")
-parser.add_argument('-V', '--version',
-                    action="version",
-                    version="temp-log %s" % ntp.util.stdversion())
 parser.add_argument('-w', '--wait',
                     default=[60],
                     dest='wait',
                     help="Set delay time in seconds, default is 60",
                     nargs=1,
                     type=int)
+parser.add_argument('-V', '--version',
+                    action="version",
+                    version="temp-log %s" % ntp.util.stdversion())
 args = parser.parse_args()
 
 
@@ -211,11 +236,7 @@ def logging_setup(fileName, logLevel):
         _file = logging.handlers.TimedRotatingFileHandler(
             fileName,
             when='midnight',
-            interval=1,
-            backupCount=5,
-            encoding=None,
-            delay=False,
-            utc=False)
+            interval=1)
     else:
         _file = logging.StreamHandler(sys.stdout)
 
@@ -277,4 +298,5 @@ try:
         log = sys.stdout
     log_data()
 except (KeyboardInterrupt, SystemExit):
+    print("")    # be nice to bash
     sys.exit(0)



View it on GitLab: https://gitlab.com/NTPsec/ntpsec/compare/33da600f8897baaf338dc2e98082aa3c841a4a27...4f9623acf55868f0bb08a5a8e5d6014cd3d2b95b
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ntpsec.org/pipermail/vc/attachments/20170127/7043d8fe/attachment.html>


More information about the vc mailing list