Mini Shell

Direktori : /opt/sharedrads/
Upload File :
Current File : //opt/sharedrads/fixwpcron.py

#!/opt/imh-python/bin/python3
"""wp-cron was a hacky Wordpress feature added to compensate for Windows's
lack of scheduling system. Certain plugins can trigger very poor behavior that
causes it to be run every time anything happens on the site. The end result is
dozens of thousands of redundant hits to wp-cron.php. This script disables the
wp-cron feature, and sets up a cronjob to run once every three hours"""


import sys
import os
import getpass
import random
import argparse
import crontab
from rads import is_cpuser


def parse_args():
    """Parse commandline args"""
    parser = argparse.ArgumentParser(description=__doc__)
    group = parser.add_mutually_exclusive_group(required=True)
    # fmt: off
    group.add_argument(
        '--path', '-p', metavar='PATH',
        type=os.path.realpath,
        help='path to wordpress installation. If using this argument, we assume'
        ' the customer has not modified the site to have wp-config.php in an '
        'alternate directory. Both wp-config.php and wp-cron.php should be '
        'present in the supplied directory',
    )
    all_help = """Set this up for every WordPress installation that the user
        owns. Installations modified to have wp-config.php in an alternate folder
        for security are supported; wp-config.php and wp-cron.php files will
        be located separately
    """
    current_user = getpass.getuser()
    if current_user == 'root':
        group.add_argument('--user', '-u', help=all_help)
    else:
        group.add_argument('--all', '-a', action='store_true', help=all_help)
    # fmt: on
    args = parser.parse_args()
    if args.path:
        if not os.path.isdir(args.path):
            sys.exit(f'{args.path} does not exist')
        try:
            assert args.path.split('/')[1] == 'home'
            args.user = args.path.split('/')[2]
        except (AssertionError, IndexError):
            sys.exit("Incorrect path. Should be in a user's homedir")
    if not hasattr(args, 'all'):
        args.all = False
    if args.all:
        args.user = current_user
    if not is_cpuser(args.user):
        sys.exit(f'{args.user} is not a cPanel user')
    return args


def turn_off(filename):
    """Sticks the DISABLE_WP_CRON line in wp-config"""
    with open(filename, encoding='utf-8') as handle:
        linelist = handle.readlines()
    for index, line in enumerate(linelist):
        if 'DB_USER' in line:
            if linelist[index + 1] == "define('DISABLE_WP_CRON', 'true');\n":
                print('File already modified:', filename)
                return
            if linelist[index + 1] == '\n':
                linelist[index + 1] = "define('DISABLE_WP_CRON', 'true');\n"
            else:
                print(
                    'Non-standard wp-config file at {}. Add this manually '
                    'under DB_USER:'.format(filename),
                    "define('DISABLE_WP_CRON', 'true');",
                    sep='\n',
                )
                return
            break
    with open(filename, 'w', encoding='utf-8') as handle:
        handle.writelines(linelist)


def setup_cron(user, path, not_root):
    """Setup php -q wp-cron.php system cron"""
    if not_root:
        ctab = crontab.CronTab()
    else:
        ctab = crontab.CronTab(user=user)
    cmd = f'cd {path}; php -q wp-cron.php'
    if len([x for x in ctab.find_command(cmd) if x.is_enabled()]) > 0:
        print('Cron already enabled:', cmd)
        return
    job = ctab.new(command=cmd)
    job.hour.every(3)
    job.minute.on(random.randint(0, 59))
    ctab.write()


def find_files(user):
    """Find wp-config.php files and dirs containing wp-cron.php"""
    crondirs = []  # directories containing wp-cron.php
    configs = []  # wp-config.php files
    for root, _, filenames in os.walk(os.path.join('/home', user)):
        if 'wp-config.php' in filenames:
            configs.append(os.path.join(root, 'wp-config.php'))
        if 'wp-cron.php' in filenames:
            crondirs.append(root)
    return configs, crondirs


def main():
    """Main program logic"""
    args = parse_args()
    if args.path:
        configs = [os.path.join(args.path, 'wp-config.php')]
        crondirs = [args.path]
    else:
        configs, crondirs = find_files(args.user)
    if len(configs) > 0:
        print("wp-config.php file(s):")
        print(*configs, sep='\n')
        print()
    if len(crondirs) > 0:
        print('dir(s) to setup system crons for wp-cron.php:')
        print(*crondirs, sep='\n')
        print()
    for path in configs:
        try:
            turn_off(path)
        except OSError:
            print('Error reading/writing to', path)
    for path in crondirs:
        setup_cron(args.user, path, args.all)
    print('done.')


if __name__ == '__main__':
    main()

Zerion Mini Shell 1.0