Mini Shell

Direktori : /proc/self/root/opt/sharedrads/oldrads/extras/
Upload File :
Current File : //proc/self/root/opt/sharedrads/oldrads/extras/apache-top.py

#!/opt/imh-python/bin/python3
#
# apache-top
# Copyright (C) 2006  Carles Amigó
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#

from html.parser import HTMLParser
import operator
import sys
import urllib.request, urllib.parse, urllib.error
import curses
import getopt
import time


class ApacheStatusParser(HTMLParser):
    """
    Clase que parseja la sortida del handler server-status de apache
    """

    performance_info = 2
    scoreboard = 3
    proceses = 4

    status = 0

    store = False  # defineix si el contingut s'ha de guardar o no
    append = False  # defineix si els seguents caracters s'han d'afegir o posar en un altre camp

    performance_info_data = []
    scoreboard_data = []
    proceses_data = []

    def __init__(self):
        HTMLParser.__init__(self)
        self.performance_info_data = []
        self.scoreboard_data = []
        self.proceses_data = []
        self.store = False
        self.append = False
        self.status = 1

    def handle_starttag(self, tag, attrs):
        if tag == "b":
            return
        self.store = False
        if self.status <= self.performance_info:
            if tag == "dt":
                self.store = True
        elif self.status <= self.scoreboard:
            if tag == "pre":
                self.store = True
        elif self.status <= self.proceses:
            if tag == "tr":
                # if len(self.proceses_data[-1]) != 0:
                if len(self.proceses_data) == 0:
                    self.proceses_data.append([])
                else:
                    if len(self.proceses_data[-1]) > 0:
                        self.proceses_data.append([])

            elif tag == "td":
                self.store = True

    def handle_endtag(self, tag):
        if tag == "b":
            return
        self.store = False
        self.append = False
        if self.status <= self.performance_info and tag == "dl":
            self.status += 1
        elif self.status <= self.scoreboard and tag == "pre":
            self.status += 1
        elif self.status <= self.proceses and tag == "table":
            self.status += 1

    def handle_data(self, data):
        if self.store and data != "\n":
            if self.status <= self.performance_info:
                self.performance_info_data.append(data.replace("\n", ""))
            elif self.status <= self.scoreboard:
                self.scoreboard_data.append(data.replace("\n", ""))
            elif self.status <= self.proceses:
                if not self.append:
                    self.proceses_data[-1].append(data.replace("\n", ""))
                else:
                    self.proceses_data[-1][-1] += data.replace("\n", "")

    def handle_charref(self, ref):
        self.append = True
        self.handle_data("&#%s;" % ref)

    def handle_entityref(self, ref):
        self.append = True
        self.handle_data("&%s;" % ref)

    def eval_data(self):
        for process in self.proceses_data:
            # PID
            try:
                process[1] = eval(process[1])
            except Exception:
                process[1] = 0
            # Acc Number of accesses this connection / this child / this slot
            process[2] = process[2].split("/")
            process[2][0] = eval(process[2][0])
            process[2][1] = eval(process[2][1])
            process[2][2] = eval(process[2][2])
            # M Mode of operation
            # pass
            # CPU CPU usage, number of seconds
            process[4] = eval(process[4])
            # SS Seconds since beginning of most recent request
            process[5] = eval(process[5])
            # Req Milliseconds required to process most recent request
            process[6] = eval(process[6])
            # Conn Kilobytes transferred this connection
            process[7] = eval(process[7])
            # Child Megabytes transferred this child
            process[8] = eval(process[8])
            # Slot Total megabytes transferred this slot
            process[9] = eval(process[9])


def usage(exit=1):
    print(main.__doc__)
    sys.exit(exit)


def print_screen(screen, url):

    screen = stdscr.subwin(0, 0)
    screen.nodelay(1)

    end = False
    sort = 5
    message = ""
    reverse = True
    show_only_active = True
    c = ""

    while not end:
        try:
            data = ApacheStatusParser()
            statusdata = urllib.request.urlopen(url).read()
            data.feed(statusdata)
            data.eval_data()
            # width = curses.tigetnum('cols') or 80
            # height = curses.tigetnum('lines') or 24
            (height, width) = screen.getmaxyx()
            screen.clear()

            # imprimim el header
            screen.addstr(
                0,
                0,
                data.performance_info_data[5]
                .replace("Server uptime: ", "Uptime:")
                .replace(" days", "d")
                .replace(" day", "d")
                .replace(" hours", "h")
                .replace(" hour", "h")
                .replace(" minutes", "m")
                .replace(" minute", "m")
                .replace(" seconds", "s")
                .replace("second", "s")
                + ", "
                + data.performance_info_data[3],
            )
            screen.addstr(1, 0, data.performance_info_data[7])
            screen.addstr(
                2,
                0,
                data.performance_info_data[8]
                .replace("request", "req")
                .replace("second", "sec")
                + ", Active/Idle: "
                + data.performance_info_data[9].split()[0]
                + "/"
                + data.performance_info_data[9].split()[5],
            )

            # imprimim el scoreboard
            for num in range(0, len(data.scoreboard_data[0]), width):
                screen.addstr(
                    4 + num / width,
                    0,
                    data.scoreboard_data[0][num : num + width],
                )

            if len(message) > 0:
                screen.addstr(
                    5 + num / width,
                    0,
                    message,
                    curses.A_BOLD | curses.A_REVERSE,
                )
                message = ""

            print_proceses(
                6 + num / width,
                0,
                screen,
                data.proceses_data,
                columns=[1, 3, 5, 4, 11, 10, 12],
                sort=sort,
                reverse=reverse,
                width=width,
                show_only_active=show_only_active,
            )

            # screen.hline(2, 1, curses.ACS_HLINE, 77)
            screen.refresh()
            time.sleep(2)

            try:
                c = screen.getkey()
            except Exception:
                pass

            if c == "q":
                # sortir
                end = True
            elif c == "P":
                # ordenar per PID
                sort = 1
                message = "Sort by PID"
            elif c == "C":
                # ordenar per cpu
                sort = 4
                message = "Sort by CPU usage"
            elif c == "S":
                # ordenar per SS"
                sort = 5
                message = (
                    "Sort by Seconds since beginning of most recent request"
                )
            elif c == "V":
                # ordenar per vhost
                sort = 11
                message = "Sort by VirtualHost"
            elif c == "M":
                # ordenar per Mode of operation
                sort = 3
                message = "Sort by Mode of operation"
            elif c == "R":
                # ordenar per request
                sort = 12
                message = "Sort by Request"
            elif c == "I":
                # ordenar per ip
                sort = 10
                message = "Sort by IP"
            elif c == "a":
                # mostra els actius
                if show_only_active:
                    show_only_active = False
                    message = "Show all processes"
                else:
                    show_only_active = True
                    message = "Show only active processes"
            elif c == "r":
                # cambiar l'ordre
                if reverse:
                    reverse = False
                    message = "Reversed sorting"
                else:
                    reverse = True
                    message = "Normal sorting"
            c = ""

        except IndexError:
            raise
        except Exception:
            pass


def print_proceses(
    y, x, screen, proceses, columns, sort, reverse, width, show_only_active=True
):
    header = "PID   M SS     CPU  VHost           IP              Request"
    screen.addstr(y, x, header + " " * (width - len(header)), curses.A_REVERSE)

    n = 1

    if sort != None:
        for process in sorted(
            proceses, key=operator.itemgetter(sort), reverse=reverse
        ):
            n += print_process(
                y + n, x, screen, process, columns, show_only_active, width
            )
    else:
        for process in proceses:
            n += print_process(
                y + n, x, screen, process, columns, show_only_active, width
            )
    try:
        screen.addstr(y + n, x, " " * width)
    except Exception:
        pass


def print_process(y, x, screen, process, columns, show_only_active, width):
    if not show_only_active or (process[3] != "." and process[3] != "_"):
        try:
            screen.addstr(y, x, " " * width)
            n = x
            screen.addstr(y, n, str(process[columns[0]]))  # SS
            n = n + 6
            screen.addstr(y, n, process[columns[1]])  # M
            n = n + 2
            screen.addstr(y, n, str(process[columns[2]]))  # PID
            n = n + 6

            cpu = str(process[columns[3]])
            if len(cpu.split('.')[1]) < 2:
                cpu = cpu + "0" * (2 - len(cpu.split('.')[1]))
            screen.addstr(y, n + (4 - len(cpu)), cpu)  # CPU

            n = n + 6
            screen.addstr(y, n, str(process[columns[4]]))  # VHOST

            n = n + 16
            screen.addstr(y, n, str(process[columns[5]]))  # IP

            n = n + 15
            screen.addstr(y, n, " " + str(process[columns[6]]))  # REQUEST
            return 1
        except Exception:
            return 1
    else:
        return 0


def main(url, stdscr):
    """Shows the actual status of the Apache web server using the server-status
    url. It needs the ExtendedStatus flag

        Usage: apache-top -u url
            -u url    Url where apache-status is located
                      Example: apache-top.py -u http://www.domain.com/server-status


        Interactive keys:
            q       Exit
            P       Sort by PID
            C       Sort by CPU usage
            S       Sort by Seconds since beginning of most recent request
            V       Sort by VirtualHost
            M       Sort by Mode of operation
            R       Sort by Request
            I       Sort by Ip
            a       Switch between show all processes and show only active processes (default)
            r       Reverse sort

    """

    cols = {
        "srv": 0,
        "pid": 1,
        "acc": 2,
        "m": 3,
        "cpu": 4,
        "ss": 5,
        "req": 6,
        "conn": 7,
        "child": 8,
        "slot": 9,
        "client": 10,
        "vhost": 11,
        "request": 12,
    }

    try:
        print_screen(stdscr, url)
    except Exception:
        raise


if __name__ == "__main__":

    url = None

    try:
        opt_list = getopt.getopt(sys.argv[1:], "u:h")
    except Exception:
        usage()

    for opt in opt_list[0]:
        if opt[0] == "-h":
            usage(0)
        elif opt[0] == "-u":
            url = opt[1]
        else:
            usage

    if url == None:
        print(
            "*** Please wait...  Loading default IMH local WHM server status page.\n"
        )
    url = "http://127.0.0.1/whm-server-status"

    try:
        # Initialize curses
        stdscr = curses.initscr()
        # Turn off echoing of keys, and enter cbreak mode,
        # where no buffering is performed on keyboard input
        curses.noecho()
        curses.cbreak()
        curses.curs_set(0)
        # In keypad mode, escape sequences for special keys
        # (like the cursor keys) will be interpreted and
        # a special value like curses.KEY_LEFT will be returned
        stdscr.keypad(1)
        try:
            main(url, stdscr)  # Enter the main loop
        except Exception:
            raise
        # Set everything back to normal
        curses.curs_set(1)
        stdscr.keypad(0)
        curses.echo()
        curses.nocbreak()
        curses.endwin()  # Terminate curses

    except Exception:
        # In event of error, restore terminal to sane state.
        stdscr.keypad(0)
        curses.echo()
        curses.nocbreak()
        curses.endwin()
        # traceback.print_exc()           # Print the exception
        print(
            "ERROR parsing the data. Please, make sure you are alowed to read the server-status page and you have ExtendedStatus flag activated"
        )

Zerion Mini Shell 1.0