Syslog发送日志+Logstash处理日志

Syslog发送日志

Syslog(System Logging Protocol)是一种用于计算机系统日志记录的标准协议。它允许设备(如服务器、路由器、防火墙等)将事件消息发送到指定的日志收集服务器,以便集中管理和分析。通过使用Syslog,您可以跟踪您的网络中的活动并在出现问题时快速识别和解决问题。

要将告警日志发送到某台机器的某个端口,您需要在发送端(产生日志的设备)和接收端(日志收集服务器)上配置Syslog。以下是详细方案:

  1. 安装和配置Syslog服务器(接收端):

这里我们以rsyslog为例,rsyslog是Linux系统上常用的Syslog服务器。如果您使用的是Windows系统,可以考虑使用Kiwi Syslog Server或其他适用于Windows的Syslog服务器。

(1)安装rsyslog:

对于大多数Linux发行版,rsyslog已经是默认安装的。如果没有,可以使用以下命令安装:

  • 对于基于Debian的系统(如Ubuntu):
sudo apt-get update
sudo apt-get install rsyslog
  • 对于基于RHEL的系统(如CentOS):
sudo yum install rsyslog

(2)配置rsyslog以接收远程日志:

编辑rsyslog配置文件(通常位于/etc/rsyslog.conf):

sudo nano /etc/rsyslog.conf

取消以下行的注释以启用UDP和/或TCP日志接收:

module(load="imudp")
input(type="imudp" port="514")module(load="imtcp")
input(type="imtcp" port="514")

保存并退出。

(3)重启rsyslog服务:

sudo systemctl restart rsyslog
  1. 配置发送端设备发送告警日志到Syslog服务器:

这里以Linux系统为例,配置rsyslog将告警日志发送到远程服务器。

(1)编辑rsyslog配置文件:

sudo nano /etc/rsyslog.conf

(2)添加以下行以将告警日志发送到远程服务器:

*.alert @remote_server_IP:514

请将remote_server_IP替换为实际的Syslog服务器IP地址。*.alert表示发送所有告警级别的日志。@表示使用UDP协议,如果要使用TCP协议,请使用@@

(3)重启rsyslog服务:

sudo systemctl restart rsyslog

现在,您的发送端设备将告警日志发送到指定的Syslog服务器和端口。您可以在Syslog服务器上查看和分析这些日志。

如果您的设备不是Linux系统,您需要查找针对该设备的Syslog配置方法。通常,您可以在设备的管理界面或配置文件中找到相应的设置。

在发送端发送指定的日志:

  1. 首先,您需要确定要发送的日志文件的路径。例如,假设您要发送的日志文件位于/var/log/myapp.log

  2. 编辑rsyslog配置文件:

sudo nano /etc/rsyslog.conf
  1. 在配置文件中添加以下内容,以将指定日志文件发送到远程服务器:
$ModLoad imfile
$InputFileName /var/log/myapp.log
$InputFileTag myapp:
$InputFileStateFile myapp_state
$InputFileSeverity info
$InputRunFileMonitor
if $programname == 'myapp' then @remote_server_IP:514

请将remote_server_IP替换为实际的Syslog服务器IP地址。@表示使用UDP协议,如果要使用TCP协议,请使用@@

这段配置是将发送端的指定日志文件(/var/log/myapp.log)通过rsyslog发送到远程Syslog服务器。下面是每行配置的解释:

  • $ModLoad imfile:加载imfile模块,该模块用于从文件中读取日志。
  • $InputFileName /var/log/myapp.log:指定要读取的日志文件路径(/var/log/myapp.log)。
  • $InputFileTag myapp::为从该日志文件读取的消息添加一个标签(myapp)。
  • $InputFileStateFile myapp_state:指定状态文件(myapp_state),用于记录文件读取的位置,以防rsyslog重启时能从上次读取的位置继续读取。
  • $InputFileSeverity info:指定读取的日志消息的默认严重级别(info)。
  • $InputRunFileMonitor:启动文件监视器,以便实时读取日志文件的新消息。
  • if $programname == 'myapp' then @remote_server_IP:514:如果消息的标签(programname)等于myapp,则将消息发送到远程Syslog服务器的指定IP地址和端口。请将remote_server_IP替换为实际的Syslog服务器IP地址。@表示使用UDP协议,如果要使用TCP协议,请使用@@

将此配置添加到发送端设备的/etc/rsyslog.conf文件中,然后重启rsyslog服务,即可将指定日志文件发送到远程Syslog服务器。

  1. 重启rsyslog服务:
sudo systemctl restart rsyslog

现在,发送端将指定的日志文件/var/log/myapp.log发送到远程服务器。

在接收端查看日志:

  1. 默认情况下,rsyslog会将接收到的日志存储在/var/log目录下。您可以在/etc/rsyslog.conf配置文件中找到具体的日志存储路径。例如,以下配置表示将接收到的日志存储在/var/log/remote目录下:
$template RemoteLogs,"/var/log/remote/%HOSTNAME%/%PROGRAMNAME%.log"
*.* ?RemoteLogs
  1. 您可以使用cattailless等命令查看日志文件。例如,查看名为myapp.log的日志文件:
cat /var/log/remote/sender_hostname/myapp.log

请将sender_hostname替换为发送端设备的主机名。

  1. 您还可以使用日志分析工具(如Logstash、Graylog等)对接收到的日志进行处理、分析和可视化。这些工具可以帮助您更有效地管理和监控日志。

Logstash处理日志

Logstash是一个开源的数据收集、处理和转发工具,它可以轻松地从各种来源接收日志数据,对其进行处理和转换,并将其发送到不同的目标,如Elasticsearch、Kafka等。以下是使用Logstash处理接收到的日志的详细步骤和方法:

  1. 安装Logstash:

这里以安装在基于Debian的系统(如Ubuntu)为例:

(1)导入Elasticsearch的GPG密钥:

wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -

(2)安装HTTPS传输:

sudo apt-get install apt-transport-https

(3)将Elasticsearch存储库添加到系统:

echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-7.x.list

(4)更新软件包列表并安装Logstash:

sudo apt-get update
sudo apt-get install logstash
  1. 配置Logstash:

Logstash的配置文件通常位于/etc/logstash/conf.d/目录。我们需要创建一个配置文件,包含三个部分:输入(input)、过滤器(filter)和输出(output)。

(1)创建配置文件:

sudo nano /etc/logstash/conf.d/logstash.conf

(2)配置输入:

在配置文件中添加以下内容,以从Syslog服务器接收日志:

input {syslog {port => 5140type => "syslog"}
}

这里我们使用端口5140作为Logstash的Syslog输入端口。您可以根据需要选择其他端口。

(3)配置过滤器(可选):

过滤器用于对日志进行处理和转换。例如,您可以使用grok过滤器解析日志消息,提取有用的字段:

filter {if [type] == "syslog" {grok {match => { "message" => "%{SYSLOGTIMESTAMP:syslog_timestamp} %{SYSLOGHOST:syslog_hostname} %{DATA:syslog_program}(?:\[%{POSINT:syslog_pid}\])?: %{GREEDYDATA:syslog_message}" }add_field => [ "received_at", "%{@timestamp}" ]add_field => [ "received_from", "%{host}" ]}date {match => [ "syslog_timestamp", "MMM  d HH:mm:ss", "MMM dd HH:mm:ss" ]}}
}

这个例子中,我们使用grok过滤器解析Syslog消息,并提取诸如时间戳、主机名、程序名等字段。

(4)配置输出:

配置输出部分,以将处理后的日志发送到目标。例如,将日志发送到Elasticsearch:

output {elasticsearch {hosts => ["localhost:9200"]index => "logstash-%{+YYYY.MM.dd}"}
}

这里,我们将日志发送到本地运行的Elasticsearch实例,并使用按日期分割的索引。

  1. 启动Logstash:

启动Logstash并将其设置为在系统启动时自动运行:

sudo systemctl start logstash
sudo systemctl enable logstash
  1. 修改Syslog服务器配置:

为了将日志从Syslog服务器转发到Logstash,您需要修改Syslog服务器的配置。以rsyslog为例:

编辑rsyslog配置文件:

sudo nano /etc/rsyslog.conf

将以下内容添加到配置文件中,以将日志转发到Logstash:

*.* @@localhost:5140

这里,我们使用@@将日志通过TCP协议发送到本地运行的Logstash实例的端口5140

重启rsyslog服务:

sudo systemctl restart rsyslog

现在,Syslog服务器将接收到的日志转发到Logstash进行处理,然后将处理后的日志发送到Elasticsearch。您可以使用Kibana等工具对这些日

Logstash字段说明

Logstash支持多种输入、过滤器和输出插件,每个插件都有自己的参数。以下是一些常见插件的参数及其用法示例:

  1. 输入(input)插件:
  • file:从文件中读取日志。

    参数:

    • path:要读取的文件路径,可以使用通配符。
    • start_position:从文件的哪个位置开始读取,可以是beginning(从头开始)或end(从末尾开始)。

    示例:

    input {file {path => "/var/log/*.log"start_position => "beginning"}
    }
    
  • syslog:从Syslog协议中读取日志。

    参数:

    • port:要监听的端口。
    • type:为事件分配的类型。

    示例:

    input {syslog {port => 5140type => "syslog"}
    }
    
  • beats:从Filebeat或其他Beats中读取日志。

    参数:

    • port:要监听的端口。

    示例:

    input {beats {port => 5044}
    }
    
  1. 过滤器(filter)插件:
  • grok:使用正则表达式解析日志。

    参数:

    • match:一个哈希,包含要匹配的字段和正则表达式模式。

    示例:

    filter {grok {match => { "message" => "%{SYSLOGTIMESTAMP:syslog_timestamp} %{SYSLOGHOST:syslog_hostname} %{DATA:syslog_program}(?:\[%{POSINT:syslog_pid}\])?: %{GREEDYDATA:syslog_message}" }}
    }
    
  • date:解析日期并将其设置为事件的时间戳。

    参数:

    • match:一个数组,包含要解析的字段和日期格式。

    示例:

    filter {date {match => [ "syslog_timestamp", "MMM  d HH:mm:ss", "MMM dd HH:mm:ss" ]}
    }
    
  • mutate:对事件执行通用转换。

    参数:

    • add_field:添加新字段。
    • remove_field:删除字段。
    • rename:重命名字段。

    示例:

    filter {mutate {add_field => { "new_field" => "new_value" }remove_field => [ "old_field" ]rename => { "old_name" => "new_name" }}
    }
    

在Logstash的配置文件中,=>是键值对的分隔符,用于指定参数的名称和值。例如,在hosts => ["localhost:9200"]中,hosts是参数名称,["localhost:9200"]是参数值。

match参数后面的字段是一个哈希,用于指定要匹配的字段和正则表达式模式。哈希中的键是字段名称,值是正则表达式模式。

例如,在以下配置中:

grok {match => { "message" => "%{SYSLOGTIMESTAMP:syslog_timestamp} %{SYSLOGHOST:syslog_hostname} %{DATA:syslog_program}(?:\[%{POSINT:syslog_pid}\])?: %{GREEDYDATA:syslog_message}" }
}

message是要匹配的字段,"%{SYSLOGTIMESTAMP:syslog_timestamp} %{SYSLOGHOST:syslog_hostname} %{DATA:syslog_program}(?:\[%{POSINT:syslog_pid}\])?: %{GREEDYDATA:syslog_message}"是正则表达式模式。

这个正则表达式模式使用了多个grok模式:

  • %{SYSLOGTIMESTAMP:syslog_timestamp}:匹配Syslog时间戳,并将匹配的值保存到syslog_timestamp字段。
  • %{SYSLOGHOST:syslog_hostname}:匹配Syslog主机名,并将匹配的值保存到syslog_hostname字段。
  • %{DATA:syslog_program}:匹配任意非空白字符,并将匹配的值保存到syslog_program字段。
  • (?:\[%{POSINT:syslog_pid}\])?:匹配可选的进程ID(在方括号中),并将匹配的值保存到syslog_pid字段。
  • %{GREEDYDATA:syslog_message}:匹配任意字符,并将匹配的值保存到syslog_message字段。

这个正则表达式模式会对message字段的值进行解析,并提取出各个部分的值保存到新的字段中。例如,对于以下的Syslog消息:

Oct 11 22:14:15 myhost myprogram[123]: This is a message

解析后的结果将是:

  • syslog_timestampOct 11 22:14:15
  • syslog_hostnamemyhost
  • syslog_programmyprogram
  • syslog_pid123
  • syslog_messageThis is a message
  1. 输出(output)插件:
  • elasticsearch:将事件发送到Elasticsearch。

    参数:

    • hosts:一个数组,包含Elasticsearch实例的地址和端口。
    • index:要写入的索引名称。

    示例:

    output {elasticsearch {hosts => ["localhost:9200"]index => "logstash-%{+YYYY.MM.dd}"}
    }
    
  • file:将事件写入文件。

    参数:

    • path:要写入的文件路径。

    示例:

    output {file {path => "/var/log/output.log"}
    }
    
  • stdout:将事件输出到标准输出。

    参数:

    • codec:输出格式,例如rubydebug(易于阅读的文本格式)。

    示例:

    output {stdout {codec => rubydebug}
    }
    

这些示例仅涵盖了部分插件和参数。Logstash支持许多其他插件和选项,您可以根据需要进行组合和配置。请参阅官方文档以获取更多信息和示例。

Syslog日志格式说明

Syslog是一种标准的日志传输协议,它定义了日志消息的格式和传输方式。Syslog可以使用UDP(用户数据报协议)或TCP(传输控制协议)作为其下层的传输协议。

Syslog over UDP和Syslog over TCP的主要区别在于它们的传输可靠性和资源消耗:

  • Syslog over UDP:UDP是一种无连接的协议,它不保证消息的到达和顺序。因此,如果网络状况不佳,Syslog消息可能会丢失或到达的顺序可能会打乱。然而,UDP的优点是它的开销较小,对于大量的日志消息,使用UDP可能会更有效率。

  • Syslog over TCP:TCP是一种可靠的连接协议,它保证了消息的到达和顺序。如果网络状况允许,使用TCP可以确保所有的Syslog消息都能正确地到达接收端。然而,TCP的缺点是它的开销较大,对于大量的日志消息,使用TCP可能会消耗更多的网络资源和处理器时间。

Syslog消息的格式由RFC 5424定义,主要包含以下字段:

  • PRI(Priority):一个数字,表示消息的优先级。它是由设施代码(Facility Code)和严重性级别(Severity Level)组合而成的。

  • HEADER:包含两个字段,TIMESTAMP(时间戳)和 HOSTNAME(主机名)。

  • MSG:消息部分,包含TAG(标签)和 CONTENT(内容)。

Syslog over UDP和Syslog over TCP的消息格式是相同的,它们都遵循RFC 5424的规定。然而,由于TCP是一种流协议,所以Syslog over TCP还需要一种方法来确定消息的边界。这通常通过在每个消息后面添加一个特殊的分隔符(如换行符)来实现。

Syslog消息主要包含以下几部分:

  1. PRI(Priority):一个由设施代码(Facility Code)和严重性级别(Severity Level)组合而成的数字,表示消息的优先级。

  2. VERSION:Syslog协议的版本号。

  3. TIMESTAMP:消息的时间戳。

  4. HOSTNAME:发送消息的设备的主机名。

  5. APP-NAME:生成消息的应用程序的名称。

  6. PROCID:生成消息的进程的ID。

  7. MSGID:消息的ID。

  8. STRUCTURED-DATA:结构化的数据,可选。

  9. MSG:消息的内容。

以下是一个Syslog消息的例子:

<34>1 2003-10-11T22:14:15.003Z mymachine.example.com su - ID47 - 'su root' failed for lonvick on /dev/pts/8
  • <34>是PRI,表示优先级。这个数字是由设施代码和严重性级别计算得出的。例如,设施代码为4(auth)和严重性级别为2(critical)计算得出的优先级为34。

  • 1是VERSION,表示Syslog协议的版本。

  • 2003-10-11T22:14:15.003Z是TIMESTAMP,表示消息的时间戳。

  • mymachine.example.com是HOSTNAME,表示发送消息的设备的主机名。

  • su是APP-NAME,表示生成消息的应用程序的名称。

  • -是PROCID,表示生成消息的进程的ID。在这个例子中,进程ID未知,所以用-表示。

  • ID47是MSGID,表示消息的ID。

  • -是STRUCTURED-DATA,表示结构化的数据。在这个例子中,没有结构化的数据,所以用-表示。

  • 'su root' failed for lonvick on /dev/pts/8是MSG,表示消息的内容。

这个消息的含义是,在mymachine.example.com上,用户lonvick尝试使用su命令切换到root用户,但是失败了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/615199.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【MySQL】MySQL基本语句

1.使用 MySQL 客户端登录&#xff1a; 打开终端并运行以下命令&#xff0c;使用你的 MySQL 用户名和密码登录到 MySQL 服务器&#xff1a; mysql -u your_username -p2.连接成功后&#xff0c;运行以下 SQL 查询语句来获取数据库的数量&#xff1a; SHOW DATABASES;3.选择数据…

从传统训练到预训练和微调的训练策略

目录 前言1 使用基础模型训练手段的传统训练策略1.1 随机初始化为模型提供初始点1.2 目标函数设定是优化性能的关键 2 BERT微调策略: 适应具体任务的精妙调整2.1 利用不同的representation和分类器进行微调2.2 通过fine-tuning适应具体任务 3 T5预训练策略: 统一任务形式以提高…

[BJDCTF2020]ZJCTF,不过如此

题目源码&#xff1a; <?phperror_reporting(0); $text $_GET["text"]; $file $_GET["file"]; if(isset($text)&&(file_get_contents($text,r)"I have a dream")){echo "<br><h1>".file_get_contents($tex…

Echarts 引入地图

# 地图数据获取 获取地址&#xff1a;DataV.GeoAtlas地理小工具系列 # 地图渲染 // 地图 mapOption: { title: {text: 作物省市分布图,left: left,subtext: provincial and cities distribution of crops }, // 浮窗样式 tooltip: {show: true, // 提示浮窗是否显示trigger:…

C++学习笔记(二十一)

一、set/multiset容器 1. set基本概念 简介&#xff1a;所有元素都会在插入时自动被排序 本质&#xff1a;set/multiset属于关联式容器&#xff0c;底层结构是用二叉树实现的 set和multiset的区别&#xff1a;set不允许容器中有重复的元素&#xff0c;multiset允许容器中有…

数学建模 | 一文读懂:支持向量机(matlab源码)

===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== 支持向量机 1 支持向量分类机的基本原理1.1 线性可分支持向量分类机1.2…

数据分析基础之《pandas(1)—pandas介绍》

一、pandas介绍 1、2008年Wes McKinney&#xff08;韦斯麦金尼&#xff09;开发出的库 2、专门用于数据分析的开源python库 3、以numpy为基础&#xff0c;借力numpy模块在计算方面性能高的优势 4、基于matplotlib能够简便的画图 5、独特的数据结构 6、也是三个单词组合而…

使用numpy处理图片——图片拼接

大纲 左右拼接上下拼接 在《使用numpy处理图片——图片切割》一文中&#xff0c;我们介绍了如何使用numpy将一张图片切割成4部分。本文我们将反其道而行之&#xff0c;将4张图片拼接成1张图片。 基本的思路就是先用两张图以左右结构拼接成上部&#xff0c;另外两张图也以左右拼…

2024年Ubuntu18.04执行do-release-upgrade报错的解决方案

2024年Ubuntu18.04执行do-release-upgrade报错的解决方案 背景报错情况解决方法先升级可用的软件包执行 do-release-upgrade方法一&#xff1a;直接执行 github 上写好的脚本方法二&#xff1a;手动执行 还原配置 背景 公司用的信服云&#xff0c;公共镜像中最新的Ubuntu镜像是…

ansible从入门到精通(完整篇)

文章目录 01 Ansible介绍与安装1. 介绍 Ansible1.1 什么是 Ansible?1.2 Ansible 无需代理1.3 Ansible 方式 2. 安装 Ansible2.1 控制节点2.2 受管主机2.3 基于Windows的受管主机2.4 受管网络设备2.5 安装Ansible 02 部署Ansible1. 构建Ansible清单1.1 定义清单1.2 使用静态清单…

Ubuntu20.04下A-LOAM配置安装及测试教程(包含报错问题踩坑)

参考文章&#xff1a; ubuntu20.04下ros运行A-LOAM Ubuntu20.04下运行LOAM系列&#xff1a;A-LOAM、LeGO-LOAM、SC-LeGO-LOAM、LIO-SAM 和 LVI-SAM 需要学习源码的同学可以下载LOAM论文 LOAM论文链接 1.需要安装的库文件 1.1Eigen 3.3 可以直接使用apt命令安装&#xff0c;或…

芯课堂 | 如何配置SWM系列系统时钟?

如何配置SWM系列 系统时钟&#xff1f; 华芯微特科技有限公司SWM系列芯片可通过软件配置改变时钟的速度&#xff0c;可以让我们的设计更加灵活,频率可选空间也更加广泛&#xff0c;用户可以根据自己的实际需求配置需要的系统时钟。为了让用户能够更简单的使用这一功能&#xf…

android studio使用总结

gradle是项目构建的工具&#xff0c;在gradle-wrapper.properties这个文件中设置&#xff0c; 然后就会下载相应版本的安装包到这个路径C:\Users\ly.gradle\wrapper\dists&#xff0c;例如这里是7.0.2&#xff0c; gradle和studio中的jdk版本需要对应&#xff0c;否则无法构建项…

无代码DIY图像检索

软件环境准备 可参见《HuggingFists-低代码玩转LLM RAG-准备篇》中的HuggingFists安装及Milvus安装。 流程环境准备 图片准备 进入HuggingFists内置的文件系统&#xff0c;数据源->文件系统->sengee_fs_settings_201创建Image文件夹将事先准备的多张相同或不同种类的图…

那么多编程语言,我为什么选择了Python?

我为什么选择了Python 目前&#xff0c;Python语言的发展势头在国内国外都是不可阻挡的&#xff0c;Python凭借其简单优雅的语法&#xff0c;强大的生态圈从众多语言中脱颖而出&#xff0c;如今已经是稳坐编程语言排行榜前三的位置&#xff0c;而且在GitHub和IEEE发布的最受欢…

IDEA GitHub令牌原理(Personal Access Token)

1.IDEA的add github account 是什么原理&#xff1f; 在IntelliJ IDEA中添加GitHub账户&#xff0c;主要是为了让IDEA能够与GitHub进行交互&#xff0c;如克隆GitHub上的仓库&#xff0c;提交代码到GitHub等。其基本原理如下&#xff1a; 用户在IDEA中输入GitHub的用户名和密…

Jenkins使用随笔

1、如果要部署的springboot程序和jenkins在同一台linux上&#xff0c;需要增加一条 export BUILD_IDtomcat_mobile_build_id 如下图&#xff1a; 原因是&#xff1a;jenkins在执行sh脚本的时候&#xff0c;如果脚本中有启动后台进程的情况&#xff0c;例如tomcat的关闭和启动…

C#上位机与欧姆龙PLC的通信11----【再爆肝】上位机应用开发(WPF版)

1、先上图 继上节完成winform版的应用后&#xff0c;今天再爆肝wpf版的&#xff0c;看看看。 可以看到&#xff0c;wpf的确实还是漂亮很多&#xff0c;现在人都喜欢漂亮的&#xff0c;颜值高的&#xff0c;现在是看脸时代&#xff0c;作为软件来说&#xff0c;是交给用户使用的…

Ubuntu 上CUDA移动到别的目录

在 Ubuntu 上使用 CUDA 进行 GPU 加速的过程如下所示&#xff1a; 首先确保已经安装了 NVIDIA 显卡驱动。可以通过运行 nvcc -V 命令来查看当前系统中是否存在 NVIDIA 显卡并且正常工作。 接下来需要安装 CUDA Toolkit。CUDA Toolkit 包含了编译、调试和运行 CUDA 应用程序所必…

Linux之Iptables简易应用

文档形成时期&#xff1a;2009-2024年 和iptables打交道有15年了&#xff0c;经过无数实践后&#xff0c;形成一个简易应用文档。 文档主题是简易应用&#xff0c;所以其原理不详述了。 因软件世界之复杂和个人能力之限&#xff0c;难免疏漏和错误&#xff0c;欢迎指正。 文章目…