Ansible Playbook原理与实践(Principles and Practice of Ansible Playbook)
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
本人主要分享计算机核心技术:系统维护、数据库、网络安全、自动化运维、容器技术、云计算、人工智能、运维开发、算法结构、物联网、JAVA 、Python、PHP、C、C++等。
不同类型针对性训练,提升逻辑思维,剑指大厂,非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。
云平台管理之Ansible Playbook 原理与实践
Ansible Playbook 简介
Ansible Playbook 是 Ansible 的核心组件之一,它允许用户以 YAML 格式编写配置文件,用于描述希望远程系统执行的一系列任务。Playbook 提供了一种方式来编排和执行这些任务,确保配置的一致性,或者简单地执行一些常见的任务。Playbook 的使用使得 Ansible 成为一个强大的配置管理工具,尤其适用于需要跨多个系统执行多个操作的情况。
Playbook 的基本原理包括:
- 配置管理:通过 Playbook,可以定义和执行一系列任务,以管理和配置远程系统的状态。
- 编排任务:Playbook 可以对任务进行排序和编排,确保按照正确的顺序执行任务。
- 并行处理:通过异步执行和适当的配置,Playbook 可以实现并行处理多个任务,提高工作效率。
- 权限管理:通过使用 become 功能,Playbook 可以以不同的用户权限执行任务,满足不同的系统需求。
实践方面,使用 Playbook 可以大大简化复杂的应用部署和配置管理过程。通过编写 Playbook,可以清晰地定义部署流程、配置变更、系统状态检查等任务,并通过 Ansible 引擎执行这些任务。Playbook 的使用不仅提高了工作效率,还减少了人为错误的可能性,使得 IT 基础设施的管理更加可靠和高效。
Playbooks是Ansible的配置,部署和编排语言。playbook是由一个或多个play组成的列表,play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓的task无非是调用ansible的一个module。将多个play组织在一个playbook中,即可以让它们联合起来按事先编排的机制完成某一任务。
Ansible Palybook的编写是基于YAML语言的。YAML语言,即Yet Another Markup Language,是一种能被计算机直接识别的标记语言,同时也方便人的阅读,且方便和脚本语言交互。但是,YAML的配置即为严格,在配置时必须注重空格的数量。总的来看,YAML语言特性如下:
- 1、可读性强
- 2、和脚本语言的交互性好
- 3、使用实现语言的数据类型
- 4、一致的信息模型
- 5、易于实现
- 6、可以基于流来处理
- 7、可扩展性强
Ansible Playbook 组件
Ansible的Playbook有以下组件:
- Target
- 定义playbook的远程主机组,即控制的下游设备信息
- Variable
- 定义Playbook所使用的变量。
- Task
- 定义Playbook控制下游设备要执行的命令。
- Handler
- 定义在Palybook在Task执行完毕后要调用的任务。
Ansible Playbook各组件参数
Ansible的上述组件的参数如下:
Target常用参数
代码语言:javascript
hosts #定义Ansible用户控制的下游设备
remote_user #定义执行Ansible设置的用户
sudo #设置为yes时,执行任务时使用root权限
sudo_user #指定sudo的普通用户
connection #默认基于ssh链接客户端
gather_facts #获取远程主机facts基础信息
Variable常用参数
vars #定义变量
vars_files #指定变量文件
vars_prompt #用户交互模式自定义变量
setup #通过远程gather_facts获取的信息
Task常用参数
name #任务的名称,在Ansible运行的过程中起到提示的作用,会打印在屏幕上
action #Ansible控制下游设备的命令,通过Ansible的各个模块来进行控制
template #Ansible控制下游设备的模板
handler #定义一个调用,该调用在Handler处被定义,在所有的Task结束后被执行。
Playbook基本语法
playbook使用yaml语法格式,后缀可以是yaml,也可以是yml。
[root@localhost ~]$ vim test.yaml
--- #表示文档开始
- hosts: test # "- "表示一个块序列的节点,注意:横杠后面有空格,可以写主机名,主机组名,多个使用逗号隔开remote_user: root #指定在进行远程操作时使用root用户进行操作tasks: #使用tasks关键字指明要进行操作的任务列表,之后的行都属于tasks键值对中的值。- name: Ping #每个任务都以"- "开头,每个任务都有自己的名字,任务名使用name关键字进行指定ping: #ansible模块- name: make directory test #第二个任务使用file模块,使用file模块时,指定了path参数与state参数的值。file: #ansible模块path: /data/test #模块的参数state: directory --- #标记文件的开始
- hosts: webservers #指定该playbook在哪个服务器上执行vars: #表示下面是定义的变量,http_port: 80 #变量的形式,key: value,这里http_port是变量名,80是值max_clients: 200remote_user: root #指定远程的用户名,这里缩进和vars保持了一致,说明变量的代码块已经结束。tasks: #下面构成playbook的tasks,每个task都有 - name: 开始,name指定该任务的名称。- name: ensure apache is at the latest version #指定该任务的名称。yum: pkg=httpd state=latest #yum说明要是用的模板名称,后面指定对应的参数,这两行结合起来就相当于一个shell命令。- name: write the apache config file #每个task之间可以使用空行来做区分。template: src=/srv/httpd.j2 dest=/etc/httpd.conf#需要说明的是缩进的意义和python中缩进的意义是一样,是来区分代码块的。
检测语法
[root@localhost ~]$ ansible-playbook --syntax-check /path/to/playbook.yaml
测试运行
[root@localhost ~]$ ansible-playbook -C /path/to/playbook.yaml
运行
[root@localhost ~]$ ansible-playbook /path/to/playbook.yaml
示例:Playbook 创建用户
[root@localhost ~]$ vim sysuser.yml
---
- hosts: allremote_user: roottasks:- name: create mysql useruser: name=mysql system=yes uid=36- name: create a groupgroup: name=httpd system=yes
Playbook示例 安装nginx服务
[root@localhost ~]$ vim nginx.yml
- hosts: allremote_user: roottasks:- name: add group nginxuser: name=nginx state=present- name: add user nginxuser: name=nginx state=present group=nginx- name: Install Nginxyum: name=nginx state=present- name: Start Nginxservice: name=nginx state=started enabled=yes
tags: 添加标签
可以指定某一个任务添加一个标签,添加标签以后,想执行某个动作可以做出挑选来执行,多个动作可以使用同一个标签。
示例:httpd.yml
代码语言:javascript复制
- hosts: websrvsremote_user: roottasks:- name: Install httpdyum: name=httpd state=presenttage: install - name: Install configure filecopy: src=files/httpd.conf dest=/etc/httpd/conf/tags: conf- name: start httpd servicetags: serviceservice: name=httpd state=started enabled=yesansible-playbook -t install,conf httpd.yml 指定执行install,conf 两个标签
handlers
handlers和notify结合使用触发条件
Handlers 实际上就是一个触发器是task列表,这些task与前述的task并没有本质上的不同,用于当关注的资源发生变化时,才会采取一定的操作。
Notify此action可用于在每个play的最后被触发
这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作
在系统中,我们修改了服务器的配置文件,这时候就需要重启操作服务,就可以使用到handlers。配合 notify使用。
代码语言:javascript
---
- hosts: control-noderemote_user: rootvars:- pkg: httpd- name: template configuration filetemplate: src=template.j2 dest=/etc/foo.conf #修改了配置文件然后依次启动memcached和apache服务。notify: #使用notify来声明引用handlers。- restart memcached- restart apachehandlers: #下面定义了两个handlers- name: restart memcachedservice: name=memcached state=restarted- name: restart apacheservice: name=apache state=restarted
在使用handlers的过程中,有以下几点需要注意:
- handlers只有在其所在的任务被执行时,都会被运行;
- handlers只会在Play的末尾运行一次;如果想在一个Playbook的中间运行handlers,则需要使用meta模块来实现,例如:- meta: flush_handlers。
- 如果一个Play在运行到调用handlers的语句之前失败了,那么这个handlers将不会被执行。我们可以使用mega模块的–force-handlers选项来强制执行handlers,即使在handlers所在Play中途运行失败也能执行。
register 和when
register 用于注册一个变量,保存命令的结果(shell或command模块),这个变量可以在后面的task、when语句或模板文件中使用。
代码语言:javascript
- shell: /bin/pwdregister: pwd_result
debug:#msg: "{{ pwd_result }}" # 输出全部信息#msg: "{{ pwd_result.cmd }}" # 引用方式一msg: "{{ pwd_result['stdout_lines'] }}" # 引用方式二
when 相当于shell脚本里的if 判断,when语句就是用来实现这个功能的,它是一个jinja2的语法,但是不需要双大括号,用法很简单。
- name: echo date #执行了一个 date 命令,register 关键字将 date 命令的输出存储到 date_output 变量名command: date register: date_output - name: echo date_output #用 when 对关键字对分析后的进行判断,如果匹配,则执行这个 task,不匹配就不执行command: echo "30"when: date_output.stdout.split(' ')[2] == "30"
这里第 1 个 task 是执行了一个 date 命令,register 关键字将 date 命令的输出存储到 date_output 变量名。第 2 个 task 对输出进行分析,并使用 when 对关键字对分析后的进行判断,如果匹配,则执行这个 task,不匹配就不执行。这里要重点说下的,因为 register 获取到的输出内容都是字符串,而 ansible 又是 python 写的,你可以使用 python 字符串的方法对其做处理,比如本文中使用的 split,还可以使用 find 方法。
示例
tasks:- name: "shutdown RedHat flavored systems"shell: /sbin/shutdown -h nowwhen: ansible_os_family == "RedHat" #当系统属于红帽系列,执行shell模块
循环
标准循环关键字:”with_items” ,对迭代项的引用,固定变量名为"item”,使用with_item属性给定要迭代的元素。
[root@localhost ~]$ cat xh.yml
---
- hosts: allgather_facts: notasks:- name: dispaly listdebug: msg="{{item}}"with_items:- one- two- three- four
[root@localhost ~]$ ansible-playbook -i hosts xh.yml PLAY [all] *************************************************************************************************************
TASK [dispaly xunhuan] *************************************************************************************************
ok: [192.168.52.129] => (item=one) => {"changed": false, "item": "one", "msg": "one"
}
ok: [192.168.52.129] => (item=two) => {"changed": false, "item": "two", "msg": "two"
}
ok: [192.168.52.129] => (item=three) => {"changed": false, "item": "three", "msg": "three"
}
ok: [192.168.52.129] => (item=four) => {"changed": false, "item": "four", "msg": "four"
}
安装一堆软件包。
---- hosts: localhosttasks: - yum: name="{{item}}" state=installedwith_items: - pkg1- pkg2- pkg3
它会一个一个迭代到特殊变量"{{item}}"处。
loop
等价于with_list,从名字上可以知道它是遍历数组(列表)的,所以在loop指令中,每个元素都以列表的方式去定义。列表有多少个元素,就循环执行file模块多少次,每轮循环中,都会将本次迭代的列表元素保存在控制变量 item中。
安装多个软件
tasks:- name: "Install Packages"yum: name={{ item }} state=latestloop:- httpd- mysql-server- php
模板templates
Jinja2语言,使用字面量,有下面形式
字符串:使用单引号或双引号
数字:整数,浮点数
列表:[item1, item2, …]
元组:(item1, item2, …)
字典:{key1:value1, key2:value2, …}
布尔型:true/false
算术运算:+, -, *, /, //, %, **
比较操作:==, !=, >, >=, <, <=
逻辑运算:and,or,not
流表达式:For,If,When
template 的使用
templates是ansible的一个模块,其功能是根据模板文件动态生成配置文件,templates文件必须存放于templates目录下,且命名为".j2"结尾,yaml/yml文件需要和templates目录平级,这样我们在yml文件中调用模板的时候,就不需要写模板文件的路径,否则需要描述模板文件的路径,因为template模块会自动去找templates目录下的模板文件.
./
├── temnginx.yml
└── templates
└── nginx.conf.j2
template示例
示例:利用template 同步nginx配置文件,准备templates/nginx.conf.j2文件。
vim temnginx.yml
- hosts: websrvsremote_user: roottasks:- name: template config to remote hoststemplate: src=nginx.conf.j2 dest=/etc/nginx/nginx.confansible-playbook temnginx.yml
for循环使用
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.listen }}
}
{% endfor %}
if单分支选择使用
{% if vhost.server_name is defined %}server_name {{ vhost.server_name }}
{% endif %}
if多分支选择使用
{%if vhost.port is undefined %}http_port=80
{%elif vhost.port == 81%}http_port=81
{%else%}http_port = 83
{%endif%}
单行注释
{#% for i in list %#}
roles
Roles介绍
ansible自1.2版本引入的新特性,用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令引入即可。简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷的include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。主要使用场景代码复用度较高的情况下。
Roles目录结构
各目录含义解释
roles: <--所有的角色必须放在roles目录下,这个目录可以自定义位置,默认的位置在/etc/ansible/rolesproject: <---具体的角色项目名称,比如nginx、tomcat、phpfiles: <--用来存放由copy模块或script模块调用的文件。templates: <--用来存放jinjia2模板,template模块会自动在此目录中寻找jinjia2模板文件。tasks: <--此目录应当包含一个main.yml文件,用于定义此角色的任务列表,此文件可以使用include包含其它的位于此目录的task文件。main.ymlhandlers: <--此目录应当包含一个main.yml文件,用于定义此角色中触发条件时执行的动作。main.ymlvars: <--此目录应当包含一个main.yml文件,用于定义此角色用到的变量。main.ymldefaults: <--此目录应当包含一个main.yml文件,用于为当前角色设定默认变量。main.ymlmeta: <--此目录应当包含一个main.yml文件,用于定义此角色的特殊设定及其依赖关系。main.ymlroles/example_role/files/ #所有文件,都将可存放在这里
roles/example_role/templates/ #所有模板都存放在这里
roles/example_role/tasks/main.yml #主函数,包括在其中的所有任务将被执行
roles/example_role/handlers/main.yml #所有包括其中的 handlers 将被执行
roles/example_role/vars/main.yml #所有包括在其中的变量将在roles中生效
roles/example_role/meta/main.yml #roles所有依赖将被正常登入
Roles示例
通过ansible roles安装配置httpd服务,此处的roles使用默认的路径/etc/ansible/roles
。
#在ansible目录下面,建立roles目录
#修改配置文件,使系统能够读取roles目录
[root@ansible ~]$ cat /etc/ansible/ansible.cfg | grep roles
# additional paths to search for roles in, colon separated
#roles_path = /etc/ansible/roles #roles默认路径
# by default, variables from roles will be visible in the global variable
创建role的步骤:
- (1) 创建以roles命名的目录。
- (2) 在roles目录中分别创建以各角色名称命名的目录,如webservers等。
- (3) 在每个角色命名的目录中分别创建files、handlers、meta、tasks、templates和vars目录;用不到的目录可以创建为空目录,也可以不创建 。
- (4) 在playbook文件中,调用各角色。
实验: 创建httpd角色
#创建roles目录
mkdir roles/{httpd,mysql,redis}/tasks -pv
mkdir roles/httpd/{handlers,files}
#查看目录结构
tree roles/roles/├── httpd│ ├── files│ ├── handlers│ └── tasks├── mysql│ └── tasks└── redis└── tasks
#创建目标文件
cd roles/httpd/tasks/
touch install.yml config.yml service.yml
#vim install.yml- name: install httpd packageyum: name=httpdvim config.yml- name: config file copy: src=httpd.conf dest=/etc/httpd/conf/ backup=yes vim service.yml- name: start service service: name=httpd state=started enabled=yes#创建main.yml主控文件,调用以上单独的yml文件,main.yml定义了谁先执行谁后执行的顺序vim main.yml- include: install.yml- include: config.yml- include: service.yml#准备httpd.conf文件,放到httpd单独的文件目录下cp /app/ansible/flies/httpd.conf ../files/#创建一个网页vim flies/index.html<h1> welcome to weixiaodong home <\h1>#创建网页的yml文件vim tasks/index.yml- name: index.htmlcopy: src=index.html dest=/var/www/html #将网页的yml文件写进mian.yml文件中vim mian.yml- include: install.yml- include: config.yml- include: index.yml- include: service.yml#在handlers目录下创建handler文件mian.yml
vim handlers/main.yml
- name: restart service httpdservice: name=httpd state=restarted#创建文件调用httpd角色
cd /app/ansidle/roles
vim role_httpd.yml
---
# httpd role
- hosts: appsrvsremote_user: root roles: #调用角色- role: httpd #查看目录结构
tree
.
httpd
├── files
│ ├── httpd.conf
│ └── index.html
├── handlers
│ └── main.yml
└── tasks├── config.yml├── index.yml├── install.yml├── main.yml└── service.ymlansible-playbook role_httpd.yml
创建目录
[root@ansible ~]$ cd /etc/ansible/roles/
# 创建需要用到的目录
[root@ansible roles]$ mkdir -p httpd/{handlers,tasks,templates,vars}
[root@ansible roles]$ cd httpd/
[root@ansible httpd]$ tree .
.
├── handlers
├── tasks
├── templates
└── vars4 directories, 0 file
变量文件准备vars/main.yml
[root@ansible httpd]$ vim vars/main.yml
PORT: 8088 #指定httpd监听的端口
USERNAME: www #指定httpd运行用户
GROUPNAME: www #指定httpd运行组
配置文件模板准备templates/httpd.conf.j2
# copy一个本地的配置文件放在templates/下并已j2为后缀
[root@ansible httpd]$ cp /etc/httpd/conf/httpd.conf templates/httpd.conf.j2# 进行一些修改,调用上面定义的变量
[root@ansible httpd]$ vim templates/httpd.conf.j2
Listen {{ PORT }}
User {{ USERNAME }}
Group {{ GROUPNAME }}
任务剧本编写,创建用户、创建组、安装软件、配置、启动等
# 创建组的task
[root@ansible httpd]$ vim tasks/group.yml
- name: Create a Startup Groupgroup: name=www gid=60 system=yes# 创建用户的task
[root@ansible httpd]$ vim tasks/user.yml
- name: Create Startup Usersuser: name=www uid=60 system=yes shell=/sbin/nologin# 安装软件的task
[root@ansible httpd]$ vim tasks/install.yml
- name: Install Package Httpdyum: name=httpd state=installed# 配置软件的task
[root@ansible httpd]$ vim tasks/config.yml
- name: Copy Httpd Template Filetemplate: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.confnotify: Restart Httpd# 启动软件的task
[root@ansible httpd]$ vim tasks/start.yml
- name: Start Httpd Serviceservice: name=httpd state=started enabled=yes# 编写main.yml,将上面的这些task引入进来
[root@ansible httpd]$ vim tasks/main.yml
- include: group.yml
- include: user.yml
- include: install.yml
- include: config.yml
- include: start.ym
编写重启httpd的handlers,handlers/main.yml
[root@ansible httpd]$ vim handlers/main.yml
# 这里的名字需要和task中的notify保持一致
- name: Restart Httpdservice: name=httpd state=restarted
编写主的httpd_roles.yml文件调用httpd角色
[root@ansible httpd]$ cd ..
[root@ansible roles]$ vim httpd_roles.yml
---
- hosts: allremote_user: rootroles:- role: httpd #指定角色名称
整体的一个目录结构查看
[root@ansible roles]$ tree .
.
├── httpd
│ ├── handlers
│ │ └── main.yml
│ ├── tasks
│ │ ├── config.yml
│ │ ├── group.yml
│ │ ├── install.yml
│ │ ├── main.yml
│ │ ├── start.yml
│ │ └── user.yml
│ ├── templates
│ │ └── httpd.conf.j2
│ └── vars
│ └── main.yml
└── httpd_roles.yml5 directories, 10 files
测试playbook语法是否正确
[root@ansible roles]$ ansible-playbook -C httpd_roles.ym
上面的测试没有问题,正式执行playbook
[root@ansible roles]$ ansible-playbook httpd_roles.ym
Ansible性能调优
相比于其他的自动化配置工具,Ansible的一个突出特性就是它是基于SSH链接对下游设备进行控制的,这样做的突出好处就是方便,下游设备不需要安装客户端软件。但是这也不可避免的带来一个问题,即Ansible的执行速度较慢。并且,随着Ansible控制设备的增多,Ansible的执行速度会越来越慢。
关于Ansible执行速度的问题,尽管是Ansible的硬伤,但是我们还是可以对其进行部分的优化,尽量的加快Ansible的执行速度。对Ansible的优化可以有两个思路,一个是优化SSH链接,使得SSH的传输速度变快。
另一个如下图所示:
每次Ansible Playbook在执行时,都会收集下游设备的信息,这个过程通常要耗费较长的时间。因此,我们可以考虑使用Redis对这些信息进行缓存,从而加快收集信息的速度,如果业务环境允许,我们也可以直接控制Ansible设备跳过该步骤。
Ansible SSH链接调优
SSH关闭密钥检测
在默认情况下,以SSH登录远程设备时,该设备会检查远程主机的公钥,并且将该公钥记录在~/.ssh/known_hosts文件中,当下次该主机访问时,OpenSSH会核对公钥。如果公钥不同,则OpenSSH会发出警告,如果公钥相同,则OpenSSH则会提示输入密码。
SSH对主机公钥的检查是根据StrictHostKeyChecking变量来设定的,StrictHostKeyChecking的检查级别包括:no(不检查),ask(是否检查要询问),yes(每次都检查),False(关闭检查)。
我们可以在Ansible的配置文件中defaults模块下加入如下代码:
host_key_checking = False
加入后,配置文件如下所示:
这样,Ansible就可以关闭密钥检测了。
OpenSSH链接优化
在使用OpenSSH服务时,默认情况下服务器端会根据客户端的IP地址进行DNS反向解析,得到客户端的主机名,然后根据获取到的主机名再次进行DNS查询得到IP地址,比较这两个IP地址是否一样。这样做可以在一定程度上提高安全性,但是却会浪费时间,因此,我们可以通过关闭这一特性,来实现加速SSH链接速度的目的。 关闭该特新需要进入到/etc/ssh/sshd_config目录下,找到UseDNS的参数,将其修改为no,修改后的配置文件如下所示:
之后,重启SSHD服务即可生效。
SSH pipelining链接加速
SSH的pipelining是另一个加速Ansible执行速度的方法。在Ansible的设置中,SSH的pipelining功能时默认关闭的,这是为了兼容不同的sudo配置,主要是requieretty选项。因此,如果我们不需要在Ansible的控制中使用sudo选项,可以关闭这一选项以加快SSH链接速度。
如果要关闭这一项,可以打开Ansible的配置文件/etc/ansible/ansbile.cfg,将pipelining = False改为True即可,修改后的配置文件如下所示:
Ansible Facts调优
关闭Gather Facts
为了减少Ansible在收集客户端信息时的时间,我们首先想到的就是直接删除这一选项。要删除这一步骤,我们可以在palybook文件中添加一行:
gather_facts: no
添加后的Playbook文件如下所示:
这样,我们在执行该Playbook时,就不会再次进行gather_facts的步骤了,结果如下所示:
将Facts信息存入Redis缓存
除了删除这一步之外,我们还可以考虑将客户端信息写入内存,以加快信息查询。
相关文章:
Ansible Playbook原理与实践(Principles and Practice of Ansible Playbook)
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 本人主要分享计算机核心技…...
解决OpenCV保存视频 视频全部为绿色的bug
目录 项目场景: 问题描述 原因分析: 解决方案: 项目场景: 使用OpenCV-Python 保存视频,视频为numpy array格式,保存的视频全部为无意义的绿色。 问题描述 用opencv 保存的视频会出现全部为绿色的情况&…...
手机使用指南:如何在没有备份的情况下从 Android 设备恢复已删除的联系人
在本指南中,您将了解如何从 Android 手机内存中恢复已删除的联系人。Android 诞生、见证并征服了 80% 的智能手机行业。有些人可能将此称为“非常大胆的宣言”,但最近的统计数据完全支持我们的说法。灵活性、高度改进的可用性和快速性是 Android 操作系统…...
TS系列(6):函数
你好,我是沐爸,欢迎点赞、收藏、评论和关注。 TS系列(1):TS是什么?如何使用? TS系列(2):类型声明、类型推断和类型总览 TS系列(3)&…...
网盘能否作为FTP替代产品?企业该如何进行FTP国产化替代?
近年来,信创的概念引入和高效实践落地让更多的行业企业自发性地进行国产化替代,目前信创国产化替代还多发生在操作系统和应用层面,软件工具等目前还在下一阶段规划,但很多企业未雨绸缪,已经在做调研和尝试。 FTP作为世…...
Python操作MongoDB
一、Python链接MongoDB 1、安装pymongo包 使用包管理器安装 pip3 insatll pymongo 2、连接MongoDB 首先需要导入pymongo包: from pymongo import MongoClient 创建MongoClient对象: from pymongo import MongoClient #创建MongoClient对象&#…...
Redis --- 第二讲 --- 特性和安装
一、背景知识 Redis特性: Redis是一个在内存中存储数据的中间件,用于作为数据库,作为缓存,在分布式系统中能够大展拳脚。Redis的一些特性造就了现在的Redis。 在内存中存储数据,通过一系列的数据结构。MySQL主要是通…...
基于单片机的两轮直立平衡车的设计
本设计基于单片机设计的两轮自平衡小车,其中机械部分包括车体、车轮、直流电机、锂电池等部件。控制电路板采用STC12C5A60S2作为主控制器,采用6轴姿态传感器MPU6050测量小车倾角,采用TB6612FNG芯片驱动电机。通过模块化编程完成了平衡车系统软…...
828华为云征文|部署个人知识管理系统 SiyuanNote
828华为云征文|部署个人知识管理系统 SiyuanNote 一、Flexus云服务器X实例介绍二、Flexus云服务器X实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置2.4 Docker 环境搭建 三、Flexus云服务器X实例部署 SiyuanNote3.1 SiyuanNote 介绍3.2 SiyuanNote 部署3.3 Siyua…...
MATLAB中pcg函数用法
目录 语法 说明 示例 线性系统的迭代解 使用指定了预条件子的 pcg 提供初始估计值 使用函数句柄代替数值矩阵 pcg函数的功能是求解线性系统 - 预条件共轭梯度法。 语法 x pcg(A,b) x pcg(A,b,tol) x pcg(A,b,tol,maxit) x pcg(A,b,tol,maxit,M) x pcg(A,b,tol,ma…...
Veritus netbackup 管理控制台无法连接:未知错误
节假日停电,netbackup服务器意外停机后重新开机,使用netbackup管理控制台无法连接,提示未知错误。 ssh连接到服务器,操作系统正常,那应该是应用有问题,先试一下重启服务器看看。重新正常关机,重…...
安全中心 (SOC) 与 网络运营中心 (NOC)
NOC 和 SOC 之间的区别 网络运营中心 (NOC) 负责维护公司计算机系统的技术基础设施,而安全运营中心 (SOC) 则负责保护组织免受网络威胁。 NOC 专注于防止自然灾害、停电和互联网中断等自然原因造成的网络干扰,而 SOC 则从事监控、管理和保护。 NOC 提…...
WPS使用越来越卡顿
UOS统信wps频繁的使用后出现卡顿问题,通过删除或重命名kingsoft文件缓存目录。 文章目录 一、问题描述二、问题原因三、解决方案步骤一步骤二步骤三 一、问题描述 用户在频繁的使用wps处理工作,在使用一段时间后,用户反馈wps打开速度慢&…...
吴恩达深度学习笔记:卷积神经网络(Foundations of Convolutional Neural Networks)2.5-2.6
目录 第四门课 卷积神经网络(Convolutional Neural Networks)第二周 深度卷积网络:实例探究(Deep convolutional models: case studies)2.5 网络中的网络以及 11 卷积(Network in Network and 11 convoluti…...
C# 解决Excel边框样式无法复制问题及实现格式刷功能
目录 问题现象 范例运行环境 解决方案 剪贴板加特殊粘贴 自定义样式 直接赋值 完美方案 小结 问题现象 在运行数据表数据导出到 EXCEL 数据输出时遇到了一个问题,开发者设计了单行细线下边框的输出模板,如下图设计: 其中 <%syst…...
前端组件化开发
假设这个页面是vue开发的,如果一整个页面都是编写在一个vue文件里面,后期不好维护,会特别的庞大,那么如何这个时候需要进行组件化开发。组件化开发后必然会带来一个问题需要进行组件之间的通信。组要是父子组件之间通信࿰…...
异步操作实现线程池
文章目录 futureasyncpromisepackage task C11线程池实现 future 在C11标准库中,提供了一个future的模板类,它表示的是一个异步操作的结果,当在多线程编程中使用异步任务的时候,使用这个类可以帮助在需要的时候获取到对应的数据处…...
长期提供APX515/B原装二手APX525/B音频分析仪
Audio Precision APx515 是一款针对生产测试而优化的高性能音频分析仪。它因其速度、性能、自动化和易用性而成为一流的仪器。它具有卓越的性能,具有 –106 dB 的典型 THDN、1M 点 FFT 和 192k 数字 I/O,以及所有 APx 系列音频分析仪的一键式自动化和易用…...
【数据库差异研究】update与delete使用表别名的研究
目录 ⚛️总结 ☪️1 Update ♋1.1 测试用例UPDATE users as a SET a.age 111 WHERE a.name Alice; ♏1.2 测试用例UPDATE users as a SET a.age 111 WHERE name Alice; ♐1.3 测试用例UPDATE users as a SET age 111 WHERE a.name Alice; ♑1.4 测试用例UPDATE us…...
idea远程连接docker
idea远程连接docker docker、ubuntu、linux、远程连接、IntelliJ idea注意!本文中开启docker远程连接的方法只能在确定环境安全的内网中使用,不可在公网服务器设置,有极大安全风险! 注意!本文中开启docker远程连接的…...
Docker 安装 ClickHouse 教程
Docker 安装 ClickHouse 教程 创建目录 首先,创建必要的目录用于存放 ClickHouse 的配置、数据和日志文件。 mkdir -p /home/clickhouse/conf mkdir -p /home/clickhouse/data mkdir -p /home/clickhouse/log chmod -R 777 /home/clickhouse/conf chmod -R 777 /…...
过渡到内存安全语言:挑战和注意事项
开放源代码安全基金会 ( OpenSSF )总经理 Omkhar Arasaratnam 讨论了内存安全编程语言的演变及其为应对 C 和 C 等语言的局限性而出现的现象。 内存安全问题已存在五十多年,它要求程序员从内存管理任务中抽离出来。 Java、Rust、Python 和 JavaScript 等现代语言通…...
在Pycharm中安装Cv2
安装OpenCV: 在Terminal中,输入以下pip命令来安装OpenCV: pip install opencv-python pip install opencv-contrib-python 如果下载速度较慢,可以考虑使用国内的pip镜像源,如清华大学源: pip install openc…...
减少重复的请求之promise缓存池(构造器版) —— 缓存promise,多次promise等待并返回第一个promise的结果
减少重复的请求之promise缓存池 —— 缓存promise,多次promise等待并返回第一个promise的结果 背景简介 当一个业务组件初始化调用了接口,统一个页面多吃使用同一个组件,将会请求大量重复的接口 如果将promise当作一个普通的对象࿰…...
cdq+bitset处理高维偏序
高维偏序 CDQ分治 假设处理的区间为 [ l , r ] [l,r] [l,r] ,CDQ分治的过程: 如果 l ≥ r l\geq r l≥r ,返回。设区间中点为 m i d mid mid ,递归处理 [ l , m i d ] [l,mid] [l,mid] 和 [ m i d 1 , r ] [mid1,r] [mid…...
敏捷开发和传统开发,你更适合哪种?
时间:2024年 10月 03日 作者:小蒋聊技术 邮箱:wei_wei10163.com 微信:wei_wei10 音频:喜马拉雅 大家好,欢迎来到“小蒋聊技术”,我是小蒋!今天我们来聊聊两个开发模式的“对决”…...
python之with
with上下文管理是什么呢? 一般都是使用系统提供的一些with语句,列如我要去读取一些数据进行分析,就可以使用with open去读取某些数据,或者我要把一些图片给他保存到某些地方,可以用with给他写入。 上下午管理器with是…...
vue3 升级实战笔记
最近要将公司项目的移动端进行 vue3 的升级工作,就顺便记录下升级过程。 项目迁移的思路 我的想法是最小改动原则。 从 vue2.x 升级到 vue3,且使用 vue3 的 选项式 API。构建工具要从 vue-cli(webpack)升级到 vite。路由需要升级到…...
利用函数模块化代码实操 ← Python
【知识点】 ● 模块化可以使代码易于维护和调试,并且提高代码的重用性。 ● 函数可以用来减少冗余的代码并提高代码的可重用性。函数也可以用来模块化代码并提高程序的质量。 ● 在 Python 中,可以将函数的定义放在一个被称为模块的文件中,这种文件的后缀…...
Java高效编程(12):重写toString方法
解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 尽管 Object 类提供了 toString 方法的默认实现,但它返回的字符串通常不是类的使用者想要看到的。默认返回的字符串格式是类名加上“”符号和哈希码的十六进制表示,例如 PhoneNu…...
网站建设每月工作多少/北京seo收费
本节内容 迭代器&生成器装饰器Json & pickle 数据序列化软件目录结构规范作业:ATM项目开发1.列表生成式,迭代器&生成器 列表生成式 孩子,我现在有个需求,看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],我要求你把列表里的每个值加1&…...
电子书网站建设/seo实战培训机构
最后博文,我们引入软件体系结构的基本概念,接下来,我们将介绍如何构建一个软件系统。 当我们開始进行系统架构设计的时候。一般会考虑下面几点: 所设计的软件体系结构的主要功能要素是什么。怎样将这些要素与其它系统关联。哪些信…...
html做网站项目案例/汕头网站建设平台
2019独角兽企业重金招聘Python工程师标准>>> 在一个锁中使用多个条件(Using multiple conditions in a Lock) 一个Lock可能关联着一个或者多个条件,这些条件表现在Condition接口。这些条件(conditions)的目的是允许多个线程控制一个锁对象并且…...
光谷做网站推广/万网官网
前言 磁盘可以说是计算机系统最慢的硬件之一,读写速度相差内存 10 倍以上,所以针对优化磁盘的技术非常的多,比如零拷贝、直接 I/O、异步 I/O 等等,这些优化的目的就是为了提高系统的吞吐量,另外操作系统内核中的磁盘高…...
html5网站制作编辑源码/百度下载安装免费
1.安装目录如下: . 2.关闭所有的安全助手和杀毒软件 3.双击halcon-12.0-windows安装,注意选择32位 4.将32位破解文件夹下面的halcon.dll,halconxl.dll两个dll拷贝到C:\Program Files\MVTec\HALCON-12.0\bin\x86sse2-win32下面替换掉已有的dll即可...
做cpa能用什么网站/厦门小鱼网
VMLogin防关联指纹纹浏览器:用于亚马逊测评、FACEBOOK广告投放等多平台多账号批量注册多登防关联管理软件。用虚拟浏览器配置文件代替若干电脑,具有浏览器指纹防护功能,每个浏览器文件的Cookies、本地存储和其他缓存文件将被完全隔离,浏览器配…...