Ansible 是什么 ?

ansible架构图

ansible特性 

模块化:调用特定的模块,完成特定的任务;

基于Python语言研发,由Paramiko, PyYAML和Jinja2三个核心库实现;

部署简单:agentless;

支持自定义模块,使用任意编程语言;

强大的playbook机制;

幂等性;

安装及程序环境:

程序:

ansible

ansible-playbook

ansible-doc

配置文件:

/etc/ansible/ansible.cfg

主机清单:

/etc/ansible/hosts

插件目录:

/usr/share/ansible_plugins/

安装ansible

安装依赖包

ansible命令的使用:

Usage: ansible <host-pattern> [options]

常用选项:

-m MOD_NAME

-a MOD_ARGS

配置Host Inventory:

/etc/ansible/hosts

[group_id]

HOST_PATTERN1

HOST_PATTERN2

示例:

首先对此文件进行备份操作,以防后面需要用到默认配置文件

进入到/etc/ansible/hosts文件,此处绿色光标以下的内容是没有用的,都是示例,可以删除掉,然后添加我们下面实验操作用到的主机。

添加一组websrvs服务器,以用于下面的测试

测试主机连通性

这里报错是因为实验用的主机交换其他两台主机的公钥/私钥的原因导致的

实验SSH免密码登陆设置

生成私钥和公钥 ssh-keygen -t rsa -P ''

复制公钥文件问authorized_keys

把公钥传送到其他主机

在68的主机上面可以看见公钥已经传送过来了,并且确认文件的权限是否正确

重复以上操作把公钥发送给69的主机

然后重新执行ansible的ping模块命令查看该两台主机的连通性

可以发现此时已经成功,那么下面就开始介绍ansilbe的其他模块

最后记得利用ansible同步一下所有主机的时间,以免某主机的时间有错误,后面看日志起来会造成混乱

ansible模块:

获取模块列表:ansible-doc -l

获取指定模块的使用帮助:ansible-doc -s MOD_NAME

常用模块:

ping模块:探测目标主机是否存活;

示例:测试所有的主机的连通性

command模块:在远程主机执行命令;

示例1:让所有主机同步时间

此处没有给出指定的-m command命令,是因为ansible的模块默认就是command

示例2:让每一台主机都执行uname -r命令

示例3:在主机上面都创建一个用户

查看两台主机是否已经创建该用户

查看用户信息:

帮这两个用户改密码,此处需要注意的是,虽然用下面的命令看似执行成功,但是当我们验证的时候,就会发现密码错误了,这是因为ansible的command模块并不支持管道等输出,所以下面介绍另外一个ansible的模块shell

shell模块 :在远程主机上调用shell解释器运行命令,支持shell的各种功能,例如管道等

注意:command和shell模块的核心参数直接为命令本身;而其它模块的参数通常为“key=value”格式;

示例:批量修改其他主机的特定用户的密码

此时可以发现已经可以登陆成功

copy模块:复制文件到远程主机

用法:

(1) 复制文件

-a "src='#'"  "

(2) 给定内容生成文件

-a "content=  dest=  "

其它参数:mode, owner, group, ...

示例:复制文件到其他主机

此处创建一个测试文件

复制文件到其他主机

下面红色的报错信息是,如果要传送文件,该主机的指定目录需要存在,如果不存在,就是提示错误

创建对应的目录

重新传送文件,已经没有错误提示,但是此处也可以看见,如果文件已经存在,则原文件会被覆盖掉,并且此处也没有任何提示覆盖文件的信息,所以操作的时候就需要注意了,以免覆盖掉重要的文件

验证文件

file模块:设置文件的属性

用法:

(1) 创建目录:

-a "path=  state=directory"

(2) 创建链接文件:

-a "path=  src='#'" /p>

(3) 删除文件:

-a "path=  state=absent“

示例:修改文件的权限和属主

验证文件

示例:创建文件的软连接

验证文件

设置文件的状态为absent(即删除文件)

验证

fetch模块:从远程主机拿文件

示例:从10.1.156.69主机拿一个文件

当抓去一堆文件的时候,也会创建对应的ip地址的目录,以区分文件

cron模块 :管理计划任务条目

用法:

-a ""

minute=

hour=

day=

month=

weekday=

job=

name=

user=

state={present|absent}

示例:创建一个同步时间的计划任务,每5分钟同步一下服务器的时间

验证任务

示例:删除计划任务

验证

hostname模块:管理主机名

用法:

name=

示例:修改主机名

yum模块:使用yum命令完成程序包管理

用法:

-a ""

(1) name=  state={present|latest}

(2) name=  state=absent

示例:安装指定包

此实验,首先,确定主机的yum源是可用的,否则实验会失败

安装samba包

验证

删除samba安装包

已经没有安装的字眼了

service模块:服务管理

用法:

-a ""

name=

state=

started

stopped

restarted

enabled=

runlevel=

示例:开启主机的httpd服务

首先我们确认httpd服务是关闭的

开启httpd服务,并且设置为开机启动

验证,80端口已经开启

group模块:增加或删除组

用法:

-a ""

name=

state=

system=

gid=

示例:添加一个组

验证

删除组

验证

user模块:用户管理

使用格式:

name= : 创建的用户名

state= : present新增,absent删除

force= : 删除用户的时候删除家目录

system= : 创建系统用户

uid= : 指定UID

shell= : 指定shell

home= : 指定用户家目录

示例:增加一个系统用户

验证

删除用户

setup模块:收集主机里面的各种信息

示例:收集所有主机的信息

YAML  一种数据序列化工具的语言格式     

YAML is a data serialization format designed for human readability and  interaction with scripting languages.

数据结构:

key:value

- item1

- item2

- item3

例如{name:jerry, age:21}

PlayBook

核心元素:

Tasks:任务,由模块定义的操作的列表;

Variables:变量

Templates:模板,即使用了模板语法的文本文件;

Handlers:由特定条件触发的Tasks;

Roles:角色;

playbook的基础组件:

Hosts:运行指定任务的目标主机;

remote_user:在远程主机以哪个用户身份执行;

sudo_user:非管理员需要拥有sudo权限;

tasks:任务列表

模块,模块参数:

格式:

(1) action: module arguments

(2) module: arguments

运行playbook,使用ansible-playbook命令

(1) 检测语法

ansible-playbook  --syntax-check  /path/to/playbook.yaml

(2) 测试运行

ansible-playbook -C /path/to/playbook.yaml

--list-hosts

-list-tasks

--list-tags

(3) 运行

ansible-playbook  /path/to/playbook.yaml

-t TAGS, --tags=TAGS

--skip-tags=SKIP_TAGS

--start-at-task=START_AT

示例1:定义一个playbook任务来新增用户和组

定义一个yaml的模板

查查语法有没有错误,没有提示即表示语法应该没有问题。

测试运行看看,-C表示仅测试跑一边,但是不会实际操作

也可以单独测试某些特定的选项

查看仅影响的主机

查看运行哪些任务

查看哪个任务打标了,这里并没有任何任务打标记,后面再演示

以上没有错误,开始正式运行该任务

验证

示例2:定义一个playbook任务来修改文件端口

此步骤里面有安装httpd的安装包,其实此处有点多余,因为测试的两台主机均已经安装该服务,此处添加上去是为了演示效果,因为当生产环境中,假如存在一台服务器没有该安装包,那么次处就能帮我们安装上去,不然的话,漏了这一步,到后面查原因也挺麻烦的

检查语法问题

先从一台主机上面把httpd.conf文件拷问来编辑

修改httpd.conf文件

比如修改端口为8080,其他都为默认配置

首先备份好各自主机里面的配置文件,以防后面出错

检查备份是否成功

测试运行web.yml,看看有没有问题,没有问题的话就正常运行

    执行改文件

验证服务器端口打开没有,可以看见8080端口已经打开,实验成功。

Handlers的使用:由特定条件触发的Tasks;

格式:

tasks:

- name: TASK_NAME

module: arguments

notify: HANDLER_NAME

handlers:

- name: HANDLER_NAME

module: arguments

示例:参照上面的例子继续修改apache的端口

修改端口号为8090

修改原来的web.yml脚本实现操作

检测语法

测试运行,可以看出,当复制文件过去的时候,会触发到restart httpd service的handlers任务,所以任务就重启了,而不是启动

正式运行

验证结果,8090端口已经打开,实验成功

tags:给指定的任务定义一个调用标识;

使用格式:

- name: NAME

module: arguments

tags: TAG_ID

示例:执行特定的tags

修改文件的端口为8088

在此前的配置文件上面插入一个标签instconf

检查语法

此处可以查看到该yml脚本有一个标签,影响着websrvs组

测试运行

正式运行一下,指定以instconf的标签运行,所以此处不会显示器其他多余的信息,包括安装httpd包和启动httpd服务

验证该结果

此处也可以对同一个文件标记多个标签同时执行

测试运行,因为此处已经安装了httpd包和文件已经复制过去,所以都是绿色,此处就演示到这里,其他步骤可以参考上面的操作

Variables:变量

类型:

内建:

(1) facts

自定义:

(1) 命令行传递;

-e VAR=VALUE

(2) 在hosts Inventory中为每个主机定义专用变量值;

(a) 向不同的主机传递不同的变量 ;

IP/HOSTNAME variable_name=value

(b) 向组内的所有主机传递相同的变量 ;

[groupname:vars]

variable_name=value

(3) 在playbook中定义

vars:

- var_name: value

- var_name: value

(4) Inventory还可以使用参数:

用于定义ansible远程连接目标主机时使用的属性,而非传递给playbook的变量;

ansible_ssh_host

ansible_ssh_port

ansible_ssh_user

ansible_ssh_pass

ansible_sudo_pass

...

(5) 在角色调用时传递

roles:

- { role: ROLE_NAME, var: value, ...}

变量调用:

{{ var_name }}

示例1:利用命令行传递变量来安装不同的包

此处{{ pkgname }}表示为一个变量

检查一下语法,居然报错了,什么情况?仔细看了即便发现是漏了空格

加上空格

再次检查,还是还是有报错的情况,各位不要慌,因为这只是因为还没有给变量赋值才会报的错,所以此处报错是很正常

给变量赋值再跑一遍,此时就不会报错

修改一下变量,发现也是正常的,此处68因为已经安装过vsftpd所以就不会执行,所以并不会changed

示例2:在playbook中定义变量

测试,也没有问题的

思考?假如同时利用-e的参数传递一个变量的参数的话会怎么样?

测试结果如下,是-e传递的变量参数的优先级更高,这样的话能避免传递参数的时候,因为文本里面定义的优先级更高而出错?

示例3:在hosts Inventory中为每个主机定义专用变量值

删除掉文档里面原有的变量

测试,没有问题

示例4:在hosts Inventory中为每个主机定义专用变量值的第二种方法

测试,也是可以的

Templates :模板,文本文件,内部嵌套有模板语言脚本(使用Jinja2模板语言编写)

Jinja2 is a template engine written in pure Python. It provides a Django inspired non-XML syntax but supports inline expressions and an optional sandboxed environment.

语法:

字面量:

字符串:使用单引号或双引号;

数字:整数、浮点数;

列表:[item1, item2, ...]

元组:(item1, item2, ...)

字典:{key1:value1, key2:value2, ...}

布尔型:true/false

算术运算:

+, -, *, /, //, %, **

比较操作:

==, !=, >, <, >=, <=

逻辑运算:and, or, not

执行模板文件中的脚本,并生成结果数据流,需要使用template模块;

template:

-a " "

src=

dest=

mode=

onwer=

group=

注意:此模板不能在命令行使用,而只能用于playbook;

示例:利用templates模板来设置nginx的定义cpu的数量

首先利用ansible命令获取当前系统系统的cpu数量

首先备份一下默认的文件

首先在下面的主机传送一个配置文件过来

编辑该文件,修改此处为上面利用ansible的setup模块获取的名称

重命名该文件为Jinja2格式后缀的文件

新建一个playbook文件,为了演示,建立一个ngxsrvs组,虽然看上去都一样。。。

建立playbook文档

此处为了演示效果,此处把原来的nginx包卸载掉

确认安装包卸载掉,并且服务没在线

检查playbook的文件有没语法错误

测试运行,此处报错是因为找不到nginx的服务,所以应该是没有问题的

正式运行,没有问题

查看一下端口是否已经打开

重点检查一下cpu的变量是否有改变,这里可以看到,跟我们ansible_processor_vcpus的值是一样,这样符合我们预期,此处就展示完毕

条件测试 :when语句:在tasks中使用,Jinja2的语法格式;

示例:利用Ansible条件测试在CentOS_6和CentOS_7的启动服务

这边首先增加一台ip为10.1.156.70的CentOS7的主机

然后我们利用setup模块的命令

在7的上面可以找到该行

在6的上面可以找到该行

根据以上的信息,我们就可以创建一个基于条件判断的playbook文件test.yml

为了演示效果,实验前把CentOS6的nginx先卸载掉,此处70的报错只是因为ssh缺少那边没有提供公钥文件,此处就不再演示

检查playbook语法有没有问题

测试运行,没有报错,可以看出当执行service nginx start命令时候,只有CentOS6的主机执行了命令,不过开始那里提示有skipping信息是为什么?CentOS7开始也提示有skipping信息?但是后面确实是执行成功了,下面正式运行该playbook看看效果。

正式运行,似乎没有报什么错误

看看服务是否已经开启,此处可见80端口已经开发,应该是没有问题的,此处就不浏览主页做测试了

循环 :迭代,需要重复执行的任务;

对迭代项的引用,固定变量名为"item”,使用with_item属性给定要迭代的元素;

元素:列表

字符串

字典

基于字符串列表给出元素示例:

示例:基于列表的方式安装多个安装包

检查语法

测试运行,没有报错(这里就以69和70两台不同的版本的CentOS来做测试)

正式运行,69的机器报错了,看了一下原因,是下载php-mbstring的时候出错了,此处原因应该是虚拟挂载CentOS6.8的cd1导致的,挂载cd2应该就解决此问题,不过部分安装包应该是在cd1里面,所以小伙伴们最好找一个安全包都全的yum仓库

重新配置好yum仓库,并且把先前安装的先卸载掉,以配置实验

此处可以看出来,由于69主机刚报错了一个,所以所有的包都没有安装,7上面倒是都已经安装过了

重新运行脚本,没有报错了

验证,发现已经安装上了,此处就不再看其他安装包的安装情况了,应该没有大问题

基于字典列表给元素示例:

示例:创建指定的用户并属于指定的组

检查语法

测试运行,没有提示有任何变化?

正式运行,可以看见创建了对应的用户和组

验证,符合我们预期

角色:roles

以特定的层级目录结构进行组织的tasks、variables、handlers、templates、files等;

role_name/

files/:存储由copy或script等模块调用的文件;

tasks/:此目录中至少应该有一个名为main.yml的文件,用于定义各task;其它的文件需要由main.yml进行“包含”调用;

handlers/:此目录中至少应该有一个名为main.yml的文件,用于定义各handler;其它的文件需要由main.yml进行“包含”调用;

vars/:此目录中至少应该有一个名为main.yml的文件,用于定义各variable;其它的文件需要由main.yml进行“包含”调用;

templates/:存储由template模块调用的模板文本;

meta/:此目录中至少应该有一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关系;其它的文件需要由main.yml进行“包含”调用;

default/:此目录中至少应该有一个名为main.yml的文件,用于设定默认变量;

在playbook中调用角色的方法:

- hosts: HOSTS

remote_user: USERNAME

roles:

- ROLE1

- ROLE2

- { role: ROLE3, VARIABLE: VALUE, ...}

- { role: ROLE4, when: CONDITION }

示例:创建对应的服务目录下面的模版

首先创建对应的目录

确认一下目录是否正确

首先准备一个安装包,放到nginx/file/目录下面

新建一个nginx的task模板

大家可以发现此处的模板跟之前的不一样,比如说,开头没有了定义主机、用户、和task等,此处的task会自行查找/etc/ansible/roles/nginx/task/main.yml的任务(此处文件本身也是在task目录下面)。再比如说,该处指定的copy命令的src=FILENAME也是相对路径,其绝对路径为/etc/ansible/roles/nginx/file/FILENAME。又比如说定义了notify但是这里并没有handlers,是因为此处定义了的notify的名字会自行去查看该目录下面即/etc/ansible/roles/nginx/handlers/main.yml里面的handlers。还有template那里,大家有没发现也是用的相对路径,此处绝对路径为在/etc/ansible/roles/nginx/template/nginx.conf.j2。所以大家清楚了吗?

接着是定义/etc/ansible/roles/nginx/handlers/main.yml

此处的文件就是用来承上面的notify里面为什么没有定义的handlers的原因,因为已经定义在../handlers/main.yml里面了。

复制nginx.conf文件到templates目录下面为nginx.conf.j2

编辑里面定义的cpu数量,之前是2,所以此处我们也可以利用算数表达式来控制cpu的数量,比如此处-1,到时候看到的cpu数量应该是为1。

再复制/etc/nginx/conf.d/default.conf到nginx/templates/default.conf.j2

然后编辑此文件

编辑原来的端口号为一个变量值ngxport

此时需要重新编辑task/main.yml文件

主要添加一下内容

此时我们就可以定义变量文件了

比如说定义ngxport的变量为8888

此时所有的元素暂时都足够了,meta和default的文件夹在此处暂时用不上,然后我们在/etc/ansible/目录下面创建一个nginx.yml的文件

注意此处的roles里面的nginx要在/etc/ansible.cfg文件里面有对应的设定

编辑查看ansible.cfg文件

可以看见系统默认的roles路径也是在此处,所以我们去掉#号来启用它

修改成如下

以上都准备好了以后,检查一下nginx.yml语法,暂时并没有报错

然后测试运行,可以看见此处报错了,看了一下报错的原因,是因为找不到/tmp/nginx安装包,因为只是测试运行,并没有传送安装包到目标主机上面,所以此处报错是正常的可以不予理会。

下面正式运行该脚本,此处报错了,原因看了一下,nginx安装包是el7版本的,在centos6上面并不能安装。以及handlers出问题了。

此处修改一下tasks/main.yml,以下红色内容为修改部分,意思就是,CentOS7系统从远程复制的安装包安装,CentOS6则直接从yum仓库源安装,6和7的nginx的配置文件应该是一样的,暂时先这么操作实验看看结果,并且先把CentOS7系统的nginx安装包删除掉,以重新演示效果。notify处的语法错误,此处补上。

修改完以上的内容,重新测试运行

可以看出来此处还是有报错内容,

第一个报错内容为找不到安装包,此处是正常的,因为安装包还是传过去(上一次运行的时候传送过去的安装包我已经删掉了,所以此处需要重传)

第二个报错内容为找不到nginx服务,此处也是正常的,因为nginx安装包还没有安装

正常重新运行一下nginx.yml脚本看看,发现已经没有报错的地方了

验证结果,发现8888端口已经打开

cpu数量的设置也跟我们之前配置的是一样的,实验到此结束

示例 2: 根据以上内容,修改端口号

当我们写好模板以后,需要修改端口号,也是非常容易的,而且我们也可以通过在nginx.yml上面通过roles传递变量

例如像以下这样子操作

测试运行一下看看有没有错误,可以看见在复制配置文件和重启服务那里有了变化,这符合我们预期

正式运行一下看看,能正常运行

验证端口号是否修改成功,看到8080端口,表示操作没有问题

以上是运行成功了,但是细心的同学会发现,这样所有程序都跑一遍也麻烦,所以我们可以用之前了解到的标签来执行特定的操作即可,也可以直接传递相应的变量。

直接传递参数测试运行,好像没有问题

正式运行

查看端口号是否正确,此处可以看见是我们定义的8099端口,测试成功

示例:实现 httpd 不同主机不同的端口号

首先先把定义的端口号先屏蔽掉

编辑/etc/ansible/hosts文件

定义对应的端口号,然后测试

然后记得把nginx.yml文件里面也改回来

这里直接运行就不先做测试了,不过一般同学们还是做好测试工作比较好,本人比较懒O.O

验证端口号,也符合我们预期

示例:在同一个 yml 配置文件里面运行两个服务模板程序

这里以memcached为例,首先复制memcached的配置文件到对应的templates目录下来为.j2的文件

memcached服务是依靠设置内存参数来定义的,所以我们得首先用ansible来确认系统的内存变量参数值是什么,并且通过以下图可以看见两个系统参数都是一致的。

编辑memcached.j2文件

定义变量参数

改成 

开始定义memcached的任务文件

定义handlers文件

把memcached定义在ngnix.yml文件一同运行

测试运行,只是安装包还没有安装,提示的错误都问题不大,是正常的

正式运行

验证服务是否开启,且是否设置好预期可用内存

可以看见11211端口已经打开

查看可用内存,原来的数值是970~980多,这里200多,符合除以4的预期效果

示例 : 根据不同的系统安装 mysql 包

首先定义一个tasks的模板

定义一个yaml调用角色脚本

设置hosts文件添加dbsrvs组

测试语法

测试运行调用角色脚本db.yml,应该没有大问题

正式运行,没有报任何错误

验证服务是否已经开启

可以看见mysql和mariadb服务均已经开启

写在最后,关于ansible的能最多控制几台主机

此处是在配置文件里面定义的,默认是5台主机,如果把主机的控制的主机调大,估计也要相对应性能的主机当ansible服务器

至此,本博文已经完结,下面总结几个小点:

1、 ansible的playbook.yml文件要求的格式比较严格,有时候少了几个空格,或者空格位置不妥当的时候,系统均默认此格式为错误,所以需要小心

2、 有时候输入错了ansibile不能识别的错误,用- - syntax-check 或者 �Ccheck 测试文件的时候并不会提示有任何提示,需要实际运行才能会报错。

3、 有一次写playbook.yml文件的时候,检查过是没有问题,但是测试一直出问题,后来把所有重写一遍就好,也可能是哪里错了自己没看见。

Ansible无敌详细入门教程相关推荐

  1. TypeScript超详细入门教程(上)

    TypeScript超详细入门教程(上) 01 开篇词:Hello~TypeScript 01 开篇词:Hello~TypeScript 更新时间:2019-10-30 13:49:46 既然我已经踏 ...

  2. 543、RabbitMQ详细入门教程系列 -【Confirm与Mandatory】 2022.09.05

    目录 一.前言概述 二.SpringAMQP配置Confirm 2.1 Connection设置 2.2 template设置 2.3 Confirm实现 三.SpringAMQP配置ManDator ...

  3. 544、RabbitMQ详细入门教程系列 -【手动消费确认】 2022.09.05

    目录 一.前言概述 二.配置实现 2.1 XML配置 2.2 MessageListener实现 三.消息预取 四.并发消费 五.参考链接 一.前言概述 RabbitMQ(四) --消费者Consum ...

  4. 【endnote详细入门教程】

    Endnote详细入门教程 一.下载引用,导入文献 二.在word中插入引用 三.文献分类.注释 四.预览.引用格式 一.下载引用,导入文献 1.可以从不同的文献下载网站进行导入: (1)web of ...

  5. Swig超详细入门教程(Java调用C/C++, CMake)——更新于2021.12

    目录 相关教程 环境配置 0基础上手例子(C/C++) 使用CMake的例子(C语言) 使用CMake的例子(C++) 本文主要是手把手教萌新们如何用官方用例构建(有许多本人亲身踩坑血泪史) 相关教程 ...

  6. Apollo Control——超详细入门教程(二):连续状态空间方程离散化与离散LQR公式推导

    专栏文章列表 Apollo Control--超详细入门教程(一):基于道路误差的车辆动力学模型 Apollo Control--超详细入门教程(二):连续状态空间方程离散化与离散LQR公式推导 Ap ...

  7. python画图颜色表示大小变化_python画图(线条颜色、大小、类型:点、虚线等)(图文详细入门教程四)...

    初衷 本人由于平常写论文需要输出一些结果图,但是苦于在网上搜python画图时,详细的教程非常多,但是就是找不到能马上解决自己问题那一行代码,所以打算写一些适合需求简单的朋友应急用的教程,应急就必须方 ...

  8. MFC 最详细入门教程

    From:https://blog.csdn.net/wang18323834864/article/details/78621633/ Visual Studio 2019:https://visu ...

  9. python画图marker显示_python画图(标记、marker、设置标记大小、marker符号大全)(图文详细入门教程五)...

    初衷 本人由于平常写论文需要输出一些结果图,但是苦于在网上搜python画图时,详细的教程非常多,但是就是找不到能马上解决自己问题那一行代码,所以打算写一些适合需求简单的朋友应急用的教程,应急就必须方 ...

最新文章

  1. Java中的对象和包
  2. Java新手如何学习Spring、Struts、Hibernate三大框架?
  3. logistics and sigmoid
  4. Winform自动更新组件分享
  5. Silverlight动态创建XAML对象和遍历对象
  6. Android ListView 实现下拉刷新上拉加载
  7. [转载] 1006- Python 字典(Dictionary) items()方法
  8. Unity3d面向英特尔® x86 平台的 Unity* 优化指南: 第 3 部分
  9. 拓端tecdat|约会数据动态可视化分析:R语言使用ggplot和ganimate制作的动画图
  10. 计算机基础知识贾辉,《计算机基础知识》读后感
  11. 牛顿三次插值 matlab,matlab 牛顿插值法 三次样条插值法[行业二类]
  12. 三个优秀的Android图表开源控件
  13. 10247: 爱好数学的国王(唯一分解定理)
  14. 递归的本质(栈:后进先出)
  15. 使用scrapy框架爬取链家网站租房信息
  16. 浅谈四轴PID调试心得
  17. 【python MySQL 笔记】MySQL 查询
  18. 童年记忆中的湾里老爷爷
  19. Menu菜单,MenuBar菜单栏,MenuItem菜单项
  20. Matlab中的插值算法

热门文章

  1. Linux VirtualBox安装及使用指南
  2. Python基础语法学习整理
  3. Spring的两种任务调度Scheduled和Async
  4. JavaScript基础之Number对象和Math对象
  5. 0623TP框架联系
  6. AP 1532E register   Cisco 2504 AP注册WLC
  7. 线程----Monitor(互斥锁)类设置超时值
  8. SQL Server 2005 高级程序设计 学习笔记(2)
  9. 在 CCR 环境中使用 Exchange 命令行管理程序移动存储组和数据库
  10. python 某个数是不是在某个范围内_教写一个简单的python小程序(04)