1
0
mirror of https://github.com/certbot/certbot.git synced 2026-01-21 19:01:07 +03:00

CLI debug log file

This commit is contained in:
Jakub Warmuz
2015-06-22 12:41:08 +00:00
parent 5b9a2f9637
commit eb149b9129
5 changed files with 59 additions and 9 deletions

View File

@@ -3,8 +3,10 @@
import argparse
import atexit
import logging
import logging.handlers
import os
import sys
import time
import configargparse
import zope.component
@@ -70,9 +72,6 @@ More detailed help:
def _account_init(args, config):
le_util.make_or_verify_dir(
config.config_dir, constants.CONFIG_DIRS_MODE, os.geteuid())
# Prepare for init of Client
if args.email is None:
return client.determine_account(config)
@@ -559,6 +558,8 @@ def _paths_parser(helpful):
help=config_help("config_dir"))
add("paths", "--work-dir", default=flag_default("work_dir"),
help=config_help("work_dir"))
add("paths", "--logs-dir", default=flag_default("logs_dir"),
help="Path to a directory where logs are stored.")
add("paths", "--backup-dir", default=flag_default("backup_dir"),
help=config_help("backup_dir"))
add("paths", "--key-dir", default=flag_default("key_dir"),
@@ -575,14 +576,39 @@ def _paths_parser(helpful):
def _setup_logging(args):
level = -args.verbose_count * 10
logging.getLogger().setLevel(level)
fmt = "%(asctime)s:%(levelname)s:%(name)s:%(message)s"
if args.text_mode:
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter(fmt))
else:
handler = log.DialogHandler()
handler.setFormatter(logging.Formatter(logging.BASIC_FORMAT))
logging.getLogger().addHandler(handler)
# dialog box is small, display as less as possible
handler.setFormatter(logging.Formatter("%(message)s"))
handler.setLevel(level)
# TODO: use fileConfig?
# unconditionally log to file for debugging purposes
# TODO: change before release?
log_file_name = os.path.join(args.logs_dir, 'letsencrypt.log')
file_handler = logging.handlers.RotatingFileHandler(
log_file_name, maxBytes=2**20, backupCount=10)
# rotate on each invocation, rollover only possible when maxBytes
# is nonzero and backupCount is nonzero, so we set maxBytes as big
# as possible not to overrun in single CLI invocation (1MB).
file_handler.doRollover() # TODO: creates empty letsencrypt.log.1 file
file_handler.setLevel(logging.DEBUG)
file_handler_formatter = logging.Formatter(fmt=fmt)
file_handler_formatter.converter = time.gmtime # don't use localtime
file_handler.setFormatter(file_handler_formatter)
root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG) # send all records to handlers
root_logger.addHandler(handler)
root_logger.addHandler(file_handler)
logging.debug("Root logging level set at %d", level)
logging.info("Saving debug log to %s", log_file_name)
def main(cli_args=sys.argv[1:]):
@@ -599,6 +625,13 @@ def main(cli_args=sys.argv[1:]):
displayer = display_util.NcursesDisplay()
zope.component.provideUtility(displayer)
for directory in config.config_dir, config.work_dir:
le_util.make_or_verify_dir(
directory, constants.CONFIG_DIRS_MODE, os.geteuid())
# TODO: logs might contain sensitive data such as contents of the
# private key! #525
le_util.make_or_verify_dir(args.logs_dir, 0o700, os.geteuid())
_setup_logging(args)
# do not log `args`, as it contains sensitive data (e.g. revoke --key)!
logging.debug("Arguments: %r", cli_args)

View File

@@ -15,6 +15,7 @@ CLI_DEFAULTS = dict(
rollback_checkpoints=0,
config_dir="/etc/letsencrypt",
work_dir="/var/lib/letsencrypt",
logs_dir="/var/log/letsencrypt",
no_verify_ssl=False,
dvsni_port=challenges.DVSNI.PORT,
cert_path="./cert.pem",

View File

@@ -106,6 +106,9 @@ def _paths_parser(parser):
help=cli.config_help("config_dir"))
add("--work-dir", default=cli.flag_default("work_dir"),
help=cli.config_help("work_dir"))
add("--logs-dir", default=cli.flag_default("logs_dir"),
help="Path to a directory where logs are stored.")
return parser

View File

@@ -1,5 +1,8 @@
"""Tests for letsencrypt.cli."""
import itertools
import os
import shutil
import tempfile
import unittest
import mock
@@ -8,10 +11,19 @@ import mock
class CLITest(unittest.TestCase):
"""Tests for different commands."""
@classmethod
def _call(cls, args):
def setUp(self):
self.tmp_dir = tempfile.mkdtemp()
self.config_dir = os.path.join(self.tmp_dir, 'config')
self.work_dir = os.path.join(self.tmp_dir, 'work')
self.logs_dir = os.path.join(self.tmp_dir, 'logs')
def tearDown(self):
shutil.rmtree(self.tmp_dir)
def _call(self, args):
from letsencrypt import cli
args = ['--text'] + args
args = ['--text', '--config-dir', self.config_dir,
'--work-dir', self.work_dir, '--logs-dir', self.logs_dir] + args
with mock.patch('letsencrypt.cli.sys.stdout') as stdout:
with mock.patch('letsencrypt.cli.sys.stderr') as stderr:
with mock.patch('letsencrypt.cli.client') as client:

View File

@@ -6,6 +6,7 @@
root="$(mktemp -d)"
echo "\nRoot integration tests directory: $root"
store_flags="--config-dir $root/conf --work-dir $root/work"
store_flags="$store_flags --logs-dir $root/logs"
common() {
# first three flags required, rest is handy defaults