#!/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"""
from rads import is_cpuser
"""Parse commandline args"""
parser = argparse.ArgumentParser(description=__doc__)
group = parser.add_mutually_exclusive_group(required=True)
'--path', '-p', metavar='PATH',
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
current_user = getpass.getuser()
if current_user == 'root':
group.add_argument('--user', '-u', help=all_help)
group.add_argument('--all', '-a', action='store_true', help=all_help)
args = parser.parse_args()
if not os.path.isdir(args.path):
sys.exit(f'{args.path} does not exist')
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'):
if not is_cpuser(args.user):
sys.exit(f'{args.user} is not a cPanel user')
"""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 linelist[index + 1] == "define('DISABLE_WP_CRON', 'true');\n":
print('File already modified:', filename)
if linelist[index + 1] == '\n':
linelist[index + 1] = "define('DISABLE_WP_CRON', 'true');\n"
'Non-standard wp-config file at {}. Add this manually '
'under DB_USER:'.format(filename),
"define('DISABLE_WP_CRON', 'true');",
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"""
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)
job = ctab.new(command=cmd)
job.minute.on(random.randint(0, 59))
"""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:
configs = [os.path.join(args.path, 'wp-config.php')]
configs, crondirs = find_files(args.user)
print("wp-config.php file(s):")
print(*configs, sep='\n')
print('dir(s) to setup system crons for wp-cron.php:')
print(*crondirs, sep='\n')
print('Error reading/writing to', path)
setup_cron(args.user, path, args.all)
if __name__ == '__main__':