十.Shell编程

10.1 Shell的基本介绍:

Shell是一个命令行解释器,它为用户提供了一个向linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell来启动,挂起,停止甚至编写一些程序。

10.2 Shell脚本执行的方式:

# 能用vim就不要用vi,但是vim需要下载安装
yum install vim

#Ubuntu命令有所区别
apt install vim

进入脚本 : vim 文件名.sh

脚本格式要求:

①.脚本以#!/bin/bash开头

②脚本需要有可执行权限

脚本编辑的命令:

插入:按住i,然后继续代码编写

保存:按住Esc,然后输入:wq

运行脚本:sh 文件名.sh

10.3 Shell变量

10.3.1 Shell变量介绍

1.Shell变量分为: 系统变量自定义变量

2.系统变量: $HOME,$PWD.$SHELL.$USER(比如 echo $HOME)

3.显示当前shell中所有变量: set

10.3.2 Shell变量的定义

基本语法:

1.定义变量: 变量名=值 (中间不能有空格)

2.撤销变量: unset 变量

3.声明静态变量: readonly 变量,注意不能unset

10.3.3 变量的输出

变量输出前要加$符号

#!/bin/bash
#定义变量A
A=100
#此时输出的是100
echo $A
#以下两种情况输出的是A=100
echo A=$A
echo "A=$A"
#撤销变量A
unset A
#此时输出的是A=
echo"A=$A"

10.3.4 定义变量的规则

1.变量名称可以由字母,数字和下划线组成,但是不能以数字开头,(5A=100是错的)

2.等号两侧不能有空格

3.变量名称一般习惯为大写,这是一个规范

4.将命令的返回值赋给变量要用`Esc下面的键`,即为把结果返回给变量A

5.A=$(data)等价于A=`data`的反引号

#将指令返回的结果赋给变量
C=`date`
D=$(date)
echo "C=$C"
echo "D=$D"

10.3.5 位置参数变量

介绍:当我们执行一个shell脚本时,如果希望获取到命令行的参数信息,就可以使用到位置参数变量

基本语法:

10.3.6 条件判断

语法:

[ condition ](注意condition前后要有空格)

 #非空返回true,可使用$?验证(0为true,>1为false)

条件判断: 

#!/bin/bash
#案例1:"OK"是否等于"OK"
#判断语句: 使用=
if [ "ok"="ok" ]
then
      echo "equal"
fi

注意: if代表开始,fi代表结束

#案例三:/root/shcode/aaa.txt目录中的文件是否存在
# 判断语句:使用 -f
if [ -f /root/shcode/aaa.txt ]
then
      echo "存在"

十一. 系统安全与防火墙

11.1 Linux系统安全

linux服务器的安全可以分为系统安全网络安全两部分:

  • 系统安全: 保障用户,文件和进程的访问安全

         ①权限三部曲: 基本的UGO模型特殊权限SUID|SGID|SBIT和ACL权限

         ②附加组件:SELinux

  • 网络安全:主要通过防火墙技术,对服务器的网络访问进行控制

        Centos的Netfilter,iptables和firewall

        Ubuntu的ufw

11.2 权限三部曲

11.2.1基本UGO补充---默认权限

11.2.1.1 默认权限命令 umask

➡ umask命令用于查看或设定新建文件和目录时的默认权限

➡ umask命令设定的权限值为权限掩码,其值越小,默认权限越大

新建文件的默认权限=666 - umask值

新建目录的默认权限=777 - umask值

11.2.2 UGO特殊权限

为什么要有特殊权限?

11.2.2.1 三种特殊权限

SUID:设定二进制程序执行时用户的权限用s表示

SGID:设定二进制程序执行时组的权限,用s表示

SBIT:、设定删除文件的特殊权限,用t表示

❖ SUID和SGID的⽤法

➡ 仅对二进制文件有效、且仅在运行时有效;

➡ 执行者在拥有该程序的x权限的前提下,将拥有该程序所有者的权限。(即被代替的要有权限x)

❖ SBIT的用法

其作用是:当用户拥有某目录的写入权限时(同时具 有w和x权限)在该目录下创建的文件只有该用户和root用户才能进行更名、移动、 删除操作

11.2.2.2设置和修改三种特殊权限

数字方法SUID、SGID和SBIT分别对应4、2、1,即在权限数字前添加一个数字

字符方法SUID为u+s、SGID为g+s、SBIT为o+t

1. 符号解释
u:表示文件/目录的所有者(User)

g:表示文件/目录的所属组(Group)

o:表示其他用户(Others)

+:表示添加权限

s 和 t:代表特殊权限(SUID、SGID、SBIT)
2. 具体规则
u+s:为文件所有者添加 SUID 权限

作用:临时拥有所有者的权限(如普通用户执行 passwd 命令时,能修改需要 root 权限的密码文件)。

示例:
chmod u+s my_script.sh
原权限 -rwxr-xr-x → 添加后变为 -rwsr-xr-x(所有者执行位 x 变为 s)

 11.2.3 ALC(Access Control List)

❖ ACL权限简介

➡ ACL,访问控制列表,用于在传统的UGO模型之上提供更加细粒度的权限管理。

➡ ACL可以针对单一用户、单一文件或目录进行r、w、x的权限管理。

➡ ACL的实现需要文件系统的支撑

11.2.3.1 setfacl和getfacl命令
  • setfacl命令,用于设置文件访问控制列表策略,实现精细化权限控制
  • getfacl命令用于查看文件的访问控制策略
# setfacl是set file access control list的缩写
# setfacl指令可以更精确控制权限的分配,比如让某一个用户对某一个文件有某种权限
setfacl [参数] 文件或者目录名

通俗理解UGO和ACL的区别

  • UGO 像“分班级”
    老师(Owner)、本班学生(Group)、外班学生(Others)统一权限,无法单独管理某个学生。

  • ACL 像“点名授权”
    给每个学生(用户)或班级(组)单独发不同权限的“通行证”,精准控制谁能进门、能做什么。

11.3 SELinux

  • SELinux的设计目标为解决Linux系统权限管理缺陷,导致内部员工误用的问题
  • 这一缺陷的核心问题是:权限管理主要针对用户和文件,而真正运行的却是进程
  • 传统Linux权限管理机制:DAC即根据进程的所有者与⽂件的rwx权限来控制
  • SELinux权限管理机制MAC,对特定的进程和特定的文件进行专门的权限控制

11.3.1 SELinux相关概念

➡ 主体:运行中的程序,进程;
➡ 目标:即进程想要访问的资源/文件;
➡ 策略:指SELinux针对不同类型应用设置的一系列规则,可以分为限制较少的targeted规则
和更为严格的strict规则;
➡ 安全上下文:SELinux中安全上下文相当于传统权限中的rwx。(告诉它你能做什么事情)

11.3.2 SELinux的三种运行模式

➡ enforcing:强制模式,代表SELinux在运行中,且已正确的根据策略和安全上下文控
制访问。
➡ Permissive:宽容模式,代表SELinux在运行中,但并不限制访问,只提供警告。
➡ disabled:关闭SELinux。

11.4 防火墙技术

11.4.1 Linux防火墙的基本概念

  • 防火墙是⼀种隔离系统内部网络和外部网络过滤技术。
  • 通过实现方式分为硬件防火墙软件防火墙
  • 软件防火墙按技术原理可以分为包过滤防火墙代理服务防火墙(可以理解为系统内还装了一个虚拟机)
  • 包过滤防⽕墙采用数据包过滤技术,在⽹络层(IP层)依据预设的过滤规则对数据包进⾏选

11.4.2 Linux防火墙技术

11.4.2.1 Netfilter框架
  • Netfilter是Linux内核中实现包过滤技术,连接跟踪,地址转换等功能的实现框架
  • 包过滤防火墙中相关的过滤特定的数据包或者需要修改数据包的内容再转发等功能,都是通过Netfilter在内核中完成的
  • Netfilter的实质是通过定义一系列hook点(钩子),每个hook上可以挂载多个hook函数,hook函数中就实现对数据包的处理

11.4.2.2 iptables (四表五链常考)

iptables链(五链):即数据包进入到网卡后流向的五个阶段,包括路由前prerouting入站
input
转发forward、出站output、路由后postrouting。

 iptables表:即用来存储过滤规则的表,包括filter表、nat表、mangle表和raw表

  • filter表用于包过滤(iptable中的默认表)
  • nat用于网络地址转换
  • mangle用于包重构
  • raw表用于数据跟踪处理(优先级最高)

filter--->input,output,forward

nat --->prerouting,postrouting,output

mangle--->五链都有

row--->prerouting,output

iptables的基本原理就是在数据包进入到网卡后的不同阶段,查找对应表,用相关的
规则对数据包进行处理。

11.4.2.3 nftables

  • nftables 是基于 Netfilter 框架的改进版,用于替换 iptables,解决其在性能、可扩展性上的不足 。
  • 统一的框架:iptables 过去有4套类似工具管理,语法类似但需分别维护 
  • nftables 则以单一工具 nft 管理所有协议,通过 family 概念区分
  • nftables的主要改进是为IPv4和IPv6提供统一的接口。

11.4.2.4 firewall

❖ firewall在iptables的基础上有如下改进:

➡ Firewall可以热部署即可以动态修改规则,不需要整体重写;
➡ Firewall新增zone概念将网络连接分为多种可信等级,不同等级已经配置好一些默认操作,比
如工作zone、家庭zone、限制zone、信任zone等,方便使用和配置;
由于可以热部署,所以firewall的规则设定可以分为临时(runtime)和永久(permanent)两种方式,区别是重启(reload)防火墙服务后是否有效;
➡ firewall还提供可视化图形界面进行设置,firewall-config程序;
Cent OS 6.x默认使用iptables,Cent OS 7.x默认使用firewall,iptables需自行安装。
Cent OS 8.x使用nftables取代iptables框架,firewalld守护进程现在使用nftables作为默认后端。

11.5 Linux防火墙的使用

11.5.1 firewall的常用操作

开启或者关闭

firewall-cmd --state #查看防火墙状态

systemctl stop firewalld.service # 关闭防火墙

systemctl start firewalld.service # 开启防火墙

systemtcl enable|disable firewalld.service # 设置开机启动或者禁止防火墙

开放或关闭端口

# 语法
# 查看所有打开的端口
firewall-cmd [--zone=zone] --list-port

#打开端口
firewall-cmd [--zone=zone] --add-port=port/tcp --permanent|runtime 

# 重新加载服务
firewall -cmd --reload

#使用范例
firewall-cmd --zone=public --add-port=80 --permanent

11.5.2 iptables规则组成

基本语法格式

# 表名或者链名用于指定iptables命令操作的表和链
# 命令选项用于指定管理iptables规则的方式(比如插入,删除,增加,查看)
# 条件匹配用于指定对符合什么样条件的数据包进行处理
# 目标动作或跳转用于指定数据包的处理方式(比如运行通过,拒绝,丢弃,跳转)给其它链处理
# 如果省略不加-t,则默认操作的是filter表
iptables [-t 表名] 命令选项 [链名] [条件匹配] [-j 目标动作或跳转]

命令选项: 

# -A 在指定链的末尾添加(append)一条新的规则
# -D 删除(delete)指定链中的某一条规则,可以按照序号和内容删除
# -I 在指定链中插入(Insert)新的规则
# -R 修改,替换(replace)指定链中的某一条规则
# -L 列出(list)指定链中所有的规则进行查看

条件匹配:

-s 源地址
-d 目的地址
-p 协议

使用范例:

# 对所有地址开放本机的基于TCP协议的22端口的访问
iptables -I INPUT -p tcp --deport 22 -j ACCEPT

# 对所有来源开放本机的基于ICMP协议的数据包访问(开放Ping)
iptables -I INPUT -p icmp -j ACCEPT

# 其他未被配置的端⼜则禁⽌访问
iptables -A INPUT -j  REJECT

11.5.3 使用iptables防范攻击

limit模块

-connlimit模块用于限制流量和带宽

主要参数:--limit 参数 --limit-burst 参数

# 示例
# 这两条命令结合使用的效果是:
# 允许每分钟最多3个ICMP包通过,并且在达到这个限制前可以容忍最多100个突发包。
# 超过限制的ICMP包将被丢弃。

# -A INPUT:向INPUT链添加一条规则。
# -p icmp:指定协议为ICMP(通常用于ping请求)。
# -m limit:调用limit模块。
# --limit 3/m:每分钟最多允许3个ICMP包通过。
# --limit-burst 100:在达到每分钟3个包的限制前,允许最多100个包通过。
iptables -A INPUT -p icmp -m limit --limit 3/m --limit-burst 100

iptables -A INPUT -p icmp -j DROP

11.5.4 nfttables的使用

✓ ⼀种是直接用 nft 命令⾏添加规则,
✓ 另⼀种是将规则写成脚本⽂件然后加载。nftables 将规则划分为表(table)、链
(chain)和规则(rule),概念与iptables类似但组织更灵活

十二.Linux系统引导

现代操作系统的启动一般分为两个阶段:系统引导和系统启动

  • 系统引导:开始于打开计算机电源,结束于内核初始化完成和init或systemd进程成功运⾏
  • 系统启动:init或systemd进程接管⼯作,运⾏相关程序,直到用户可以正常操作计算机。

12.1 系统引导的基本流程

引导阶段包括固件初始化引导加载程序内核加载初始化进程启动,以及最终进入用户空间

12.1.1 BIOS和UEFI

BIOS(Basic Input/Output System 基本输入输出系统)和UEFI(统一扩展固件接口)是两种固件标准,但存在差异:(可以将UEFI看作BIOS的进阶完善版)

  • 硬件兼容性:BIOS用传统的MBR分区(最多支持2TB的硬盘),而UEFI支持GUID分区表(GPT),可处理更大的存储设备 

BIOS/UEFI 共同职责是在硬件上电自检后,将控制权交给下⼀级的引导加载程序因此在启动顺序中,无论采用哪种固件,引导流程的下⼀步都是读取启动介质上的引导程序(如 GRUB)

12.1.2GRUB程序

负责从硬件接管控制,加载操作系统内核

GRUB引导程序由引导配置文件定义

GRUB引导界面范例:

GRUB引导程序由引导配置文件定义。常见配置文件路劲:

  • /etc/default/grub:GRUB默认设置文件,包括启动菜单超时时间,默认内核参数等用户可选选项
  • /boot/grub/grub.cfg或/boot/grub2/grub.cfg:GRUB 主配置脚本,由系统⽣成,列出启动菜单各项及对应内核、initrd路径 。

12.1.3 内核加载和初始化

当GRUB将控制权交给Linux内核后,系统进入内核阶段。主要包括硬件初始化,挂载根文件系统,启动第一个进程(查找名为init的可执行程序路径)

12.2 init进程和systemd机制

12.2.1 init进程

一.init主要任务: 

init进程是Linux用户空间的第一个进程(PID=1),承担系统初始化和管理的责任。以下是init阶段的主要工作:

  • 运行级别和系统目标:init使用运行级别定义系统状态(0-6)
  • 启动系统服务
  • 挂载文件系统与配置
  • 启动终端/图形界面
二.init机制中运行级别:

# 由上述得知,每个级别对应的启动服务保存在etc/rc.d/*.d中
# 当init启动机制中启动其它服务apache为
sudo /etc/init.d/apache2 start

# 或者
service apache2 start
三.init启动机制的缺点 
  • 启动时间长init进程是串⾏启动,只有前⼀个进程启动完,才会启动下⼀个进程
  • 启动脚本复杂:init进程只是执⾏启动脚本,每个守护进程或服务需要自⼰处理各种情况,这往往使得脚本变得很长

为解决init机制的问题,Linux社区中诞⽣了systemd机制(

systemd取代init成为系统的第⼀个进程。

12.2.2 Systemd初始化

一.systemd机制的主要特点:
  • 守护进程被称为unit(服务单元),unit按功能被分为多种不同类型(service、socket等),多个unit可以组合成⼀个服务组(target)
  • 所有守护进程全部并行处理,加速开机启动流程
  • 使用systemctl主命令进行守护进程的统一管理
二.systemd的系统服务(进程)类型

十三.Linux日志系统

  • 现代Linux通常有systemd-journald和传统rsyslogd两种日志系统
  • systemd-journald将日志以⼆进制形式存储(默认保存在内存,重启后丢失),记录启动和服务相关消息;⽽rsyslogd将这些日志转换为⽂本格式并保存到 /var/log/下 。简⾔之,journald 负责收集日志,rsyslogd负责输出持久化日志 。

13.1 常见日志文件

日志文件基本上都是放在/var/log/下面

  • /var/log/messages:核心系统消息,记录系统发生错误或异常的重要消息
  • /var/log/cron: cron日志
  • /var/log/httpd/*:记录Web服务器相关信息(比如tomcat)

13.2 查看日志文件

查看⽇志命令:使⽤ journalctl 命令查看 journald ⽇志

日志文件的内容一般格式:

  • 事件发生的日期和时间
  • 事件相关的主机名
  • 事件相关进程或函数
  • 时间详细的内容或数据

13.3 日志的配置文件

日志的配置文件保存在/etc/日志服务.conf的配置文件中(eg;etc/rsyslog.conf)

日志配置⽂件的功能是:规定哪些服务什么等级信息需要被记录在哪个文件

Web服务器⽇志⼀般可以为访问日志(Access Log)错误日志(Error Log)

十四.Linux 计划任务

计划任务也被称为例⾏性⼯作,在Linux系统中是指由系统在某⼀时间或周期性自动执行的程序或应用。

14.1 单次执行任务(at)

 at任务的工作依赖于名为atd系统服务,使用at任务需要确保系统中的atd服务可用

# 查看系统中at服务的状态
systemctl status atd

# 重启系统的at服务器
systemctl restart atd

#设置开机自动启动atd服务
systemctl enable atd

at任务的运行原理:

  • 每⼀个at任务在/var/spool/at/目录内都会对应⼀个⽂件,该⽂件保存at任务需要执行的脚本和对应的时间,atd进程通过读取该⽂件完成at任务
  • 为了控制at任务的权限,在/etc/目录下保存两个⽂件,分别白名单用户文件/etc/at.allow⿊名单用户⽂件/etc/at.deny,其中白名单文件优先级高于⿊名单⽂件,如果这两个⽂件均不在,则只有root用于有权限设置at任务。

14.2 例行性任务计划cron

cron任务和crond服务

cron任务的⼯作也依赖于名为crond的系统服务,和at任务不同的是该系统服务默认开启,且常驻内存。

使用cron计划任务有两种⽅式:

crontab命令: 

14.3 其它计划相关命令 

batch

用于设置系统空闲时间才执⾏的at任务,且在后台运⾏。

anacron

用于设置可被唤醒的cron任务,因为有些cron任务因为某些原因(关机、⽹络等原因)没有执⾏成功。

十五. 文件服务器

15.1Linux文件传输和文件共享简介

15.1.1 文件传输常见命令

15.1.1.1 wget下载文件

wget用来在Linux系统中下载文件,具体用法为:

wget [参数] [url地址]
# 常用参数
# -c 断点续传

# 使用范例
wget http://111.centos.org/...iso
15.1.1.2 scp网间拷贝

scp是Secure Copy的缩写,表示安全拷贝,其作用是将文件从一台计算机拷贝到网络上的另一台计算机,采用类似SSH协议的方式保证文件传输的安全性

# 命令语法
scp 源文件 目的文件

# 使用范例
scp image.png root@89.231.45.67:/root/images/

15.1.2 文件服务器

文件服务器是一种专门由于存储,管理和共享文件的计算机系统或设备,其主要功能是通过网络向其它计算机提供文件访问服务。

客户端服务器可以通过局域网或者互联网访问文件服务器上的共享目录,对其中的文件操作,就好像是访问本地文件一样

15.2常见文件共享服务

15.2.1 NFS(主要用于linux/Unix相互之间,可挂载)

  • NFS为网络文件系统,是一种分布式文件系统协议,主要用于类Unix系统之间通过网络共享文件系统
  • NFS的核心思想是允许一台机器将本地文件系统的一部分"导出"给网络上的其它主机,使远程主机能够通过网络挂载这个文件系统,并像访问本地磁盘一样访问其中的文件
  • 这一机制实现了跨主机的文件共享,使应用程序在客户端可以透明的访问服务器上的文件数据
  • NFS采用C/S架构,NFS服务器负责共享本地文件系统(通过导出目录的方式),NFS客户端通过网络挂载该远程文件系统
  • 传统的NFS是无状态协议,意味着服务器不追踪客户端的会话信息,每次请求都是独立的

NFS工作机制

  • NFS服务器启动后,会向RPC服务注册自己可用的端口。RPC负责端口管理映射,使用户可以找到NFS服务所在的端口。
  • 客户端希望挂载远程文件系统时,先联系服务器的RPC查询对应的端口,获取端口后,客户端与NFS建立连接
  • 建立连接后,客户端向NFS发送文件请求,NFS接收请求并将相应文件操作操作到服务器本地文件系统上,并将结果返回客户端。

搭建NFS文件共享服务

1.安装NFS服务

2.NFS服务器通过导出列表指定哪些目录共享给客户端

3.设置防火墙

4.客户端挂载

15.2.2 Samba(可兼容unix和windows,也可挂载)

  • Samba是Linux/Unix系统上实现SMB/CIFS协议的一个开源软件套件(Server Message Block/Common Internet File System)
  • Samba由服务器和客户端程序组成,用于不同操作系统之间共享文件和打印机等资源
  • Samba通过实现SMB/CIFS,使得Linux服务器能与Windows客户端进行无缝的文件共享
  • Samba最大的优点是实现了跨操作系统的文件共享兼容性
  • Samba成为了混合网络环境下文件共享的首选方案

Samba工作机制

通俗类比

假设 Samba 是一个「快递中转站」(让 Windows 电脑访问 Linux 的文件):

  • smbd 是 仓库管理员 + 快递员(干实事的)

  • nmbd 是 前台客服 + 广告牌(搞宣传的)

15.2.3 FTP(安全性不如其它两个)

  • FTP(File Transfer Protocol) 文件传输协议,工作于C/S模式
  • FTP允许用户将文件在本地计算机和远程服务器之间上传或者下载
15.2.3.1 FTP协议特点:
  • FTP使用两个TCP端口来连接
  • 控制连接,默认使用TCP端口21,客户端和服务器在控制通道上发送命令和响应,该连接在整个会话期间保持打开
  • 数据连接,用于传输文件数据,在需要传输文件或目录列表时建立,完成后关闭,默认情况下使用20,但实际端口可能变化(见下述主动/被动模式)
  • 数据连接的建立方向和端口取决于FTP模式
15.2.3.2 vsftpd文件共享服务范例

1.什么是vsftpd(very secure ftp deamon)?

  • vsftpd是Linux中常用的一个FTP服务器软件,用于实现FTP服务
  • 相比于其它FTP服务的主要优势为最小权限设计,用户隔离,支持FTPS(对传统的FTP协议增强)

2.搭建vsftpd文件共享服务范例

 用户与权限设置: 根据配置,决定允许哪些用户访问

  • 匿名用户:确保系统存在用户名为ftp或nobody的账户作为匿名用户身份,其主目录存在(var/ftp),默认情况下匿名用户即使开启上传也只能上传到/var/ftp/pub等目录
  • 本地用户:vsftpd允许系统账户直接用于ftp登录。本地用户可以上传到其具有写权限的目录,需要确保文件系统权限与vsftpd配置匹配。

注意:

  • FTP在互联网上传输不加密,不安全
  •  如果需要Internet传输敏感⽂件,应使用SFTP(基于SSH)或FTPS
  • vsftpd支持FTPS,可通过设置ssl_enable=YES并配置证书来启用加密。除此之外,服务器防⽕墙需要开放21端⼝以及被动端⼝范围

 15.3 Git/Github/GitLab基础

Git是一种分布式版本控制系统,Git采纳了分布式的理念:每个开发者在自己电脑上都持有整个代码仓库的完整拷贝,包括项目的所有版本历史。

Git与文件共享/传输的区别:

  • NFS,Samba,FTP都是直接的文件共享或传输方式,而Git关注的是版本演变和协作开发
  • 使用Git并不意味着实时共享文件(不向NFS/Samba那样看到同一份文件),而是每个协作者各自拥有一份仓库,通过同步变更的方式共享更新
  • Git更适合协同编辑代码

15.3.1  GitLab

  • GitLab 是⼀个基于 Git 的版本控制平台,与 GitHub 类似,但GitLab支持企业或个人“自己部署”私有 Git 仓库平台
  •  GitLab 是“私有版 GitHub”,适合校内、企业、封闭网络环境使用。
     
Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐