Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,6 @@ cython_debug/

# PyPI configuration file
.pypirc

# MAC
.DS_Store
12 changes: 8 additions & 4 deletions tools/config_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from general_process_profiler import general_process_profiler
from memory_process_profiler import memory_process_profiler
from file_descriptor_process_profiler import file_descriptor_process_profiler
from thread_process_profiler import thread_process_profiler

# Menu ANSI Colors
BLACK = '\033[30m'
Expand Down Expand Up @@ -101,8 +102,9 @@ def display_menu():
print("1. Create General Process Profiler")
print("2. Create Memory Process Profiler")
print("3. Create File Descriptor Profiler")
print("4. Exit")
watch_list_choice = input(f"\n{BRIGHT_CYAN}Enter your choice (1-4):{RESET}\n")
print("4. Create Thread Descriptor Profiler")
print("5. Exit")
watch_list_choice = input(f"\n{BRIGHT_CYAN}Enter your choice (1-5):{RESET}\n")
if watch_list_choice == '1':
clear_screen()
general_process_profiler()
Expand All @@ -115,10 +117,12 @@ def display_menu():
clear_screen()
file_descriptor_process_profiler()
break
clear_screen()
if watch_list_choice == '4':
clear_screen()
thread_process_profiler()
break
if watch_list_choice == '5':
break
clear_screen()
print(f"\n{BLACK}{BACKGROUND_BRIGHT_MAGENTA}Invalid choice. Please try again.{RESET}")
elif top_choice == '4':
print(f"\n{BRIGHT_GREEN}Quitting...{RESET}")
Expand Down
18 changes: 1 addition & 17 deletions tools/file_descriptor_process_profiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import os
import textwrap
import subprocess

# Base Directory
base_dir = os.path.dirname(os.path.abspath(__file__))
Expand All @@ -21,21 +20,6 @@
def clear_screen():
os.system('cls' if os.name == 'nt' else 'clear')

# Identify Process By Name Return PID
def find_pid_by_name(name):
try:
with subprocess.Popen(['pgrep', '-f', name], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) as all_pids:
output, errors = all_pids.communicate()
if errors:
print(f"Errors:\n{errors.decode()}")
return None
all_pids_array = output.strip().split("\n")
first_pid = all_pids_array[0]
return first_pid
except Exception as e:
print(f"{BLACK}{BACKGROUND_BRIGHT_MAGENTA}\nAn error occurred: {e}{RESET}")
return None

# Write configuration file to watch_list directory
def write_to_file(filename, template):
try:
Expand Down Expand Up @@ -81,7 +65,7 @@ def file_descriptor_process_profiler():

def find_pid_by_name(name):
try:
with subprocess.Popen(['pgrep', '-f', name], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) as all_pids:
with subprocess.Popen(['pgrep', '-xf', name], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) as all_pids:
output, errors = all_pids.communicate()
if errors:
logging.error(f"Errors:\\n{{errors.decode()}}")
Expand Down
18 changes: 1 addition & 17 deletions tools/general_process_profiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import os
import textwrap
import subprocess

# Menu ANSI Colors
BLACK = '\033[30m'
Expand All @@ -17,21 +16,6 @@
def clear_screen():
os.system('cls' if os.name == 'nt' else 'clear')

# Identify Process By Name Return PID
def find_pid_by_name(name):
try:
with subprocess.Popen(['pgrep', '-f', name], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) as all_pids:
output, errors = all_pids.communicate()
if errors:
print(f"Errors:\n{errors.decode()}")
return None
all_pids_array = output.strip().split("\n")
first_pid = all_pids_array[0]
return first_pid
except Exception as e:
print(f"{BLACK}{BACKGROUND_BRIGHT_MAGENTA}\nAn error occurred: {e}{RESET}")
return None

# Write configuration file to watch_list directory
def write_to_file(filename, template):
try:
Expand Down Expand Up @@ -69,7 +53,7 @@ def general_process_profiler():

def find_pid_by_name(name):
try:
with subprocess.Popen(['pgrep', '-f', name], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) as all_pids:
with subprocess.Popen(['pgrep', '-xf', name], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) as all_pids:
output, errors = all_pids.communicate()
if errors:
logging.error(f"Errors:\\n{{errors.decode()}}")
Expand Down
18 changes: 1 addition & 17 deletions tools/memory_process_profiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import os
import textwrap
import subprocess

# Base Directory
base_dir = os.path.dirname(os.path.abspath(__file__))
Expand All @@ -21,21 +20,6 @@
def clear_screen():
os.system('cls' if os.name == 'nt' else 'clear')

# Identify Process By Name Return PID
def find_pid_by_name(name):
try:
with subprocess.Popen(['pgrep', '-f', name], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) as all_pids:
output, errors = all_pids.communicate()
if errors:
print(f"Errors:\n{errors.decode()}")
return None
all_pids_array = output.strip().split("\n")
first_pid = all_pids_array[0]
return first_pid
except Exception as e:
print(f"{BLACK}{BACKGROUND_BRIGHT_MAGENTA}\nAn error occurred: {e}{RESET}")
return None

# Write configuration file to watch_list directory
def write_to_file(filename, template):
try:
Expand Down Expand Up @@ -81,7 +65,7 @@ def memory_process_profiler():

def find_pid_by_name(name):
try:
with subprocess.Popen(['pgrep', '-f', name], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) as all_pids:
with subprocess.Popen(['pgrep', '-xf', name], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) as all_pids:
output, errors = all_pids.communicate()
if errors:
logging.error(f"Errors:\\n{{errors.decode()}}")
Expand Down
115 changes: 115 additions & 0 deletions tools/thread_process_profiler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#!/usr/bin/env python3

import os
import textwrap

# Base Directory
base_dir = os.path.dirname(os.path.abspath(__file__))
os.chdir(base_dir)

# Menu ANSI Colors
BLACK = '\033[30m'
GREEN = '\033[32m'
BRIGHT_GREEN = '\033[92m'
BRIGHT_CYAN = '\033[96m'
BRIGHT_YELLOW = '\033[93m'
BACKGROUND_BRIGHT_MAGENTA = '\033[105m'
RESET = '\033[0m'

# Reset Screen
def clear_screen():
os.system('cls' if os.name == 'nt' else 'clear')

# Write configuration file to watch_list directory
def write_to_file(filename, template):
try:
with open(os.path.join(os.pardir, "watch_list", filename), 'w', encoding="utf-8") as file:
file.write(template)
clear_screen()
print(f"\n{GREEN}'{filename}' configuration created.{RESET}")
except Exception as e:
print(f"{BLACK}{BACKGROUND_BRIGHT_MAGENTA}\nAn error occurred: {e}{RESET}")

# Thread Process Profiler Menu
def thread_process_profiler():
print(f"\n{BRIGHT_GREEN}THREAD PROCESS PROFILER SETTINGS:{RESET}")
filename = input(f"\n{BRIGHT_CYAN}Enter the name of the configuration file:{RESET}\n")
sanitized_filename = filename.replace(".", "-")
process_name = input(f"\n{BRIGHT_CYAN}Enter the process name to monitor {GREEN}(use name in ps ouput){RESET}:{RESET}\n")
while True:
try:
interval = int(input(f"\n{BRIGHT_CYAN}Enter the monitoring interval {GREEN}(in seconds){RESET}:{RESET}\n"))
break
except ValueError:
print(f"{BLACK}{BACKGROUND_BRIGHT_MAGENTA}\nInvalid input. Please enter a number of seconds.{RESET}")
while True:
try:
thread_threshold = int(input(f"\n{BRIGHT_CYAN}Enter the thread threshold of the process:{RESET}\n"))
break
except ValueError:
print(f"{BLACK}{BACKGROUND_BRIGHT_MAGENTA}\nInvalid input. Please enter the number of threads.{RESET}")
action = input(f"\n{BRIGHT_CYAN}Enter the action to take upon the thread threshold being met {GREEN}(leave blank for no action){RESET}:{RESET}\n") or "echo"

template = f"""
#Thread Process Profiler
import os
import sys
import time
import logging
import threading
import psutil
import subprocess

thread_process_profiler_file = (f"{{str(os.getcwd())}}/logs/{sanitized_filename}-thrd-profiler.log")
error_file = (f"{{str(os.getcwd())}}/logs/error.log")

def find_pid_by_name(name):
try:
with subprocess.Popen(['pgrep', '-xf', name], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) as all_pids:
output, errors = all_pids.communicate()
if errors:
logging.error(f"Errors:\\n{{errors.decode()}}")
return None
all_pids_array = output.strip().split("\\n")
first_pid = all_pids_array[0]
return first_pid
except Exception as e:
logging.error("An error occurred in Process Watch: %s", e, exc_info=True)
raise sys.exit(1)
return None

def find_thread_usage_by_pid(pid):
process = psutil.Process(pid)
thread_usage_info = process.num_threads()
if thread_usage_info:
return thread_usage_info
else:
return("0.0")

def monitor():
while True:
try:
process_pid = find_pid_by_name('{process_name}')
process_thread_set = {{find_thread_usage_by_pid(int(find_pid_by_name('{process_name}')))}}
process_thread = int(process_thread_set.pop())
if int(process_thread) >= {thread_threshold}:
with open(thread_process_profiler_file, "a", encoding="utf-8") as f:
f.write(f"{{time.ctime()}} - Thread Alert - Above Threshold {thread_threshold} - Process: [ {process_name} ], PID: {{int(find_pid_by_name('{process_name}'))}}, Threads: {{find_thread_usage_by_pid(int(find_pid_by_name('{process_name}')))}}\\n")
process_action = subprocess.run(['{action}'], capture_output=True, text=True)
time.sleep(5)
f.write(f"{{time.ctime()}} - Thread Alert - After Remediation - Action Taken: [ {action} ], Process: [ {process_name} ], PID: {{int(find_pid_by_name('{process_name}'))}}, Threads: {{find_thread_usage_by_pid(int(find_pid_by_name('{process_name}')))}}\\n")
time.sleep({interval})
except Exception as e:
print(f"An error occurred in Process Watch configuration file {sanitized_filename}: {{e}}")
with open(error_file, "a", encoding="utf-8") as file:
file.write(str(e) + (f" in {sanitized_filename}") + "\\n")
raise sys.exit(1)

def worker():
monitor_thread = threading.Thread(target=monitor)
monitor_thread.start()

worker()
"""
# Write the template into a config
write_to_file(os.path.abspath(f"../watch_list/{sanitized_filename}_thrd.py"), textwrap.dedent(template))