使用Ansible实现数据中心自动化运维管理
长久以来,IT 运维在企业内部一直是个耗人耗力的事情。随着虚拟化的大量应用、私有云、容器的不断普及,数据中心内部的压力愈发增加。传统的自动化工具,往往是面向于数据中心特定的一类对象,例如操作系统、虚拟化、网络设备的自动化运维工具往往是不同的。那么,有没有一种数据中心级别的统一的自动化运维工具呢?
答案就是Ansible。和传统的自动化工具 (如 Puppet)相比,Ansible 尤其明显的优势:
- 简单,是一种高级的脚本类语言,而非标准语言。
- 不需要安装 agent, 分为管理节点和远程被管节点通过 SSH 认证。
- 纳管范围广泛,不仅仅是操作系统,还包括各种虚拟化、公有云,甚至网络设备。
接下来,本文将针对 Ansible 这一开源 IT 自动化运维工具进行介绍,并通过实验场景让您了解 Ansible 的实际作用。
Ansible 简介
Ansible 是一个简便的 IT 自动化引擎。近期,Ansible 在Github 上是一个非常热门的开源项目,可以参见下图该项目的 Star、Fork 和 commits 数量。
图 1. Github 上 Ansible Repo
那么,Ansible 能够纳管(管理)哪些数据中心对象呢?通过查看 Ansible 的模块(Modules,后文将具体介绍)可知,它几乎支持数据中心的一切自动化,包括(不限于):
免费试用 IBM Cloud
利用 IBM Cloud Lite 快速轻松地构建您的下一个应用程序。您的免费帐户从不过期,而且您会获得 256 MB 的 Cloud Foundry 运行时内存和包含 Kubernetes 集群的 2 GB 存储空间。了解所有细节并确定如何开始。如果您不熟悉 IBM Cloud,请查阅developerWorks 上的 IBM Cloud Essentials 课程。
- 操作系统层面:从 Linux(物理机、虚拟机、云环境), Unix,到 Windows。
- 虚拟化平台:VMware、Docker、Cloudstack、LXC、Openstack 等。
- 商业化硬件:F5、ASA、Citrix、Eos 以及各种服务器设备的管理。
- 系统应用层:Apache、Zabbix、RabbitMQ、SVN、GIT 等。
- 红帽解决方案:Openshift、Ceph、GlusterFS 等,支持几乎所有红帽解决方案的一键部署和配置。
- 云平台:IBM Cloud、AWS、Azure、Cloudflare、Red Hat CloudForms、Google、Linode、Digital Ocean 等。
接下来,我们来了解一下 Ansible 的相关组件,看它如何纳管数据中心的对象。
Ansible 的组件
Ansible 的核心组件包括:Modules、Inventory、Playbook、Roles 和 Plugins。
Modules
我们在 Linux 上书写 Shell,需要调用 Linux 操作系统命令,如 ls、mv、chmod
等;在书写 POJO 时,需要调用 Java 相关 Pattern。Linux 系统命令对 Shell 而言和 Java Pattern 对于 POJO 而言,都是被调用的模块。Modules 就是使用 Ansible 进行自动化任务时调用的模块。在工作方时,Ansible 首先连接(默认通过 SSH)被管理节点(可能是服务器、公有云或、网络设备等),然后向这些节点推送 Modules、执行这些 Modules,并在完成后删除 Modules。
Modules 是 Ansible 的核心资产,有了 Modules,我们才能调用这些 Modules 来完成我们想要执行的自动化任务。举个例子:selinux - Change policy and state of SELinux。这个 Module 对的作用是配置配置 SELinux 模式和策略。我们可以通过调用这个 Module,来配置 RHEL/CentOS 的 SELinux 模式(eforcing、permissive 或 disabled)。目前社区中 Modules 数量非常多、涵盖范围非常广,并且以较快的速度进行增长。
Inventory
Inventory 是 Ansible 要管理对象的清单。在清单中,还可以配置分组信息等。举例如下:
清单 1. Inventory 示例
1
2
3
4
5
6
7
|
[webservers] www1.example.com www2.example.com [dbservers] db0.example.com db1.example.com |
如果说 Modules 是我们使用 Ansible 进行自动化任务时调用的模块。那么 Playbook 就是 Ansible 自动化任务的脚本(YAML 格式)。
Roles
Roles 是将 Playbook 分成多个文件的主要机制。这简化了编写复杂的 Playbook,并使其更易于重用。通过 Roles 可以将 Playbook 分解为可重用的组件。
Plugins
Plugins是增强 Ansible 核心功能的代码。Ansible 附带了许多方便的插件,如果这些插件不够,我们可以编写自己的插件。Ansible 自带的 Plugins 如下图所示:
图 2. Ansible Plugins
Plugins 与 Modules 一起执行 Playbook 任务所需的自动化任务的动作。当我们使用 Modules 的时候如果需要调用 Plugins,Action Plugins 默认会被自动执行。
以上文提到的 Selinux Module 举例。在书写 Playbook 是要调用 Selinux Modules,完成对 RHEL/CentOS 的 SElinux 模式的配置,这就是一个 Action。这需要 Selinux Modules 调用 Action Plugins 一起完成。
Plugins 的作用有很多,例如 Cache Plugins 的作用是实现后端缓存机制,允许 Ansible 存储收集到的 inventory 源数据。
Ansible 基本使用场景
在本章中,我们将介绍 Ansible 的基本使用场景,展示如果通过调用 Ansible Modules 执安装 HTTP 并启动 HTTP 服务。此外,我们还会介绍如何调用 Ansible Roles 来执行自动化任务。
调用 Ansible Modules 执行自动化任务
在本案例中,我们调用两个 Modules,yum 和 service,它们的作用如下:
在 Linux 系统中查看 Ansible 的版本,版本号为 2.5.3:
图 3. 查看 Ansible 版本
在 Ansible 主机上配置 Inventory。配置两个 Group:web 和 sql,分别包含一台 Linux 被管系统。
清单 2. Inventory 内容
1
2
3
4
5
|
[root@workstation-d04e ~]# cat /etc/ansible/hosts [web] servera.example.com [sql] serverb.example.com |
配置 Ansible 主机到两台被管主机之间的无密码 SSH 互信,之后,Ansible 可以与两台被管主机正常通讯:
图 4. 查看 Ansible 与被管节点之间的通讯
通过 Ansible 调用 yum Modules,为 Inventory 中的 Web Group 主机安装 httpd:
图 5. 执行 Ansible Modules
手工确认 HTTP 成功安装:
图 6. 确认 HTTP 安装成功
Ansible 调用 service Module,启动 httpd:
图 7. 执行 Ansible Modules
检查服务是否启动:
图 8. 确认 HTTP 启动成功
通过本案例,我们了解了 Modules 和 Inventory 的功能。接下来,我将展示 Roles 的功能。
调用 Ansible Galaxy Roles 执行自动化任务
Roles 可以自行书写,也可以使用Ansible Galaxy 官网上大量已经书写好的 Roles。本案例将通过书写 Playbook 调用 Roles,完成数据库的安装和配置。
登录 Ansible Galaxy 网站,搜索并挑选一个质量评分高的 mysql Roles。
图 9. 查看 mysql Roles
在 Ansible 主机上安装 mysql Roles:
图 10. 安装 Ansible mysql Roles
接下来,书写一个 Playbook,调用 mysql Role,为 Inventory 中定义的 Web 主机安装 mysql。
清单 3. 书写安装 mysql 的 Playbook
1
2
3
4
5
|
[root@workstation-d04e ansible]# cat install-database.yml - hosts: sql name: Install the database server from an Ansible Galaxy role roles: - geerlingguy.mysql |
执行 Playbook。至此,通过书写 Playbook 调用 Roles,完成了数据库的安装和配置。
图 11. 查看 Playbook 执行结果
使用 Ansible Playbook 执行自动化任务
在本小节中,我们将书写 Playbook,完成如下任务:
- 在 Web 主机上安装 Web Server(httpd 和 mod_wsgi 这两个组件)并启动它。
- 将书写好的 jinja2 配置加载到 Web Sever 中。关于 jinja2 的配置,不是本文介绍的重点。
首先创建 templates 目录,在目录中添加 httpd.conf.j2 模板:
清单 4. 创建 httpd.conf.j2 模板
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
[root@workstation-d04e ansible]# mkdir templates [root@workstation-d04e ansible]# cat httpd.conf.j2 ServerRoot "/etc/httpd" Listen 80 Include conf.modules.d/*.conf User apache Group apache ServerAdmin root@localhost < Directory /> AllowOverride none Require all denied </ Directory > DocumentRoot "/var/www/html" < Directory "/var/www"> AllowOverride None Require all granted </ Directory > < Directory "/var/www/html"> Options Indexes FollowSymLinks AllowOverride None Require all granted </ Directory > < IfModule dir_module> DirectoryIndex index.html </ IfModule > < Files ".ht*"> Require all denied </ Files > ErrorLog "logs/error_log" MaxKeepAliveRequests {{ apache_max_keep_alive_requests }} LogLevel warn < IfModule log_config_module> LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%h %l %u %t \"%r\" %>s %b" common < IfModule logio_module> LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio </ IfModule > CustomLog "logs/access_log" combined </ IfModule > < IfModule alias_module> ScriptAlias /cgi-bin/ "/var/www/cgi-bin/" </ IfModule > < Directory "/var/www/cgi-bin"> AllowOverride None Options None Require all granted </ Directory > < IfModule mime_module> TypesConfig /etc/mime.types AddType application/x-compress .Z AddType application/x-gzip .gz .tgz AddType text/html .shtml AddOutputFilter INCLUDES .shtml </ IfModule > AddDefaultCharset UTF-8 < IfModule mime_magic_module> MIMEMagicFile conf/magic </ IfModule > EnableSendfile on IncludeOptional conf.d/*.conf |
然后,在目录中添加 index.html.j2 模板:
清单 5. 创建 index.html.j2 模板
1
2
3
4
5
6
7
|
[root@workstation-d04e templates]# cat index.html.j2 {{ apache_test_message }} {{ ansible_distribution }} {{ ansible_distribution_version }} Current Host: {{ ansible_hostname }} Server list: {% for host in groups['web'] %} {{ host }} {% endfor %} |
书写 Playbook 如下:
清单 6. Playbook 内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
[root@workstation-d04e ansible]# cat site.yml --- - hosts: web name: Install the web server and start it become: yes vars: httpd_packages: - httpd - mod_wsgi apache_test_message: This is a test message apache_max_keep_alive_requests: 115 tasks: - name: Install the apache web server yum: name: "{{ item }}" state: present with_items: "{{ httpd_packages }}" notify: restart apache service - name: Generate apache's configuration file from jinga2 template template: src: templates/httpd.conf.j2 dest: /etc/httpd/conf/httpd.conf notify: restart apache service - name: Generate a basic homepage from jinga2 template template: src: templates/index.html.j2 dest: /var/www/html/index.html - name: Start the apache web server service: name: httpd state: started enabled: yes handlers: - name: restart apache service service: name: httpd state: restarted enabled: yes |
我们对 Playbook 做简单的分析:
- 第一段(3-11 行):定义了 httpd_packages 变量,并进行赋值:httpd 和 mod_wsgi。
- 第二段(13-19 行):调用 yum 模块,安装 httpd 和 mod_wsgi。
- 第三段(21-25 行)和第四段(27-30 行):根据事先定义好的模板,生成 Apache 配置文件和 Homepage。
- 第五段(32-36 行):调用 Modules service,启动 httpd。
在上面的 Playbook 中,还用到了 Handlers 语法,以在变更时运行操作。Playbooks 有一个可用于响应变化的事件系统。当任务执行结束,notify(在 Playbook 中的每个任务块结束时以事件的方式通知 Handlers,从而触发 handler 中定义的任务。)会触发名字为 restart apache service 的 Handlers。在 Ansible 中,即使多个任务都有 notify 的定义,但一个 Playbook 中,handler 只被触发一次。这个 handler 的作用是调用 Module service 重启 httpd 服务。
接下来,执行写好的 Playbook,并观察执行过程。输出如下:
清单 7. 执行 Playbook
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
[root@workstation-d04e ansible]# ansible-playbook site.yml PLAY [Install the web server and start it] ******************************************************** TASK [Gathering Facts] **************************************************************************** ok: [servera.example.com] TASK [Install the apache web server] ************************************************************** changed: [servera.example.com] => (item=[u'httpd', u'mod_wsgi']) TASK [Generate apache's configuration file from jinga2 template] ********************************** changed: [servera.example.com] TASK [Generate a basic homepage from jinga2 template] ********************************************* changed: [servera.example.com] TASK [Start the apache web server] **************************************************************** changed: [servera.example.com] RUNNING HANDLER [restart apache service] ********************************************************** changed: [servera.example.com] PLAY RECAP **************************************************************************************** servera.example.com : ok=6 changed=5 unreachable=0 failed=0 |
Playbook 执行成功以后,通过 curl 验证 Apache 的配置。
图 12. 验证 Apache 的配置
通过本章,相信您已经了解了如何通过 Modules、Roles 来执行简单的自动化任务。接下来,我们将介绍如何通过 Ansible 执行较为复杂的自动化任务。
使用 Ansible 部署三层架构应用
在自动化的场景中,我们通常会遇到较为复杂的场景,而不是简单在一个系统上部署或配置一个服务组件。接下来,我们通过 Ansible 执行一个较为复杂的自动化任务——部署一个三层应用,其中包括:一个前端(HAproxy)、两个 app 服务器(Tomcat)、一个数据库(Postgresql)。架构图如下:
图 13. 三层应用架构图
第一步,编写 Playbook
由于本案例较为复杂,为了增加 Playbook 的可读性、可重复利用性,我用三个 Roles 完成安装配置 HAproxy、Tomcat 和 Postgres,然后用一个主 Playbook 调用这个三个 Roles。
清单 8 中,我们先定义整个自动化任务的主 playbook:main.yml:
清单 8. 书写主 Playbook
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
[root@bastion 3tier-good]# cat main.yml --- # Setup front-end load balancer tier - name: setup load-balancer tier hosts: frontends become: yes roles: - {name: base-config, tags: base-config} - {name: lb-tier, tags: [lbs, haproxy]} # Setup application servers tier - name: setup app tier hosts: apps become: yes gather_facts: false roles: - {name: base-config, tags: base-config} - {name: app-tier, tags: [apps, tomcat]} # Setup database tier - name: setup database tier become: yes hosts: appdbs roles: - {name: base-config, tags: base-config} - {name: geerlingguy.postgresql, tags: [dbs, postgres]} |
接下来,书写三个 Roles。由于篇幅有限,仅以配置 load-balancer tier Roles 为例进行分析。
在 frontends group 的主机上,执行两个 Roles:base-config 和 lb-tier。我们可以查看这两个 Roles 的具体内容。先查看 base-config 的目录结构:
图 14. base-config 的目录结构
查看 tasks 下的 main.yaml:
清单 9. 查看 base-config 的 main.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
--- # Initial, common, system setup steps - name: enable sudo without tty for some ansible commands replace: path: /etc/sudoers regexp: '^Defaults\s*requiretty' replace: 'Defaults !requiretty' backup: yes - name: enable repos template: src: repos_template.j2 dest: /etc/yum.repos.d/open_three-tier-app.repo mode: 0644 #- name: setup hostname # hostname: # name: "{{ inventory_hostname }}" - name: install base tools and packages yum: name: "{{ item }}" state: latest with_items: - httpie - python-pip |
上面 Playbook 执行的操作如下:
- 替换文件内容:将 /etc/sudoers 文件中的
^Defaults\s*requiretty
替换为Defaults !requiretty
。 - enable repos:将./templates/repos_template.j2 文件拷贝到 /etc/yum.repos.d/open_three-tier-app.repo。
- 设置主机名:将主机名设置成
inventory_hostname
变量的赋值。 - 安装 HTTP 和 python-pip。
接下来,我们查看 lb-tier 的目录结构:
图 15. lb-tier 的目录结构
查看 tasks 目录下的 main.yml:
清单 10. 查看 lb-tier 的 main.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
--- - name: install {{ payload }} yum: name: "{{ payload }}" state: latest - name: enable {{ payload }} at boot service: name: "{{ payload }}" enabled: yes - name: configure haproxy to load balance over app servers template: src: haproxy.cfg.j2 dest: /etc/haproxy/haproxy.cfg mode: 0644 - name: start {{ payload }} service: name: "{{ payload }}" state: restarted |
上面的 Playbook 完成的任务:
- 安装、配置、设置开机启动一个变量
{{ payload }}
定义的服务。 - 通过将 ./templates/haproxy.cfg.j2 拷贝到 /etc/haproxy/haproxy.cfg,配置 HAproxy 以便两个 app 服务器可以实现负载均衡。
- 重启变量
{{ payload }}
定义的服务
查看./vars/main.yml
的内容,可以看到变量{{ payload }}
的赋值为 haproxy
。
清单 11. 查看 lb-tier 的环境变量
1
2
|
[root@bastion vars]# cat main.yml payload: haproxy |
所以,lb-tier Roles 执行的任务就是安装、配置、启动 HAproxy 服务。
第二步,执行 Playbook
接下来,我们执行 Playbook,首先确认相关节点可以和 Ansible 正常通信:
图 16. 确认 Ansible 与被管节点之间正常通信
接下来,执行 Playbook,由于篇幅有限我们只列出前端配置部分的关键日志:
清单 12. 执行主 Playbook
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
[root@bastion 3tier-good]# ansible-playbook -i /etc/ansible/hosts main.yml PLAY [setup load-balancer tier] ************************************************ TASK [Gathering Facts] ********************************************************* ok: [frontend1.cefe.internal] TASK [base-config : enable sudo without tty for some ansible commands] ********* ok: [frontend1.cefe.internal] TASK [base-config : enable repos] ********************************************** changed: [frontend1.cefe.internal] TASK [base-config : install base tools and packages] *************************** [DEPRECATION WARNING]: Invoking "yum" only once while using a loop via squash_actions is deprecated. Instead of using a loop to supply multiple items and specifying `name: "{{ item }}"`, please use `name: ['httpie', 'python- pip']` and remove the loop. This feature will be removed in version 2.11. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg. changed: [frontend1.cefe.internal] => (item=[u'httpie', u'python-pip']) PLAY RECAP ********************************************************************* app1.cefe.internal : ok=8 changed=7 unreachable=0 failed=0 app2.cefe.internal : ok=8 changed=7 unreachable=0 failed=0 appdb1.cefe.internal : ok=26 changed=13 unreachable=0 failed=0 frontend1.cefe.internal : ok=8 changed=6 unreachable=0 failed=0 |
可以看到任务的执行逻辑与我们前文介绍的内容是一致的。
接下来,验证部署的应用。通过RESTClient向前端发起 POST 请求,可以看到负载均衡的效果。
第一次请求,响应返回为 Tomcat app1:
图 17. 客户端发起请求
第二次请求,响应返回为 Tomcat app2:
图 18. 客户端发起请求
至此,我们实现了通过 Ansible 部署一个三层应用的工作。
结束语
通过本文,相信您对 Ansible 及其核心组件的使用有了一些了解。随着 Ansible 社区越来越受重视、 Modules 数量的迅速增加,Ansible 对整个数据中心的自动化管理能力越来越强。
使用Ansible实现数据中心自动化运维管理的更多相关文章
- 【转】使用 Ansible 实现数据中心自动化管理
长久以来,IT 运维在企业内部一直是个耗人耗力的事情.随着虚拟化的大量应用.私有云.容器的不断普及,数据中心内部的压力愈发增加.传统的自动化工具,往往是面向于数据中心特定的一类对象,例如操作系统.虚拟 ...
- 比Ansible更吊的自动化运维工具,自动化统一安装部署_自动化部署udeploy 1.0
新增功能: 2015-03-11 除pass(备份与更新)与start(启动服务)外,实现一切自动化. 注:pass与start设为业务类,由于各类业务不同,所以无法实现自动化.同类业务除外,如更新的 ...
- 比Ansible更吊的自动化运维工具,自动化统一安装部署自动化部署udeploy 1.0 版本发布
新增功能: 逻辑与业务分离,完美实现逻辑与业务分离,业务实现统一shell脚本开发,由框架统一调用. 并发多线程部署,不管多少台服务器,多少个服务,同时发起线程进行更新.部署.启动. 提高list规则 ...
- 自动化运维工具-Ansible之7-roles
自动化运维工具-Ansible之7-roles 目录 自动化运维工具-Ansible之7-roles Ansible Roles基本概述 Ansible Roles目录结构 Ansible Roles ...
- 自动化运维工具-Ansible之3-playbook
自动化运维工具-Ansible之3-playbook 目录 自动化运维工具-Ansible之3-playbook PlayBook初识 YAML语法 PlayBook部署httpd PlayBook实 ...
- 自动化运维工具-Ansible之2-ad-hoc
自动化运维工具-Ansible之2-ad-hoc 目录 自动化运维工具-Ansible之2-ad-hoc Ansible ad-hoc Ansible命令模块 Ansible软件管理模块 Ansibl ...
- python自动化运维篇
1-1 Python运维-课程简介及基础 1-2 Python运维-自动化运维脚本编写 2-1 Python自动化运维-Ansible教程-Ansible介绍 2-2 Python自动化运维-Ansi ...
- 企业级自动化运维工具应用实战-ansible
背景 公司计划在年底做一次大型市场促销活动,全面冲刺下交易额,为明年的上市做准备.公司要求各业务组对年底大促做准备,运维部要求所有业务容量进行三倍的扩容,并搭建出多套环境可以共开发和测试人员做测试,运 ...
- linux自动化运维工具Ansible saltstack Puppet、Chef、Fabric之间的对比
发现分布式是一个发展的趋势,无论是大型网站的负载均衡架构还是大数据框架部署,以及云存储计算系统搭建都离不开多台服务器的连续部署和环境搭建. 当我们的基础架构是分散式或者基于云的,并且我们经常需要处理在 ...
随机推荐
- Secondary Indices
[Secondary Indices] EOSIO has the ability to sort tables by up to 16 indices. A table's struct cann ...
- 单点登录(SSO)解决方案之 CAS 入门案例
单点登录: 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. ...
- 视频和swf的相对路径加载,卸载
package com{ import flash.display.MovieClip; import flash.net.NetConnection; import flash.net.NetStr ...
- spring整合kafka(配置文件方式 消费者)
Kafka官方文档有 https://docs.spring.io/spring-kafka/reference/htmlsingle/ 这里是配置文件实现的方式 先引入依赖 <depend ...
- sqlplus中设定行大小、页大小、字符列格式、数字列格式、清屏
sqlplus虽然是DBA们最为经常使用的Oracle客户端工具,但是它在输出结果格式化上不是很好,如折行.分页不好等,所以一般启动sqlplus后多少都要做些设置,如linesize.pagesiz ...
- 如何在chrome上打开SSL3.0
Chrome默认关闭对SSL3.0的支持,无法访问一些Web应用.可以手动打开他. 启动chrome依次选择 设置->高级->系统->打开代理设置->安全 将使用SSL 3.0 ...
- 如何通过RNA-Seq了解转录本的结构
[转载]如何通过RNA-Seq了解转录本的结构 已有 1942 次阅读 2014-12-26 15:22 |个人分类:转录组测序|系统分类:科研笔记|关键词:RNA-Seq,转录组测序,转录本结构| ...
- js原生的节点操作API
// yi获取元素节点 //一 :过id的方式( 通过id查找元素,大小写敏感,如果有多个id只找到第一个) document.getElementById('div1'); // 通过类名查找元素, ...
- nc 画界面,触发效果(第一种)
package nc.ui.hzctr.sellctr.action; import java.awt.BorderLayout; import java.awt.Dimension; import ...
- error while loading shared libraries的解決方法
我是在启动nginx的时候报这个错误,搜索这个错误时发现这篇文章,非本人(小渡博客)原创. 原文地址:http://blog.csdn.net/dumeifang/article/details/29 ...