【Python】不一样的Ansible(一)
不一样的Ansible——进阶学习
前言
Ansible
是一个极其简单的 IT 自动化引擎,可自动执行云配置、配置管理、应用程序部署、服务内编排和许多其他 IT 需求;基本上每一个运维工程师都会听过或者使用过Ansible
(这是必然的,只要你需要管理超过2位数的服务器,Ansible
基本是一个必备的工具),如果你还不知道Ansible
是怎么用的,一定要找一个环境试试,这是一个真正让运维工作自动化并且事半功倍的工具。
Ansible
不使用任何代理程序,也就是不需要部署agent
,也不使用额外的自定义安全基础设施,因此很容易部署 - 最重要的是,使用yaml
配置就能编写整个自动化流程,不需要学习太多额外的编程知识。
这一部分的内容,不是对Ansible
做基本介绍的,而是对其中一些进阶的或者平时不会知道的东西做一个学习和记录的。比如各种插件的特殊用法、如何在我们自己的Python
程序中去使用Ansible
、以及一些其他的技巧或者知识点。
本系列文章的所有内容基于
Ansible 9
编写,Ansible 9
使用Ansible-core 2.16
正文
概念
Ansible Core
Ansible Core
或ansible-core
是Ansible
的主要构件和架构,包含了许多的核心逻辑,比如:
- CLI 工具,如 ansible-playbook、ansible-doc 等,用于驱动自动化并与之交互。
- Ansible 语言使用 YAML 创建一套用于开发 Ansible Playbook 的规则,包括
conditionals
,blocks
,includes
,loops
以及其他的一些内容。 - 允许通过
Ansible collections
进行扩展的架构框架
总结来说,Ansible Core
提供你目前所熟知的所有Ansible的基础能力,并且允许开发者在现有基础上拓展Ansible的功能。
Plugins和Modules
Ansible
中非常重要的两个概念,插件和模块,那么他们有什么区别,以及怎么在自己实现拓展功能的时候选择使用哪个特性:
Plugins
:扩展了Ansible Core
的功能。大多数插件都在/usr/bin/ansible
进程的控制节点上执行。插件为Ansible
的核心功能提供选项和扩展:转换数据、记录输出、连接Inventory
等Modules
:本质也是一种Plugins
,但是其特点在于能够在远程服务器上执行自动化任务
。模块以独立脚本的形式运行,由Ansible
在控制节点之外的进程中执行。模块与Ansible
的接口主要是json
,接受参数并在退出前通过向stdout
打印json
字符串返回信息。与其他插件(必须用 Python 编写)不同,模块可以用任何语言编写;不过Ansible
只提供Python
和Powershell
版本的模块。
这其实很好理解,Plugins
是用来添加Ansible的核心代码逻辑的,因此需要Ansible
能够把它加载进来,Ansible既然是Python
编写的,自然也要求Plugins
是要用Python
编写,而Modules
是通过ssh分发到受管节点执行的,那么他可以是任意程序,只要远程服务器能够运行它就可以了,默认Ansible
的那些模块其实在受管节点也是调用了Python
解释器来运行的
插件
插件类型
上面已经介绍了插件是什么,在Ansible
中有多种插件类型,下面将官网的:
- Action plugins:
Action
与module
一起执行playbook
任务所需的动作,通常在后台自动运行,在模块实际运行前执行一些前期工作; - Become plugins:用于执行命令时进行提权或者用户切换,我们最常用的就是借助
become
完成sudo
操作; - Cache plugins:
Cache
插件允许Ansible
存储收集到的受管节点信息或者inventory
信息,避免因为从源数据检索而影响性能,这个最直观的体现就是我们执行playbook
时如果没有关闭gather_fact
,可能会等待很长时间,借助cache
可以有效减少重复在受管节点执行操作时的这个步骤耗时; - Callback plugins:回调插件可以在
Ansible
响应事件时添加新的行为。默认情况下,回调插件可控制运行命令行程序时看到的大部分输出,但也可用于添加额外输出、与其他工具集成以及将事件汇聚到存储后端;对于想要对接Ansible
做自动化管理的同学来说,这个插件很重要; - Cliconf plugins:
Cliconf
插件是网络设备CLI
接口的抽象。它们为Ansible
在这些网络设备上执行任务提供了标准接口,主机维护不常用,我也没用过; - Connection plugins:
Connection
插件允许Ansible
使用既定方式连接到目标主机,以便在上面执行任务,Ansible
自身附带了许多连接插件,比如openssh
和paramiko
,但每台主机一次只能使用一个; - Docs fragments:
Docs fragments
可让使用者在一个地方记录多个插件或模块的通用参数; - Filter plugins:
Filter
插件也是一个功能常用的插件,他允许对数据进行特定的序列化或者其他自定义的处理,比如对字符串进行拆分和连接,默认Ansible
使用的是jinja2
提供的标准Filter功能,同时增加了一些特性; - Httpapi plugins:
Httpapi
插件告诉Ansible
如何与远程设备基于HTTP
的API
交互,并在设备上执行任务; - Inventory plugins:
Inventory
插件是一个允许用户指向仓库数据源的插件,也就是我们执行ad-hoc
命令式的-i
参数执行的逻辑; - Lookup plugins:
Lookup
插件是Jinja2
模板语言的Ansible
特定扩展。用户可以使用该插件从外部来源(文件、数据库、key/value存储、API 和其他服务)访问playbook
中的数据。与所有模板一样,Lookup
在Ansible
控制节点上运行。Ansible
使用标准模板系统提供查找插件返回的数据。你可以使用查找插件从外部资源加载变量或模板信息。 - Modules:上文说过,
Modules
也是一种插件,所以这里也有它; - Module utilities:包含多个插件使用的共享代码,最好把它和
Modules
一起理解; - Netconf plugins:网络设备
Netconf
接口抽象,用于在网络设备上执行ansible
任务; - Shell plugins:
Shell
插件的作用是确保Ansible
运行的基本命令格式正确,能够在目标计算机上运行,并允许用户配置与Ansible
执行任务方式相关的某些行为,具体的情况可以跳转到 - Strategy plugins:
Strategy
通过handles
和受管节点的调度来控制playbook
的执行流程,具体的策略可以查看:更改Strategy - Terminal plugins:
Terminal
插件包含有关如何正确初始化特定网络设备的SSH shell
以配合Ansible
使用的信息。这通常包括禁用自动分页、检测输出中的错误,以及在设备支持和需要的情况下启用特权模式。 - Test plugins:
Test
插件可评估模板表达式并返回True
或False
。有了测试插件,用户就可以创建条件(比如when
关键字)来实现tasks、blocks、play、playbooks和roles的逻辑。Ansible
使用作为Jinja
一部分提供的标准测试,并添加了一些专门的测试插件 - Vars plugins:
Vars
插件拓展了一些变量的使用方式
上面所说的插件,其中一部分(Action
、Cache
、Callback
、Connection
、Filter
、Inventory
、Lookup
、Test
、Vars
)支持开发者进行自定义的编写,实现新的功能。
编写自定义插件
基本要求
让我们先来编写一个自定义的插件来为Ansible提供额外的核心能力,编写之前我们要知道一个Ansible
插件必须要满足的条件:
- 使用
Python
编写,这个在上一节已经说明原因 - 对异常进行合适的处理,使用
raise
抛出异常 - 返回值要是
unicode
编码的字符串 - 符合
Ansible
的配置和文档标准
接下来针对上面的要求做一下分别的解释
使用Python编写
使用Python
编写插件,这样它才能被PluginLoader
加载,并作为任何模块都能使用的Python
对象返回。由于插件将在控制节点上执行,因此必须使用兼容的 Python 版本编写插件
使用raise处理异常
在插件执行过程中遇到错误时,应通过引发AnsibleError()
或类似类来返回错误信息。在将其他异常包装成错误信息时,应始终使用to_native
Ansible函数,以确保不同Python
版本的字符串兼容,下面是一个简单的样例:
from ansible.module_utils.common.text.converters import to_nativetry:cause_an_exception()
except Exception as e:raise AnsibleError('Something happened, this was original exception: %s' % to_native(e))
由于Ansible
仅在需要时才会对变量进行解析,因此filter
插件和test
插件应使用jinja2.exceptions.UndefinedError
和AnsibleUndefinedVariable
异常,以确保未定义变量仅在必要时才引起程序的Fatal
返回值符合unicode编码
这个要求是为了保证过程中的字符串str
能够在Jinja2
中正常运行和解析,Ansible提供了响应的方法进行转换:
from ansible.module_utils.common.text.converters import to_text
result_string = to_text(result_string)
插件选项
为了给我们自己的插件定义可配置选项,我们需要在Python文件的DOCUMENTATION
部分进行描述和声明,这种规范可以确保我们插件响应选项的文档时钟保持正确和最新,以下是格式定义:
options:option_name:description: describe this config optiondefault: default value for this config optionenv:- name: NAME_OF_ENV_VARini:- section: section_of_ansible.cfg_where_this_config_option_is_definedkey: key_used_in_ansible.cfgvars:- name: name_of_ansible_var- name: name_of_second_varversion_added: X.xrequired: True/Falsetype: boolean/float/integer/list/none/path/pathlist/pathspec/string/tmppathversion_added: X.x
我们来看一个样例,这里以自带的Callback插件中的json.py演示:
# (c) 2016, Matt Martz <matt@sivel.net>
# (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = typeDOCUMENTATION = '''callback: jsonshort_description: Ansible screen output as JSONversion_added: "2.2"description:- This callback converts all events into JSON output to stdouttype: stdoutrequirements:- Set as stdout in configoptions:show_custom_stats:version_added: "2.6"name: Show custom statsdescription: 'This adds the custom stats set via the set_stats plugin to the play recap'default: Falseenv:- name: ANSIBLE_SHOW_CUSTOM_STATSini:- key: show_custom_statssection: defaultstype: boolnotes:- When using a strategy such as free, host_pinned, or a custom strategy, host results willbe added to new task results in ``.plays[].tasks[]``. As such, there will exist duplicatetask objects indicated by duplicate task IDs at ``.plays[].tasks[].task.id``, each with anindividual host result for the task.
'''
ok,现在假设我们设定好了自己的配置项,如果要在插件内部使用对应的配置项,一般使用self.get_option(<option_name>)
进行获取,不过有些插件的处理方式会有些不同;
配置部分遵循了Ansible中值的优先原则,当在同一个类别下定义多个值时,最后一个值优先,比如上述样例的这部分:
vars:- name: name_of_ansible_var- name: name_of_second_var
此时option_name
选项的值使用name_of_second_var
,如果要对option值进行设置,则要使用self.set_option()
方法;
文档标准
支持嵌入式文档(参见 ansible-doc
列表)的插件应包含格式良好的文档字符串,如果我们继承一个插件,则必须在文档中记录被继承插件的选项;
编写插件
以Action plugin为例,编写一个插件,首先,编写的插件应该继承自对应的Base类,比如:
from ansible.plugins.action import ActionBaseclass ActionModule(ActionBase):pass
允许使用_execute_module
方法来调用内置的Module
并获取返回结果:
module_return = self._execute_module(module_name='<NAME_OF_MODULE>',module_args=module_args,task_vars=task_vars, tmp=tmp)
我们以官方文档中的示例为准,进行讲解,这里添加了一个通过setup
模块获取的内容进行服务器时间差异的比对动作的action
:
from __future__ import (absolute_import, division, print_function)
__metaclass__ = typefrom datetime import datetime
from ansible.plugins.action import ActionBaseclass ActionModule(ActionBase):"""Action"""def run(self, tmp=None, task_vars=None):super().run(tmp, task_vars)module_args = self._task.args.copy()module_return = self._execute_module(module_name='setup',module_args=module_args,task_vars=task_vars, tmp=tmp)ret = {}remote_date = Noneif not module_return.get('failed'):for key, value in module_return['ansible_facts'].items():if key == 'ansible_date_time':remote_date = value['iso8601']if remote_date:remote_date_obj = datetime.strptime(remote_date, '%Y-%m-%dT%H:%M:%SZ')time_delta = datetime.utcnow() - remote_date_objret['delta_seconds'] = time_delta.secondsret['delta_days'] = time_delta.daysret['delta_microseconds'] = time_delta.microsecondsreturn {"ansible_facts": dict(ret)}
在上述代码中,调用了内部的setup
模块,拉取受管节点的信息,在其返回值中,有这样的数据结构:
"ansible_date_time": {"date": "2024-01-08","day": "08","epoch": "1704704528","epoch_int": "1704704528","hour": "17","iso8601": "2024-01-08T09:02:08Z","iso8601_basic": "20240108T170208306063","iso8601_basic_short": "20240108T170208","iso8601_micro": "2024-01-08T09:02:08.306063Z","minute": "02","month": "01","second": "08","time": "17:02:08","tz": "CST","tz_dst": "CST","tz_offset": "+0800","weekday": "Monday","weekday_number": "1","weeknumber": "02","year": "2024"},
随后在自定义插件逻辑中我们比对了iso8061
的值,计算出时间的差异值,然后返回,这个插件的返回值类似以下的格式:
172.18.0.25 | SUCCESS => {"ansible_facts": {"delta_days": 0,"delta_microseconds": 152565,"delta_seconds": 0},"changed": false
}
如果想要进一步修改插件,满足自己的需求,只需要在刚才编写的ActionModule
中进行变更即可。
添加一个本地插件
上面我们已经编写了一个自定义的插件,但是只是把代码写好是没法按照预期的方式通过ad-hoc
的方式使用的,大概率会出现以下的报错:
172.18.0.25 | FAILED! => {"msg": "The module myaction was not found in configured module paths"
}
而想要直接便利的使用自定义的插件,有以下几种方式进行配置:
注册为内置插件
这种方法不建议,只做介绍,直接将编写好的python
文件拷贝到ansible
的安装目录下,比如我们使用虚拟环境,通过pip
安装的ansible
,那么我们的ansible
安装目录ANSIBLE_INSTALL_DIR
大概是这样的:$ENV_HOME/lib/python3.9/site-packages/ansible
,那么只需要把我们的插件放在$ANSIBLE_INSTALL_DIR/plugins/
目录下对应的插件类型下:
不建议使用这种方法的原因主要是因为我们个人编写的代码在规范性上和官方的多少有些差异,最好还是做一些区分,这样在出问题的时候排查也会变得容易一些
指定插件目录
这个方式是比较规范的,当我们编写的插件是一个提供给全局使用的插件时,我们就这样做就可以了,编辑ansible
的配置文件/etc/ansible/ansible.cfg
,添加action_plugins
配置项:
[defaults]
# ...
# 可以自定义为自己需要的目录
action_plugins = /usr/share/ansible/plugins/action
然后把我们的插件放在上面配置的目录下,就能正常使用了
这种配置便于我们对插件进行管理,且配置一次后,所有人都能使用
除此之外,插件也可以放在Collection
中,这个在讲到Collection
时再单独写
其他一些技巧
更改Strategy
默认情况下,Ansible使用linear strategy
进行任务的调度,除此之外,Ansible还提供了以下集中Strategy plugins
:
- debug strategy – 在
debug
模式下运行Task
. - free strategy – 不等待其他受管节点完成当前状态,直接运行
Task
, - host_pinned strategy – 尽可能快的在每个受管节点执行
play
(按照serial
定义的批次执行,默认为全部),除非一个play
可以在不被其他主机Task中断的情况下完成,否则Ansible
不会给一个新的主机启动play
,即:拥有执行中的play的受管节点数量不超过forks
规定的数量 - linear strategy – 默认的策略,线性执行,这个线性是指
Task
,也是我们熟知的,一个Task
会在所有服务器执行完后再执行下一个Task
假设我们希望每个节点都能速度拉满,我们可以把策略改成free,通过在playbook中指定或者更改配置文件都可以实现,先看更改playbook:
- hosts: allstrategy: freetasks:# ...
或者更改ansible.cfg
:
[defaults]
strategy = free
结语
本篇文章主要抛砖引玉,说明了Ansible中模块和插件的区别,以及如何自己编写一个简单的Action Ansible插件,接下来会再多讲解一些其他类型的插件编写方法。
相关文章:

【Python】不一样的Ansible(一)
不一样的Ansible——进阶学习 前言正文概念Ansible CorePlugins和Modules 插件插件类型编写自定义插件基本要求插件选项文档标准编写插件 添加一个本地插件注册为内置插件指定插件目录 其他一些技巧更改Strategy 结语 前言 Ansible 是一个极其简单的 IT 自动化引擎,…...

分布式图文详解!
分布式理论 1. 说说CAP原则? CAP原则又称CAP定理,指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性)这3个基本…...

Unity SRP 管线【第五讲:自定义烘培光照】
文章目录 一、自定义烘培光照1. 烘培光照贴图2. 获取光照贴图3. 获取物体在光照贴图上的UV坐标4. 采样光照贴图 二、自定义光照探针三、 Light Probe Proxy Volumes(LPPV)四、Meta Pass五、 自发光烘培 一、自定义烘培光照 细节内容详见catlikecoding.c…...
CentOS快速安装Mysql5.7(Alibaba Cloud Linux兼容)
1、安装 在线下载 http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm 下载rpm安装包 [roottheo bin]# cd /usr/local [roottheo local]# wget http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm安装rpm [roottheo local]# rpm -iv…...

【css】快速实现鼠标悬浮变色效果
<div class"nav-item"><div class"ic-img"></div><div>切换</div> </div>.nav-item {width: 100rem;height: 45rem;line-height: 45rem;display: flex;text-align: center;justify-content: center;align-items: cent…...

21. Mysql 事件或定时任务,解放双手,轻松实现自动化
文章目录 概念常见操作事件调度器操作查看事件创建事件删除事件启动与关闭事件 精选示例构造实时数据定时统计数据 总结参考资料 概念 Mysql 事件是一种在特定时间点自动执行的数据库操作,也可以称呼为定时任务,它可以自动执行更新数据、插入数据、删除…...

Apache Doris 2.0.2 安装步骤 Centos8
Linux 操作系统版本需求 Linux 系统版本当前系统版本CentOS7.1 及以上CentOS8Ubuntu16.04 及以上- 软件需求 软件版本当前版本Java1.81.8.0_391GCC4.8.2 及以上gcc (GCC) 8.5.0 20210514 (Red Hat 8.5.0-4) 1、查看操作系统版本 方法 1:使用命令行 打开终端或…...

Java学习苦旅(二十五)——哈希表
本篇博客将详细讲解哈希表。 文章目录 哈希表概念冲突概念避免冲突哈希函数设计常见哈希函数 负载因子调节解决冲突闭散列开散列(哈希桶) 和java类集的关系 结尾 哈希表 概念 顺序结构以及平衡树中,元素关键码与其存储位置之间没有对应的关…...

性能分析与调优: Linux 实现 CPU剖析与火焰图
目录 一、实验 1.环境 2.CPU 剖析 3.CPU火焰图 一、实验 1.环境 (1)主机 表1-1 主机 主机架构组件IP备注prometheus 监测 系统 prometheus、node_exporter 192.168.204.18grafana监测GUIgrafana192.168.204.19agent 监测 主机 node_exporter192…...

leetcode动态规划问题总结 Python
目录 一、基础理论 二、例题 1. 青蛙跳台阶 2. 解密数字 3. 最长不含重复字符的子字符串 4. 连续子数组的最大和 5. 最长递增子序列 6. 最长回文字符串 7. 机器人路径条数 8. 礼物的最大价值 一、基础理论 动态规划其实是一种空间换时间的基于历史数据的递推算法&…...

strtok函数的介绍
_str指被分解的字符串 delim指分隔符字符串 返回类型是指针 strtok()用来将字符串分割成一个个片段。参数s指向欲分割的字符串,参数delim则为分割字符串中包含的所有字符。当strtok()在参数s的字符串中发现参数delim中包含的分割字符时,则会将该字符改为\0 字符…...

CF1909_C. Heavy Intervals题解
CF1909_C. Heavy Intervals题解 题目传送门(Problem - C - CodeforcesCodeforces. Programming competitions and contests, programming communityhttps://codeforces.com/contest/1909/problem/C)。 题目翻译如下:(图片来源&a…...
【Python机器学习】理论知识:决策树
决策树是广泛用于分类和回归任务的模型,本质上是从一层层if/else问题中进行学习,并得出结论。这些问题类似于“是不是”中可能问到的问题。 决策树的每个结点代表一个问题或一个包含答案的终结点(叶结点)。树的边奖问题的答案与将…...

天软特色因子看板 (2024.01 第2期)
该因子看板跟踪天软特色因子A04001(当日趋势强度),该因子为反映股价走势趋势强弱,用以反映股价走势趋势强弱,abs(值)越接近1,趋势 性越强,符号代表涨跌方向 今日为该因子跟踪第2期,跟踪其在SH000905 (中证5…...

java智慧医院互联网智慧3D导诊系统源码,经由智慧导诊系统多维度计算,准确推荐科室
什么是智慧导诊系统? 简单地说,智慧导诊系统是一种利用人工智能技术,为医生提供帮助的系统。它可以通过分析患者的症状和病史为医生提供疾病诊断和治疗方案的建议。 系统介绍: 医院智慧导诊系统是在医院中使用的引导患者自助就诊挂号&…...
WiFi7: MLD寻址
原文:MLD使用MLD MAC address唯一的标识本MLD。 MLD下的STA(s)使用与之不同的MAC address。 NOTE MLD MAC address可以和其下的某个STA的MAC address相同或者不同于任一MAC Address。 原文:对于individually addressed 帧。以下规则适用: Address 2(TA)设置为STA的MAC Add…...
laravel-admin之 浏览器自动填充密码(如果需要渲染数据库密码的话,首先确认数据库密码是否可以逆向解密)
参考 https://blog.51cto.com/u_10401840/5180106 为什么浏览器端保存的密码一直自动写入到$form->password 解决办法 2、在页面进入的时候,默认表单的type值为text;推荐指数:2颗星 5、设置表单的readonly属性;推荐指数:4颗…...

jquery图形验证码
效果展示 js图形随机验证码(表单验证) html代码片段 <form class"formwrap"><div class"item"><input type"text" id"code_input" value"" placeholder"请输入验证码"/>…...

dp专题10 目标和
本题链接:. - 力扣(LeetCode) 题目: 思路: 根据这道题,可以通过暴力的方法进行取 号或者 - 号 两个操作,通过当刚好得到 target 的时候 答案 1,但是通过长度是 20 ,操…...
详解 docker 镜像制作的两种方式
概要 制作Docker镜像一般有2种方法: 通过Dockerfile,完成镜像的创建使用仓库中已有的镜像,安装自己使用的软件环境后完成新镜像创建 docker 常用命令 docker build: 用于构建 Docker 镜像。该命令可以从 Dockerfile 构建镜像,…...

VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...

华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...

Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...

面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制
目录 节点的功能承载层(GATT/Adv)局限性: 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能,如 Configuration …...

9-Oracle 23 ai Vector Search 特性 知识准备
很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…...