集中管理与实时审计:构建Linux集群(1300台服务器)日志平台的最佳实践
简介
随着企业IT基础设施的不断扩大,Linux服务器的数量也日益增多,传统的单机日志管理方式已无法满足对日志数据集中管理、审计和分析的需求。尤其是在大型集群环境中,如何高效地收集、存储和分析日志成为了一项重要的技术挑战。
背景
在实现对大型Linux集群的日志集中管理与审计,特别是针对rsyslog日志的收集、操作命令日志以及登录日志的审计。通过部署集中的rsyslog服务端,能够统一收集1300多台Linux服务器的系统日志,确保日志数据的集中化管理。使用Filebeat作为日志收集工具,将日志数据推送至Logstash进行清洗和转换,最终存储到Elasticsearch中,并通过Kibana实现实时数据可视化展示。这种方式不仅简化了日志管理流程,还提高了系统的监控效率和安全性。
需求
统一管理 1300 台服务器的Linux系统日志,能够及时发现问题和告警。
解决方案
- 集中管理:通过统一的服务端收集所有Linux服务器的日志数据,减少单独配置每台服务器的工作量。
- 日志审计:对操作命令日志、登录日志等进行审计,确保系统行为的可追溯性。
- 数据清洗与分析:通过日志清洗与格式转换,确保日志数据的标准化,便于后续的分析和可视化展示。
- 实时展示:利用Kibana将清洗后的数据实时可视化,帮助运维人员快速发现潜在问题。
整体架构
为实现这些目标,我们设计了以下的系统架构:
- rsyslog:作为日志收集的核心组件,它负责将来自Linux系统的各种日志(包括
/var/log/messages
等)统一推送到中心化的日志服务端。 - Filebeat:作为轻量级的日志收集器,部署在各个Linux节点上,负责将日志文件传输到Logstash。
- Logstash:对收集到的日志进行清洗、解析和转换,确保数据符合预定格式,便于存入Elasticsearch。
- Elasticsearch:存储经过清洗和转换的日志数据,提供强大的全文搜索和数据查询功能。
- Kibana:通过Kibana仪表盘实时展示存储在Elasticsearch中的日志数据,帮助运维人员进行数据分析和可视化展示。
rsyslog汇总
rsyslog服务端
首先配置rsyslog服务器,可以统一收集集群内部的日志。
# 加载本地系统日志模块(例如通过 logger 命令发送的日志)
$ModLoad imuxsock
# 加载内核日志模块(之前由 rklogd 处理)
$ModLoad imklog
# 加载 UDP 模块,支持通过 UDP 协议接收日志
$ModLoad imudp
# 配置 UDP 服务器在 514 端口接收日志
$UDPServerRun 514
# 加载 TCP 模块,支持通过 TCP 协议接收日志
$ModLoad imtcp
# 配置 TCP 服务器在 514 端口接收日志
$InputTCPServerRun 514
# 定义一个自定义的日志格式模板 'myFormat'
$template myFormat,"%timestamp:::date-rfc3339% %fromhost-ip% %HOSTNAME% [%programname%] %syslogseverity-text%:%msg%\n"
# 设置默认的文件格式为传统的 rsyslog 格式
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
# 加载 /etc/rsyslog.d/ 目录下的所有配置文件
$IncludeConfig /etc/rsyslog.d/*.conf
# 配置收集 info 级别的日志,排除 mail、authpriv、cron 类别的日志,输出到 /var/log/messages 文件,并使用 myFormat 格式
*.info;mail.none;authpriv.none;cron.none /var/log/messages;myFormat
# 收集所有 authpriv 类别的日志(通常是认证相关的日志),输出到 /var/log/secure 文件,并使用 myFormat 格式
authpriv.* /var/log/secure;myFormat
# 收集所有 mail 类别的日志,输出到 /var/log/maillog 文件,使用异步写入(- 表示异步)
mail.* -/var/log/maillog
# 收集所有 cron 类别的日志(定时任务日志),输出到 /var/log/cron 文件
cron.* /var/log/cron
# 收集所有紧急级别(emerg)的日志,将其通过系统消息发送
*.emerg :omusrmsg:*
# 收集 uucp 和 news 类别的严重级别(crit)日志,输出到 /var/log/spooler 文件
uucp,news.crit /var/log/spooler
# 收集所有 local7 类别的日志,输出到 /var/log/boot.log 文件
local7.* /var/log/boot.log
重启服务端
systemctl restart rsyslog
修改前:
修改后:
rsyslog客户端
所有集群的客户端配置最后一行IP,就可以把数据汇总在一切
[root@zabbix ~]# cat /etc/rsyslog.conf |tail -n 2
#authpriv.* @10.10.10.17
*.* @@192.168.102.20 # rsyslog 服务端的IP
重启
systemctl restart rsyslog.service
日志已经打印到rsyslog 服务端的 /var/log/messages /var/log/secure 等文件
filebeaet收集
在rsyslog 服务端的安装filebeaet,并且使用如下配置启动
filebeat.config.modules:path: ${path.config}/modules.d/*.ymlreload.enabled: false
filebeat.inputs:
- type: logenabled: truetail_files: truepaths:- /var/log/messages
output.logstash:hosts: ["192.168.1.100:5514"] # 把日志发送到logstatsh中
logstatsh配置
[root@game logstash]# cat config/rsyslog.conf
input {beats {port => 5514type => syslog}
}filter {grok {match => { "message" => "%{TIMESTAMP_ISO8601:time} %{IP:client_ip} %{HOSTNAME:host_name} \[%{DATA:type}\] %{GREEDYDATA:info}"}overwrite => ["message"]}mutate { split => ["type",","] }mutate{add_field => {"types" => "%{[type][1]}"
} }mutate{remove_field => [ "tags","agent","host","log","ecs","type" ]}date {match => ["time", "yyyy-MM-dd HH:mm:ss,SSS", "UNIX"]target => "@timestamp"locale => "cn"}
}output {stdout {codec=> rubydebug}elasticsearch {hosts => ["127.0.0.1:9200"]index => "message"}
}
数据格式
2024-12-03T18:35:30+08:00 192.168.102.30 master01 [kubelet] info: E1203 18:35:30.827608 1065 summary_sys_containers.go:83] "Failed to get system container stats" err="failed to get cgroup stats for \"/system.slice/docker.service\": failed to get container info for \"/system.slice/docker.service\": unknown container \"/system.slice/docker.service\"" containerName="/system.slice/docker.service"
GROK解析
%{TIMESTAMP_ISO8601:time} %{IP:client_ip} %{HOSTNAME:host_name} \[%{DATA:type}\] %{GREEDYDATA:info}
输出格式
{"client_ip": "192.168.102.30","time": "2024-12-03T18:35:30+08:00","type": "kubelet","host_name": "master01","info": "info: E1203 18:35:30.827608 1065 summary_sys_containers.go:83] \"Failed to get system container stats\" err=\"failed to get cgroup stats for \\\"/system.slice/docker.service\\\": failed to get container info for \\\"/system.slice/docker.service\\\": unknown container \\\"/system.slice/docker.service\\\"\" containerName=\"/system.slice/docker.service\"\r"
}
操作系统命令审计
Linux一般都是终端执行命令,我们可以让命令写到message日志上,在通过过滤,获取操作命令记录。
Linux终端配置
[root@zabbix ~]# cat /etc/profile | tail -n 2
unset MAILCHECK
export PROMPT_COMMAND='{ msg=$(history 1 | { read x y; echo $y; });logger -p local2.info "euid=$(whoami)" $(who am i) `pwd` "$msg"; }'日志格式
Oct 11 17:32:41 zabbix root: euid=root root pts/0 2021-10-11 15:13 (10.10.10.3) /root cat /etc/profile
Oct 11 17:32:47 zabbix root: euid=root root pts/0 2021-10-11 15:13 (10.10.10.3) /root cat /etc/profile | tail -n 2
rsyslog服务端展示
filebeat配置
[root@logserver01 filebeat]# cat system_messages.yml
#=========================== Filebeat inputs =============================
filebeat.inputs:
- type: logenabled: truetail_files: truepaths:- /var/log/messages
logstatsh配置
[root@logserver01 config]# cat system_userlog_FromKafkaInES.conf
input{beats {host => '172.17.9.200'port => 5046}# kafka{
# bootstrap_servers => ["172.17.8.232:6667"]
# topics => ["sys_os_exe"]
# codec => "json"
# group_id => "ELK_SYSTEM_EXE_GROUP"
# consumer_threads => 3
# client_id => "logstash"
# decorate_events => false
# auto_offset_reset => "earliest"
# request_timeout_ms => "300000"
# session_timeout_ms => "20000"
# max_poll_interval_ms => "600000"
# }
}
filter{if ([message] =~ "euid"){grok{match => {"message" => '^(?<exetime>\d+-\d+-\d+)(?:[^\d]+)(?<hhmmss>\d+:\d+:\d+)(?:[^\d]+\d+:\d+)(?:\s)(?<deshost>[^ ]+)(?:\s)(?<name>[^ ]+)(?:\s\[)(?<loginuser>[^ |\]]*)(?:\]\s[^ ]+\seuid=)(?<exeuser>[^ ]+)(?:\s+)(?<userinfo>[^\(]+)(?:\s\()(?<srchost>[^\)]+)(?:\)\s)(?<exepath>[^ ]+)(\s+)(?<exeinfo>.*)'}}if "_grokparsefailure" in [tags] { drop { } }mutate{add_field => ["tmp_exeinfo","%{exeinfo}"]}mutate{split => ["exetime","-"]split => ["tmp_exeinfo"," "]}mutate{add_field => ["indextime","%{[exetime][0]}%{[exetime][1]}"]add_field => ["evtTime","%{[exetime][0]}-%{[exetime][1]}-%{[exetime][2]} %{hhmmss}"]add_field => ["cmd","%{[tmp_exeinfo][0]}"]}#Retention log insertion time to ES..............ruby { code => "event.set('inserttime', event.get('@timestamp').time.to_i)" }#replace InsertTime with evtTime "yyyy-MM-dd HH:mm:ss eg:2020-06-29 09:24:29"date{match => ["evtTime","yyyy-MM-dd HH:mm:ss"]#kibana use this time....................target => "@timestamp"}mutate{replace => ["evtTime","%{evtTime} +0800"]}date{match => ["evtTime","yyyy-MM-dd HH:mm:ss +0800"]timezone =>"UTC"#log event time timestamp................target => "logtimestamp"}#log event time long string......................ruby { code => "event.set('longtime', event.get('logtimestamp').time.to_i)" }mutate{remove_field => [ "tmp_exeinfo","evtTime","host","ecs","log","hhmmss","input","agent","exetime" ]}}else{drop{}}
}
output{stdout{codec => rubydebug}if [indextime] !~ "index"{elasticsearch{hosts => ["http://172.17.9.176:9200"]#hosts => "172.17.9.176"index => "sys_os_userlog_%{[indextime]}"user => "*********"password => "*********"}}
}
数据格式
2024-12-03T18:39:05+08:00 192.168.102.30 master01 [root] info: euid=root root pts/0 2024-12-03 18:21 (192.168.96.19) /root [2024-12-03 18:39:05]ip a
GROK解析
^(?<exetime>\d+-\d+-\d+)(?:[^\d]+)(?<hhmmss>\d+:\d+:\d+)(?:[^\d]+\d+:\d+)(?:\s)(?<deshost>[^ ]+)(?:\s)(?<name>[^ ]+)(?:\s\[)(?<loginuser>[^ |\]]*)(?:\]\s[^ ]+\seuid=)(?<exeuser>[^ ]+)(?:\s+)(?<userinfo>[^\(]+)(?:\s\()(?<srchost>[^\)]+)(?:\)\s)(?<exepath>[^ ]+)(\s+)(?<exeinfo>.*)
输出格式
{"loginuser": "root","hhmmss": "18:39:05","exepath": "/root","deshost": "192.168.102.30","srchost": "192.168.96.19","name": "master01","exeinfo": "[2024-12-03 18:39:05]ip a\r","exeuser": "root","userinfo": "root pts/0 2024-12-03 18:21","exetime": "2024-12-03"
}
系统用户登录审计
filebeat配置
[root@logserver01 filebeat]# cat system_secure.yml
#=========================== Filebeat inputs =============================
filebeat.inputs:
- type: logenabled: truetail_files: truepaths:- /var/log/secure
#=========================== Filebeat outppp_id: messuts =============================
output.logstash:hosts: ["172.17.9.200:5045"]
logstatsh配置
[root@logserver01 config]# cat system_login_FromKafkaInES.conf
input{beats {host => '172.17.9.200'port => 5045}#
# kafka{
# bootstrap_servers => ["172.17.8.232:6667"]
# topics => ["sys_os_login"]
# codec => "json"
# group_id => "ELK_SYSTEM_LOGIN_GROUP"
# consumer_threads => 3
# client_id => "logstash"
# decorate_events => false
# auto_offset_reset => "earliest"
# request_timeout_ms => "300000"
# session_timeout_ms => "20000"
# max_poll_interval_ms => "600000"
# }
}
filter{#login successed logif ([message] =~ "Accepted"){grok{match => {"message" => '^(?<atime>\d+-\d+-\d+)(?:[^\d]+)(?<hhmmss>\d+:\d+:\d+)(?:[^\d]+\d+:\d+)(?:\s+)(?<deshost>\d+\.\d+\.\d+\.\d+)(?:\s)(?<name>[^ ]+)(?:[\S\s]*Failed\spassword\sfor[\sinvalid\suser]*\s)(?<loginuser>[^ ]+)(?:\sfrom\s)(?<srchost>[\d.]+)(?:\s\w+\s\d+\s)(?<loginmode>\w*)'}}if "_grokparsefailure" in [tags] { drop { } }mutate{add_field => ["type","systemlogin"]split => ["atime","-"]}mutate{add_field => ["indextime","%{[atime][0]}%{[atime][1]}"]add_field => ["evtTime","%{[atime][0]}-%{[atime][1]}-%{[atime][2]} %{hhmmss}"]}#Retention log insertion time to ES..............ruby { code => "event.set('inserttime', event.get('@timestamp').time.to_i)" }#replace InsertTime with evtTime "yyyy-MM-dd HH:mm:ss eg:2020-06-29 09:24:29"date{match => ["evtTime","yyyy-MM-dd HH:mm:ss"]#kibana use this time....................target => "@timestamp"}mutate{replace => ["evtTime","%{evtTime} +0800"]}date{match => ["evtTime","yyyy-MM-dd HH:mm:ss +0800"]timezone =>"UTC"#log event time timestamp................target => "logtimestamp"}#log event time long string......................ruby { code => "event.set('longtime', event.get('logtimestamp').time.to_i)" }mutate{remove_field => [ "evtTime","host","ecs","log","hhmmss","input","agent","atime" ]}}#login failed logelse if ([message] =~ "Failed password for"){grok{match => {"message" => '^(?<atime>\d+-\d+-\d+)(?:[^\d]+)(?<hhmmss>\d+:\d+:\d+)(?:[^\d]+\d+:\d+)(?:\s+)(?<deshost>\d+\.\d+\.\d+\.\d+)(?:[\S\s]*Failed\spassword\sfor[\sinvalid\suser]*\s)(?<loginuser>[^ ]+)(?:\sfrom\s)(?<srchost>[\d.]+)(?:\s\w+\s\d+\s)(?<loginmode>\w*)'}}if "_grokparsefailure" in [tags] { drop { } }mutate{add_field => ["type","systemloginfailed"]split => ["atime","-"]}mutate{add_field => ["indextime","%{[atime][0]}%{[atime][1]}"]add_field => ["evtTime","%{[atime][0]}-%{[atime][1]}-%{[atime][2]} %{hhmmss}"]}#Retention log insertion time to ES..............ruby { code => "event.set('inserttime', event.get('@timestamp').time.to_i)" }#replace InsertTime with evtTime "yyyy-MM-dd HH:mm:ss eg:2020-06-29 09:24:29"date{match => ["evtTime","yyyy-MM-dd HH:mm:ss"]#kibana use this time....................target => "@timestamp"}mutate{replace => ["evtTime","%{evtTime} +0800"]}date{match => ["evtTime","yyyy-MM-dd HH:mm:ss +0800"]timezone =>"UTC"#log event time timestamp................target => "logtimestamp"}#log event time long string......................ruby { code => "event.set('longtime', event.get('logtimestamp').time.to_i)" }mutate{remove_field => [ "evtTime","host","ecs","log","hhmmss","input","agent","atime" ]}}#other logelse{drop{}}
}
output{if [type] == "systemlogin"{if [indextime] !~ "index"{stdout{codec => rubydebug}elasticsearch{hosts => "172.17.9.176"index => "sys_os_systemlogin_%{[indextime]}"user => "elastic"password => "f5OPbv6sqfstmc+"}}}else if [type] == "systemloginfailed"{if [indextime] !~ "index"{stdout{codec => rubydebug}elasticsearch{hosts => "172.17.9.176"index => "sys_os_systemloginfailed_%{[indextime]}"user => "elastic"password => "xxxxxxx+"}}}
}
成功日志解析
日志格式
2024-12-03T18:45:09+08:00 192.168.102.42 node03 [sshd] info: Accepted password for root from 192.168.96.19 port 14347 ssh2
GROK语法
%{TIMESTAMP_ISO8601:atime} %{IP:deshost} %{HOSTNAME:name} \[%{WORD:type}\] %{DATA:loglevel}: Accepted password for %{WORD:loginuser} from %{IP:srchost} port %{NUMBER:port} %{WORD:loginmode}
日志格式
{"loginuser": "root","atime": "2024-12-03T18:45:09+08:00","type": "sshd","deshost": "192.168.102.42","srchost": "192.168.96.19","port": "14347","loglevel": "info","name": "node03","loginmode": "ssh2"
}
失败日志格式
日志格式
2024-12-03T19:01:57+08:00 192.168.102.42 node03 [sshd] info: Failed password for invalid user 123 from 192.168.96.19 port 12103 ssh2
GROK语法
^(?<atime>\d+-\d+-\d+)(?:[^\d]+)(?<hhmmss>\d+:\d+:\d+)(?:[^\d]+\d+:\d+)(?:\s+)(?<deshost>\d+\.\d+\.\d+\.\d+)(?:[\S\s]*Failed\spassword\sfor[\sinvalid\suser]*\s)(?<loginuser>[^ ]+)(?:\sfrom\s)(?<srchost>[\d.]+)(?:\s\w+\s\d+\s)(?<loginmode>\w*)
日志输出
{"loginuser": "123","atime": "2024-12-03","hhmmss": "19:01:57","deshost": "192.168.102.42","srchost": "192.168.96.19","loginmode": "ssh2"
}
相关文章:

集中管理与实时审计:构建Linux集群(1300台服务器)日志平台的最佳实践
简介 随着企业IT基础设施的不断扩大,Linux服务器的数量也日益增多,传统的单机日志管理方式已无法满足对日志数据集中管理、审计和分析的需求。尤其是在大型集群环境中,如何高效地收集、存储和分析日志成为了一项重要的技术挑战。 背景 在实…...
在Scala中Array不可变的学习
package gjhs114import scala.collection.mutable.ArrayBuffer object Arrray114 {// 不可变数组:Array// def main(args: Array[String]): Unit {1 创建不可变数组// val arr1 Array(1,2,3)//2 访问.数组名(下标)。下标是从0开始到…...

vue3+vite 批量引入组件动态使用
import { ref, reactive, toRaw, markRaw, defineAsyncComponent, onMounted } from vue import type { Component } from vue// vue3vite 批量引入组件动态使用 const modules import.meta.glob<Component>(./details/*.vue) // 明确指定导入的模块类型为Component con…...
设计模式——方法链or流式接口
方法链或流式接口是一种编程模式或设计模式。核心思想是通过返回对象自身的应用,使得可以在一个表达式中连续调用多个方法。 c中实现这种模式 1.基本语法规则 (1)每个可链接的方法都返回对象自身的引用(通常是*this)…...
JAVA OPCUA 服务端开发,客户端连接会话监听和订阅事件监听
前言 关于使用milo开源库,开发opc ua服务器,有网友咨询如何设置服务端如何监听客户端的连接或断开事件,如何监听客户端发起订阅事件的代码实现,于是我完善了这部分的空缺整理整了这篇教程,希望能解决有同样需求,但是遇到困难的网友!因为milo没有官方文档的教程且网上详…...
pytest相关总结
1.pytest -v -s -v将测试用例名称和用例中的输出进行展示,将每条用例脚本的内容逐行进行结果展示; -s 参数是为了显示用例执行层级的打印信息 pytest使用总结笔记 - fengf233 - 博客园 2....

cin/cout的性能优化和缓冲区同步问题
目录 背景导入 问题 1.1ios::sync_with_stdio(false) 1.2为什么要解除C/C IO流同步? 1.3使用场景 2.1cin和cout的绑定关系 2.2为什么要解除绑定关系? 2.3注意事项 背景导入 大家可以先看一下这段背景知识;后面我会谈谈自己的理解; 1.在C中,标准输⼊输出流…...
redisson-spring-data与Spring-Data-Redis的版本关系问题
redisson-spring-boot-starter https://github.com/redisson/redisson/tree/master/redisson-spring-boot-starter https://github.com/redisson/redisson/tree/master/redisson-spring-data#spring-data-redis-integration 将 Redisson 与 Spring Boot 库集成。依赖于Spring…...

Puppeteer代理认证的最佳实践和示例
在现代网络环境中,代理服务器的使用越来越普遍,尤其是在数据抓取、网页自动化测试和网络监控等领域。Puppeteer作为一个流行的Node库,它提供了高级的API来控制Chrome或Chromium浏览器。在某些情况下,我们需要通过代理服务器来执行…...
js 字符串 只显示数字
1. 使用正则表达式的match方法 原理:正则表达式\d用于匹配一个或多个数字。match方法会在字符串中查找与正则表达式匹配的部分,并返回一个包含所有匹配结果的数组。示例代码: let str "abc123def456"; let numbers str.match(/…...

STM32标准库-FLASH
FLASH模仿EEPROM STM32本身没有自带EEPROM,但是自带了FLASH存储器。 STM32F103ZET6自带 1M字节的FLASH空间,和 128K64K的SRAM空间。 STM32F4 的 SPI 功能很强大,SPI 时钟最高可以到 37.5Mhz,支持 DMA,可以配置为 SPI协…...

PowerShell:查找并关闭打开的文件
Get-SmbOpenFile 打开 Windows PowerShell 并运行 Get-SmbOpenFile | Format-List 若要仅显示特定文件共享的连接,请使用 Where-Object 运行 Get-SmbOpenFile。 Get-SmbOpenFile | Where-Object Path -eq "C:\Data\" | Format-List Get-SmbSession 显…...

【AI系统】昇腾异构计算架构 CANN
昇腾异构计算架构 CANN 本文将介绍昇腾 AI 异构计算架构 CANN(Compute Architecture for Neural Networks),这是一套为高性能神经网络计算需求专门设计和优化的架构。CANN 包括硬件层面的达芬奇架构和软件层面的全栈支持,旨在提供…...

STM32 HAL库开发学习3.STM32启动浅析
STM32 HAL库开发学习3.STM32启动浅析 一、STM32启动模式(也称自举模式)1. MSP与PC指针赋值2. F1系列的启动模式:3. F4系列启动模式4. F7系列启动模式5. H7系列启动模式 二、STM32启动过程1. MSP 栈顶地址2. PC值3. Reset_Handler4. 启动文件内…...

FakeLocation 1.3.5 BETA 提示校园跑漏洞修复解决
任务一 作者对此又进行了更新,在本次更新中,我们依旧使用hookvip进行破解 本次的更新,使得包名强制写入更加严重,之前靠一些方法已经无法阻止appconfigs.xml的文件的修改,而且使得验证加强,和云端加强&…...

Figma入门-约束与对齐
Figma入门-约束与对齐 前言 在之前的工作中,大家的原型图都是使用 Axure 制作的,印象中 Figma 一直是个专业设计软件。 最近,很多产品朋友告诉我,很多原型图都开始用Figma制作了,并且很多组件都是内置的,…...

腾讯元宝深度搜索AI多线程批量生成TXT原创文章软件
腾讯元宝深度搜索AI多线程批量生成TXT原创文章软件说明: 腾讯元宝深度搜索AI:能够理解用户意图,对搜索结果进行提炼和总结,直接提供用户所需的答案或信息摘要,从而提升用户体验。 腾讯元宝深度搜索AI:通过…...

Git操作学习1
一、一些Linux相关指令 在当前目录下,创建文件并写入内容:echo "这是第一个文件">file1.txt 查看文件的内容: cat file1.txt 会显示:这是第一个文件 修改文件名:mv file.txt file4.txt 把file.txt修改…...
【计算机网络】细说IP
文章目录 概述IP地址的组成IP地址的分类IP地址的作用 分类一、A类IP地址二、B类IP地址三、C类IP地址四、D类IP地址五、E类IP地址 协议报文子网掩码一、定义与功能二、表示方法三、子网掩码与IP地址的关系四、子网掩码的设置与配置五、实例说明 IPv6一、定义与背景二、地址格式与…...

树与图深度优先遍历——acwing
题目一:树的重心 846. 树的重心 - AcWing题库 分析 采用暴力枚举,试探每个点,除去之后,连通分量最大值是多少, 各个点的最大值找最小的 因为可以通过 dfs 来得到 根u以下点数,以及可以求各分树的点数&am…...

第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...

【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...
精益数据分析(98/126):电商转化率优化与网站性能的底层逻辑
精益数据分析(98/126):电商转化率优化与网站性能的底层逻辑 在电子商务领域,转化率与网站性能是决定商业成败的核心指标。今天,我们将深入解析不同类型电商平台的转化率基准,探讨页面加载速度对用户行为的…...

【记录坑点问题】IDEA运行:maven-resources-production:XX: OOM: Java heap space
问题:IDEA出现maven-resources-production:operation-service: java.lang.OutOfMemoryError: Java heap space 解决方案:将编译的堆内存增加一点 位置:设置setting-》构建菜单build-》编译器Complier...

vxe-table vue 表格复选框多选数据,实现快捷键 Shift 批量选择功能
vxe-table vue 表格复选框多选数据,实现快捷键 Shift 批量选择功能 查看官网:https://vxetable.cn 效果 代码 通过 checkbox-config.isShift 启用批量选中,启用后按住快捷键和鼠标批量选取 <template><div><vxe-grid v-bind"gri…...