Files
WPIQ/wo/cli/plugins/log.py

578 lines
26 KiB
Python
Raw Normal View History

2018-11-13 21:55:59 +01:00
"""Logfile Plugin for WordOps"""
from cement.core.controller import CementBaseController, expose
from cement.core import handler, hook
from wo.core.logging import Log
from wo.cli.plugins.site_functions import logwatch
from wo.core.variables import WOVariables
from wo.core.fileutils import WOFileUtils
from wo.core.shellexec import WOShellExec
from wo.core.sendmail import WOSendMail
from wo.core.mysql import WOMysql
import os
import glob
import gzip
def wo_log_hook(app):
pass
class WOLogController(CementBaseController):
class Meta:
label = 'log'
description = 'Perform operations on Nginx, PHP and MySQL log files'
stacked_on = 'base'
stacked_type = 'nested'
usage = "wo log [<site_name>] [options]"
@expose(hide=True)
def default(self):
self.app.args.print_help()
class WOLogShowController(CementBaseController):
class Meta:
label = 'show'
description = 'Show Nginx, PHP, MySQL log file'
stacked_on = 'log'
stacked_type = 'nested'
arguments = [
(['--all'],
dict(help='Show All logs file', action='store_true')),
(['--nginx'],
dict(help='Show Nginx Error logs file', action='store_true')),
(['--php'],
dict(help='Show PHP Error logs file', action='store_true')),
(['--fpm'],
dict(help='Show PHP5-fpm slow logs file',
action='store_true')),
(['--mysql'],
dict(help='Show MySQL logs file', action='store_true')),
(['--wp'],
dict(help='Show Site specific WordPress logs file',
action='store_true')),
(['--access'],
dict(help='Show Nginx access log file',
action='store_true')),
(['site_name'],
dict(help='Website Name', nargs='?', default=None))
]
usage = "wo log show [<site_name>] [options]"
@expose(hide=True)
def default(self):
"""Default function of log show"""
self.msg = []
if self.app.pargs.php:
self.app.pargs.nginx = True
if ((not self.app.pargs.nginx) and (not self.app.pargs.fpm)
and (not self.app.pargs.mysql) and (not self.app.pargs.access)
and (not self.app.pargs.wp) and (not self.app.pargs.site_name)):
self.app.pargs.nginx = True
self.app.pargs.fpm = True
self.app.pargs.mysql = True
self.app.pargs.access = True
if ((not self.app.pargs.nginx) and (not self.app.pargs.fpm)
and (not self.app.pargs.mysql) and (not self.app.pargs.access)
and (not self.app.pargs.wp) and (self.app.pargs.site_name)):
self.app.pargs.nginx = True
self.app.pargs.wp = True
self.app.pargs.access = True
self.app.pargs.mysql = True
if self.app.pargs.nginx and (not self.app.pargs.site_name):
self.msg = self.msg + ["/var/log/nginx/*error.log"]
if self.app.pargs.access and (not self.app.pargs.site_name):
self.msg = self.msg + ["/var/log/nginx/*access.log"]
if self.app.pargs.fpm:
open('/var/log/php5/slow.log', 'a').close()
open('/var/log/php5/fpm.log', 'a').close()
self.msg = self.msg + ['/var/log/php5/slow.log',
'/var/log/php5/fpm.log']
if self.app.pargs.mysql:
# MySQL debug will not work for remote MySQL
if WOVariables.wo_mysql_host is "localhost":
if os.path.isfile('/var/log/mysql/mysql-slow.log'):
self.msg = self.msg + ['/var/log/mysql/mysql-slow.log']
else:
Log.info(self, "MySQL slow-log not found, skipped")
else:
Log.warn(self, "Remote MySQL found, WordOps does not support"
"remote MySQL servers or log files")
if self.app.pargs.site_name:
webroot = "{0}{1}".format(WOVariables.wo_webroot,
self.app.pargs.site_name)
if not os.path.isdir(webroot):
Log.error(self, "Site not present, quitting")
if self.app.pargs.access:
self.msg = self.msg + ["{0}/{1}/logs/access.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
if self.app.pargs.nginx:
self.msg = self.msg + ["{0}/{1}/logs/error.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
if self.app.pargs.wp:
if os.path.isdir('{0}/htdocs/wp-content'.format(webroot)):
if not os.path.isfile('{0}/logs/debug.log'
.format(webroot)):
if not os.path.isfile('{0}/htdocs/wp-content/debug.log'
.format(webroot)):
open("{0}/htdocs/wp-content/debug.log"
.format(webroot),
encoding='utf-8', mode='a').close()
WOShellExec.cmd_exec(self, "chown {1}: {0}/htdocs/"
"wp-content/debug.log"
"".format(webroot,
WOVariables
.wo_php_user)
)
# create symbolic link for debug log
WOFileUtils.create_symlink(self, ["{0}/htdocs/wp-content/"
"debug.log"
.format(webroot),
'{0}/logs/debug.log'
.format(webroot)])
self.msg = self.msg + ["{0}/{1}/logs/debug.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
else:
Log.info(self, "Site is not WordPress site, skipping "
"WordPress logs")
watch_list = []
for w_list in self.msg:
watch_list = watch_list + glob.glob(w_list)
logwatch(self, watch_list)
class WOLogResetController(CementBaseController):
class Meta:
label = 'reset'
description = 'Reset Nginx, PHP, MySQL log file'
stacked_on = 'log'
stacked_type = 'nested'
arguments = [
(['--all'],
dict(help='Reset All logs file', action='store_true')),
(['--nginx'],
dict(help='Reset Nginx Error logs file', action='store_true')),
(['--php'],
dict(help='Reset PHP Error logs file', action='store_true')),
(['--fpm'],
dict(help='Reset PHP5-fpm slow logs file',
action='store_true')),
(['--mysql'],
dict(help='Reset MySQL logs file', action='store_true')),
(['--wp'],
dict(help='Reset Site specific WordPress logs file',
action='store_true')),
(['--access'],
dict(help='Reset Nginx access log file',
action='store_true')),
(['--slow-log-db'],
dict(help='Drop all rows from slowlog table in database',
action='store_true')),
(['site_name'],
dict(help='Website Name', nargs='?', default=None))
]
usage = "wo log reset [<site_name>] [options]"
@expose(hide=True)
def default(self):
"""Default function of log reset"""
self.msg = []
if self.app.pargs.php:
self.app.pargs.nginx = True
if ((not self.app.pargs.nginx) and (not self.app.pargs.fpm)
and (not self.app.pargs.mysql) and (not self.app.pargs.access)
and (not self.app.pargs.wp) and (not self.app.pargs.site_name)
and (not self.app.pargs.slow_log_db)):
self.app.pargs.nginx = True
self.app.pargs.fpm = True
self.app.pargs.mysql = True
self.app.pargs.access = True
self.app.pargs.slow_log_db = True
if ((not self.app.pargs.nginx) and (not self.app.pargs.fpm)
and (not self.app.pargs.mysql) and (not self.app.pargs.access)
and (not self.app.pargs.wp) and (self.app.pargs.site_name)
and (not self.app.pargs.slow-log-db)):
self.app.pargs.nginx = True
self.app.pargs.wp = True
self.app.pargs.access = True
self.app.pargs.mysql = True
if self.app.pargs.slow_log_db:
if os.path.isdir("/var/www/22222/htdocs/db/anemometer"):
Log.info(self, "Resetting MySQL slow_query_log database table")
WOMysql.execute(self, "TRUNCATE TABLE "
"slow_query_log.global_query_review_history")
WOMysql.execute(self, "TRUNCATE TABLE "
"slow_query_log.global_query_review")
if self.app.pargs.nginx and (not self.app.pargs.site_name):
self.msg = self.msg + ["/var/log/nginx/*error.log"]
if self.app.pargs.access and (not self.app.pargs.site_name):
self.msg = self.msg + ["/var/log/nginx/*access.log"]
if self.app.pargs.fpm:
open('/var/log/php5/slow.log', 'a').close()
open('/var/log/php5/fpm.log', 'a').close()
self.msg = self.msg + ['/var/log/php5/slow.log',
'/var/log/php5/fpm.log']
if self.app.pargs.mysql:
# MySQL debug will not work for remote MySQL
if WOVariables.wo_mysql_host is "localhost":
if os.path.isfile('/var/log/mysql/mysql-slow.log'):
self.msg = self.msg + ['/var/log/mysql/mysql-slow.log']
else:
Log.info(self, "MySQL slow-log not found, skipped")
else:
Log.warn(self, "Remote MySQL found, WordOps does not support"
"remote MySQL servers or log files")
if self.app.pargs.site_name:
webroot = "{0}{1}".format(WOVariables.wo_webroot,
self.app.pargs.site_name)
if not os.path.isdir(webroot):
Log.error(self, "Site not present, quitting")
if self.app.pargs.access:
self.msg = self.msg + ["{0}/{1}/logs/access.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
if self.app.pargs.nginx:
self.msg = self.msg + ["{0}/{1}/logs/error.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
if self.app.pargs.wp:
if os.path.isdir('{0}/htdocs/wp-content'.format(webroot)):
if not os.path.isfile('{0}/logs/debug.log'
.format(webroot)):
if not os.path.isfile('{0}/htdocs/wp-content/debug.log'
.format(webroot)):
open("{0}/htdocs/wp-content/debug.log"
.format(webroot),
encoding='utf-8', mode='a').close()
WOShellExec.cmd_exec(self, "chown {1}: {0}/htdocs/"
"wp-content/debug.log"
"".format(webroot,
WOVariables
.wo_php_user)
)
# create symbolic link for debug log
WOFileUtils.create_symlink(self, ["{0}/htdocs/wp-content/"
"debug.log"
.format(webroot),
'{0}/logs/debug.log'
.format(webroot)])
self.msg = self.msg + ["{0}/{1}/logs/debug.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
else:
Log.info(self, "Site is not WordPress site, skipping "
"WordPress logs")
reset_list = []
for r_list in self.msg:
reset_list = reset_list + glob.glob(r_list)
# Clearing content of file
for r_list in reset_list:
Log.info(self, "Resetting file {file}".format(file=r_list))
open(r_list, 'w').close()
class WOLogGzipController(CementBaseController):
class Meta:
label = 'gzip'
description = 'GZip Nginx, PHP, MySQL log file'
stacked_on = 'log'
stacked_type = 'nested'
arguments = [
(['--all'],
dict(help='GZip All logs file', action='store_true')),
(['--nginx'],
dict(help='GZip Nginx Error logs file', action='store_true')),
(['--php'],
dict(help='GZip PHP Error logs file', action='store_true')),
(['--fpm'],
dict(help='GZip PHP5-fpm slow logs file',
action='store_true')),
(['--mysql'],
dict(help='GZip MySQL logs file', action='store_true')),
(['--wp'],
dict(help='GZip Site specific WordPress logs file',
action='store_true')),
(['--access'],
dict(help='GZip Nginx access log file',
action='store_true')),
(['site_name'],
dict(help='Website Name', nargs='?', default=None))
]
usage = "wo log gzip [<site_name>] [options]"
@expose(hide=True)
def default(self):
"""Default function of log GZip"""
self.msg = []
if self.app.pargs.php:
self.app.pargs.nginx = True
if ((not self.app.pargs.nginx) and (not self.app.pargs.fpm)
and (not self.app.pargs.mysql) and (not self.app.pargs.access)
and (not self.app.pargs.wp) and (not self.app.pargs.site_name)):
self.app.pargs.nginx = True
self.app.pargs.fpm = True
self.app.pargs.mysql = True
self.app.pargs.access = True
if ((not self.app.pargs.nginx) and (not self.app.pargs.fpm)
and (not self.app.pargs.mysql) and (not self.app.pargs.access)
and (not self.app.pargs.wp) and (self.app.pargs.site_name)):
self.app.pargs.nginx = True
self.app.pargs.wp = True
self.app.pargs.access = True
self.app.pargs.mysql = True
if self.app.pargs.nginx and (not self.app.pargs.site_name):
self.msg = self.msg + ["/var/log/nginx/*error.log"]
if self.app.pargs.access and (not self.app.pargs.site_name):
self.msg = self.msg + ["/var/log/nginx/*access.log"]
if self.app.pargs.fpm:
open('/var/log/php5/slow.log', 'a').close()
open('/var/log/php5/fpm.log', 'a').close()
self.msg = self.msg + ['/var/log/php5/slow.log',
'/var/log/php5/fpm.log']
if self.app.pargs.mysql:
# MySQL debug will not work for remote MySQL
if WOVariables.wo_mysql_host is "localhost":
if os.path.isfile('/var/log/mysql/mysql-slow.log'):
self.msg = self.msg + ['/var/log/mysql/mysql-slow.log']
else:
Log.info(self, "MySQL slow-log not found, skipped")
else:
Log.warn(self, "Remote MySQL found, WordOps does not support"
"remote MySQL servers or log files")
if self.app.pargs.site_name:
webroot = "{0}{1}".format(WOVariables.wo_webroot,
self.app.pargs.site_name)
if not os.path.isdir(webroot):
Log.error(self, "Site not present, quitting")
if self.app.pargs.access:
self.msg = self.msg + ["{0}/{1}/logs/access.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
if self.app.pargs.nginx:
self.msg = self.msg + ["{0}/{1}/logs/error.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
if self.app.pargs.wp:
if os.path.isdir('{0}/htdocs/wp-content'.format(webroot)):
if not os.path.isfile('{0}/logs/debug.log'
.format(webroot)):
if not os.path.isfile('{0}/htdocs/wp-content/debug.log'
.format(webroot)):
open("{0}/htdocs/wp-content/debug.log"
.format(webroot),
encoding='utf-8', mode='a').close()
WOShellExec.cmd_exec(self, "chown {1}: {0}/htdocs/"
"wp-content/debug.log"
"".format(webroot,
WOVariables
.wo_php_user)
)
# create symbolic link for debug log
WOFileUtils.create_symlink(self, ["{0}/htdocs/wp-content/"
"debug.log"
.format(webroot),
'{0}/logs/debug.log'
.format(webroot)])
self.msg = self.msg + ["{0}/{1}/logs/debug.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
else:
Log.info(self, "Site is not WordPress site, skipping "
"WordPress logs")
gzip_list = []
for g_list in self.msg:
gzip_list = gzip_list + glob.glob(g_list)
# Gzip content of file
for g_list in gzip_list:
Log.info(self, "Gzipping file {file}".format(file=g_list))
in_file = g_list
in_data = open(in_file, "rb").read()
out_gz = g_list + ".gz"
gzf = gzip.open(out_gz, "wb")
gzf.write(in_data)
gzf.close()
class WOLogMailController(CementBaseController):
class Meta:
label = 'mail'
description = 'Mail Nginx, PHP, MySQL log file'
stacked_on = 'log'
stacked_type = 'nested'
arguments = [
(['--all'],
dict(help='Mail All logs file', action='store_true')),
(['--nginx'],
dict(help='Mail Nginx Error logs file', action='store_true')),
(['--php'],
dict(help='Mail PHP 7.2 Error logs file', action='store_true')),
2018-11-13 21:55:59 +01:00
(['--fpm'],
dict(help='Mail PHP 7.2-fpm slow logs file',
2018-11-13 21:55:59 +01:00
action='store_true')),
(['--mysql'],
dict(help='Mail MySQL logs file', action='store_true')),
(['--wp'],
dict(help='Mail Site specific WordPress logs file',
action='store_true')),
(['--access'],
dict(help='Mail Nginx access log file',
action='store_true')),
(['site_name'],
dict(help='Website Name', nargs='?', default=None)),
(['--to'],
dict(help='Email addresses to send log files', action='append',
dest='to', nargs=1, required=True)),
]
usage = "wo log mail [<site_name>] [options]"
@expose(hide=True)
def default(self):
"""Default function of log Mail"""
self.msg = []
if self.app.pargs.php:
self.app.pargs.nginx = True
if ((not self.app.pargs.nginx) and (not self.app.pargs.fpm)
and (not self.app.pargs.mysql) and (not self.app.pargs.access)
and (not self.app.pargs.wp) and (not self.app.pargs.site_name)):
self.app.pargs.nginx = True
self.app.pargs.fpm = True
self.app.pargs.mysql = True
self.app.pargs.access = True
if ((not self.app.pargs.nginx) and (not self.app.pargs.fpm)
and (not self.app.pargs.mysql) and (not self.app.pargs.access)
and (not self.app.pargs.wp) and (self.app.pargs.site_name)):
self.app.pargs.nginx = True
self.app.pargs.wp = True
self.app.pargs.access = True
self.app.pargs.mysql = True
if self.app.pargs.nginx and (not self.app.pargs.site_name):
self.msg = self.msg + ["/var/log/nginx/*error.log"]
if self.app.pargs.access and (not self.app.pargs.site_name):
self.msg = self.msg + ["/var/log/nginx/*access.log"]
if self.app.pargs.fpm:
open('/var/log/php5/slow.log', 'a').close()
open('/var/log/php5/fpm.log', 'a').close()
self.msg = self.msg + ['/var/log/php5/slow.log',
'/var/log/php5/fpm.log']
if self.app.pargs.mysql:
# MySQL debug will not work for remote MySQL
if WOVariables.wo_mysql_host is "localhost":
if os.path.isfile('/var/log/mysql/mysql-slow.log'):
self.msg = self.msg + ['/var/log/mysql/mysql-slow.log']
else:
Log.info(self, "MySQL slow-log not found, skipped")
else:
Log.warn(self, "Remote MySQL found, WordOps does not support"
"remote MySQL servers or log files")
if self.app.pargs.site_name:
webroot = "{0}{1}".format(WOVariables.wo_webroot,
self.app.pargs.site_name)
if not os.path.isdir(webroot):
Log.error(self, "Site not present, quitting")
if self.app.pargs.access:
self.msg = self.msg + ["{0}/{1}/logs/access.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
if self.app.pargs.nginx:
self.msg = self.msg + ["{0}/{1}/logs/error.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
if self.app.pargs.wp:
if os.path.isdir('{0}/htdocs/wp-content'.format(webroot)):
if not os.path.isfile('{0}/logs/debug.log'
.format(webroot)):
if not os.path.isfile('{0}/htdocs/wp-content/debug.log'
.format(webroot)):
open("{0}/htdocs/wp-content/debug.log"
.format(webroot),
encoding='utf-8', mode='a').close()
WOShellExec.cmd_exec(self, "chown {1}: {0}/htdocs/"
"wp-content/debug.log"
"".format(webroot,
WOVariables
.wo_php_user)
)
# create symbolic link for debug log
WOFileUtils.create_symlink(self, ["{0}/htdocs/wp-content/"
"debug.log"
.format(webroot),
'{0}/logs/debug.log'
.format(webroot)])
self.msg = self.msg + ["{0}/{1}/logs/debug.log"
.format(WOVariables.wo_webroot,
self.app.pargs.site_name)]
else:
Log.info(self, "Site is not WordPress site, skipping "
"WordPress logs")
mail_list = []
for m_list in self.msg:
mail_list = mail_list + glob.glob(m_list)
for tomail in self.app.pargs.to:
Log.info(self, "Sending mail to {0}".format(tomail[0]))
WOSendMail("wordops", tomail[0], "{0} Log Files"
.format(WOVariables.wo_fqdn),
"Hi,\n The requested logfiles are attached."
"\n\nBest regards,\nYour WordOps worker",
files=mail_list, port=25, isTls=False)
def load(app):
# register the plugin class.. this only happens if the plugin is enabled
handler.register(WOLogController)
handler.register(WOLogShowController)
handler.register(WOLogResetController)
handler.register(WOLogGzipController)
handler.register(WOLogMailController)
# register a hook (function) to run after arguments are parsed.
hook.register('post_argument_parsing', wo_log_hook)