普通视图

Received today — 2026年4月18日Liu Zijian's Blog

使用filebeat采集Nginx日志到ES

2026年4月18日 00:00

filebeat是传统elk组件中logstach的升级替代,能够高性能的采集一些中间件的日志到es中,供检索分析。

1.安装filebeat

首先要安装filebeat到nginx所在服务器,因为我的服务器是rocky linux属于redhat系,故这里通过yum安装,先设置安装源

导入GPG-KEY

rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch

新建一个elastic.repo文件在/etc/yum.repos.d下,并粘贴安装源地址

vim /etc/yum.repos.d/elastic.repo

[elastic-9.x]name=Elastic repository for 9.x packagesbaseurl=https://artifacts.elastic.co/packages/9.x/yumgpgcheck=1gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearchenabled=1autorefresh=1type=rpm-md

接下来执行安装,直到安装完成

yum install filebeat -y

2.设置nginx和filebeat

首先确认nginx的日志路径和日志格式,一般日志路径默认就是:

  • /var/log/nginx/access.log 常规访问日志
  • /var/log/nginx/error.log 错误日志

在nginx.conf配置文件中,默认的日志格式是:

log_format  main  ' $remote_addr - $remote_user [$time_local] "$request" '                  '$status $body_bytes_sent "$http_referer" '                  '"$http_user_agent" "$http_x_forwarded_for"';

为了区分各个主机的访问记录,我选择增加一个主机的字段:$host

log_format  main  '$host $remote_addr - $remote_user [$time_local] "$request" '                  '$status $body_bytes_sent "$http_referer" '                  '"$http_user_agent" "$http_x_forwarded_for"';

亲测filebeat可以识别上述的日志格式,自动提取有效信息

然后设置filebeat,通过yum安装的filebeat,默认全局配置文件位于/etc/filebeat/filebeat.yml,有这样几项需要修改

output.elasticsearch:  # 改成自己es地址和端口  hosts: ["localhost:9016"]  # 改成自己的索引格式  index: "nginx-logs-%{+yyyy.MM.dd}"  # 通信协议按需要修改  protocol: "http"  # es用户名密码,必须设置  username: "elastic"  password: "***************"# 需要新增这两项,索引数据格式模板名称setup.template.name: "tx-custom-logs"setup.template.pattern: "tx-custom-logs-*"

然后对nginx的采集功能进行设置,filebeat支持很多中间件的日志采集,通过yum安装的filebeat,默认的各中间件的采集配置文件位于:/etc/filebeat/modules.d/

首先要将默认的nginx配置文件nginx.yml.disabled复制出一份nginx.yml,因为最后filebeat只会自动导入读取.yml结尾的文件

cp /etc/filebeat/modules.d/nginx.yml.disabled /etc/filebeat/modules.d/nginx.yml

vim编辑/etc/filebeat/modules.d/nginx.yml配置文件,针对nginx的采集进行配置

- module: nginx  # 打开常规访问日志采集,指定日志路径  access:    enabled: true    var.paths: ["/var/log/nginx/access.log"]    var.timezone: "Asia/Shanghai"  # 打开错误日志采集,指定日志路径  error:    enabled: true    var.paths: ["/var/log/nginx/error.log"]    var.timezone: "Asia/Shanghai"

都修改完成后,通过filebeat test config命令,验证配置文件是否有语法错误

[root@VM-0-3-rockylinux ~]# filebeat test configConfig OK

然后启动filebeat,并且能看到进程,启动成功

[root@VM-0-3-rockylinux ~]# systemctl start filebeat[root@VM-0-3-rockylinux ~]# ps -ef | grep filebeatroot      279214       1  0 Apr17 ?        00:00:09 /usr/share/filebeat/bin/filebeat --environment systemd -c /etc/filebeat/filebeat.yml --path.home /usr/share/filebeat --path.config /etc/filebeat --path.data /var/lib/filebeat --path.logs /var/log/filebeatroot      484905  454652  0 14:33 pts/2    00:00:00 grep --color=auto filebeat

3.查看索引

登录kibana,打开开发工具,就能看到filebeat建的索引和采集到的日志了,还可以根据业务需要制作图表等

还可以通过检索,通过链接和访问次数进行聚合,查出一些攻击和刺探的恶意请求,例如:

GET /nginx-logs-2026.04.18/_search{  "size": 0,   "aggs": {    "ip_counts": {      "terms": {        "field": "url.domain.keyword",       "size": 20000      },      "aggs": {        "domains_per_ip": {          "terms": {            "field": "source.ip.keyword",            "size": 20000                      },          "aggs": {            "domains_per_path": {              "terms": {                "field": "url.path.keyword",                "size": 20000                              }            }          }        }      }    }  }}
Received before yesterdayLiu Zijian's Blog

Python的函数

2026年1月10日 00:00

本文未完待续

1.定义

1.函数代码以def关键字开头,后接函数标识符名称和圆括号()
2.任何传入的参数和自变量必须放在圆括号内,圆括号中定义参数
3.函数内容以冒号:开始,需要缩进
4.return表达式结束函数,返回一个值给调用方,不带表达式的return相当于返回None

def 函数名(参数列表):    函数体    return 返回值

例:

def greet(name, age):    print("Hello World")

2.类型注解 Type Hints

Python函数参数不需要声明类型,解释器会自动推断,但是会带来难以理解,隐藏BUG,开发效率低下等问题,因此类型注解通过引入可选的类型信息解决这些问题,明确指出函数和返回值的类型,让代码更加健壮可维护。

在实现复杂逻辑和对外提供公共接口时,都应当使用类型注解

例:
func.py

def greet(name: str, age: int) -> str:    return f"Hello  World {name}, age {age}"

但是,调用时仍然可以不遵守

func.py

def greet(name: str, age: int) -> str:    return f"Hello  World {name}, age {age}"if __name__ == '__main__':    print( greet('lzj', 12.6) )

此时可以通过mypy工具包,对我们的代码进行检测,会检测出问题

先安装mypy工具 pip install mypy,再进行检测

PS D:\PycharmProjects\python-lang-test> mypy .\func\func.pyfunc\func.py:5: error: Argument 2 to "greet" has incompatible type "float"; expected "int"  [arg-type]Found 1 error in 1 file (checked 1 source file)

如果要彻底避免,需要进行严格类型检查

def add(a: int, b: int) -> int:    if not isinstance(a, int):        raise TypeError(f"参数a期望类型int,实际传入{type(a).__name__}")    if not isinstance(b, int):        raise TypeError(f"参数b期望类型int,实际传入{type(b).__name__}")    return a + bresult2 = add('5', 3)print(result2)
Traceback (most recent call last):  File "D:\PycharmProjects\python-lang-test\func\func.py", line 9, in <module>    result2 = add('5', 3)  File "D:\PycharmProjects\python-lang-test\func\func.py", line 4, in add    raise TypeError(f"参数a期望类型int,实际传入{type(a).__name__}")TypeError: 参数a期望类型int,实际传入str

在函数返回值是某种特定类型或None时使用Optional,等价于Union[具体类型, None]

例:dic.get(name)可能返回字典的值,也可能在没有值时返回None

from typing import Optionaldef age(name: str) -> Optional[int]:    dic = {'a':16, 'b':17, 'c':18}    return dic.get(name)if __name__ == '__main__':    print(age('dd'))    print(age('a'))
None16

3.参数

3.1 必须参数

以正确的形式传入函数,数量要和声明时保持一致

from typing import Optionaldef fun(age:int) -> Optional[int]:    print(age)    return agefun(10)

3.2 关键字参数

函数调用使用关键字参数来确定传入的参数值

def fun(age:int, name:str) :    print(age)    print(name)fun(name='lzj', age=10)
10lzj

3.3 默认参数

调用函数时,如果没有传递参数,则会使用默认参数

def fun(name:str = "a", age:int = 25) :    print(f"fun---name:{name} age:{age}")fun()fun("zhangliang")fun("wangqiang", 28)
fun---name:a age:25fun---name:zhangliang age:25fun---name:wangqiang age:28

3.4 “*”可变参数

加了*的参数会以元组的形式传入,一般这种参数放在最后

格式:

def fun([普通参数], *var_args_tuple) :    函数体

例:

def print_info(num, *var_tuple):    print(num)    print(var_tuple)print_info(70,1,2,3,4,5)print_info(80)
70(1, 2, 3, 4, 5)80()

如果后面还有参数,必须通过关键字参数传入,如果没有给不定长的参数传参,那么得到的是空元组

def print_info1(seq, *var_tuple, age) :    print(seq)    print(var_tuple)    print(age)print_info1(1,20,30,40,50, age = 25)print_info1(70, age = 29)
1(20, 30, 40, 50)2570()29

3.5 “**”可变参数

❌