Nginx实现浏览器可实时查看访问日志的步骤详解

以下是“Nginx实现浏览器可实时查看访问日志的步骤详解”的攻略。

步骤一:安装WebSocket模块

首先,我们需要在Nginx上安装WebSocket模块来实现实时查看访问日志的功能。WebSocket模块可以让我们建立与浏览器的长连接,从而实现实时推送日志信息到浏览器端。具体安装步骤如下:

  1. 打开Nginx的官网(https://nginx.org/)并从“Download”页面下载最新的Nginx源码压缩包。
  2. 解压缩该压缩包并进入解压后的文件夹。
  3. 在终端中输入以下命令:
./configure --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --add-module=path/to/nginx_http_push_module --add-module=path/to/nginx_http_websocket_module
make
sudo make install

其中, --add-module 后接的 path/to/nginx_http_push_modulepath/to/nginx_http_websocket_module 是WebSocket模块的路径。

  1. 执行以上命令后,Nginx的WebSocket模块就已经安装完成了。

步骤二:修改配置文件

接下来,我们需要修改Nginx的配置文件。具体操作步骤如下:

  1. 打开Nginx的主配置文件(一般存放在 /usr/local/nginx/conf/nginx.conf 下),找到 http 部分下的 server 配置段。
  2. 向该配置段下添加以下内容:
access_log /var/log/nginx/access.log;

location = /real-time-log {
    websocket_pass localhost:8080;
    access_log off;
    proxy_pass http://localhost:8080;
}

location /tail {
    tail;
}

其中,access_log 配置项用于启用Nginx的访问日志,location 配置项用于定义WebSocket长连接地址(即 /real-time-log ),websocket_pass 配置项用于指定实时日志服务器的地址和端口,access_log off; 配置项用于关闭对实时日志 WebSocket 的访问日志记录,proxy_pass 配置项用于将 WebSocket 连接替换到 TCP 长连接上,tail 配置项表示启用tail模块,tail模块可以让我们查看访问日志的尾部。

  1. 然后在 http 部分中向 server 配置段下方添加以下内容:
location /logs {
    alias /var/log/nginx/;
}

该配置项用于定义访问日志存放的路径,从而实现在浏览器中查看访问日志。

步骤三:重启Nginx

修改完配置文件后,需要重启Nginx使配置项生效。在终端中输入以下命令:

sudo /usr/local/nginx/sbin/nginx -s reload

步骤四:使用浏览器查看日志

完成以上步骤后,在浏览器中输入 http://localhost/logs 即可查看Nginx的访问日志,日志内容会自动更新并实时刷新,让我们实时追踪网站的访问情况。

示例一

以下是一个在Nginx配置中启用WebSocket模块和实时尾部tail模块的例子:

http {
    upstream websocket_servers {
        server 127.0.0.1:8000;
    }

    map $http_upgrade $connection_upgrade {
        default upgrade;
        ""      close;
    }

    server {
        listen       80;
        server_name  www.example.com;
        root   PATH_TO_ROOT;
        index  index.html;

        access_log /var/log/nginx/access.log;

        location = /real-time-log {
            internal;
            proxy_pass http://websocket_servers;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }

        location /tail {
            tail;
        }

        location / {
            try_files $uri /index.html;
        }
    }
}

该配置文件中, WebSocket的 upstream 服务被配置为 127.0.0.1:8000 ,当访问日志发生时,该服务会推送给所有的连接。 实时的访问日志是在 location /real-time-log 中定义的。 /tail 是用来查看访问日志尾部的。当访问源 /logs 时, nginx会返回当前访问日志的目录。

示例二

以下是一个使用WebSocket实时推送Nginx访问日志的 Python 代码示例:

#!/usr/bin/env python3
import argparse
import asyncio
import json
import signal
import string
import sys
import time
import random

from aiohttp import web
import aiohttp

class WebSocketError(Exception):
    pass

class RealTimeLog: 
    def __init__(self):
        self.sockets = set()

    async def __call__(self, request):
        ws = web.WebSocketResponse(protocols=('chat',))
        await ws.prepare(request)
        self.sockets.add(ws)
        try:
            async for record in self.log():
                for socket in self.sockets.copy():
                    await socket.send_str(json.dumps(record))
        except WebSocketError:
            pass
        finally:
            self.sockets.remove(ws)
        return ws

    async def log(self):
        raise NotImplementedError()

class NginxLog(RealTimeLog):
    def __init__(self, log_file='/var/log/nginx/access.log'):
        super().__init__()
        self._state = 'tail'
        self._log_file = log_file

    async def log(self):
        cmd = f'tail -f {self._log_file}'
        process = await asyncio.create_subprocess_shell(
            cmd,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE,
        )
        while True:
            data = await process.stdout.readline()
            if not data:
                break
            yield {
                'state': self._state,
                'log': data.decode(),
            }

    async def set_state(self, request):
        self._state = await request.text()

async def on_shutdown(app):
    for ws in app['websockets']:
        await ws.close(code=aiohttp.WSCloseCode.GOING_AWAY,
                       message='Server shutdown')

async def websocket_handler(request):
    ws = web.WebSocketResponse()
    await ws.prepare(request)

    app = request.app
    app['websockets'].add(ws)
    async for msg in ws:
        if msg.type == aiohttp.WSMsgType.TEXT:
            if msg.data == 'tail':
                await app['real_time_log'].set_state(msg)
                continue
            await ws.send_json({
                'state': 'unknown',
                'message': 'Unknown operation'
            })
        elif msg.type == aiohttp.WSMsgType.ERROR:
            break

    app['websockets'].remove(ws)
    await ws.close()
    return ws

async def real_time_log_factory(app, handler):
    real_time_log = app['real_time_log'] = NginxLog('/var/log/nginx/access.log')
    app.router.add_route('GET', '/real-time-log', real_time_log)
    app.router.add_route('GET', '/websocket', handler)
    return real_time_log

async def clk():
    return int(time.time())

def attrs():
    # Rotate the list.
    # This means that the first round could have remote_addr on 
    # index 4 and second round on index 3 and so on.
    for i in random.sample(range(len(string.ascii_letters)), len(string.ascii_letters)):
        yield string.ascii_letters[i]

async def response(request):
    ctime = await clk()
    headers = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKMNOPQRSTUVWXYZ0123456789 ,.:;{}[]()*&^^%$#@!~`'"
    bodyattrs = ''.join(attrs())
    headersattrs = ''.join(attrs())
    data = "".join(
            [headers[i % len(headers)] if i % 17 == 0 else bodyattrs[i % len(bodyattrs)]
                         for i in range(0, 1024)
                    ]
                )
    return web.Response(body=data.encode(), headers={"X-Response-Time": str(ctime), headersattrs: headersattrs})

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Nginx Real-time log')
    parser.add_argument('--port', type=int, default=8080,
                            help='Port to run web-server on')
    parser.add_argument('--host', type=str, default='localhost',
                            help='Host to run web-server on')
    args = parser.parse_args()
    app = web.Application()
    app['websockets'] = set()
    app.router.add_route('GET', '/sample-response', response)
    app.on_shutdown.append(on_shutdown)
    real_time_log = app.loop.run_until_complete(
        real_time_log_factory(app, websocket_handler))
    app_runner = web.AppRunner(app)
    app.addr = args.host
    app.port = args.port
    app.url = f"http://{app.addr}:{app.port}"
    app.task = app.loop.create_task(aiohttp.web.run_app(app, host='localhost', port=args.port))
    try:
        app.loop.run_forever()
    except KeyboardInterrupt as e:
        pass
    finally:
        print("Exiting.")
        sys.exit(0) 

该代码中, RealTimeLog 类是一个抽象类, NginxLog 是对其的具体实现。它在父类 RealTimeLog 中实现了 WebSocket 连接的追踪和推送。在子类 NginxLog 中, 使用了 Tail 作为传入的文件。

attrs 生成用于改变响应体的属性和头部的随机字符串。 clk 生成用于将当前时间添加到头部中的时间戳。 response 使用了 attrs 方法和生成的时间。

调用函数中, 首先从参数解析器中提取参数。 app['websockets'] = set() 实例化一个全局的 socket 集合,其中, real_time_log 是从方法 real_time_log_factory 中获取的。后者通过 WebSocket 传输的数据由此生成,并且会一直在后台运行。

最后,通过aiohttp.web.run_app 方法开始将 app 对象转换为一个 HTTP 服务器。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Nginx实现浏览器可实时查看访问日志的步骤详解 - Python技术站

(0)
上一篇 2023年5月30日
下一篇 2023年5月30日

相关文章

  • jsp SmartUpload 中文乱码问题解决

    请看下面的详细讲解: JSP SmartUpload 中文乱码问题解决 背景 在使用JSP SmartUpload进行文件上传时,经常会碰到一些中文乱码的问题。这是由于SmartUpload默认的编码方式与我们的页面编码方式不同所导致的。为了解决这个问题,我们需要针对SmartUpload的默认编码方式进行修改。 解决步骤 以下是详细的解决步骤:1. 打开S…

    html 2023年5月31日
    00
  • html标签之Object和EMBED标签详解

    让我来详细讲解一下“HTML标签之Object和EMBED标签详解”。 什么是Object标签? <object> 标签定义了嵌入对象,比如图像、声音、视频、Java applets、ActiveX、PDF,以及 Flash 等等。<object> 标签最常用于在 HTML 页面中插入基于插件的媒体以及其他应用程序。 Object标签…

    html 2023年5月30日
    00
  • ajax中文乱码的各种解决办法总结

    标题: Ajax中文乱码的各种解决办法总结 正文:在使用Ajax进行数据交互过程中,有时候会遇到中文乱码的问题。这种情况通常是由于字符集不统一或编码格式不正确引起的。本文将为大家总结几种解决Ajax中文乱码问题的常见方法。 1、在服务端指定字符集 在服务端脚本中指定正确的字符集可以避免中文乱码问题。常见示例如下: header(‘Content-type:t…

    html 2023年5月31日
    00
  • XSLT轻松入门第三章:XSLT的元素语法

    第三章:XSLT的元素语法 XSLT的语法是由XML元素和属性构成的,这些元素和属性定义了如何将一个文档转换成另一个文档。XSLT的元素语法主要包括以下4个方面: 根元素 每个XSLT文档只能有一个根元素,它的名称必须是xsl:stylesheet。根元素可以包含一些属性,用于指定XSLT样式表的一些信息,例如命名空间、版本号等。以下是一个简单的根元素的示例…

    html 2023年5月30日
    00
  • win10笔记本已连接充电器却不显示连接怎么解决?

    如果您的Win10笔记本已连接充电器却不显示连接,可能是由于以下原因导致的:充电器故障、电源线松动、电池老化等。以下是解决此问题的完整攻略: 步骤1:检查充电器和电源线 确认充电器插头已插入笔记本电脑的电源插口。 确认电源线插头已插入充电器。 确认电源线插头已插入电源插座。 确认电源线没有损坏或磨损。 步骤2:检查电池 关闭笔记本电脑。 拆下电池。 检查电池…

    html 2023年5月17日
    00
  • C#写入XML文档

    下面就分享一下C#写入XML文档的完整攻略,包括几个方面: 引用命名空间 首先需要引用System.Xml命名空间,它包含了C#中使用XML的基本类和方法。 using System.Xml; 创建XML文档对象 在C#中,可以通过XmlDocument类创建一个XML文档对象。创建文档对象的代码如下: XmlDocument xmlDoc = new Xm…

    html 2023年5月30日
    00
  • 网马生成器 MS Internet Explorer XML Parsing Buffer Overflow Exploit (vista) 0day

    首先需要说明的是,网马生成器 MS Internet Explorer XML Parsing Buffer Overflow Exploit (vista) 0day是一种恶意软件攻击方式,对于网站的作者来说,需要采取一些措施来保护自己的网站,以避免遭到此类攻击。 攻击过程的大致步骤如下: 攻击者发现了一个漏洞,利用该漏洞可以向页面注入恶意代码。 攻击者通…

    html 2023年5月30日
    00
  • 计算机中的字符串编码、乱码、BOM等问题详解

    计算机中的字符串编码、乱码、BOM等问题详解 字符编码的概念 计算机中的字符本质上是一个数字,用来表示各种相应的字符,例如字母、数字、符号、汉字等等。这个数字就是字符编码。 在计算机领域,常见的字符编码有ASCII、GB2312、GBK、UTF-8等,它们都有不同的编码规则和代表字符的范围,例如ASCII编码只能表示英文和基本符号。 乱码的原因 当使用不同的…

    html 2023年5月31日
    00
合作推广
合作推广
分享本页
返回顶部