diff --git a/tools/scripts/env_checker.py b/tools/scripts/env_checker.py new file mode 100644 index 000000000..ba3e35766 --- /dev/null +++ b/tools/scripts/env_checker.py @@ -0,0 +1,310 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import os +import sys +import time +import socket +import resource +import traceback +import psutil +import argparse +from collections import defaultdict + +if os.name == 'posix' and sys.version_info[0] < 3: + from subprocess32 import Popen, PIPE + reload(sys) + sys.setdefaultencoding('utf8') +else: + from subprocess import Popen, PIPE + +__version__ = 0.1 + +K = 1024 +M = 1024 ** 2 +G = 1024 ** 3 + +def execute_command(command, env=None, timeout=None): + try: + p = Popen(command, env=env, shell=True, stdout=PIPE, stderr=PIPE) + output, error = p.communicate(timeout=timeout) + code = p.returncode + output = output.decode(errors='replace') + error = error.decode(errors='replace') + except Exception as e: + output = '' + error = traeback.format_exc() + code = 255 + return code, output, error + +class EnvChecker(object): + def __init__(self): + self.args = None + self.parser = argparse.ArgumentParser( + "env_checker", + usage = """ + # default usage without any option will print basic environment info + python env_checker.py + + # for detailed info, specify one or more option + python env_checker.py [options] + """, + description = "check environment info on host" + ) + + self.parser.add_argument('-v', '--version', + action='version', + version='{prog}-{version}'.format(prog=self.parser.prog, version=__version__)) + + self.parser.add_argument("-a", "--all", action='store_true', default=False, help='show all info') + self.parser.add_argument("-u", "--ulimit", action='store_true', default=False, help='show ulimit info') + self.parser.add_argument("-i", "--io", action='store_true', default=False, help='show io throughput info') + self.parser.add_argument("-f", "--fd", action='store_true', default=False, help='show fd usage info') + self.parser.add_argument("-b", "--block", action='store_true', default=False, help='show bad block info') + self.parser.add_argument("-g", "--gcc", action='store_true', default=False, help='show gcc version info') + + def parse_args(self): + self.args = self.parser.parse_args() + + def get_cpu_info(self): + cpu_info_dict = dict() + cpu_info_dict["count"] = "{0} cores".format(psutil.cpu_count()) + cpu_info_dict["frequency"] = "{0} MHz".format(psutil.cpu_freq().max) + cpu_info_dict["current_usage_percent"] = "{0}".format(psutil.cpu_percent()) + return cpu_info_dict + + def get_memory_info(self): + memory_info = psutil.virtual_memory() + memory_info_dict = dict() + memory_info_dict["memory_total"] = "{0} GB".format(memory_info.total / G) + memory_info_dict["memory_used"] = "{0} GB".format(memory_info.used / G) + memory_info_dict["memory_free"] = "{0} GB".format(memory_info.free / G) + memory_info_dict["memory_cached"] = "{0} GB".format(memory_info.cached / G) + memory_info_dict["memory_available"] = "{0} GB".format(memory_info.available / G) + memory_info_dict["page_size"] = "{0} KB".format(resource.getpagesize() / K) + return memory_info_dict + + def get_network_info(self): + net_info_dict = defaultdict(lambda: dict()) + net_stats = psutil.net_if_stats() + for dev, stat in net_stats.items(): + if stat.isup: + net_info_dict["bandwidth"] = "{0} Mb".format(stat.speed) + net_addrs = psutil.net_if_addrs() + for dev in net_addrs.keys(): + addrs = net_addrs[dev] + for addr_info in addrs: + # AddressFamily.AF_INET + if addr_info.family == socket.AF_INET: + net_info_dict[dev]["IPv4 address"] = addr_info.address + # AddressFamily.AF_INET6 + if addr_info.family == socket.AF_INET6: + net_info_dict[dev]["IPv6 address"] = addr_info.address + return net_info_dict + + def get_disk_info(self): + disk_info_list = list() + all_disks = psutil.disk_partitions() + for disk in all_disks: + disk_info = dict() + disk_usage = psutil.disk_usage(disk.mountpoint) + disk_info["device"] = disk.device + disk_info["mountpoint"] = disk.mountpoint + disk_info["filesystem"] = disk.fstype + disk_usage_dict = dict() + disk_usage_dict["total"] = "{0} GB".format(disk_usage.total / G) + disk_usage_dict["free"] = "{0} GB".format(disk_usage.free / G) + disk_usage_dict["used"] = "{0} GB".format(disk_usage.used / G) + disk_usage_dict["used_percent"] = disk_usage.percent + disk_info["usage"] = disk_usage_dict + disk_info_list.append(disk_info) + return disk_info_list + + def get_os_info(self): + os_info = os.uname() + os_info_dict = dict() + os_info_dict["sysname"] = os_info[0] + os_info_dict["release"] = os_info[2] + os_info_dict["machine"] = os_info[4] + return os_info_dict + + def get_cpu_usage(self): + last_worktime, last_idletime + fd = open("/proc/stat", "r") + line = "" + while not "cpu " in line: line = f.readline() + f.close() + spl = line.split(" ") + worktime = int(spl[2]) + int(spl[3]) + int(spl[4]) + idletime = int(spl[5]) + dworktime = (worktime - last_worktime) + didletime = (idletime - last_idletime) + rate = float(dworktime) / (didletime + dworktime) + last_worktime = worktime + last_idletime = idletime + if (last_worktime == 0): return 0 + return rate + + def get_bad_blocks(self): + disk_badblocks = dict() + all_disks = psutil.disk_partitions() + for disk in all_disks: + cmd = "badblocks -b 4096 -c 128 {0}".format(disk.device) + status, output, error = execute_command(cmd) + if status != 0: + print("get bad blocks for device {0} failed: {1}".format(disk.device, error)) + else: + disk_badblocks[disk.device] = output + return disk_badblocks + + def show_fd_info(self): + cmd = "lsof -n | awk '{print $1\" \"$2}' | sort | uniq -c | sort -nr" + status, output, error = execute_command(cmd) + if status != 0: + print("get fd info failed: {0}".format(error)) + else: + total_count = 0 + limit = 10 + idx = 0 + results = output.split("\n") + for result in results: + result_parts = result.strip().split() + if len(result_parts) == 0 or not (result_parts[0].isdigit() and result_parts[-1].isdigit()): + continue + else: + total_count += int(result_parts[-1]) + if idx < limit: + print("process: {0}, Pid: {1}, fd count: {2}".format(result_parts[1], result_parts[-1], result_parts[0])) + idx += 1 + print("total opened fds: {0}".format(total_count)) + + def get_io_throuput_info(self): + disk_throughput = defaultdict(lambda: dict()) + all_disks = psutil.disk_partitions() + for disk in all_disks: + cmdBufferedWrite = "dd if=/dev/zero of={0}/test_file bs=4k count=100000".format(disk.mountpoint) + cmdDirectWrite = "dd if=/dev/zero of={0}/test_file bs=4k count=100000 oflag=dsync".format(disk.mountpoint) + cmdBufferedRead = "dd of=/dev/null if={0}/test_file bs=4k".format(disk.mountpoint) + cmdDirectRead = "dd of=/dev/null if={0}/test_file bs=4k iflag=dsync".format(disk.mountpoint) + t_start = time.time() + status, output, error = execute_command(cmdBufferedWrite) + t_end = time.time() + elapsed_time = t_end - t_start + if status != 0: + print("get throughput for device {0} failed: {1}".format(disk.device, error)) + else: + disk_throughput[disk.device]["bufferdwrite"] = "{0}M/s".format(400 / elapsed_time) + + t_start = time.time() + status, output, error = execute_command(cmdDirectWrite) + t_end = time.time() + elapsed_time = t_end - t_start + if status != 0: + print("get throughput for device {0} failed: {1}".format(disk.device, error)) + else: + disk_throughput[disk.device]["directwrite"] = "{0}M/s".format(400 / elapsed_time) + + t_start = time.time() + status, output, error = execute_command(cmdBufferedRead) + t_end = time.time() + elapsed_time = t_end - t_start + if status != 0: + print("get throughput for device {0} failed: {1}".format(disk.device, error)) + else: + disk_throughput[disk.device]["bufferdread"] = "{0}M/s".format(400 / elapsed_time) + + t_start = time.time() + status, output, error = execute_command(cmdDirectRead) + t_end = time.time() + elapsed_time = t_end - t_start + if status != 0: + print("get throughput for device {0} failed: {1}".format(disk.device, error)) + else: + disk_throughput[disk.device]["directread"] = "{0}M/s".format(400 / elapsed_time) + return disk_throughput + + def get_gcc_version(self): + cmd = "gcc -v 2>&1" + status, output, error = execute_command(cmd) + if status != 0: + print("get gcc version failed: {0}".format(error)) + else: + return output + + def get_ulimit(self): + cmd = "ulimit -a" + status, output, error = execute_command(cmd) + if status != 0: + print("get gcc version failed: {0}".format(error)) + else: + return output + + def print_system_info(self): + print('==================== os info ====================') + print_dict(self.get_os_info()) + print("") + + print('==================== cpu info ===================') + cpu_info_dict = self.get_cpu_info() + print_dict(cpu_info_dict) + print("") + + print('==================== mem info ===================') + memory_info_dict = self.get_memory_info() + print_dict(memory_info_dict) + print("") + + print('==================== net info ===================') + net_info_dict = self.get_network_info() + print_dict(net_info_dict) + print("") + + print('=================== disk info ===================') + disk_info_list = self.get_disk_info() + for disk_info_dict in disk_info_list: + print_dict(disk_info_dict) + print("") + print("") + + if self.args.gcc or self.args.all: + print('==================== gcc info ===================') + print(self.get_gcc_version()) + print("") + + if self.args.ulimit or self.args.all: + print('================== ulimit info ==================') + ulimit_info = self.get_ulimit() + print(ulimit_info) + print("") + + if self.args.io or self.args.all: + print('==================== io info ====================') + io_throuput_dict = self.get_io_throuput_info() + print_dict(io_throuput_dict) + print("") + + if self.args.fd or self.args.all: + print('==================== fd info ====================') + self.show_fd_info() + print("") + + if self.args.block or self.args.all: + print('================= badblock info =================') + badblock_info_dict = self.get_bad_blocks() + print_dict(badblock_info_dict) + print("") + +def print_dict(d, indent=0): + if len(d) == 0: + print("no result") + for k, v in d.items(): + if isinstance(v, dict): + print(k) + print_dict(v, indent=indent + 2) + else: + print("{0}{1}: {2}".format(" " * indent, k, v)) + +if '__main__' == __name__: + env_checker = EnvChecker() + env_checker.parse_args() + env_checker.print_system_info() diff --git a/tools/scripts/requirements.txt b/tools/scripts/requirements.txt new file mode 100644 index 000000000..e7ab8f585 --- /dev/null +++ b/tools/scripts/requirements.txt @@ -0,0 +1,2 @@ +psutil==5.8.0 +subprocess32==3.5.4 diff --git a/tools/scripts/requirements3.txt b/tools/scripts/requirements3.txt new file mode 100644 index 000000000..e2d08e70c --- /dev/null +++ b/tools/scripts/requirements3.txt @@ -0,0 +1 @@ +psutil==5.8.0