diff --git a/BroControl/control.py b/BroControl/control.py index 96456c17..3d50f5ef 100644 --- a/BroControl/control.py +++ b/BroControl/control.py @@ -1005,48 +1005,29 @@ def df(self, nodes): return results # Returns a list of tuples of the form (node, error, vals) where 'error' is - # an error message string, or None if there was no error. 'vals' is a list - # of dicts which map tags to their values. Tags are "pid", "proc", "vsize", + # an error message string, or None if there was no error. 'vals' is a + # dict which maps tags to their values. Tags are "pid", "vsize", # "rss", "cpu", and "cmd". def get_top_output(self, nodes): results = [] - cmds = [] running = self._isrunning(nodes) # Get all the PIDs first. pids = {} - parents = {} for (node, isrunning) in running: if isrunning: - pid = node.getPID() - pids[node.name] = [pid] - parents[node.name] = pid - - cmds += [(node, "get-childs", [str(pid)])] + pids[node.name] = node.getPID() else: - results += [(node, "not running", [{}])] + results += [(node, "not running", {})] continue - if not cmds: + if not pids: return results - for (node, success, output) in self.executor.run_helper(cmds): - if not success: - results += [(node, "cannot get child pids", [{}])] - continue - - try: - pidlist = [int(line) for line in output.splitlines()] - except ValueError as err: - results += [(node, "invalid PID: %s" % err, [{}])] - continue - - pids[node.name] += pidlist - cmds = [] hosts = {} @@ -1080,41 +1061,41 @@ def get_top_output(self, nodes): # The error msg gets written to stats.log, so we only want # the first line. errmsg = output.splitlines()[0] if output else "" - results += [(node, "top failed: %s" % errmsg, [{}])] + results += [(node, "top failed: %s" % errmsg, {})] continue if not output: - results += [(node, "no output from top", [{}])] + results += [(node, "no output from top", {})] continue - # Get a list of all bro processes, where each bro process is a list - # of fields from the "top" helper. + # Get the bro process info, which is a list of fields from + # the "top" helper. + procinfo = [] try: - procs = [line.split() for line in output.splitlines() if int(line.split()[0]) in pids[node.name]] + for line in output.splitlines(): + if int(line.split()[0]) == pids[node.name]: + procinfo = line.split() + break except (IndexError, ValueError) as err: - results += [(node, "bad output from top: %s" % err, [{}])] + results += [(node, "bad output from top: %s" % err, {})] continue - if not procs: + if not procinfo: # It's possible that the process is no longer there. - results += [(node, "not running", [{}])] + results += [(node, "not running", {})] continue - vals = [] + vals = {} try: - for p in procs: - d = {} - pid = int(p[0]) - d["pid"] = pid - d["proc"] = "parent" if pid == parents[node.name] else "child" - d["vsize"] = int(float(p[1])) #May be something like 2.17684e+9 - d["rss"] = int(float(p[2])) - d["cpu"] = p[3] - d["cmd"] = " ".join(p[4:]) - vals += [d] + pid = int(procinfo[0]) + vals["pid"] = pid + vals["vsize"] = int(float(procinfo[1])) #May be something like 2.17684e+9 + vals["rss"] = int(float(procinfo[2])) + vals["cpu"] = procinfo[3] + vals["cmd"] = " ".join(procinfo[4:]) except (IndexError, ValueError) as err: - results += [(node, "unexpected top output: %s" % err, [{}])] + results += [(node, "unexpected top output: %s" % err, {})] continue results += [(node, None, vals)] @@ -1127,21 +1108,18 @@ def top(self, nodes): for (node, error, vals) in self.get_top_output(nodes): top_info = {"name": node.name, "type": node.type, - "host": node.host, "pid": None, "proc": None, + "host": node.host, "pid": None, "vsize": None, "rss": None, "cpu": None, "cmd": None, "error": None} if error: top_info["error"] = error - results.set_node_data(node, False, {"procs": [top_info]}) + results.set_node_data(node, False, {"procs": top_info}) continue - proclist = [] - for d in vals: - top_info2 = top_info.copy() - top_info2.update(d) - proclist.append(top_info2) + top_info2 = top_info.copy() + top_info2.update(vals) - results.set_node_data(node, True, {"procs": proclist}) + results.set_node_data(node, True, {"procs": top_info2}) return results diff --git a/BroControl/cron.py b/BroControl/cron.py index 577a1ee1..e9701218 100644 --- a/BroControl/cron.py +++ b/BroControl/cron.py @@ -56,11 +56,8 @@ def log_stats(self, interval): with open(self.config.statslog, "a") as out: for (node, error, vals) in top: if not error: - for proc in vals: - parentchild = proc["proc"] - for (val, key) in sorted(proc.items()): - if val != "proc": - out.write("%s %s %s %s %s\n" % (t, node, parentchild, val, key)) + for (val, key) in sorted(vals.items()): + out.write("%s %s parent %s %s\n" % (t, node, val, key)) else: out.write("%s %s error error %s\n" % (t, node, error)) diff --git a/CMakeLists.txt b/CMakeLists.txt index c0ba8f27..1e8b16cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,7 +101,6 @@ InstallShellScript(share/broctl/scripts bin/update) InstallShellScript(share/broctl/scripts/helpers bin/helpers/check-pid) InstallShellScript(share/broctl/scripts/helpers bin/helpers/df) InstallShellScript(share/broctl/scripts/helpers bin/helpers/first-line) -InstallShellScript(share/broctl/scripts/helpers bin/helpers/get-childs) InstallShellScript(share/broctl/scripts/helpers bin/helpers/start) InstallShellScript(share/broctl/scripts/helpers bin/helpers/stop) InstallShellScript(share/broctl/scripts/helpers bin/helpers/top) diff --git a/bin/broctl.in b/bin/broctl.in index ccc34671..153d7d84 100755 --- a/bin/broctl.in +++ b/bin/broctl.in @@ -263,41 +263,38 @@ class BroCtlCmdLoop(brocmd.ExitValueCmd): hostwidth = 16 data = results.get_node_data() if data: - proclist = data[0][2]["procs"] - if proclist[0]["type"] == "standalone": + procinfo = data[0][2]["procs"] + if procinfo["type"] == "standalone": # In standalone mode, we need a wider "type" column. typewidth = 10 hostwidth = 13 - lines = ["%-12s %-*s %-*s %-7s %-7s %-6s %-4s %-5s %s" % ("Name", - typewidth, "Type", hostwidth, "Host", "Pid", "Proc", "VSize", + lines = ["%-12s %-*s %-*s %-7s %-6s %-4s %-5s %s" % ("Name", + typewidth, "Type", hostwidth, "Host", "Pid", "VSize", "Rss", "Cpu", "Cmd")] for data in results.get_node_data(): - proclist = data[2]["procs"] - for top_info in proclist: - msg = ["%-12s" % top_info["name"]] - msg.append("%-*s" % (typewidth, top_info["type"])) - msg.append("%-*s" % (hostwidth, top_info["host"])) - if top_info["error"]: - msg.append("<%s>" % top_info["error"]) - else: - msg.append("%-7s" % top_info["pid"]) - msg.append("%-7s" % top_info["proc"]) - msg.append("%-6s" % util.number_unit_str(top_info["vsize"])) - msg.append("%-4s" % util.number_unit_str(top_info["rss"])) - msg.append("%3s%% " % top_info["cpu"]) - msg.append("%s" % top_info["cmd"]) + procinfo = data[2]["procs"] + msg = ["%-12s" % procinfo["name"]] + msg.append("%-*s" % (typewidth, procinfo["type"])) + msg.append("%-*s" % (hostwidth, procinfo["host"])) + if procinfo["error"]: + msg.append("<%s>" % procinfo["error"]) + else: + msg.append("%-7s" % procinfo["pid"]) + msg.append("%-6s" % util.number_unit_str(procinfo["vsize"])) + msg.append("%-4s" % util.number_unit_str(procinfo["rss"])) + msg.append("%3s%% " % procinfo["cpu"]) + msg.append("%s" % procinfo["cmd"]) - lines.append(" ".join(msg)) + lines.append(" ".join(msg)) return (results.ok, lines) def do_top(self, args): """- [] - For each of the nodes, prints the status of the two Bro - processes (parent process and child process) in a *top*-like - format, including CPU usage and memory consumption. If + For each of the nodes, prints the status of the Bro process in + a *top*-like format, including CPU usage and memory consumption. If executed interactively, the display is updated frequently until key ``q`` is pressed. If invoked non-interactively, the status is printed only once.""" diff --git a/bin/helpers/get-childs b/bin/helpers/get-childs deleted file mode 100755 index 2ca513bc..00000000 --- a/bin/helpers/get-childs +++ /dev/null @@ -1,8 +0,0 @@ -#! /usr/bin/env bash -# -# Given a PID, output the PIDs of all of its child processes. -# -# get-childs - -ps ax -o pid,ppid | awk -v pid=$1 '$2==pid {print $1}' - diff --git a/doc/broctl.rst b/doc/broctl.rst index 1a345807..8b1ba0fd 100644 --- a/doc/broctl.rst +++ b/doc/broctl.rst @@ -5,7 +5,7 @@ .. Note: This file includes further autogenerated ones. .. .. Version number is filled in automatically. -.. |version| replace:: 1.7-107 +.. |version| replace:: 1.7-122 ========== BroControl @@ -715,9 +715,8 @@ nodes if none are given. .. _top: *top* *[]* - For each of the nodes, prints the status of the two Bro - processes (parent process and child process) in a *top*-like - format, including CPU usage and memory consumption. If + For each of the nodes, prints the status of the Bro process in + a *top*-like format, including CPU usage and memory consumption. If executed interactively, the display is updated frequently until key ``q`` is pressed. If invoked non-interactively, the status is printed only once. diff --git a/testing/Baseline/command.top/all.out b/testing/Baseline/command.top/all.out index 30464d97..be13e2cc 100644 --- a/testing/Baseline/command.top/all.out +++ b/testing/Baseline/command.top/all.out @@ -1,5 +1,5 @@ -Name Type Host Pid Proc VSize Rss Cpu Cmd -manager manager localhost 37156 parent 57M 57M 2% bro -proxy-1 proxy localhost 37273 parent 56M 56M 3% bro -worker-1 worker localhost 37402 parent 56M 56M 2% bro -worker-2 worker localhost 37403 parent 56M 56M 2% bro +Name Type Host Pid VSize Rss Cpu Cmd +manager manager localhost 37156 57M 57M 2% bro +proxy-1 proxy localhost 37273 56M 56M 3% bro +worker-1 worker localhost 37402 56M 56M 2% bro +worker-2 worker localhost 37403 56M 56M 2% bro diff --git a/testing/Baseline/command.top/onenode.out b/testing/Baseline/command.top/onenode.out index 8612fab6..251557be 100644 --- a/testing/Baseline/command.top/onenode.out +++ b/testing/Baseline/command.top/onenode.out @@ -1,2 +1,2 @@ -Name Type Host Pid Proc VSize Rss Cpu Cmd -worker-1 worker localhost 37402 parent 56M 56M 2% bro +Name Type Host Pid VSize Rss Cpu Cmd +worker-1 worker localhost 37402 56M 56M 2% bro diff --git a/testing/Baseline/command.top/stopped.out b/testing/Baseline/command.top/stopped.out index 2e09a65b..d2090c91 100644 --- a/testing/Baseline/command.top/stopped.out +++ b/testing/Baseline/command.top/stopped.out @@ -1,4 +1,4 @@ -Name Type Host Pid Proc VSize Rss Cpu Cmd +Name Type Host Pid VSize Rss Cpu Cmd manager manager localhost proxy-1 proxy localhost worker-1 worker localhost diff --git a/testing/Scripts/diff-top-output b/testing/Scripts/diff-top-output index 84bdc106..4c2a10f3 100755 --- a/testing/Scripts/diff-top-output +++ b/testing/Scripts/diff-top-output @@ -10,10 +10,10 @@ awk '{ # format is expected (some fields have unpredictable length, but # we need a constant-width string of Xs). if ( $4 ~ /^[0-9]+$/ ) { $4 = "XXXXX" } # Pid - if ( $6 ~ /^[0-9]+[KMG]$/ ) { $6 = "XXX" } # VSize - if ( $7 ~ /^[0-9]+[KMG]$/ ) { $7 = "XXX" } # Rss - if ( $8 ~ /^[0-9]+%$/ ) { $8 = "XX%" } # Cpu - if ( $9 ~ /^(bro|[Pp]ython.*)$/ ) { $9 = "XXX" } # Cmd + if ( $5 ~ /^[0-9]+[KMG]$/ ) { $5 = "XXX" } # VSize + if ( $6 ~ /^[0-9]+[KMG]$/ ) { $6 = "XXX" } # Rss + if ( $7 ~ /^[0-9]+%$/ ) { $7 = "XX%" } # Cpu + if ( $8 ~ /^(bro|[Pp]ython.*)$/ ) { $8 = "XXX" } # Cmd } print