when we exit poorly, start building a tool for doing a capture
as to why. This tool is expected to be consumed directly from
grenade as well.
Change-Id: Ia1bc1c2e259587035ca7252baceec25fa464cb82
| 628 | 633 |
new file mode 100755 |
| ... | ... |
@@ -0,0 +1,88 @@ |
| 0 |
+#!/usr/bin/env python |
|
| 1 |
+# |
|
| 2 |
+# Copyright 2014 Hewlett-Packard Development Company, L.P. |
|
| 3 |
+# |
|
| 4 |
+# Licensed under the Apache License, Version 2.0 (the "License"); you may |
|
| 5 |
+# not use this file except in compliance with the License. You may obtain |
|
| 6 |
+# a copy of the License at |
|
| 7 |
+# |
|
| 8 |
+# http://www.apache.org/licenses/LICENSE-2.0 |
|
| 9 |
+# |
|
| 10 |
+# Unless required by applicable law or agreed to in writing, software |
|
| 11 |
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
|
| 12 |
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
|
| 13 |
+# License for the specific language governing permissions and limitations |
|
| 14 |
+# under the License. |
|
| 15 |
+ |
|
| 16 |
+"""Dump the state of the world for post mortem.""" |
|
| 17 |
+ |
|
| 18 |
+import argparse |
|
| 19 |
+import datetime |
|
| 20 |
+import os |
|
| 21 |
+import os.path |
|
| 22 |
+import sys |
|
| 23 |
+ |
|
| 24 |
+ |
|
| 25 |
+def get_options(): |
|
| 26 |
+ parser = argparse.ArgumentParser( |
|
| 27 |
+ description='Dump world state for debugging') |
|
| 28 |
+ parser.add_argument('-d', '--dir',
|
|
| 29 |
+ default='.', |
|
| 30 |
+ help='Output directory for worlddump') |
|
| 31 |
+ return parser.parse_args() |
|
| 32 |
+ |
|
| 33 |
+ |
|
| 34 |
+def filename(dirname): |
|
| 35 |
+ now = datetime.datetime.utcnow() |
|
| 36 |
+ return os.path.join(dirname, now.strftime("worlddump-%Y-%m-%d-%H%M%S.txt"))
|
|
| 37 |
+ |
|
| 38 |
+ |
|
| 39 |
+def warn(msg): |
|
| 40 |
+ print "WARN: %s" % msg |
|
| 41 |
+ |
|
| 42 |
+ |
|
| 43 |
+def disk_space(): |
|
| 44 |
+ # the df output |
|
| 45 |
+ print """ |
|
| 46 |
+File System Summary |
|
| 47 |
+=================== |
|
| 48 |
+""" |
|
| 49 |
+ dfraw = os.popen("df -Ph").read()
|
|
| 50 |
+ df = [s.split() for s in dfraw.splitlines()] |
|
| 51 |
+ for fs in df: |
|
| 52 |
+ try: |
|
| 53 |
+ if int(fs[4][:-1]) > 95: |
|
| 54 |
+ warn("Device %s (%s) is %s full, might be an issue" % (
|
|
| 55 |
+ fs[0], fs[5], fs[4])) |
|
| 56 |
+ except ValueError: |
|
| 57 |
+ # if it doesn't look like an int, that's fine |
|
| 58 |
+ pass |
|
| 59 |
+ |
|
| 60 |
+ print dfraw |
|
| 61 |
+ |
|
| 62 |
+ |
|
| 63 |
+def process_list(): |
|
| 64 |
+ print """ |
|
| 65 |
+Process Listing |
|
| 66 |
+=============== |
|
| 67 |
+""" |
|
| 68 |
+ psraw = os.popen("ps auxw").read()
|
|
| 69 |
+ print psraw |
|
| 70 |
+ |
|
| 71 |
+ |
|
| 72 |
+def main(): |
|
| 73 |
+ opts = get_options() |
|
| 74 |
+ fname = filename(opts.dir) |
|
| 75 |
+ print "World dumping... see %s for details" % fname |
|
| 76 |
+ sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) |
|
| 77 |
+ with open(fname, 'w') as f: |
|
| 78 |
+ os.dup2(f.fileno(), sys.stdout.fileno()) |
|
| 79 |
+ disk_space() |
|
| 80 |
+ process_list() |
|
| 81 |
+ |
|
| 82 |
+ |
|
| 83 |
+if __name__ == '__main__': |
|
| 84 |
+ try: |
|
| 85 |
+ sys.exit(main()) |
|
| 86 |
+ except KeyboardInterrupt: |
|
| 87 |
+ sys.exit(1) |