/opt/dedrads
NameSizeModeActions
account_review/-0555rm
check_software_mods/-0555rm
cms_tools/-0555rm
etc/-0555rm
extras/-0555rm
mailparse/-0555rm
mysql/-0555rm
nlp_scripts/-0555rm
oldrads/-0555rm
perl/-0555rm
provision/-0555rm
python/-0555rm
suspended/-0555rm
__pycache__/-0555rm
account-review7990555editdlrm
allfw62590555editdlrm
alp.py165530555editdlrm
autossl_sync62670555editdlrm
check_apache92050555editdlrm
check_bandwidth45460555editdlrm
check_boxtrapper16840555editdlrm
check_cpu122120555editdlrm
check_crons18270555editdlrm
check_dcpumon19730555editdlrm
check_dns18270555editdlrm
check_domlogs610555editdlrm
check_exim37310555editdlrm
check_hacks226040555editdlrm
check_imap52490555editdlrm
check_io66350555editdlrm
check_max_children163410555editdlrm
check_mem16600555editdlrm
check_misc15100555editdlrm
check_pacct52010555editdlrm
check_php43440555editdlrm
check_pop322950555editdlrm
check_prov.py47140555editdlrm
check_server6960555editdlrm
check_size4900555editdlrm
check_software98490555editdlrm
check_spamd24260555editdlrm
check_traffic19330555editdlrm
check_user18870555editdlrm
clean_exim.py63900555editdlrm
clusterfix53430555editdlrm
cmspass.py39700555editdlrm
cms_check.py98250555editdlrm
cms_counter.py367340555editdlrm
cms_creds7130555editdlrm
cms_dumpdb44850555editdlrm
cms_pw14160555editdlrm
cpanel-api70400555editdlrm
cpanel_postgres_manager.py290040555editdlrm
cpmerge46310555editdlrm
cpumon21950555editdlrm
dcpumon.pl12390555editdlrm
dedcheck181270555editdlrm
dns-sync143860555editdlrm
docroot.py44250555editdlrm
du-tree74500555editdlrm
envinfo.py66330555editdlrm
exclude_rbl.py52490555editdlrm
extract-vhost26910555editdlrm
filescan35660555editdlrm
find_warez14600555editdlrm
first_setup.py191200555editdlrm
fixwpcron.py48220555editdlrm
fix_dns_cluster3530555editdlrm
goaccess12177200555editdlrm
hostsfilemods44670555editdlrm
imap_io23230555editdlrm
innodb_converter.py93430555editdlrm
killall9115300555editdlrm
killdns9410555editdlrm
lastcommcache.sh13740555editdlrm
legal_lock_down.sh74500555editdlrm
lil-cpanel520020555editdlrm
listacct45750555editdlrm
mailscan45440555editdlrm
mail_sources.py74070555editdlrm
megaclisas-status386640555editdlrm
migrate2central.sh144180555editdlrm
modify-account406310555editdlrm
modsec_disable.py114610555editdlrm
monarxctl89120555editdlrm
msp.pl277140555editdlrm
mysql_dstat4740555editdlrm
mysql_selector.py731020555editdlrm
nlp45820555editdlrm
procscrape18630555editdlrm
quarantine110830555editdlrm
radsfunctions.sh8630555editdlrm
recent-cp161480555editdlrm
remote_dump183470555editdlrm
reset_cpanel32050555editdlrm
server-load21920555editdlrm
show-conns201050555editdlrm
show-conns-adv.py546670555editdlrm
sparta.py3824980555editdlrm
sqltop271290555editdlrm
telcheck24110555editdlrm
temprootreset1860555editdlrm
unsuspend_user13070555editdlrm
unsusprunner.sh18400555editdlrm
updatednsadmin5260555editdlrm
update_spf149720555editdlrm
upgrade-check92160555editdlrm
vhost_data.py62210555editdlrm
wp-xray.sh858160555editdlrm
Edit: /opt/dedrads/check_pacct (5201B)
#!/usr/lib/rads/venv/bin/python3 import argparse import re import subprocess from collections import defaultdict from datetime import datetime, timedelta from prettytable import PrettyTable from rads import is_cpuser, get_plan def parse_args(): parser = argparse.ArgumentParser( description="Process pacct files and total CPU time for cPanel users." ) parser.add_argument( "--days", type=int, default=10, help="Number of pacct files to process (default: 10)", ) parser.add_argument( "-l", "--limit-users", type=int, default=5, help="Number users to display (default: 5)", ) parser.add_argument( "--date", type=str, default=datetime.today().strftime("%Y-%m-%d"), help="Start date in format YYYY-MM-DD (default: today)", ) return parser.parse_args() def get_pacct_files(start_date: str, days: int): """ Generate a list of process accounting (pacct) file paths for a given number of days. Args: start_date (str): The start date in 'YYYY-MM-DD' format. days (int): The number of days of pacct files to retrieve. Returns: list[str]: A list of file paths to the compressed pacct logs in `/var/account/`, named in the format `pacct-YYYYMMDD.gz`. Raises: ValueError: If `start_date` is not in the correct 'YYYY-MM-DD' format. Notes: - If `start_date` is today, the function returns files from the previous `days` days. - Otherwise, it returns files counting backward from the given `start_date`. """ try: start = datetime.strptime(start_date, "%Y-%m-%d") except ValueError as exc: raise ValueError("Date must be in YYYY-MM-DD format.") from exc today = datetime.today().date() start_date_obj = start.date() files = [] if start_date_obj == today: for i in range(1, days + 1): day = today - timedelta(days=i) files.append(f"/var/account/pacct-{day.strftime('%Y%m%d')}.gz") else: for i in range(days): day = start_date_obj - timedelta(days=i) files.append(f"/var/account/pacct-{day.strftime('%Y%m%d')}.gz") return files def process_pacct_file(file_path): """ Run 'zcat' on a compressed pacct file and pipe the output to 'sa -cmi -'. Returns the output lines from the 'sa' command as a list of strings. """ try: with subprocess.Popen( ["zcat", file_path], stdout=subprocess.PIPE ) as zcat_proc: with subprocess.Popen( ["sa", "-cmi", "-"], stdin=zcat_proc.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, ) as sa_proc: zcat_proc.stdout.close() stdout, stderr = sa_proc.communicate() if sa_proc.returncode != 0: print("Error running sa:", stderr) return [] return stdout.splitlines() except Exception as e: print(f"Failed to process {file_path}: {str(e)}") return [] def main(): args = parse_args() pacct_files = get_pacct_files(args.date, args.days) sa_cp_data = defaultdict(float) sa_proc_data = defaultdict(int) sa_top_user = defaultdict(int) for file_path in pacct_files: pacct_data = process_pacct_file(file_path) try: i = 1 for line in pacct_data: columns = re.split(r"\s+", line.strip()) if is_cpuser(columns[0]): try: username = columns[0] num_proc = int(columns[1]) cpu_time = float(columns[5].replace("cp", "")) sa_cp_data[username] += cpu_time sa_proc_data[username] += num_proc if i <= args.limit_users: sa_top_user[username] += 1 i += 1 except ValueError: continue except Exception as e: print(f"Failed to process {file_path}: {str(e)}") top_users = sorted(sa_cp_data.items(), key=lambda x: x[1], reverse=True) table = PrettyTable() table.field_names = [ "Username", "Total CPU", "Average CPU/day", "Total Procs", "Average Procs/day", f"Days in top {args.limit_users}", "Plan", ] num_days = len(pacct_files) for ( username, total_cpu_time, ) in top_users[: args.limit_users]: table.add_row( [ username, f"{total_cpu_time:.2f}cp", f"{(total_cpu_time / num_days):.2f}cp", f"{sa_proc_data[username]}", f"{(sa_proc_data[username] / num_days):.2f}", f"{sa_top_user[username]}/{num_days}", get_plan(username), ] ) print(table) if __name__ == "__main__": main()