Ansible--自动化运维工具

Ansible自动化运维工具介绍

1.Ansible介绍

Ansible是一款自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。

Ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是Ansible所运行的模块,Ansible只是提供一种框架。主要包括:

(1) 连接插件connection plugins:负责和被监控端实现通信;

(2) host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;

(3) 各种模块核心模块、command模块、自定义模块;

(4) 借助于插件完成记录日志邮件等功能;

(5) playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。

2.Ansible工作原理

基于 SSH 和模块

Ansible 通过 SSH 协议连接到目标主机。这意味着它不需要在目标主机上安装额外的代理软件。它使用一系列的模块来执行具体的任务。这些模块是 Ansible 的核心功能单元,比如 "yum" 模块用于在基于 RPM 的系统(如 CentOS、Red Hat)上安装软件包,"apt" 模块用于 Debian 和 Ubuntu 系统的软件安装,"service" 模块用于管理系统服务等。当 Ansible 执行一个任务时,它会将相应的模块发送到目标主机,然后在目标主机上运行模块来完成任务。

Inventory 文件

Ansible 使用一个名为 "Inventory" 的文件来管理目标主机列表。这个文件可以是简单的文本格式,列出了主机的 IP 地址或主机名,也可以按照组进行分类。例如,你可以将所有的 Web 服务器放在一个名为 "web_servers" 的组中,将数据库服务器放在 "db_servers" 的组中。在 playbook 中,就可以针对不同的组执行不同的任务,比如只在 "web_servers" 组中安装和配置 Web 服务器软件。

3.Ansible工作流程

(1)加载配置文件: Ansible 默认查找 /etc/ansible/ansible.cfg 配置文件,这个文件包含了Ansible运行时的行为设定,如连接方式、插件路径等。

(2)解析Inventory: Ansible 使用 Inventory 文件(默认是 /etc/ansible/hosts)来确定需要操作的目标主机或主机组。

(3)编译Playbook或命令: Ansible 准备执行的Playbook或直接执行的Ad-Hoc命令,并解析其中的任务和模块调用。

(4)模块加载与执行策略准备: 对于每个任务,Ansible 加载相应的模块(如 command 模块),并准备执行上下文,包括变量、环境等。

(5)生成并传输临时脚本: Ansible 会根据任务和模块生成一个或多个临时的Python脚本,并通过SSH连接传输到目标主机的临时目录,通常位于目标用户的 ~/.ansible/tmp/ansible-tmp-<UNIQUE_ID>/ 目录下。

(6)赋予执行权限: 在目标主机上,Ansible 会给这个临时Python脚本加上执行权限,以便能够运行。

(7)执行远程脚本: Ansible 通过SSH在目标主机上执行这个临时脚本,并收集执行结果。

结果收集与处理: 执行完毕后,各个主机的执行结果被收集并汇总,Ansible根据这些结果决定是否继续执行后续任务,或是根据Playbook中的错误处理逻辑(如 rescue 和 always 块)进行操作。

(8)清理: 一旦任务执行完成,无论成功还是失败,Ansible 会清理目标主机上的临时文件,包括删除之前上传的Python脚本。

(9)退出与报告: 清理完成后,Ansible 进程在目标主机上退出,并向控制机报告最终的执行状态和结果。

Ansible集群搭建

|----------|----------------|
| Server节点 | 192.168.100.51 |
| Host1 节点 | 192.168.100.52 |
| Host2 节点 | 192.168.100.53 |
| Host3 节点 | 192.168.100.50 |

1.编写hosts文件

|------------------------------------------------------------------------------------------------------------------------------------------------|
| 三个主机根据节点规划更改主机名,并编写映射文件 [root@server ~]# vi /etc/hosts 192.168.100.51 server 192.168.100.52 host1 192.168.100.53 host2 192.168.100.50 host3 |

2.配置免密登陆

主节点生成密钥对

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [root@server ~]# ssh-keygen -P "" -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Created directory '/root/.ssh'. Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub. The key fingerprint is: SHA256:C6R237cwGYEIGvMJRvFWj6ZQ3h1qLdagV/GKNjY//W0 root@server The key's randomart image is: +---[RSA 2048]----+ | .B.o o +. | | . X * @ + | | o B % * o | | o O o . . | | + O S . | | . + * + o | | = * . | | . = oE | | o.. | +----[SHA256]-----+ |

-P "":设置空密码

-t rsa: 指定生成密钥的类型为RSA

将公钥发给受管制节点

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [root@server ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub root@host1 /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub" The authenticity of host 'host1 (192.168.100.52)' can't be established. ECDSA key fingerprint is SHA256:67lB1mL6LK/kJPxrKPAOU+3YIixzp0oA4aTCBoqf41c. ECDSA key fingerprint is MD5:c2:17:dc:da:a3:3d:31:28:1f:74:10:77:85:9d:9d:36. Are you sure you want to continue connecting (yes/no)? yes /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys root@host1's password: Number of key(s) added: 1 Now try logging into the machine, with: "ssh 'root@host1'" and check to make sure that only the key(s) you wanted were added. |

三个受管制的节点一次发送,测试免密登陆:

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [root@server ~]# ssh host1 Last login: Sat Nov 23 14:41:46 2024 from server [root@host1 ~]# exit logout Connection to host1 closed. [root@server ~]# ssh host2 Last login: Sat Nov 23 14:41:51 2024 from server [root@host2 ~]# exit logout Connection to host2 closed. [root@server ~]# ssh host3 Last login: Sat Nov 23 01:33:26 2024 from 192.168.100.1 [root@host3 ~]# exit logout Connection to host3 closed. [root@server ~]# |

3.主节点安装Ansible

主节点安装epel-release源后,安装Ansible,并检查是否安装成功

|----------------------------------------------------------------------------------------------------------------------------------|
| [root@server ~]# yum install -y epel-release [root@server ~]# yum install -y ansible [root@server ~]# ansible --version |

4.修改主机清单设置分组

ansible常见的配置文件

• /etc/ansible/ansible.cfg:主配置文件

• /etc/ansible/hosts:主机清单文件

• /etc/ansible/roles:角色目录

备份主机求清单文件

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [root@server ~]# cd /etc/ansible/ [root@server ansible]# ls ansible.cfg hosts roles [root@server ansible]# cp -f hosts hosts.bak [root@server ansible]# ls ansible.cfg hosts hosts.bak roles |

编写主机清单文件

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [root@server ansible]# vi hosts [all-servers] server host1 host2 host3 [node1] host1 [node2] host2 [node3] host3 [mysql_test] #规划节点host1和host2节点为数据库节点 host1 host2 [web_test] #规划节点host2和host3节点为web节点 host2 host3 [manager] server |

保存配置文件

Ansible模块基本使用

1.Ansible常用参数说明

|--------------------|-----------------------------------------|
| 参数 | 说明 |
| -h | 显示帮助信息 |
| -i | 指定inventory文件路径,默认路径为/etc/ansible/hosts |
| -l | 限制palybook或命令的作用范围 |
| -u | 连接远程主机时使用的用户名。 |
| -b | 相当于sudo |
| --become-user=USER | 提上权限后切换到的用户 |
| -m | 指定要使用的模块名 |
| -a | 指定模块的参数 |
| -f | 指定并发进程数,默认为5 |
| -v | 增加输出的详细程度 |
| -e | 指定变量名 |
| --diff | 修改文件时显示修改前后的差异 |

Ansible的执行状态

绿色:执行成功并且不需要做改变的操作

黄色:执行成功并且对目标主机做变更

红色:执行失败

粉色:警告信息

蓝色:显示ansible命令执行的过程

2.ping模块

ping模块用于检查指定节点机器是否连通,用法很简单,不涉及参数

主机如果在线,则回复pong

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [root@server ansible]# ansible -m ping node1 [WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details host1 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "ping": "pong" } |

以组为单位测试

|----------------------------------------------|
| [root@server ansible]# ansible -m ping all |

3.command模块

command模块用于在远程主机上执行命令,ansible默认就是使用command模块。

|-----------------------------------------------------------------------------|
| [root@server ansible]# ansible host1 -m command -a 'ls /etc/yum.repos.d/' |

相当于远程让host1节点执行ls命令

在受管制主机host1的/opt/目录下创建文件

|-----------------------------------------------------------------------|
| [root@server ansible]# ansible host1 -m command -a 'touch /opt/hzy' |

command模块有一个缺陷就是不能使用管道符和重定向功能。

Command模块也可以多节点执行

|---------------------------------------------------------------|
| [root@server ansible]# ansible -m command -a 'hostname' all |

4.shell模块

shell模块用于在受控机上执行受控机上的脚本,亦可直接在受控机上执行命令。

shell模块亦支持管道与重定向。

|----------------------------------------------------------------------|
| [root@server ansible]# ansible host1 -m shell -a 'a=10086;echo $a' |

查看web_test组远程主机的系统版本

|-------------------------------------------------------------------------------------------------------------------|
| [root@server ansible]# ansible web_test -m shell -a 'cat /etc/os-release | grep PRETTY_NAME | cut -d "=" -f2' |

5.user模块

主要用于管理远程系统上的用户账户,包括创建、修改和删除用户。

它允许你设置用户的密码、shell、主目录、权限等属性

常用参数:

|-----------------|------------------------------------------|
| system | 创建用户设置用户是系统用户 |
| uid | 指定uid |
| group | 指定用户组 |
| home | 指定家目录 |
| comment | 用户的描述信息 |
| password | 指定用户密码 |
| state | 设置帐号状态,默认为present表示新建用户,指定值为absent表示删除 |
| update_password | 更新用户密码 |
| name | 指定用户名 |
| remove | 在使用state=absent时, 行为是与userdel --remove一致 |

|--------------------------------------------------------------------------------------------------|
| [root@server ansible]# ansible host1 -m user -a 'system=yes name=hongzy uid=777 comment="hzy"' |

指在host1节点创建一个名为hongzy的用户,uid为777,用户描述为hzy

检查hongzy用户是否被正确创建,调用shell模块

|--------------------------------------------------------------------------------------------------------------------------------|
| [root@server ansible]# ansible host1 -m shell -a 'id hongzy ; grep ^hongzy: /etc/passwd | awk -F ":" '\''{print $5}'\''' |

删除hongzy用户

|-----------------------------------------------------------------------------------------|
| [root@server ansible]# ansible host1 -m user -a 'name=hongzy state=absent remove=yes' |

再次调用shell模块检查hongzy是否被删除

|--------------------------------------------------------------------------------------------------------------------------------|
| [root@server ansible]# ansible host1 -m shell -a 'id hongzy ; grep ^hongzy: /etc/passwd | awk -F ":" '\''{print $5}'\''' |

6.group模块

group模块用于在受控机上添加或删除组

常用参数

|-----------|-------------------------------|
| gid | 用于设置组的GID |
| name | 指定组名称(必选项) |
| non_uniue | 允许组ID为非唯一值,与gid一起使用 |
| state | 指定用户组在远程主机上的状态,present和absent |
| system | 创建的用户组是否是系统组 |

创建组

|----------------------------------------------------------------------------------------|
| [root@server ansible]# ansible host1 -m group -a "name=footabll gid=1001 system=yes" |

创件一个组名为footbal,组ID为1001,并且是系统组

使用shell模块检查是否创建成功

|----------------------------------------------------------------------------------|
| [root@server ansible]# ansible host1 -m shell -a "cat /etc/group | grep 1001" |

删除组

|------------------------------------------------------------------------------------------|
| [root@server ansible]# ansible host1 -m group -a "name=football gid=1001 state=absent" |

7.copy模块

在 Ansible 中,copy模块主要是将本地(执行 Ansible 任务的控制节点)的文件或目录复制到远程的host主机(被管理节点)。

常用参数

|---------|--------------------------------------------------------|
| src | 被复制文件的本地路径 |
| dest | 复制到管控节点的绝对路径(必选) |
| content | 可以指定文件的值(内容) |
| mode | 设置文件权限 |
| force | 当目标主机含有该文件时,但内容不同时,设为yes表示强制覆盖,设置为no,表示目标主机的目标位置不存在才复制 |
| backup | 在覆盖前,将源文件备份,备份文件包含时间信息 |

创建一个txt文件并写入内容

|--------------------------------------------------------------|
| [root@server ansible]# echo "hello word" > /root/test.txt |

将该文件复制到被管理主机host1节点的/opt/目录下并赋予权限755

|----------------------------------------------------------------------------------------------------|
| [root@server ansible]# ansible host1 -m copy -a 'src=/root/test.txt dest=/opt/copy.txt mode=755' |

再次使用copy模块,进行覆盖文件操作,使用backup参数

|------------------------------------------------------------------------------------------------|
| [root@server ~]# ansible host1 -m copy -a 'src=/root/777.txt backup=yes dest=/opt/copy.txt' |

使用 Ansible 来调用 copy 模块,目的是将本地/root/777.txt 文件复制到名为 host2 的远程主机的 /opt/copt.txt 位置,并且设置了 backup=yes 参数,意味着如果远程主机上 /opt 目录下已经存在 copt.txt 文件,那么会先对原有的文件进行备份,再将本地的文件复制过去。

查看这两个文件

8.fetch模块

Ansible 的 fetch 模块用于从远程节点抓取文件并存储到Ansible控制器(执行Ansible任务的机器)上的指定目录

常用参数

|-------------------|--------------------------------------------------|
| src | 要远程拉取的文件(只能是文件) |
| dest | 用来存放文件的目录 |
| flat | 设置为yes时,即使src是目录,也会将所有内容扁平化存储到dest |
| size | 限制抓取文件的大小 |
| force | 即使本地文件已经存在了仍旧抓取,默认yes,设置为no只有当远程文件比本地文件新或不同才执行抓取 |
| validate_checksum | 当设置为yes时在下载完成后校验文件的校验和确保文件完整无误 |
| fail_on_missing | 当设置为yes时,如果远程文件不存在,则标记任务失败,否则只是简单地跳过该文件 |

从远程主机抓取文件

|---------------------------------------------------------------------------------------------------------|
| [root@server ~]# ansible host1 -m fetch -a 'src=/opt/copy.txt.2092.2024-11-24@10:33:45~ dest=/opt/' |

使用校验机制

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [root@server ~]# ansible host1 -m shell -a 'echo "fetch_text1" > /root/fetch.txt' [root@server ~]# ansible host1 -m fetch -a 'src=/root/fetch.txt dest=/opt/ validate_checksum=yes fail_on_missing=yes size=100k' |

增加了验证文件完整性,文件是否存在,文件大小限制

查看server节点下的/opt目录结构

9.file模块

file模块主要用于对文件的创建、删除、修改、权限、属性的更改。

常用参数

|-------|------------------------------------------|
| path | 定义文件/目录的路径 |
| mode | 定义文件/目录的权限 |
| owner | 定义文件/目录的所有者 |
| group | 定义文件/目录的所属组 |
| state | 选项:directory、file、link、hard、touch、absent |
| dest | 被链接到的路径(state=link) |
| src | 被链接的源文件的路径(state=link) |

在指定路径下创建目录

|-----------------------------------------------------------------------------------------------------------------|
| [root@server ~]# ansible web_test -m file -a 'path=/root/web mode=644 owner=root group=root state=directory' |

在/root目录下创建web目录,权限为644,所有者和所属组为root

查询root目录进行检查

|----------------------------------------------------------------|
| [root@server ~]# ansible web_test -m shell -a 'ls -l /root' |

创建软链接

|------------------------------------------------------------------------------------------|
| [root@server ~]# ansible web_test -m file -a 'path=/opt/web src=/root/web state=link' |

查看软链接是否创建成功

|-----------------------------------------------------------------|
| [root@server ~]# ansible web_test -m command -a 'ls -l /opt' |

删除文件操作

删除web目录

|-------------------------------------------------------------------------------|
| [root@server ~]# ansible web_test -m file -a 'path=/root/web state=absent' |

查看是否删除

10.yum模块

主要用于在基于 RPM 的 Linux 系统上管理软件包,它允许用户安装、更新、卸载软件包,并可配置额外的选项以控制操作的具体行为。

常用参数

|--------------|------------------------------------|
| name | 所安装的软件包的名称 |
| state | 安装present,安装最新版本latest,卸载软件包absent |
| update_cache | 强制更新yum缓存 |
| conf_file | 指定远程安装是所依赖的配置文件 |
| disablerepo | 临时禁用yum源 |
| skip_borken | 跳过异常软件节点 |

让host1节点和host2节点安装net-tools软件包

|----------------------------------------------------------------------------------|
| [root@server ~]# ansible host1,host2 -m yum -a 'name=net-tools state=present' |

使用netstat命令检测是否呗正确安装并且可以使用

|---------------------------------------------------------------------|
| [root@server ~]# ansible host1,host2 -m shell -a 'netstat -lnpt' |

让host2卸载net-tools软件包

|---------------------------------------------------------------------------|
| [root@server ~]# ansible host2 -m yum -a 'name=net-tools state=absent' |

检测是否卸载成功

|---------------------------------------------------------|
| [root@server ~]# ansible host2 -m shell -a 'echo $?' |

更新host1主机的所有软件包

|--------------------------------------------------------------------|
| [root@server ~]# ansible host1 -m yum -a 'name=* state=latest' |

11.service模块

Ansible的service模块用于管理系统服务(如启动、停止、重启服务等)。

这个模块与特定的系统服务管理工具(如systemd、sysvinit、upstart等)兼容,能够跨不同的Linux发行版和系统管理框架工作

常用参数

|-----------|----------------------------------------------------|
| name | 服务的名称(必选) |
| state | started启动服务,stopped停止服务,restarted重启服务,reloaded重载配置 |
| enabled | 服务是否应该在系统启动时自动启动。至少需要指定state或enabled中的一个 |
| sleep | 当服务处于restarted状态时,停止与启动命令之间暂停的秒数 |
| use | 服务模块通常通过自动检测使用系统特定的模块,此设置可以强制使用特定模块。 |
| arguments | 额外的命令行参数,提供给服务管理命令。 |

使host1节点关闭防火墙

|--------------------------------------------------------------------------------|
| [root@server ~]# ansible host1 -m service -a 'name=firewalld state=stopped' |

查看host1节点防火墙状态

再次启动host1节点的防火墙

12.script模块

Ansible的script模块允许你在远程主机上执行位于Ansible控制节点上的本地脚本

常用参数

|-----------|------------------------|
| free_form | 直接提供脚本的路径以及可选参数 |
| creates | 指定远程运行的本地脚本的路径 |
| removes | 指定远程节点的一个文件名,文件不存在则不执行 |
| cmd | 要在远程节点上运行的本地脚本的路径 |
| chdir | 在远程节点执行脚本之前要切换到的目录路径 |

在server控制节点编写一个脚本

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [root@server ~]# vi root.sh #!/bin/bash #检测当天用户是否为root用户 if [ USER == "root" \] then echo "当前为root用户" \> /root/test else echo "当前是USER用户,不是root用户" > /root/test fi |

让host1节点和host2节点执行该脚本文件

|----------------------------------------------------------------------|
| [root@server ~]# ansible host1,host2 -m script -a '/root/root.sh' |

查看/root/test文件,检查脚本是否执行成功

|----------------------------------------------------------------------|
| [root@server ~]# ansible host1,host2 -m shell -a 'cat /root/test' |

13.setup模块

Ansible的setup模块用于收集远程主机的信息,并将这些信息以facts的形式返回给Ansible控制节点。这些facts可以包括系统变量(如操作系统类型、架构、网络配置、已安装软件包等),并且在Playbook执行期间可以被其他任务使用。

常用参数

|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| filter | 用于筛选出特定的系统信息。通过指定一个或多个关键字,可以只获取与这些关键字相关的系统变量信息。 |
| fact_path | 指定自定义事实(custom facts)的路径。自定义事实是用户自己定义的关于主机的信息,除了Ansible默认收集的系统事实之外,用户可以通过在指定路径下创建文件来添加自定义的主机信息。 |
| gather_subnet | 控制setup模块收集信息的子集。默认情况下,setup模块会收集大量的系统信息,包括硬件、网络、操作系统等多个方面。使用gather_subset可以指定收集某些特定方面的信息,或者排除某些方面的信息。可能的值包括:all(全部)、min(最小集合)、hardware(硬件信息)、network(网络信息)、virtual(虚拟化信息)、ohai(类似Chef Ohai的扩展信息)、facter(使用Facter收集的信息)。 |

查看host1主机的内存信息

|------------------------------------------------------------------|
| [root@server ~]# ansible host1 -m setup -a "filter='*mem*'" |

检查(由于内存信息是实时更新的,所以会有所偏差)

|-----------------------------------------------------------|
| [root@server ~]# ansible host1 -m command -a "free -m" |

将查询到的信息保存

|------------------------------------------------------------------------------|
| [root@server ~]# ansible host1 -m setup -a 'filter="*mem*"' --tree /opt |

保存的信息存放在了server控制节点的/opt目录下

至此,Ansible的介绍和Ansible模块的基本使用就结束了,接下来会是playbook文件的编写以及后续基于ansible的实验搭建等,拜拜各位看官

相关推荐
纪伊路上盛名在13 分钟前
NCR+可变电荷块——文献hub1
笔记·学习·知识图谱·学习方法
有Li16 分钟前
AutoFOX:一种冠状动脉X线造影与OCT的自动化跨模态3D融合框架|文献速递-视觉大模型医疗图像应用
运维·3d·自动化
BuluAI1 小时前
Lazydocker:高效便捷的Docker管理工具
运维·docker·容器
找了一圈尾巴2 小时前
Wend看源码-Java-Map学习
java·学习·map
奔波儿灞爱霸波尔奔2 小时前
人工智能之基于阿里云进行人脸特征检测部署
人工智能·阿里云·云计算
山山而川粤5 小时前
母婴用品系统|Java|SSM|JSP|
java·开发语言·后端·学习·mysql
百家方案7 小时前
「下载」京东数科-数字孪生智慧园区解决方案:打通园区数据、融合园区业务、集成园区服务、共建园区生态,实现真实与数字孪生园区
人工智能·云计算·智慧园区·数智化园区
空白诗8 小时前
玩转OCR | 腾讯云智能结构化OCR推动跨行业高效精准的文档处理与数据提取新时代
云计算·ocr·腾讯云·玩转腾讯云 ocr
huhy~8 小时前
基于Ubuntu2404桌面版制作qcow2镜像
centos·云计算
飘飘燃雪9 小时前
Linux Modbus协议详解,代码示例
linux·运维·服务器·modbus