/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/innodb_converter.py (9343B)
#!/usr/lib/rads/venv/bin/python3 """Converts all MyISAM tables to InnoDB""" # import list type from pathlib import Path import os import sys from argparse import ArgumentParser import logging import pymysql # check for root if os.getuid() != 0: sys.exit('This script must be run as root') logger = logging.getLogger('innodb_convert.py') # log to /var/log/innodb_convert.log logger.setLevel(logging.DEBUG) # print info and above to log file and console console_handler = logging.StreamHandler(sys.stderr) console_handler.setLevel(logging.INFO) logger.addHandler(console_handler) file_handler = logging.FileHandler('/var/log/innodb_convert.log') file_handler.setLevel(logging.DEBUG) logger.addHandler(file_handler) def confirm_backups(check: bool, default='N'): """Confirms that backups have been taken, with configurable default (Y or N)""" if check: return prompt = f"Have you taken backups? (y/{default}) " answer = input(prompt).strip() or default if answer.lower() != 'y': prompt2 = f"Do you wish to continue anyway? (y/{default}) " answer2 = input(prompt2).strip() or default if answer2.lower() != 'y': sys.exit('Exiting...') def get_db_config() -> dict: """Returns a dictionary of the MySQL configuration""" mysql_cnf = Path('/root/.my.cnf') if not mysql_cnf.exists(): logger.error('Error: /root/.my.cnf does not exist') sys.exit(1) my_cnf_data = {} with open(mysql_cnf, encoding='utf-8') as file: for line in file: if line.startswith('['): section = line.strip('[]\n') my_cnf_data[section] = {} else: key, value = line.strip().split('=') value = value.replace("'", "").replace('"', '') my_cnf_data[section][key] = value db_config_dict = { 'host': 'localhost', 'user': my_cnf_data['client']['user'], 'password': my_cnf_data['client']['password'], 'charset': 'utf8mb4', 'cursorclass': pymysql.cursors.DictCursor, } return db_config_dict db_config = get_db_config() def list_databases() -> list: """Returns a list of all databases""" databases = [] try: with pymysql.connect(**db_config) as connection: with connection.cursor() as cursor: cursor.execute('SHOW DATABASES') databases = cursor.fetchall() databases = [x['Database'] for x in databases] return databases except pymysql.err.MySQLError as e: error = f'Error: {e}' sys.exit(error) def list_tables(database: str) -> tuple[str | None, list[str] | None]: """Returns a list of all tables in a database""" tables = [] try: with pymysql.connect(database=database, **db_config) as connection: with connection.cursor() as cursor: cursor.execute('SHOW TABLES') tables = cursor.fetchall() tables = [x['Tables_in_' + database] for x in tables] return None, tables except pymysql.err.MySQLError as e: error = f'Error on {database}: {e}' logger.error(error) return error, None def check_engine(database: str, table: str) -> tuple[str | None, str | None]: """Returns the engine of a table""" try: with pymysql.connect(database=database, **db_config) as connection: with connection.cursor() as cursor: error = None cursor.execute('SHOW TABLE STATUS LIKE %s', (table,)) table_status = cursor.fetchone() return error, table_status['Engine'] except pymysql.err.MySQLError as e: error = f'Error on {database}.{table}: {e}' logger.error(error) return error, None def convert_table(database: str, table: str, target) -> str | None: """Converts a table to InnoDB to the target engine(InnoDB or MyISAM)""" try: with pymysql.connect(database=database, **db_config) as connection: with connection.cursor() as cursor: cursor.execute(f'ALTER TABLE {table.replace("`", "``")} ENGINE={target}') return None except pymysql.err.MySQLError as e: error = f'Error: {e}' logger.error(error) return error def get_mysql_innodb_settings() -> tuple[list, dict]: """Returns the innodb settings from my.cnf and my.cnf.d""" conf_dir = Path('/etc/my.cnf.d') conf_files = list(conf_dir.glob('*.cnf')) main_conf = Path('/etc/my.cnf') innodb_settings = {} key_errors = [] conf_files.append(main_conf) for file in conf_files: innodb_settings[str(file.name)] = {} if file.exists(): with file.open('r', encoding='utf-8') as f: for line in f: if line.startswith('innodb_'): try: key, value = line.strip().split('=') key = key.strip() except ValueError: key = line.strip() value = '' for _, settings in innodb_settings.items(): if key in settings: error = ( f'Error: {key} is defined in multiple files' ) key_errors.append(error) innodb_settings[str(file.name)][key] = value return key_errors, innodb_settings def clean_db_list(databases: list) -> list: """Removes system databases from the list""" skips = ['information_schema', 'performance_schema', 'mysql', 'sys', 'test'] for database in skips: if database in databases: databases.remove(database) return databases def process_databases(databases: list, args) -> list: """Processes all databases""" errors = [] if args.myisam: current='InnoDB' target='MyISAM' else: current='MyISAM' target='InnoDB' for database in databases: error, tables = list_tables(database) if args.table: if args.table in tables: tables = [args.table] else: error = f'Error: {args.table} does not exist in {database}' logger.error(error) errors.append(error) continue if error: errors.append(error) continue for table in tables: error, engine = check_engine(database, table) if error: errors.append(error) continue if args.check: logger.info('%s.%s is %s', database, table, engine) continue if engine.lower() == current.lower(): logger.info('Converting %s.%s to %s', database, table, target) error = convert_table(database, table, target) if error: errors.append(error) continue return errors def main(): """Main function""" parser = ArgumentParser(description='Converts MyISAM tables to InnoDB') parser.add_argument('-a', '--all', help='Select all databases', action='store_true') parser.add_argument('-d', '--database', help='Database to convert') parser.add_argument('-t', '--table', help='Specify a table to convert. combine with -d') parser.add_argument('--check', help='Check selected databases', action='store_true') parser.add_argument('--myisam', help='Convert to MyISAM instead of InnoDB', action='store_true') args = parser.parse_args() if args.all and args.database: logger.error('Error: --all and --database are mutually exclusive') parser.print_help() sys.exit(1) elif not args.all and not args.database: logger.error('Error: No database specified') logger.error('must use either --all (-a) or --database (-d) flags') parser.print_help() sys.exit(1) elif args.table and not args.database: parser.error('--table requires --database') errors = [] confirm_backups(args.check) databases = list_databases() databases = clean_db_list(databases) if args.database: database = args.database if database not in databases: error = f'Error: {database} does not exist or is a system database' logger.error(error) sys.exit(error) databases = [database] errors = process_databases(databases, args) key_errors, innodb_settings = get_mysql_innodb_settings() if len(errors) > 0 or len(key_errors) > 0: logger.error('Errors occurred:') for error in errors: logger.error("\t%s", error) for key_error in key_errors: logger.error("\t%s", key_error) logger.info('InnoDB settings:') for filename, settings in innodb_settings.items(): logger.info('%s', filename) for key, value in settings.items(): if value == '': logger.info('\t%s', key) else: logger.info('\t%s = %s', key, value) if __name__ == '__main__': main()