31

您如何在 AWS 弹性 beantalk 中管理您的应用程序日志?您将应用程序日志写入哪个文件?

我在我的开发环境中使用以下日志记录配置,但是当我在 AWS 中部署时这不起作用。

DEBUG_LOG_DIR = BASE_DIR + "/django_debug.log"
LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    # How to format the output
    'formatters': {
        'standard': {
            'format' : "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
            'datefmt' : "%d/%b/%Y %H:%M:%S"
        },
    },
    # Log handlers (where to go)
    'handlers': {
        'null': {
            'level':'DEBUG',
            'class':'django.utils.log.NullHandler',
        },
        'log_file': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': DEBUG_LOG_DIR,
            'maxBytes': 50000,
            'backupCount': 2,
            'formatter': 'standard',
        },
        'console':{
            'level':'INFO',
            'class':'logging.StreamHandler',
            'formatter': 'standard'
        },
        'mail_admins': {
            'level': 'ERROR',
            'class': 'django.utils.log.AdminEmailHandler',
        },
    },
    # Loggers (where does the log come from)
    'loggers': {
        'repackager': {
            'handlers': ['console', 'log_file'],
            'level': 'DEBUG',
            'propagate': True,
        },
        'django': {
            'handlers':['console'],
            'propagate': True,
            'level':'WARN',
        },
        'django.db.backends': {
            'handlers': ['console', 'log_file'],
            'level': 'WARN',
            'propagate': False,
        },
        '': {
            'handlers': ['console', 'log_file'],
            'level': 'DEBUG',
        },
    }
}
4

7 回答 7

35

.ebextensions我有一个类似的问题,但在 Elastic Beanstalk 上,所以我在应用程序的文件夹中创建了一个配置文件(例如 applogs.config) 。如果 app-logs 文件夹不存在,这将创建它,并设置文件权限和所有者,以便应用程序可以在那里写入其日志。

commands:
  00_create_dir:
    command: mkdir -p /var/log/app-logs
  01_change_permissions:
    command: chmod g+s /var/log/app-logs
  02_change_owner:
    command: chown wsgi:wsgi /var/log/app-logs

最后,在您的 Django 设置中:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': '/var/log/app-logs/django.log',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['file'],
            'level': 'DEBUG',
            'propagate': True,
        },
    },
}

此外,如果您希望使用网络从 beanstalk 日志访问您的日志,请将其添加到您的 .ebextensions 文件中

files:
  "/opt/elasticbeanstalk/tasks/taillogs.d/django.conf":
    mode: "000755"
    owner: root
    group: root
    content: |
      /var/log/app-logs/django.log
于 2016-01-15T21:18:05.147 回答
10

好的,我想出了一个办法。

首先我通过 ssh 连接到 ec2 机器,然后在 /var/log 中创建一个名为 app_logs 的文件夹,并使用 root 用户:

mkdir /var/log/app_logs

之后我做了以下事情:

cd /var/log/
chmod g+s app_logs/
setfacl -d -m g::rw app_logs/
chown wsgi:wsgi app_logs/

这可确保在此文件夹中创建的所有文件都将 wsgi 作为所有者,并且对于该文件所属的组是可写的。我必须这样做,因为我注意到 django app 创建的日志文件有 root 作为所有者和所有者组,但应用程序通过 wsgi 用户运行。

最后我将 DEBUG_LOG_DIR 更改为 /var/log/app_logs/django_debug.log

于 2015-01-09T00:18:03.277 回答
6

有一种不需要任何 beanstalk 配置的简单方法。

LOGGING下的 django 设置中,设置一个指向文件 '/opt/python/log/{log_file_name}'的处理程序。然后可以通过“日志”下的 beanstalk 环境菜单访问日志。

LOGGING = {
    ...,
    'handlers': {
        'logfile': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': '/opt/python/log/{log_file_name}',
        },
    },
    'loggers': {
        'debugger': {
            'level': 'DEBUG',
            'handlers': ['logfile'],
        'propagate': False,
    },
}

此位置在此处的文档中进行了说明:

https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/using-features.logging.html#health-logs-instancelocation

于 2017-12-30T10:14:48.933 回答
6

- 编辑 -

此答案最初是为Amazon Linux AMI编写的,现在已经结束

为了保持清晰和独立,我为Amazon Linux 2写了一个新答案

——原始答案——

概括

在我看来,最简单的解决方案是按照bewestphal和 @thierry-j 的建议(在steve-dunlop 的回答/opt/python/log下)登录到该文件夹​​。

这也是官方 AWS EB Python示例应用程序所做的:参见python-v1.zip 源代码

当您从 EB 请求日志时,将自动包含日志文件。

.ebextensions只要您不在. _ _django-admin.py.ebextensions

但是,大多数应用程序确实需要调用django-admin.py.ebextensions例如为了migrate。这将导致日志文件过早创建,带有root所有者和root组。这会导致权限错误,因为应用程序以wsgi:wsgi.

这可以通过在您的末尾container_commands添加一个新命令来删除“过早的”日志文件来解决,例如:

container_commands:
  ...
  9999_remove_root_log_file:
    command: rm /opt/python/log/django.log
    ignoreErrors: true

详情如下。

背景

在使用 Apache 和 mod_wsgi(请参阅AWS 平台文档)的标准预配置 Amazon Linux/Python 平台上,WSGIDaemonProcessDjango 应用程序作为用户wsgi和组运行wsgi(请参阅/etc/httpd/conf.d/wsgi.conf您的 EC2 实例)。

此外,文件夹的默认文件夹权限/opt/python/log(在我的标准 EC2 实例上)是:drwxrwxr-x 3 root wsgi 4096 Mar 5 14:08 .

也就是说,该wsgi组拥有所有权限(rwx),因此 Django 应用程序(组wsgi)可以在那里创建日志文件。

正如官方 AWS EB Python 示例应用程序 ( python-v1.zip ) 所展示的那样,这是开箱即用的。

但是,如果您在您.ebextensions的文件中执行任何导致logging文件处理程序被初始化的事情(例如调用django-admin.py),它将中断。

权限问题

以下是使用django-admin.pyin.ebextensions破坏日志文件权限的方法:

中的Elastic Beanstalkcontainer_commands以用户.ebextensions身份执行root(请参阅aws 文档)。

如果您调用django-admin.py任何一个container_commands,例如使用collectstaticor migrate,这将导致您的日志文件处理程序被初始化。如果指定的日志文件尚不存在,则将创建它,并带有root所有者和root组。

这意味着作为wsgi组的一部分运行的 Django 应用程序将无权写入日志文件(属于该root组)。

这会导致权限错误,例如:PermissionError: [Errno 13] Permission denied: '/opt/python/log/django.log'

如何重现

以下代码段说明了权限问题并显示了如何修复它。

要重现此问题,请将这些添加container_commands到一个干净的项目中(例如,按照AWS EB Django 教程),将 Django 配置settings.py为登录/opt/python/log/django.log,部署到 AWS EB,然后检查eb-activity.log以查看容器命令的输出。

...

container_commands:
  0100_show_current_user:
    # show that we are running as root user
    command: whoami
  0200_try_to_remove_log_file:
    # we need a clean slate for this example (make sure no log file owned by wsgi is present)
    command: rm /opt/python/log/django.log
    ignoreErrors: true
  0300_break_log_file_permissions:
    # this causes a new log file to be created, owned by root:root (instead of wsgi:wsgi)
    command: django-admin.py
  0400_show_log_file_permissions:
    # prove that a log file was created by root, and show folder permissions
    command: ls -la /opt/python/log
  0500_fix_by_removing_log_file_after_all_django_admin_calls:
    # remove the log file created by django-admin.py, to ensure that a new log file will  
    # be created when the server starts, owned by wsgi:wsgi
    command: rm /opt/python/log/django.log
    ignoreErrors: true

干溶液

因此,没有必要明确地弄乱文件/文件夹权限。

如果你不调用 django 代码.ebextensions,登录到/opt/python/log工作,开箱即用。

如果您确实调用了 django 代码.ebextensions,例如django-admin.py collectstatic,只需删除部分末尾的日志文件即可container_commands

注意:如果您想记录文件以在部署之间持久存在,请仅在它们归root.

这是一个 DRY 示例:

.ebextensions配置中:

option_settings:
  # create EB environment property for the log file path
  aws:elasticbeanstalk:application:environment:
    LOG_FILE_PATH: /opt/python/log/django.log
...

container_commands:
  ...
  # django code called here, e.g. "django-admin.py collectstatic"
  ...
  9999_remove_any_existing_django_log_files:
    command: rm $LOG_FILE_PATH      
    ignoreErrors: true

并在settings.py

...
# get log path from environment variable, with fallback for local development
log_file_path = os.getenv('LOG_FILE_PATH', 'local.log')
# use this as 'filename' for the file handler, as described in the other answers
...
于 2020-03-05T15:54:26.693 回答
2

此答案仅适用于Amazon Linux 2。对于尚未迁移的用户请参阅我对 Amazon Linux AMI 的旧答案

背景

Amazon linux 2官方 AWS Python 示例应用程序使用该文件夹进行日志记录。/tmp

但是,从 Elastic Beanstalk 请求日志时,不会/tmp自动包含添加到的自定义日志文件。要包含自定义日志文件,我们需要在 EC2 实例的子文件夹中创建日志记录任务。请参阅文档中的说明/opt/elasticbeanstalk/tasks

示例应用程序(源代码)使用.ebextensions. 但是,AWS Linux 2 迁移文档建议我们应该改用.platform钩子:

我们建议使用平台挂钩在您的环境实例上运行自定义代码。您仍然可以在 .ebextensions 配置文件中使用命令和容器命令,但使用起来并不容易。例如,在 YAML 文件中编写命令脚本可能很麻烦且难以测试。

这具有额外的优势,即平台挂钩的输出被收集在一个单独的日志文件中,即。/var/log/eb-hooks.log,这使调试更容易一些。

Amazon Linux 2上基本 Django 应用程序的 DRY 日志记录设置

日志级别和日志路径在处定义为 Elastic Beanstalk 环境属性,例如.ebextensions/options.config

option_settings:
  aws:elasticbeanstalk:application:environment:
    LOG_LEVEL: INFO
    DJANGO_LOG_FILE_PATH: /tmp/django-app.log
    ...

现在DJANGO_LOG_FILE_PATH可以在平台挂钩中使用 environment 属性来创建日志记录任务:

.platform/hooks/postdeploy/020_create_logging_tasks.sh

#!/bin/bash
TASKS_DIR=/opt/elasticbeanstalk/tasks
# include all app log files in bundle logs (replaces ".log" by "*")
echo "${DJANGO_LOG_FILE_PATH//.log/*}" > "$TASKS_DIR/bundlelogs.d/01-app-log.conf"
# include current app log file in tail logs
echo $DJANGO_LOG_FILE_PATH > "$TASKS_DIR/taillogs.d/01-app-log.conf"

请注意,平台挂钩需要执行权限,例如chmod +x 020_create_logging_tasks.sh. 在 Windows 上,您可以git按照此处所述使用。

为了防止权限问题,我们使用另一个平台挂钩来确保日志文件始终归webapp. 注意这个钩子在 logging-tasks 钩子之前运行:

.platform/hooks/postdeploy/010_create_log_file.sh

#!/bin/bash

if test -f "$DJANGO_LOG_FILE_PATH";
then
  echo "$DJANGO_LOG_FILE_PATH exists"
else
  # create log file
  touch $DJANGO_LOG_FILE_PATH
fi

# set log file owner (we are currently "root", but the app runs as "webapp")
chown webapp:webapp $DJANGO_LOG_FILE_PATH

我们还在 Django 设置中使用LOG_LEVELDJANGO_LOG_FILE_PATH环境属性:

设置.py

...
# basic logging with file rotation ()
log_level = os.getenv('LOG_LEVEL', 'INFO')
handlers = dict(file={'class': 'logging.handlers.TimedRotatingFileHandler',
                      'filename': os.getenv('DJANGO_LOG_FILE_PATH'),
                      'when': 'midnight',
                      'interval': 1,
                      'backupCount': 1,
                      'encoding': 'utf-8'})
loggers = dict(django=dict(level=log_level, handlers=['file']),
               myapp=dict(level=log_level, handlers=['file']))
LOGGING = dict(version=1,
               disable_existing_loggers=False,
               handlers=handlers,
               loggers=loggers)
...

一些注意事项:

  • 我们通常也会指定自定义formatters,但为了清楚起见,我将它们省略了。

  • 现在可以在 EC2 实例中找到应用程序本身/var/app/current。另请参阅扩展 EB Linux 平台以了解更多详细信息。

  • 该应用程序现在webapp与 group一样运行webapp

  • eb ssh是你的朋友。请参阅文档

  • 我们还使用平台挂钩来运行 Djangomigratecollectstatic命令,如此所述。

编辑:

正如@hax0 在评论中指出的那样,如果您尝试在部署后manage.py使用 SSH 在 EC2 实例上运行命令,则可能会出现文件权限问题。

例如,使用 时eb ssh,您以 身份登录ec2-user,但日志文件归webapp用户所有,并且默认情况下,只有所有者拥有写权限(644)。因此,当运行python manage.pyas时ec2-user,您将收到一条错误消息,指出它无法配置日志文件处理程序,因为权限被拒绝。

一个快速而肮脏的解决方法是临时更改文件权限,例如使用

sudo chmod 646 /tmp/django-app.log

另一种解决方法manage.py是以webapp用户身份运行,例如:

sudo su - webapp <<'EOF'
source $(find /var/app/venv/*/bin/activate)
export $(/opt/elasticbeanstalk/bin/get-config --output YAML environment | 
         sed -r 's/: /=/' | xargs)
python3 /var/app/current/manage.py showmigrations
EOF

于 2020-12-08T16:21:24.807 回答
1

作为 linux 权限方面的初学者,我花了一些时间才让它工作。总结以上给出的答案,以下最终对我有用:

日志记录配置

commands:
  00_create_dir:
    command: mkdir -p /var/log/app-logs
  01_change_permissions:
    command: chmod g+s /var/log/app-logs
  02_change_default_owner:
    command: setfacl -d -m g::rw /var/log/app-logs
  03_change_owner:
    command: chown wsgi:wsgi /var/log/app-logs

设置.py

LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
    'file': {
        'level': 'DEBUG',
        'class': 'logging.FileHandler',
        'filename': '/var/log/app-logs/django.log',
    },
},
'loggers': {
    'django': {
        'handlers': ['file'],
        'level': 'DEBUG',
        'propagate': True,
    },
},
}

有了这个,我可以使用“eb logs”或在 Beanstalk 环境中的“logs”部分将日志视为单独的部分。

于 2019-05-17T09:33:22.660 回答
-4

默认情况下,在 elasticbeanstalk 中,您可以在此处查看 django 错误日志。

/var/log/httpd/error_log
于 2017-05-20T11:46:01.453 回答