当前位置: 首页 > news >正文

Ansible 核心功能:循环、过滤器、判断与错误处理全解析

Ansible 核心功能:循环、过滤器、判断与错误处理全解析

本文基于Ansible实践场景,系统梳理循环迭代数据过滤条件判断错误处理的核心用法,包含可直接复用的示例代码与关键注意事项,适用于Ansible自动化运维场景的学习与实战。

一、Ansible 循环迭代

循环用于批量执行重复任务(如安装多个软件、拷贝多个文件),Ansible支持传统with_*系列迭代器与现代loop(推荐配合过滤器使用)。

1. 传统 with_* 循环(适用于简单场景)

(1)with_items:迭代列表

用途:批量处理列表中的元素(如安装多个软件包、创建多个文件)。
核心逻辑{{ item }} 代表列表中的每个元素。

---
- name: with_items testhosts: node1tasks:- name: debug1debug:msg: "{{ item }}"with_items:- aaa- bbb- ccc
(2)with_dict:迭代字典

用途:处理键值对数据(如配置网络参数、批量设置变量)。
核心逻辑{{ item.key }} 取字典的键,{{ item.value }} 取字典的值。

# 示例:打印网络参数(键-值对应)
---
- name: with_dict testhosts: alltasks:- name: aaaadebug:msg: "{{ item.key }} | {{ item.value }}"with_dict:name:  "{{ ansible_hostname }}"address: "{{ ansible_enp1s0.ipv4.address }}"dns: "{{ ansible_fqdn }}"
(3)with_fileglob:迭代文件(按路径匹配)

用途:批量处理指定路径下的文件(如拷贝所有.sh.py脚本)。
注意:路径为Ansible控制节点的路径,非受控节点。

# 示例:批量拷贝控制节点/tmp下的.sh和.py文件到受控节点/tmp
---
- name: with_fileglob testhosts: node1tasks:- name: copy .sh and .py filescopy:src: "{{ item }}"  # item遍历匹配到的文件dest: /tmp/with_fileglob:- /tmp/*.sh- /tmp/*.py
(4)with_lines:迭代命令输出(按行)

用途:将Linux命令的输出按行作为迭代元素(如处理find找到的文件)。

# 示例:拷贝find命令找到的所有.yml文件到受控节点/tmp
---
- name: with_lines testhosts: node1tasks:- name: copy ansible yml filescopy:src: "{{ item }}"dest: /tmp/with_lines:- find /etc/ansible -name "*.yml"  # 命令输出按行迭代
(5)with_nested:嵌套迭代

用途:实现多列表的“笛卡尔积”组合(如A列表每个元素与B列表所有元素匹配)。
核心逻辑{{ item[0] }} 取第一个列表元素,{{ item[1] }} 取第二个列表元素。

# 示例:列表[a,b]与[1,2,3]嵌套组合
- name: with_nested testhosts: node1tasks:- name: print combined pairsdebug:msg: "字母:{{ item[0] }} | 数字:{{ item[1] }}"with_nested:- [a, b]    # 第一个列表(index 0)- [1, 2, 3] # 第二个列表(index 1)
# 输出结果:a&1、a&2、a&3、b&1、b&2、b&3
(6)with_sequence:生成有序序列

用途:生成连续数字序列(如创建编号文件、批量命名)。
参数start(起始值)、end(结束值)、stride(步长)。

# 示例:生成1-5的序列(步长1)
- name: with_sequence testhosts: node1tasks:- name: print sequencedebug:msg: "当前数字:{{ item }}"with_sequence:start=1end=5stride=1  # 每次递增1
(7)with_random_choice:随机取列表元素

用途:从列表中随机选择一个元素(如随机选择测试节点、随机生成值)。

# 示例:随机输出列表中的一个元素
- name: random choicehosts: node1tasks:- name: print random itemdebug:msg: "随机选中:{{ item }}"with_random_choice:- 1- 2- a- b- c

2. 现代 loop(推荐)

loop 是Ansible推荐的新一代循环语法,需配合过滤器(如listdict2items)使用,功能更灵活。

  • 替代with_itemsloop: [元素1, 元素2, ...]
  • 替代with_dictloop: "{{ 字典 | dict2items }}"(此时item.key/item.value仍可用)
# 示例1:用loop替代with_items(批量安装软件)
---
- name: with_dict testhosts: alltasks:- name: aaaadebug:msg: "{{ item }}"loop:- 12345678- abcdefgh- ABCDEFGH- name: bbbbdebug:msg: "{{ item.key }} -> {{ item.value }}"loop: "{{{  'name': ansible_hostname, 'address': ansible_default_ipv4.address, 'dns': ansible_fqdn } | dict2items }}"

二、Ansible 过滤器

过滤器用于数据转换与处理(如字符串大小写、数字类型转换、密码哈希),语法为{{ 变量 | 过滤器(参数) }}

1. 字符串相关过滤器

处理字符串格式、长度、截取等,常见场景:配置文件内容格式化、变量清洗。

  • upper:将字符串转为纯大写。
    示例代码:{{ "abc123ABC" | upper }},输出结果:ABC123ABC

  • lower:将字符串转为纯小写。
    示例代码:{{ "abc123ABC" | lower }},输出结果:abc123abc

  • capitalize:将字符串首字母转为大写,其余字母转为小写。
    示例代码:{{ "abc123ABC" | capitalize }},输出结果:Abc123abc

  • trim:去除字符串首尾的空格(中间空格保留)。
    示例代码:{{ " abc " | trim }},输出结果:abc

  • length/count:计算字符串的长度(字符个数),两者功能完全等效。
    示例代码:{{ "abc123" | length }},输出结果:6

  • first:获取字符串的第一个字符。
    示例代码:{{ "abc123" | first }},输出结果:a

  • last:获取字符串的最后一个字符。
    示例代码:{{ "abc123" | last }},输出结果:3

  • center(width):将字符串居中显示,总长度固定为width,不足部分用空格补全。
    示例代码:{{ "abc" | center(10) }},输出结果: abc (前后各3个空格,总长度10)。

  • list:将字符串拆分为字符列表,每个字符作为列表的一个元素。
    示例代码:{{ "1a2b" | list }},输出结果:['1','a','2','b']

  • shuffle:先将字符串拆分为字符列表,再随机打乱列表中元素的顺序(每次执行结果可能不同)。
    示例代码:{{ "1a2b" | shuffle }},可能的输出结果:['a','2','1','b']

2. 数字相关过滤器

处理数字类型转换、计算、随机数生成,解决Ansible中“字符串与数字无法直接运算”的问题。

  • int(default=值):将输入转为整数,若无法转换(如输入为非数字字符串),则返回默认值(默认值不指定时为0)。
    示例1(正常转换):{{ "8" | int }},输出结果:8
    示例2(无法转换):{{ "a" | int(6) }},输出结果:6

  • float(default=值):将输入转为浮点数,若无法转换,返回默认值(默认值不指定时为0.0)。
    示例1(正常转换):{{ "8.5" | float }},输出结果:8.5
    示例2(无法转换):{{ "a" | float(8.88) }},输出结果:8.88

  • abs:获取数字的绝对值(对负数生效,正数不变)。
    示例代码:{{ -10 | abs }},输出结果:10

  • round(n):对数字进行四舍五入,n指定保留的小数位数(不指定时默认保留0位,即整数)。
    示例1(保留整数):{{ 12.5 | round }},输出结果:13
    示例2(保留3位小数):{{ 3.14159 | round(3) }},输出结果:3.142

  • random(start=值, step=值):生成随机数,默认范围是“0到过滤器前的数字”;start指定随机数的起始值,step指定随机数的递增步长(即随机数只能是“start + 整数×step”)。
    示例1(0-100的随机整数):{{ 100 | random }},可能输出:45
    示例2(5-15、步长3的随机数):{{ 15 | random(start=5, step=3) }},可能输出:581114中的一个。

3. 文件/密码相关过滤器

用于文件校验、密码哈希(安全存储密码,避免明文),常见于用户创建、配置文件校验场景。

  • hash(算法):对字符串进行哈希计算,支持的算法包括md5sha1sha256等,相同输入会生成固定的哈希值。
    示例代码:{{ "123456" | hash("md5") }},输出结果为e10adc3949ba59abbe56e057f20f883e(固定md5值)。

  • checksum:功能与hash("md5")完全等效,常用于文件内容的校验(判断文件是否被修改)。
    示例代码:{{ "123456" | checksum }},输出结果与hash("md5")一致,。

  • password_hash(算法, 盐):对密码进行哈希处理(推荐使用sha512算法,安全性高),为可选参数——不指定时自动生成随机盐(避免彩虹表破解),指定时用自定义字符串作为盐。
    示例1(自动生成盐):{{ "redhat" | password_hash("sha512") }},输出结果为带随机盐的sha512哈希值(每次执行不同);
    示例2(自定义盐):{{ "redhat" | password_hash("sha512", "mysalt") }},输出结果为固定的sha512哈希值(盐固定,结果固定)。

实战场景:创建用户并设置哈希密码(避免明文存储)

- name: create user with hashed passwordhosts: node1tasks:- name: create user chenyuuser:name: chenyupassword: "{{ 'redhat' | password_hash('sha512') }}"  # 哈希存储密码,自动生成盐state: present

三、Ansible 条件判断(When)

when 用于根据条件决定任务是否执行,支持运算符Tests(断言) 两种判断方式。

1. 常用运算符

用于比较变量值、组合条件:

  • 比较运算符:==(等于)、!=(不等于)、>(大于)、<(小于)、>=(大于等于)、<=(小于等于)
  • 逻辑运算符:and(且,两个条件同时满足)、or(或,任意一个条件满足)、not(非,否定条件)
  • 成员运算符:in(判断元素是否在列表/字符串中)、not in(判断元素是否不在列表/字符串中)
# 示例:当变量aa等于11且变量bb包含"test"时,执行debug任务
- name: condition with operatorsdebug:msg: "条件满足,执行此任务"when: aa == 11 and "test" in bb

2. 常用 Tests(断言)

Tests 是Ansible预定义的判断逻辑,格式为变量 is Test,覆盖变量状态、任务结果、路径类型等场景。

(1)变量相关 Tests

判断变量是否定义、是否为空,常用于避免“未定义变量导致剧本报错”:

  • defined:变量已被定义(无论值是否为空),则条件为真。
    示例代码:when: aa is defined(若aa: 11aa: "",均满足条件)。

  • undefined:变量未被定义(未在vars或 inventory 中声明),则条件为真。
    示例代码:when: bb is undefined(若未声明bb,满足条件)。

  • none:变量已定义,但值为空(如空字符串、空列表、空字典),则条件为真。
    示例代码:when: cc is none(若cc: ""cc: [],满足条件)。

# 示例:变量状态判断
- name: test variable statushosts: node1vars:aa: 11    # 已定义且有值cc: ""    # 已定义但为空tasks:- debug: msg="aa已定义" when: aa is defined- debug: msg="bb未定义" when: bb is undefined- debug: msg="cc已定义但为空" when: cc is none
(2)任务结果相关 Tests

判断上一个任务的执行状态(需先用register将任务结果注册为变量),常用于“根据前序任务结果决定后续操作”:

  • success/succeeded:前序任务执行成功(退出码为0),则条件为真,两者功能等效。
    示例代码:when: task_result is success

  • failure/failed:前序任务执行失败(退出码非0),则条件为真,两者功能等效。
    示例代码:when: task_result is failed

  • changed:前序任务导致受控节点的系统状态发生变化(如创建文件、修改配置),则条件为真。
    示例代码:when: task_result is changed

  • skipped:前序任务因条件不满足被跳过(未执行),则条件为真。
    示例代码:when: task_result is skipped

# 示例:判断ls /mnt任务的执行结果
- name: test task resulthosts: node1tasks:- name: list /mnt directoryshell: ls /mntregister: ls_result  # 将任务结果注册为变量ls_result- debug: msg="ls /mnt执行成功" when: ls_result is success- debug: msg="ls /mnt执行失败" when: ls_result is failed- debug: msg="ls /mnt导致系统状态变化" when: ls_result is changed
(3)路径相关 Tests

判断Ansible控制节点上路径的类型(注意:不是受控节点!),常用于“执行文件操作前校验路径”:

  • file:路径指向一个普通文件(非目录、非链接),则条件为真。
    示例代码:when: /tmp/test.sh is file
  • directory:路径指向一个目录(非文件、非链接),则条件为真。
    示例代码:when: /tmp/data is directory
  • link:路径指向一个软链接(无论链接目标是否存在),则条件为真。
    示例代码:when: /tmp/link.sh is link
  • mount:路径是一个已挂载的挂载点(即mount命令可查看到该路径),则条件为真。
    示例代码:when: /boot is mount
  • exists:路径存在(无论路径是文件、目录还是链接),则条件为真。
    示例代码:when: /tmp/test.sh is exists

创建相关文件

student@master tmp]$ touch test.sh
[student@master tmp]$ mkdir data
[student@master tmp]$ ln -s test.sh link.sh
[student@master tmp]$ ln test.sh hardlink.sh

编写剧本

---
- name: with_dict testhosts: node1tasks:- name: aaaadebug:msg: '/tmp/test.sh is file'when: "'/tmp/test.sh' is file"- name: bbbbdebug:msg: '/tmp/data is directory'when: "'/tmp/data' is directory"- name: ccccdebug:msg: '/tmp/link.sh is link'when: "'/tmp/link.sh' is link"- name: dddddebug:msg: '/tmp/hardlink.sh is link'when: "'/tmp/hardlink.sh' is link"- name: eeeedebug:msg: '/boot is mount'when: "'/boot' is mount "- name: ffffdebug:msg: '/tmp/test.sh is exists'when: "'/tmp/test.sh' is exists "

运行剧本

TASK [aaaa] ********************************************************************************
ok: [node1] => {"msg": "/tmp/test.sh is file"
}TASK [bbbb] ********************************************************************************
ok: [node1] => {"msg": "/tmp/data is directory"
}TASK [cccc] ********************************************************************************
ok: [node1] => {"msg": "/tmp/link.sh is link"
}TASK [dddd] ********************************************************************************
skipping: [node1]TASK [eeee] ********************************************************************************
ok: [node1] => {"msg": "/boot is mount"
}TASK [ffff] ********************************************************************************
ok: [node1] => {"msg": "/tmp/test.sh is exists"
}

可以看到只有hredlink被跳过这是因为hredlink是硬链接属于普通文件

(4)其他 Tests

覆盖字符串格式、数据类型等判断场景:

  • lower:字符串中所有字母均为小写(非字母字符不影响),则条件为真。
    示例代码:when: "abc123" is lower(满足条件)、when: "aBc123" is lower(不满足条件)。

  • upper:字符串中所有字母均为大写(非字母字符不影响),则条件为真。
    示例代码:when: "ABC123" is upper(满足条件)、when: "ABc123" is upper(不满足条件)。

  • string:对象是字符串类型(即使内容是数字,如"123"),则条件为真。
    示例代码:when: "123" is string(满足条件)、when: 123 is string(不满足条件)。

  • number:对象是数字类型(整数或浮点数,如1233.14),则条件为真。
    示例代码:when: 123 is number(满足条件)、when: "123" is number(不满足条件)。

四、块处理(block/rescue/always)

用于批量控制任务的错误处理,实现“主任务-失败恢复-最终执行”的逻辑,类似编程语言中的try-catch-finally

  • block:定义“正常执行的主任务块”,若块内任意任务失败,直接跳转到rescue
  • rescue:定义“失败恢复任务块”,仅当block执行失败时才执行。
  • always:定义“最终执行任务块”,无论block成功或失败,都会执行(常用于清理、收尾操作)。

实战场景:创建逻辑卷(LV)的错误处理

需求:在research卷组创建1500MiB的dataLV;若卷组不存在则提示错误;若空间不足则用800MiB创建,且最终需格式化LV为ext4。

# 前提:node1的research卷组大小为2G(可创建1500MiB LV),node2的research卷组大小为1G(仅可创建800MiB LV)
---
- name: aaaaaahosts: all tasks:# 核心块:创建LV并处理失败- name: creat datablock:# 主任务:尝试创建1500MiB的LV- name: create lv1lvol:vg: researchlv: datasize: 1500state: presentrescue:# 恢复逻辑:创建失败(空间不足),输出错误信息并改用800MiB创建- name: not 1500debug:msg: "Could not create logical volume of that size"- name: create lv2lvol:vg: researchlv: datasize: 800Malways:# 最终执行:无论LV是否创建成功,都将其格式化为ext4- name: filesystemfilesystem:dev: /dev/research/datafstype: ext4when: "'research' in ansible_facts.lvm.vgs"  # 仅当卷组research存在时,执行该块# 卷组不存在时,输出提示信息- name: not researchdebug:msg: "Volume group does not exist"when: "'research' not in ansible_facts.lvm.vgs"

五、错误处理(fail/failed_when/ignore_errors/changed_when)

用于主动控制任务的执行状态(中断剧本、跳过错误、修改状态),确保剧本在异常场景下的可控性。

1. fail 模块:主动中断剧本

当满足特定条件时,主动中断当前剧本的执行,并输出自定义错误信息,常与when配合使用(需明确中断条件)。

- name: interrupt playbook with fail modulehosts: node1tasks:# 执行shell命令,输出含"error"的内容- name: execute shell commandshell: echo "this is a test--error"register: cmd_result  # 将命令输出注册为变量# 当输出中包含"error"时,中断剧本- name: fail and stop playbookfail:msg: "Found 'error' in command output, stopping playbook now"  # 自定义错误信息when: "'error' in cmd_result.stdout"  # 中断条件:输出含"error"# 上方任务中断后,此任务不会执行- name: unreachable taskdebug:msg: "This task will not run because playbook is stopped"

运行效果

PLAY [aaaaaa] ******************************************************************************TASK [Gathering Facts] *********************************************************************
ok: [node5]
ok: [node3]
ok: [node4]
ok: [node1]
ok: [node2]TASK [create lv1] **************************************************************************
skipping: [node3]
skipping: [node4]
skipping: [node5]
fatal: [node1]: FAILED! => {"changed": false, "err": "  Volume group \"research\" has insufficient free space (249 extents): 375 required.\n", "msg": "Creating logical volume 'data' failed", "rc": 5}
changed: [node2]TASK [dddd] ********************************************************************************
ok: [node1] => {"msg": "Could not create logical volume of that size"
}TASK [create lv2] **************************************************************************
changed: [node1]TASK [filesystem] **************************************************************************
skipping: [node3]
skipping: [node4]
skipping: [node5]
changed: [node1]
changed: [node2]TASK [cccc] ********************************************************************************
skipping: [node1]
skipping: [node2]
ok: [node3] => {"msg": "Volume group does not exist"
}
ok: [node4] => {"msg": "Volume group does not exist"
}
ok: [node5] => {"msg": "Volume group does not exist"
}

2. failed_when:自定义任务失败条件

强制将“命令执行成功(退出码为0)的任务”标记为失败,无需依赖fail模块,直接通过条件控制任务状态。

- name: custom failed condition with failed_whenhosts: node1tasks:# 执行shell命令(退出码为0,默认标记为成功)- name: execute shell commandshell: echo "this is a test--error"register: cmd_result# 自定义失败条件:输出含"error"时,将任务标记为失败failed_when: "'error' in cmd_result.stdout"# 上一步任务被标记为失败,剧本默认中断,此任务不执行- name: unreachable taskdebug:msg: "This task will not run because previous task failed"

3. ignore_errors: yes:跳过错误

当任务执行失败时(如命令退出码非0、变量未定义),忽略该错误并继续执行后续任务,不中断整个剧本。

- name: ignore task errors with ignore_errorshosts: node1tasks:# 正常执行:打印受控节点的FQDN(ansible_fqdn为Ansible内置变量,已定义)- name: print controlled node's FQDNdebug:msg: "FQDN: {{ ansible_fqdn }}"# 执行失败:打印未定义的变量ansible_ip,但忽略错误- name: print non-existent variable (ignore error)debug:msg: "IP: {{ ansible_ip }}"  # ansible_ip未定义,任务默认失败ignore_errors: yes  # 忽略此任务的失败,继续执行后续任务# 正常执行:创建/tmp/abc文件(因上一步错误被忽略,此任务可执行)- name: create /tmp/abc filefile:path: /tmp/abcstate: touch

4. changed_when:自定义任务状态

强制修改任务的changed状态(Ansible默认根据“任务是否修改系统”判断changed):

  • changed_when: true:无论任务是否修改系统,强制将状态标记为changed
  • changed_when: false:无论任务是否修改系统,强制将状态标记为ok
- name: custom task status with changed_whenhosts: node1tasks:# 强制标记为changed:debug任务默认不修改系统(状态为ok),此处强制改为changed- name: debug with forced changed statusdebug:msg: "FQDN: {{ ansible_fqdn }}"changed_when: true# 强制标记为ok:shell任务(ls /tmp)默认不修改系统(状态为ok),此处明确强制为ok- name: list /tmp directory with forced ok statusshell: ls /tmpchanged_when: false

小练习

从 http://ansible.example.com/materials/newhosts.j2 下载模板文件
完成该模板文件,用来生成新主机清单(主机的显示顺序没有要求),结构如下:
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.122.10 node1.example.com node1
192.168.122.20 node2.example.com node2
192.168.122.30 node3.example.com node3
192.168.122.40 node4.example.com node4
192.168.122.50 node5.example.com node5
创建剧本/home/student/ansible/newhosts.yml,它将使用上述模板在 node1 主机组的主机上
生成文件/etc/newhosts。

#下载模板
[student@master ansible]$ curl -O  http://ansible.example.com/materials/newhosts.j2 
#修改模板
{% for cy in groups.all %}
{{ hostvars[cy].ansible_default_ipv4.address}}  {{ hostvars[cy].ansible_fqdn }}  {{ hostvars[cy].ansible_hostname}}
{% endfor %}
编写剧本---
- name: get facthosts: all
- name: cp filehosts: node1tasks:- name: cp filetemplate:src: /home/student/ansible/newhosts.j2dest: /etc/newhosts
#运行剧本        
#查看node1是否获取到了ip域名和主机名
[student@master ansible]$ ansible node1 -m shell -a 'cat /etc/newhosts'
node1 | CHANGED | rc=0 >>
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6192.168.122.10  node1.example.com  node1
192.168.122.20  node2.example.com  node2
192.168.122.30  node3.example.com  node3
192.168.122.40  node4.example.com  node4
192.168.122.50  node5.example.com  node5

编写剧本修改远程文件内容
创建剧本 /home/student/ansible/newissue.yml,满足下列要求:
1)在所有清单主机上运行,替换/etc/issue 的内容
2)对于 test01 主机组中的主机,/etc/issue 文件内容为 test01
3)对于 test02 主机组中的主机,/etc/issue 文件内容为 test02
4)对于 web 主机组中的主机,/etc/issue 文件内容为 Webserver

inventory

[test01]
node1[test02]
node2[web]
node3
node4[test05]
node5[webtest:children]
web

创建剧本

---
- name: replace filehosts: alltasks:- name: test1copy:content: |{% if 'test01' in group_names %}test01{% elif 'test02' in group_names %}test02{% elif 'web' in group_names %}Webserver{% endif %}dest: /etc/issue

运行剧本后查看

[student@master ansible]$ ansible all -m shell -a 'cat /etc/issue'  
node1 | CHANGED | rc=0 >>
test01
node5 | CHANGED | rc=0 >>node4 | CHANGED | rc=0 >>
Webserver
node3 | CHANGED | rc=0 >>
Webserver
node2 | CHANGED | rc=0 >>
test02
http://www.dtcms.com/a/365236.html

相关文章:

  • 《苍穹外卖》开发环境搭建_后端环境搭建【简单易懂注释版】
  • PL-YOLOv8:基于YOLOv8的无人机实时电力线检测与植被风险预警框架,实现精准巡检与预警
  • 【Spring Cloud微服务】11.微服务通信演义:从飞鸽传书到5G全息,一部消息中间件的进化史诗
  • Git 别名:用简短命令大幅提升开发效率
  • 无人机报警器8G信号技术解析
  • leetcode110. 平衡二叉树
  • 深入解析Java Spliterator(Stream延迟、并行计算核心)
  • 哪些AI生成PPT的软件或网站支持多平台使用?都支持哪些平台?
  • AI生成PPT工具排名:2025年高效办公新选择
  • 关于MySQL数据库连接超时问题及解决办法
  • AR智慧运维系统介绍
  • vue项目打包后dist部署到Nginx
  • 性能测试-jmeter9-直连数据库
  • 深度学习篇---模型组成部分
  • 财务文档处理优化:基于本地运行的PDF合并解决方案
  • 【51单片机】【protues仿真】基于51单片机压力测量仪系统
  • wpf触发器
  • Dify 从入门到精通(第 73/100 篇):Dify 的高级 RAG 优化(高级篇)
  • 调制端Phase Shift Discriminator(PSD)算法原理
  • 数据结构从青铜到王者第二十话---Map和Set(3)
  • windows安装PostgreSQL 和TimescaleDB
  • 数据结构:顺序栈与链栈的原理、实现及应用
  • 集成 Node.js 模块:文件系统与网络操作
  • 深入理解 Java 集合框架:底层原理与实战应用
  • 数据结构——二叉树+堆
  • .gitignore 文件为什么无效。
  • 开学季,老师如何用阅兵仪式激励学生?
  • PNP具身解读——RSS2025论文加州伯克利RLDG: 通过强化学习实现机器人通才策略提炼。
  • 在DDPM(扩散模型)中,反向过程为什么不能和前向一样一步解决,另外实际公式推导时反向过程每一步都能得到一个预测值,为什么还要一步一步的推导?
  • GEM5学习(4): 运行全系统模式的ARM系统