使用ansible批量初始化服务器
简介
本文详细介绍ansible怎么批量初始化服务器,包括ansible批量初始化服务器详细配置和步骤,有需要的小伙伴们可以参考借鉴,希望对大家有所帮助。
详细步骤
1、ansible要初始化的主机
[root@nginx ansible]# tail -3 /etc/ansible/hosts #要初始的主机如下
[node]
192.168.20.4
192.168.20.5
2、配置ssh免密登录
playbook文件内容如下:
[root@nginx ansible]# cat ssh.yaml
---
- name: configure ssh connectionhosts: nodegather_facts: falseconnection: localtasks:- name: configure ssh connectionshell: |ssh-keyscan {{inventory_hostname}} >>~/.ssh/known_hostssshpass -p '123.com' ssh-copy-id root@{{inventory_hostname}}
...
注:
- gather\_facts:如果值为false,则表示不收集目标主机上的节点信息,默认为true,为收集节点信息,如果收集节点信息,则会慢很多,如果在接下来的操作中,不需要节点上的信息,可设置为false。
- connection:local表示在ansible端本地执行任务,hosts:localhost和connection:local容易搞混,虽然两者的效果都是在本地执行任务,但是hosts:localhost是从inventory中筛选出了目标节点localhost来执行任务,而connection:local则筛选出来执行任务的目标主机是node组中的节点,但因为指定了local连接类型,使得node组中有多少个节点,就会在ansible本地执行几次该play。
3、配置主机名
配置主机名可以使用shell模块,但是对于不太专业,ansible提供了一个专用于配置主机名的模块:hostname模块。
当然,要使用ansible去设置多个主机名,要求目标主机和目标名称已经关联好,否则多个主机和多个主机名之间无法对应去设置。
例如:分别设置node组中的两个节点主机名为node01和node02,playbook内容如下:
[root@ansible ansible]# cat test.yaml
---
- name: set hostnamehosts: nodegather_facts: falsevars:hostnames:- host: 192.168.20.4name: node01- host: 192.168.20.5name: node02tasks:- name: set hostnamehostname:name: "{{item.name}}"when: item.host == inventory_hostnameloop: "{{hostnames}}"
在上面的hostname模块中,需要详细介绍vars指令以及when、loop指令。
1)vars设置变量
vars指令可用于设置变量,可以设置一个或多个变量。下面几种方式都是合理的:
# 设置单个变量
vars:var1: value1vars:- var1: value1# 设置多个变量vars:var1: value1var2: value2vars:- var1: value1- var2: value2
vars可以设置在play级别,也可以设置在task级别,设置在play级别,该play范围内的task可以访问这些变量,其他play范围内则无法访问;设置在task级别,只有该task能访问这些变量,其他task和其他play则无法访问。
例如:
[root@ansible ansible]# cat test.yaml
---
- name: play1hosts: localhostgather_facts: falsevars:- var1: "value1"tasks:- name: access var1debug:msg: "var1's value: {{var1}}"- name: play2hosts: localhostgather_facts: falsetasks:- name: cat's access vars from play1debug:var: var1- name: set and access var2 in this taskdebug:var: var2vars:var2: "value2"- name: cat't accesss var2debug:var: var2
执行结果如下:
[root@ansible ansible]# ansible-playbook test.yaml PLAY [play1] **************************************************************************TASK [access var1] ********************************************************************
ok: [localhost] => {"msg": "var1's value: value1"
}PLAY [play2] **************************************************************************TASK [cat's access vars from play1] ***************************************************
ok: [localhost] => {"var1": "VARIABLE IS NOT DEFINED!"
}TASK [set and access var2 in this task] ***********************************************
ok: [localhost] => {"var2": "value2"
}TASK [cat't accesss var2] *************************************************************
ok: [localhost] => {"var2": "VARIABLE IS NOT DEFINED!"
}PLAY RECAP ****************************************************************************
localhost : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
回到我们更改主机名的配置vars指令中:
vars:hostnames:- host: 192.168.20.4name: node01- host: 192.168.20.5name: node02
上面只设置了一个变量hostnames,但这个变量的值是一个数组结构,数组的两个元素又都是对象(字典/hash)结构。
所以想要访问主机名node01和它的IP地址192.168.20.4,可以:
tasks:- debug:var: hostnames[0].name- debug:var: hostnames[0].host
2)when条件判断
在ansible中,提供的唯一一个通用的条件判断是when指令,当when指令的值为true时,则执行该任务,否则不执行该任务。
例如:
[root@ansible ansible]# cat test.yaml
---
- name: play1hosts: localhostgather_facts: falsevars:- myname: "Ray"tasks:- name: task will skipdebug:msg: "myname is : {{myname}}"when: myname == "lv"- name: task will executedebug:msg: "myname is : {{myname}}"when: myname == "Ray"
在上面的myname值设置为Ray,第一个任务因为when的判断条件是myname==“lv”,所以判断结果为false,该任务不执行,同理,第二个任务因为when的值为true,所以执行了。
该playbook的执行结果:
PLAY [play1] **************************************************************************TASK [task will skip] *****************************************************************
skipping: [localhost]TASK [task will execute] **************************************************************
ok: [localhost] => {"msg": "myname is : Ray"
}PLAY RECAP ****************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
4、互相添加DNS解析记录
[root@ansible ansible]# cat add_dns.yaml
---
- name: play1hosts: nodegather_facts: truetasks:- name: add DNSlineinfile:path: "/etc/hosts"line: "{{item}} {{hostvars[item].ansible_hostname}}"when: item != inventory_hostnameloop: "{{ play_hosts }}"
执行结果如下:
TASK [Gathering Facts] ****************************************************************
ok: [192.168.20.4]
ok: [192.168.20.5]TASK [add DNS] ************************************************************************
skipping: [192.168.20.4] => (item=192.168.20.4)
changed: [192.168.20.4] => (item=192.168.20.5)
changed: [192.168.20.5] => (item=192.168.20.4)
skipping: [192.168.20.5] => (item=192.168.20.5)
5、配置yum镜像源并安装软件
需求如下:
- 备份原有yum镜像源文件,并配置清华大学的yum镜像源:os源和epel源
- 安装常用软件,包括lrzsz、dos2unix、wget、curl、vim等;
playbook如下:
[root@ansible ansible]# cat config_yum.yaml
- name: config yum repo add install softwarehosts: nodegather_facts: falsetasks:- name: backup origin yum reposshell:cmd: "mkdir bak; mv *.repo bak"chdir: /etc/yum.repos.dcreates: /etc/yum.repos.d/bak- name: add os repo and epel repoyum_repository:name: "{{item.name}}"description: "{{item.name}} repo"baseurl: "{{item.baseurl}}"file: "{{item.name}}"enabled: 1gpgcheck: 0reposdir: /etc/yum.repos.dloop:- name: osbaseurl: "https://mirrors.tuna.tsinghua.edu.cn/centos/7/os/$basearch"- name: epelbaseurl: "https://mirrors.tuna.tsinghua.edu.cn/epel/7/$basearch"- name: install pkgsyum:name: lrzsz,vim,dos2unix,wget,curlstate: present
在上面的yaml文件中,第一个任务是将所有系统默认的repo文件备份到bak目录中,chdir参数表示在执行shell模块的命令前先切换到/etc/yum.repos.d目录下,creates参数表示bak目录存在时则不执行shell模块。
第二个任务是使用yum\_repository模块配置yum源,该模块可添加或移除yum源。
相关参数如下:
- name:指定repo的名称,对应于repo文件中的[name];
- description:repo的描述信息,对应repo文件中的name:xxx;
- baseurl:指定该repo的路径;
- file:指定repo的文件名,不需要加.repo后缀,会自动加上;
- reposdir:repo文件所在的目录,默认为/etc/yum.repos.d目录;
- enabled:是否启用该repo,对应于repo文件中的enabled;
- gpgcheck:该repo是否启用gpgcheck,对应于repo文件中的gpgcheck;
- state:present表示保证该repo存在,absent表示移除该repo。
在上面的配置中使用了一个loop循环来添加两个repo:os和epel。
第三个任务是使用yum模块安装一些rpm包,yum模块可以更新、安装、移除、下载包。
yum常用参数说明:
name:指定要操作的包名
- 可以带版本号;
- 可以是单个包名,也可以是包名列表,或者逗号分隔多个包名;
- 可以是url;
- 可以是本地rpm包
state:
- present和installed:保证包已安装,它们是等价的别名;
- latest:保证包已安装了最新版本,如果不是则更新;
- absent和removed:移除包,它们是等价的别名;
- download\_only:仅下载不安装包(ansible 2.7才支持)
- download\_dir:下载包存放在哪个目录下(ansible 2.8才支持)
yum模块是RHEL系列的包管理器,如果是ubuntu则无法使用,可以使用另一个更为通用的包管理器模块:package,它可以自动探测目标节点的包管理器类型并使用它们去管理软件。大多数时候使用package来代替yum或代替apt-install等不会有什么问题,但是有些包名在不同的操作系统上是不一样的,这是需要注意的。
6、时间同步
保证时间同步可以避免很多玄学性的问题,特别是对集群中的节点。
通常会使用ntpd时间服务器来保证时间的同步,这里使用aliyun提供的时间服务器来保证时间同步,并将同步后的时间同步到硬件。
playbook文件如下:
---
- name: sync timehosts: nodegather_facts: falsetasks:- name: install and sync timeblock:- name: install ntpdateyum:name: ntpdatestate: present- name: ntpdate to sync timeshell: |ntpdate ntp1.aliyun.comhwclock -w
上面使用了一个block指令来组织了两个有关联性的任务,将他们作为了一个整体。block更多的用于多个关联性任务之间的异常处理。
7、关闭selinux
关闭selinux的playbook如下:
[root@ansible roles]# cat disable_selinux.yaml
---
- name: disable selinuxhosts: nodegather_facts: falsetasks:- name: disable on the flyshell: setenforce 0ignore_errors: true #由于上条命令执行后的返回状态码不一定为0,所以为了防止非0报错并停止palsybook接下来的任务,所以使用ignore_errors忽略错误- name: disable forever in configlineinfile:path: /etc/selinux/configline: "SELINUX=disabled" #修改配置文件中的值,以便永久关闭regexp: '^SELINUX=' #要修改的内容
注:ignore\_errors也经常结合block使用,因为在block级别上设置异常处理,可以处理block内部的所有错误。
8、配置iptables规则
playbook文件如下:
- name: Set Firewallhosts: nodegather_facts: falsetasks: - name: set iptables ruleshell: |# 备份已有规则iptables-save > /tmp/iptables.bak$(date +"%F-%T")# 给它三板斧iptables -Xiptables -Fiptables -Z# 放行lo网卡和允许pingiptables -A INPUT -i lo -j ACCEPTiptables -A INPUT -p icmp -j ACCEPT# 放行关联和已建立连接的包,放行22、443、80端口iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPTiptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPTiptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPTiptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT# 配置filter表的三链默认规则,INPUT链丢弃所有包iptables -P INPUT DROPiptables -P FORWARD DROPiptables -P OUTPUT ACCEPT
9、远程修改sshd配置文件并重启
有时候为了服务器的安全,可能会去修改目标节点上sshd服务的默认配置,比如禁止root用户登录、禁止密码认证登录而只允许使用ssh密码认证等。
在修改服务的配置文件时,一般有几种方法:
- 通过远程执行sed等命令进行修改配置文件;
- 通过lineinfile模块去修改配置文件;
- 在ansible本地段写好配置文件,然后使用copy模块或者template模块传输到目标节点上。
相对来说,第三种方案是最统一、最易维护的方案。
此外,对于服务进程来说,修改了配置文件往往意味着要重启服务,使其加载新的配置文件,对于sshd也一样如此,但是sshd要比其他服务特殊一些,因为ansible默认基于ssh连接,重启sshd服务会使ansible连接断开,好在ansible默认会重试建立连接,无非是多等待几秒。但重建连接有可能会失败,比如修改了配置文件不允许重试、修改了sshd的监听端口等,这可能会使得ansible因连接失败而无法再继续执行后续任务。
所以,在修改sshd配置文件时,有如下建议:
- 将此任务作为初始化服务器的最后一个任务,即使连接失败也无所谓;
- 在playbook中加入连接失败的异常处理;
- 如果目标节点修改了sshd端口号,建议通过ansible自动或者我们手动去修改inventory文件中的ssh连接端口号。
这里为了简单,我准备使用lineinfile模块去修改配置文件,要修改的内容只有两项:
- 将PermitRootLogin指令设置为no,禁止root用户直接登录;
- 将PasswordAuthentication指令设置为no,不允许使用密码认证的方式登录
playbook内容如下:
[root@ansible roles]# cat sshd_config.yaml
---
- name: modify sshd_confighosts: nodegather_facts: falsetasks:# 1.备份/etc/ssh/sshd_config文件- name: backup sshd configshell:/usr/bin/cp -f {{path}} {{path}}.bakvars:- path: /etc/ssh/sshd_config# 2.设置PermitRootLogin no- name: disable root loginlineinfile:path: "/etc/ssh/sshd_config"line: "PermitRootLogin no"insertafter: "^#PermitRootLogin"regexp: "^PermitRootLogin"notify: "restart sshd"# 3.设置PasswordAuthentication no- name: disable password authlineinfile:path: "/etc/ssh/sshd_config"line: "PasswordAuthentication no"regexp: "^PasswordAuthentication yes"notify: "restart sshd"handlers:- name: "restart sshd"service:name: sshdstate: restarted
关于notify和handlers的作用如下:
ansible会监控playbook执行后的changed的状态,如果changed=1,则表示关注的状态发生了改变,即本次任务的执行不具备幂等性,如果changed=0,则表示本次任务要么没执行,要么执行了也没有影响,即本次任务具备幂等性。ansible提供了notify指令和handlers功能,如果在某个task中定义notify指令,当ansible在监控到该任务changed=1时,会触发该notify指令所定义的handler,然后去执行handler。所谓handler,其实就是task,无论是在写法上还是作用上它和task都没有什么区别,唯一的区别在于handler是被触发而被动执行的,不像普通task一样会按流程正常执行。
唯一需要注意的是,notify和handler中任务的名称必须一致。比如: notify: "restart sshd",那么handlers中必须得有一个任务设置了 name: "restart sshd"。
此外,在上面的playbook中,两个lineinfile任务都设置了相同的notify,但ansible不会多次去重启sshd,而是在最后重启一次。实际上,ansible在执行完某个任务之后,并不会立即去执行对应的handler,而是在当前play中所有普通任务都执行完成后再去执行handler,这样的好处是可以多次触发notify,但最后只执行一次对应的handler,从而避免多次重启。
10、整合所有任务到单个playbook中
这里将前面所有的playbook集合到单个playbook文件中去,这样就可以一次性执行所有任务。
整合后的playbook如下:
---
- name: Configure ssh Connectionhosts: nodegather_facts: falseconnection: localtasks:- name: configure ssh connectionshell: |ssh-keyscan {{inventory_hostname}} >>~/.ssh/known_hostssshpass -p'123.com' ssh-copy-id root@{{inventory_hostname}}- name: Set Hostnamehosts: nodegather_facts: falsevars:hostnames:- host: 192.168.20.4name: node01- host: 192.168.20.5name: node02tasks: - name: set hostnamehostname: name: "{{item.name}}"when: item.host == inventory_hostnameloop: "{{hostnames}}"- name: Add DNS For Eachhosts: nodegather_facts: truetasks: - name: add DNSlineinfile: path: "/etc/hosts"line: "{{item}} {{hostvars[item].ansible_hostname}}"when: item != inventory_hostnameloop: "{{ play_hosts }}"- name: Config Yum Repo And Install Softwarehosts: nodegather_facts: falsetasks: - name: backup origin yum reposshell: cmd: "mkdir bak; mv *.repo bak"chdir: /etc/yum.repos.dcreates: /etc/yum.repos.d/bak- name: add os repo and epel repoyum_repository: name: "{{item.name}}"description: "{{item.name}} repo"baseurl: "{{item.baseurl}}"file: "{{item.name}}"enabled: 1gpgcheck: 0reposdir: /etc/yum.repos.dloop:- name: osbaseurl: "https://mirrors.tuna.tsinghua.edu.cn/centos/7/os/$basearch"- name: epelbaseurl: "https://mirrors.tuna.tsinghua.edu.cn/epel/7/$basearch"- name: install pkgsyum: name: lrzsz,vim,dos2unix,wget,curlstate: present- name: Sync Timehosts: nodegather_facts: falsetasks: - name: install and sync timeblock: - name: install ntpdateyum: name: ntpdatestate: present- name: ntpdate to sync timeshell: |ntpdate ntp1.aliyun.comhwclock -w- name: Disable Selinuxhosts: nodegather_facts: falsetasks: - block: - name: disable on the flyshell: setenforce 0- name: disable forever in configlineinfile: path: /etc/selinux/configline: "SELINUX=disabled"regexp: '^SELINUX='ignore_errors: true- name: Set Firewallhosts: nodegather_facts: falsetasks: - name: set iptables ruleshell: |# 备份已有规则iptables-save > /tmp/iptables.bak$(date +"%F-%T")# 给它三板斧iptables -Xiptables -Fiptables -Z# 放行lo网卡和允许pingiptables -A INPUT -i lo -j ACCEPTiptables -A INPUT -p icmp -j ACCEPT# 放行关联和已建立连接的包,放行22、443、80端口iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPTiptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPTiptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPTiptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT# 配置filter表的三链默认规则,INPUT链丢弃所有包iptables -P INPUT DROPiptables -P FORWARD DROPiptables -P OUTPUT ACCEPT- name: Modify sshd_confighosts: nodegather_facts: falsetasks:- name: backup sshd configshell: /usr/bin/cp -f {{path}} {{path}}.bakvars: - path: /etc/ssh/sshd_config- name: disable root loginlineinfile: path: "/etc/ssh/sshd_config"line: "PermitRootLogin no"insertafter: "^#PermitRootLogin"regexp: "^PermitRootLogin"notify: "restart sshd"- name: disable password authlineinfile: path: "/etc/ssh/sshd_config"line: "PasswordAuthentication no"regexp: "^PasswordAuthentication yes"notify: "restart sshd"handlers: - name: "restart sshd"service: name: sshdstate: restarted
按照以上步骤一步一步操作,你将轻松完成批量服务器的初始化。
相关文章:
使用ansible批量初始化服务器
简介 本文详细介绍ansible怎么批量初始化服务器,包括ansible批量初始化服务器详细配置和步骤,有需要的小伙伴们可以参考借鉴,希望对大家有所帮助。 详细步骤 1、ansible要初始化的主机 [rootnginx ansible]# tail -3 /etc/ansible/hosts …...
国标GB28181安防视频云平台EasyCVR出现持续重启现象,是什么问题?该如何解决?
视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安防视频监控的能…...
【APP安卓测试工具】adb(Android Debug Bridge)
1.常见的命令 列出已连接的设备 adb device安装 adb install <APK文件路径>卸载 adb uninstall <APK文件路径>启动和停止 adb shell am start -n <包名>[/<Activity>]adb shell am force -stop <包名>截屏和录屏 adb shell screencap <文件路…...
图像融合领域的挑战
图像融合是将来自不同传感器或不同时间的多个图像集成为信息更丰富的单个图像的过程,通常预计更有利于人类或机器感知或进一步的图像处理任务。 以下是图像融合研究中的一些众所周知的挑战: 保持图像质量:确保融合图像保留每个源图像的重要特…...
Tomcat配置成服务、开机自启动
Tomcat配置成服务、开机自启动 问题解决方案 问题 在配置成开机自启动的服务时,遇到了如下提示。 最终原因是因为双击apache-tomcat-9.0.83\bin\tomcat9w.exe,在弹出的的“Startup”选项卡中的mode没有设置为Java 解决方案 右键“我的电脑”——管理—…...
IntelliJ IDEA创建一个spark的项目
在开始之前,需要说明的是 要跑通基本的wordcount程序,是不需要在windows上安装 hadoop 和spark的,因为idea在跑程序的时候,会按照 pom.xml配置文件,从指定的 repository源,按照properties指定的版本&#x…...
【数据库】数据库多种锁模式,共享锁、排它锁,更新锁,增量锁,死锁消除与性能优化
多种锁模式的封锁系统 专栏内容: 手写数据库toadb 本专栏主要介绍如何从零开发,开发的步骤,以及开发过程中的涉及的原理,遇到的问题等,让大家能跟上并且可以一起开发,让每个需要的人成为参与者。 本专栏会…...
串口通信(1)-硬件知识
本文讲解串口通信的硬件知识。让读者快速了解硬件知识,为下一步编写代码做基础。 目录 一、概述 二、串口通信分类 2.1信息的传送方向进行分类 2.2同步通信和异步通信 三、串口协议 3.1 RS232 3.1.1 电气特性 3.1.2 连接器的机械特性 3.1.3 连接类型 3.1…...
越南语翻译,人工翻译哪个值得信赖?
近年来,随着中越两国的交流日益频繁,为了促进双方的交流与理解,市场上对越南语翻译的需求也日益增加。那么,如何做好越南语翻译,人工翻译哪家公司值得信赖呢? 据了解,中文翻译越南语是一项颇具挑…...
攻防世界题目练习——Web引导模式(五)(持续更新)
题目目录 1. FlatScience2. bug3. Confusion1 1. FlatScience 参考博客: 攻防世界web进阶区FlatScience详解 题目点进去如图,点击链接只能看到一些论文pdf 用dirsearch和御剑扫描出一些隐藏文件: robots.txt: admin.php: login.php: f…...
attack vector
攻击介质,是指可以攻击信息系统,破坏其安全性的特定路径、方法或是情景。 vector 此处并不是向量的意思。...
好看的早上问候语早安图片,今天最新唯美温馨祝福语
1、天气冷了,情谊不凉,树叶黄了,思念不忘,问候像一杯热茶,让人暖心!祝愿我们与健康平安同行!朋友们,大家早上好! 2、多一个人牵挂是一种幸福;多一个人相知是一…...
人体关键点检测2:Pytorch实现人体关键点检测(人体姿势估计)含训练代码
人体关键点检测2:Pytorch实现人体关键点检测(人体姿势估计)含训练代码 目录 人体关键点检测2:Pytorch实现人体关键点检测(人体姿势估计)含训练代码 1. 前言 2.人体关键点检测方法 (1)Top-Down(自上而下)方法 (2)Bottom-Up(自下而上)方法࿱…...
聚类分析 | Matlab实现基于谱聚类(Spectral Cluster)的数据聚类可视化
聚类分析 | Matlab实现基于谱聚类(Spectral Cluster)的数据聚类可视化 目录 聚类分析 | Matlab实现基于谱聚类(Spectral Cluster)的数据聚类可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现基于谱聚类(Spectral Cluster)的聚类算法可视化(完…...
【回眸】Tessy 单元测试软件使用指南(三)怎么打桩和指针测试
目录 前言 Tessy 如何进行打桩操作 普通桩 高级桩 手写桩 Tessy单元测试之指针相关测试注意事项 有类型的指针(非函数指针): 有类型的函数指针: void 类型的指针: 结语 前言 进行单元测试之后,但凡…...
关系型数据库-SQLite介绍
优点: 1>sqlite占用的内存和cpu资源较少 2>源代码开源,完全免费 3>检索速度上十几兆、几十兆的数据库sqlite很快,但是上G的时候最慢 4>管理简单,几乎无需管理。灵巧、快速和可靠性高 5>功能简…...
使用shell脚本将一台虚拟机上面数据分发到其他虚拟机上面xsync
目录 1,功能2,注意点3,shell脚本介绍4,bash内容 1,功能 使用shell脚本将一台虚拟机上面数据分发到其他虚拟机上面。 2,注意点 需要修改的地方:hadoop250 hadoop251 hadoop252 hadoop253 hado…...
OpenGL学习(二)绘制三维图形 固定管线
一.简单步骤 考虑顶点数据上色旋转 二.完整代码 myopenglwidget.h // An highlighted block #ifndef MYOPENGLWIDGET_H #define MYOPENGLWIDGET_H #include <QOpenGLWidget> #include <QOpenGLFunctions> #include <QOpenGLShaderProgram> #include <Q…...
微信小程序游戏:移动游戏市场的新兴力量
随着移动互联网的迅猛发展,微信小程序游戏已经成为现代数字娱乐领域的一股不可忽视的力量。这些游戏通过融入微信这一广泛使用的社交平台,为用户带来了全新的游戏体验。本文探讨了微信小程序游戏的特点、发展现状和未来趋势。 微信小程序游戏最大的特点之…...
Netflix Mac(奈飞客户端)激活版软件介绍
Netflix Mac(奈飞客户端)是一款流行的视频播放软件,专为Mac用户设计。它提供了大量的高质量电影、电视剧、纪录片和动画片资源,让用户可以随时随地观看自己喜欢的内容。 首先,Netflix Mac(奈飞客户端)以其简洁直观的用户界面而闻名。用户可以…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
