zoukankan      html  css  js  c++  java
  • ansible的基本使用

    Ansible是一个非常灵活的自动化管理工具。通过Ansible可以实现批量程序部署和命令执行等操作。Ansible是无客户端的,通过OpenSSH协议来管理远程终端。本节将会介绍Ansible的Ad-Hoc模式下常用模块的使用。

    Ansible相关知识扩展内容参考自官方文档:

    # Asible官方文档https://docs.ansible.com/ansible/latest/index.html

    本节内容都是在远程服务器sandboxMP(172.16.3.100)中完成,请使用CRT工具连接到sandboxMP(172.16.3.100)。同时需要开启server1server2虚拟机。

    1 Ansible的基本使用

    1.1 安装Ansible

    1、使用yum安装:RHELCentOS系统可以直接通过yum进行安装

    [root@sandboxmp ~]$ yum install ansible

    也可以从github上下载指定版本进行安装。

    2、使用pip安装

    登陆远程主机sandboxMP(172.16.3.100),进入python虚拟环境,使用pip安装ansible

    [root@sandboxmp ~]$ workon sandboxMP

    (sandboxMP) [root@sandboxmp ~]$ pip install ansible

    在项目中采用第二种方法pip安装,注意由于ansible是安装在虚拟环境中,所以当运行ansible命令时需要指定虚拟环境中的路径,或者是进入虚拟环境后执行ansible命令。

    1.2 Ansible的配置文件

    使用yum安装的Ansible,系统会自动创建默认配置文件:

    /etc/ansible/

            |---- ansible.cfg # 默认配置文件

            |---- hosts # ansible默认管理的主机清单

    项目中使用pip工具安装Ansible,系统中没有创建配置文件,先来创建一个空的配置文件:

    (sandboxMP) [root@sandboxmp ~]$ mkdir /etc/ansible

    (sandboxMP) [root@sandboxmp ~]$ touch /etc/ansible/ansible.cfg

    Asible提供了一个配置文件示例,其中列出了大部分配置内容,你可以直接使用这个配置文件

    https://raw.githubusercontent.com/ansible/ansible/devel/examples/ansible.cfg

    查看ansible版本信息,其中会列出当前使用的配置文件路径:

    (sandboxMP) [root@sandboxmp ~]$ ansible --version

     

    ansible 2.7.6

      config file = /etc/ansible/ansible.cfg # ansible默认读取配置文件路径

      configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']

      ansible python module location = /root/.virtualenvs/sandboxMP/lib/python3.6/site-packages/ansible

      executable location = /root/.virtualenvs/sandboxMP/bin/ansible

      python version = 3.6.6 (default, Nov 26 2018, 20:00:58) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)]

    Ansible会从下面列表中自上而下查找,使用找到的第一个文件作为配置文件。:

    • ANSIBLE_CONFIG (从环境变量中读取配置文件)
    • ansible.cfg (当前目录中的配置文件)
    • ~/.ansible.cfg (主目录中的配置文件)
    • /etc/ansible/ansible.cfg (/etc/ansible/目录下的配置文件)

    1.3 Ansible常用配置项

    Ansible提供了很多配置选项,我们可以在配置文件中设置这些配置选项,也可以使用环境变量来定义配置项内容。

    # Asible配置项官方文档:

    https://docs.ansible.com/ansible/latest/reference_appendices/config.html

    常用配置项:

    • inventory:指定ansible连接的主机清单,默认/root/ansible/hosts
    • forksAnsible可以同时启用的进程数量,默认是5个;
    • remote_user:远程连接用户,默认root
    • sudo_user:默认执行命令的用户,默认root
    • remote_port:远程连接使用的端口,默认22
    • private_key_fileSSH使用密钥认证时,指定的密钥路径;
    • host_key_checking:设置是否检查SSH主机密钥,设置为False可以跳过SSH首次登陆时的验证;
    • log_path:日志文件路径,Ansible默认不记录日志。

    设置配置文件内容:

    (sandboxMP) [root@sandboxmp ~]$ vim /etc/ansible/ansible.cfg# 在配置文件中添加下面内容,保存退出vim

    [defaults]

    inventory = /etc/ansible/hosts

    sudo_user=root

    remote_port=22

    host_key_checking=False

    remote_user=root

    deprecation_warnings=False

    1.4 Ansible基本使用

    Ansible是通过OpenSSH协议和远程主机进行通信,默认使用的是密钥认证,在第8节已经完成密钥认证的相关配置。

    (sandboxMP) [root@sandboxmp ~]$ vim /etc/ansible/hosts

    # 将主机清单添加到hosts文件,保存退出vim172.16.3.101172.16.3.102

    ping hosts里面的所有主机:

    (sandboxMP) [root@sandboxmp ~]$ ansible all -m ping# 以下为命令输出信息

    172.16.3.101 | SUCCESS => {

        "changed": false,

        "ping": "pong"

    }

    172.16.3.102 | SUCCESS => {

        "changed": false,

        "ping": "pong"

    }

    hosts中所有节点上执行hostname命令,获取节点主机名:

    (sandboxMP) [root@sandboxmp ~]$ ansible all -a "/usr/bin/hostname"172.16.3.102 | CHANGED | rc=0 >>

    server2

    172.16.3.101 | CHANGED | rc=0 >>

    server1

    Ansible还提供了很多Ad-Hoc命令,可以用来快速执行某些操作。

    2 Ansible主机清单

    1.4中已经演示了主机清单(hosts)主机清单的使用,Asible通过主机清单可以同时操作多个系统。hosts配置文件支持多种格式,例如YAMLini,配置非常灵活。

    2.1 配置主机组

    在主机清单文件中可以通过[]来定义主机组,修改/etc/ansible/hosts

    (sandboxMP) [root@sandboxmp ~]# vim /etc/ansible/hosts

    # hosts文件内容,编辑保存退出vim

    [webserver]

    example.com

    server[1:2].com

    [sandboxmp]172.16.3.100:22 ansible_ssh_user=root ansible_ssh_pass='1234@abcd.com'

    [server]172.16.3.101:22 ansible_ssh_user=root ansible_private_key_file='/root/.ssh/id_rsa'172.16.3.102

     

    主机清单配置说明:

    • 定义了三个主机组:webserversandboxmp server
    • 主机组webserver 中主机列表使用的是主机名称(ansible主机需要能够解析主机名);
    • server[1:2].com:针对遵循一定规则的主机名,可以使用正则匹配;
    • 给主机172.16.3.100配置了ssh端口,认证用户和密码;
    • 给主机172.16.3.101配置了ssh端口,认证用户和密钥;

    注意:在主机清单hosts中配置的认证信息会覆盖ansible.cfg配置文件中的默认内容。

    查看主机组中包含的主机列表:

    (sandboxMP) [root@sandboxmp ~]$ ansible webserver --list

      hosts (3):

        example.com

        server1.com

        server2.com

    (sandboxMP) [root@sandboxmp ~]$ ansible sandboxmp --list

      hosts (1):

        172.16.3.100

    (sandboxMP) [root@sandboxmp ~]$ ansible server --list

      hosts (2):

        172.16.3.101

        172.16.3.102

    结果显示:sandboxmp主机组中包含一台主机,server主机组中包含了两台主机。

    2.2 设置主机变量

    主机清单中可以使用IP和域名之外,还可以定义主机变量:

    (sandboxMP) [root@sandboxmp ~]$ vim /etc/ansible/hosts

    [nginx]

    ng_m ansible_ssh_host=172.16.2.10 ansible_ssh_port=22

    ng_s ansible_ssh_host=172.16.2.11 ansible_ssh_port=22

    完成配置后就可使用别名来操作主机了。

    2.3 使用主机组作为组成员

    在配置主机清单文件时,使用:children可以将多个主机组作为另外一个主机组成员:

    (sandboxMP) [root@sandboxmp ~]$ vim /etc/ansible/hosts'''hosts前面内容省略'''

    [webserver]

    example.com

    server[1:2].com

    [sandboxmp]172.16.3.100:22 ansible_ssh_user=root ansible_ssh_pass='leadsec@7766'

    [server]172.16.3.101:22 ansible_ssh_user=root ansible_private_key_file='/root/.ssh/id_rsa'172.16.3.102

     

    [app:children]

    webserver

    sandboxmp

    查看app主机组的主机列表:

    (sandboxMP) [root@sandboxmp ~]$ ansible app --list

      hosts (4):

        example.com

        server1.com

        server2.com

        172.16.3.100

    新定义的app主机组,使用了webserversandboxmp两个主机组作为组成员,app主机列表中包含以上两个主机组中所有主机。

    2.4 在主机组中定义变量

    使用:vars可以很方便在主机组中定义变量信息:

    (sandboxMP) [root@sandboxmp ~]$ vim /etc/ansible/hosts'''hosts前面内容省略'''

    [app:vars]

    file_name=test

    timeout=30

    注意:在定义变量的时候,[app:vars]中的app是必须在前面已经定义的主机组。

    3 Ad-Hoc命令的使用

    通过使用Ad-Hoc命令可以简单、快速的对主机系统进行临时操作。
    语法结构:ansible <host-pattern> [options]

    3.1 Ad-Hoc选项

    在使用Ansible Ad-Hoc命令时有很多选项可以使用,使用--help可以查看帮助:

    (sandboxMP) [root@sandboxmp ~]$ ansible --help

    Usage: ansible <host-pattern> [options]

     

    Define and run a single task 'playbook' against a set of hosts

     

    Options:

      -a MODULE_ARGS, --args=MODULE_ARGS

                            module arguments

      --ask-vault-pass      ask for vault password

      -B SECONDS, --background=SECONDS

                            run asynchronously, failing after X seconds

                            (default=N/A)

      -C, --check           don't make any changes; instead, try to predict some

                            of the changes that may occur

      -D, --diff            when changing (small) files and templates, show the

                            differences in those files; works great with --check

      -e EXTRA_VARS, --extra-vars=EXTRA_VARS

                            set additional variables as key=value or YAML/JSON, if

                            filename prepend with @

    ...后面内容省略...

    常用选项说明:

     

    分类

    选项

    描述

        基本选项

    -a MODULE_ARGS, --args=MODULE_ARGS

    为模块提供参数

    -B SECONDS, --background=SECONDS

    将命令放到后台执行,超过时间后强行终止命令

    -f FORKS, --forks=FORKS

    设置并发进程数

    -h, --help

    查看帮助文件

    -i INVENTORY, --inventory=INVENTORY

    设置inventory配置,默认/etc/ansible/hosts

    -l SUBSET, --limit=SUBSET

    指定运行主机,支持正则匹配,可以过滤运行主机

    --list-hosts

    列出主机列表

    -m MODULE_NAME, --module-name=MODULE_NAME

    指定运行的模块

    -o, --one-line

    结果标准输出至一行内容

    -v, --verbose

    输出详细的执行过程信息,使用-vvv会输出更详细的信息

    --version

    查看版本信息

         连接选项

    -k, --ask-pass

    使用认证密码

    --private-key

    指定密钥文件

    -u REMOTE_USER, --user=REMOTE_USER

    指定用户,默认root

     

    在上面表格中整理了一些常用的选项,其中有一部分已经使用到了,其他选项会在项目中使用时再介绍。更多选项内容可以查阅官方文档:

    https://docs.ansible.com/ansible/latest/cli/ansible.html

    3.2 常用模块

    (sandboxMP) [root@sandboxmp ~]$ ansible server -m ping

    172.16.3.102 | SUCCESS =>

        "changed": false,

        "ping": "pong"

    }

    172.16.3.101 | SUCCESS => {

        "changed": false,

        "ping": "pong"

    }

    3.2.1 Command

    Ad-Hoc常用选项中介绍到 -m 用来指定运行的模块,没有指定模块 时,默认使用的是command模块。

    使用command模块可以在远程主机上执行命令:

    (sandboxMP) [root@sandboxmp ~]$ ansible server -a "tail -n2 /etc/passwd" 

    172.16.3.101 | CHANGED | rc=0 >>

    systemd-network:x:997:995:systemd Network Management:/:/sbin/nologin

    tcpdump:x:72:72::/:/sbin/nologin

     

    172.16.3.102 | CHANGED | rc=0 >>

    systemd-bus-proxy:x:998:996:systemd Bus Proxy:/:/sbin/nologin

    systemd-network:x:997:995:systemd Network Management:/:/sbin/nologin

    命令说明:

    • -a:在常用选贡中介绍到,该选项用来为模块提供参数,这里为command模块提供一条命令参数;
    • tail -n2 /etc/passwd:在远程主机上执行的命令,读取passwd文件前两行;
    • server:主机清单hosts上配置的主机组,包含172.16.3.101172.16.3.102

    3.2.2 Shell

    用来在远程主机上执行命令:

    (sandboxMP) [root@sandboxmp ~]$ ansible server -m shell -a "cat /etc/passwd |grep 'root' "172.16.3.102 | CHANGED | rc=0 >>root:x:0:0:root:/root:/bin/bashoperator:x:11:0:operator:/root:/sbin/nologin

    172.16.3.101 | CHANGED | rc=0 >>root:x:0:0:root:/root:/bin/bashoperator:x:11:0:operator:/root:/sbin/nologin

    命令说明:使用-m 选项指定使用shell模块。在server组主机上执行命令,读取用户文件内容,通过管道符进行过滤,标准输出包含root的内容。

    command 和 shell 模块都可以在远程主机上执行命令,但是command不支持变量和管道符操作,所以当需要使用到变量和管道符时需要使用shell模块。

    3.2.3 File Transfer

    1copy:文件传输模块,可以将文件并行拷贝到多台主机上。

    (sandboxMP) [root@sandboxmp ~]$ touch file_test.txt

    (sandboxMP) [root@sandboxmp ~]$ echo "ansible copy" > file_test.txt

    (sandboxMP) [root@sandboxmp ~]$ ansible server -m copy -a "src=/root/file_test.txt dest=/tmp/file_test.txt"

     172.16.3.101 | CHANGED => {

        "changed": true,

        "checksum": "8704b357e5e3f6599308184503507e769d866973",

        "dest": "/tmp/file_test.txt",

        "gid": 0,

        "group": "root",

        "md5sum": "bb0c6b81366f77241b3326f90f40bf02",

        "mode": "0644",

        "owner": "root",

        "size": 13,

        "src": "/root/.ansible/tmp/ansible-tmp-1547913223.3838925-223379897804727/source",

        "state": "file",

        "uid": 0

    }

    172.16.3.102 | CHANGED => {

        "changed": true,

        "checksum": "8704b357e5e3f6599308184503507e769d866973",

        "dest": "/tmp/file_test.txt",

        "gid": 0,

        "group": "root",

        "md5sum": "bb0c6b81366f77241b3326f90f40bf02",

        "mode": "0644",

        "owner": "root",

        "size": 13,

        "src": "/root/.ansible/tmp/ansible-tmp-1547913223.3942144-24604233894846/source",

        "state": "file",

        "uid": 0

    }

    命令执行说明:

    • 创建一个测试文件;
    • 向测试文件中写入内容;
    • 执行远程拷贝,将测试文件拷贝到server主机组。

    copy模块参数说明: 
    使用copy模块传输文件时,可以通过参数设置文件属主、属组和权限,例如:

    ansible server -m copy -a "src=/root/file_test.txt dest=/tmp/ owner=root group=root mode=600"

    使用CRT登陆远程主机server1(172.16.3.101)server2(172.16.3.102),查看文件:

    [root@server1 ~]$ ls /tmp/file_test.txt 

    /tmp/file_test.txt

    [root@server1 ~]$ cat /tmp/file_test.txt 

    ansible copy

    2file:设置文件属性 

    使用file模块可以创建文件和更改文件的所有和权限:

    (sandboxMP) [root@sandboxmp ~]$ ansible server -m file -a "dest=/tmp/file_test.txt mode=666" -l 172.16.3.101   

    172.16.3.101 | CHANGED => {

        "changed": true,

        "gid": 0,

        "group": "root",

        "mode": "0666",

        "owner": "root",

        "path": "/tmp/file_test.txt",

        "size": 13,

        "state": "file",

        "uid": 0

    }

     

    命令执行说明:

    • 修改远程文件权限为:666
    • -l 指定运行目标主机(过滤),从server主机组中找出满足过滤条件的主机来执行远程操作。

    使用file模块创建目录:

    (sandboxMP) [root@sandboxmp ~]$ ansible server -m file -a "dest=/tmp/dir_test owner=root state=directory"

    172.16.3.102 | CHANGED => {

        "changed": true,

        "gid": 0,

        "group": "root",

        "mode": "0755",

        "owner": "root",

        "path": "/tmp/dir_test",

        "size": 6,

        "state": "directory",

        "uid": 0

    }'''省略'''

    使用file模块删除文件:

    (sandboxMP) [root@sandboxmp ~]$ ansible server -m file -a "dest=/tmp/file_test.txt state=absent"

    172.16.3.102 | CHANGED => {

        "changed": true,

        "path": "/tmp/file_test.txt",

        "state": "absent"

    }'''省略'''

    3.2.4 Managing Packages

    Ansible 提供了yumapt模块,通过这些模块可以很方便在系统上安装软件包。

    项目中使用的是Centos系统,所以可以使用yum模块来安装软件包:

    (sandboxMP) [root@sandboxmp ~]$ ansible server -m yum -a "name=tcpdump state=latest"   

    172.16.3.102 | SUCCESS => {

        "ansible_facts": {

            "pkg_mgr": "yum"

        },

        "changed": false,

        "msg": "",

        "obsoletes": {

            "NetworkManager": {

                "dist": "x86_64",

                "repo": "@updates",

                "version": "1:1.0.6-31.el7_2"

            },

            "grub2": {

                "dist": "x86_64",

                "repo": "@updates",

                "version": "1:2.02-0.34.el7.centos"

            },

            "grub2-tools": {

                "dist": "x86_64",

                "repo": "@updates",

                "version": "1:2.02-0.34.el7.centos"

            },

            "pygobject3-base": {

                "dist": "x86_64",

                "repo": "@base",

                "version": "3.14.0-3.el7"

            },

            "rdma": {

                "dist": "noarch",

                "repo": "@updates",

                "version": "7.2_4.1_rc6-2.el7"

            }

        },

        "rc": 0,

        "results": [

            "All packages providing tcpdump are up to date",

            ""

        ]

    }'''省略'''

    命令执行说明:

    • 使用yum模块来安装软件包;
    • name:用来指定安装的软件包名称;
    • state:指定安装的动作(presentinstalledlatestabsentremoved

    3.2.5 Managing Services

    Ansible 还提供了服务管理模块service,可以用来管理系统服务。

    (sandboxMP) [root@sandboxmp ~]$ ansible server -m service -a "name=iptables state=restarted"  

    172.16.3.102 | CHANGED => {

        "changed": true,

        "name": "iptables",

        "state": "started",

        "status": {

            "ActiveEnterTimestamp": "Sun 2018-12-02 12:50:45 CST",

            "ActiveEnterTimestampMonotonic": "5413824",

            "ActiveExitTimestamp": "Sun 2019-01-20 21:26:42 CST",

            "ActiveExitTimestampMonotonic": "4264562592868",

            "ActiveState": "inactive",

            "After": "systemd-journald.socket system.slice syslog.target basic.target",'''省略'''

    命令执行说明:

    • service:用来管理系统服务;
    • name:指定需要管理的服务;
    • state:指定服务动作(started, restarted, stoped

    Ansible 提供了非常多的实用模块,在Ad-Hoc模式下使用这些模块,可以快速帮助我们实现一些管理操作。

    本节内容只介绍一些常用模块的使用,让你对Asible模块有一个基本了解,其他模块会在项目中使用到时再做介绍,结合项目去使用才是最有效的学习方式。

    3.2.6 setup

    使用setup模块可以获取系统信息,包含:ip、系统类型、CPU、内存、硬盘、服务器型号等信息。

    (sandboxMP) [root@sandboxmp ~]$ ansible 172.16.3.101 -m setup            

    172.16.3.101 | SUCCESS => {

        "ansible_facts": {

            "ansible_all_ipv4_addresses": [

                "172.16.3.101"

            ],

            "ansible_all_ipv6_addresses": [

                "fe80::20c:29ff:fe03:cc4b"

            ],

            "ansible_apparmor": {

                "status": "disabled"

            },

            "ansible_architecture": "x86_64",

            "ansible_bios_date": "07/02/2015",

            "ansible_bios_version": "6.00",

            "ansible_cmdline": {

                "BOOT_IMAGE": "/vmlinuz-3.10.0-862.2.3.el7.x86_64",

                "LANG": "en_US.UTF-8",

                "biosdevname": "0",

                "crashkernel": "autorhgb",

                "net.ifnames": "0",

                "quiet": true,

                "ro": true,

                "root": "UUID=edfb65f0-fe51-4278-a25a-9d7acc50f384"

            },'''后面内容省略'''

    使用setup模块会列出非常多的系统相关信息,可以使用filter来过滤我们需要的数据信息:

    (sandboxMP) [root@sandboxmp ~]$ ansible 172.16.3.101 -m setup -a "filter=ansible_distribution"            

    172.16.3.101 | SUCCESS => {

        "ansible_facts": {

            "ansible_distribution": "CentOS"

        },

        "changed": false

    }

    其他一些常用的系统信息变量:

    参数变量

    描述

    ansible_all_ipv4_addresses

    仅显示ipv4的信息

    ansible_devices

    仅显示磁盘设备信息

    ansible_distribution

    显示是什么系统,例:centos

    ansible_distribution_major_version

    显示是系统主版本

    ansible_distribution_version

    仅显示系统版本

    ansible_machine

    显示系统类型,32位,还是64位

    ansible_eth0

    仅显示eth0的信息

    ansible_hostname

    仅显示主机名

    ansible_kernel

    仅显示内核版本

    ansible_lvm

    显示lvm相关信息

    ansible_memtotal_mb

    显示系统总内存

    ansible_memfree_mb

    显示可用系统内存

    ansible_memory_mb

    详细显示内存情况

    ansible_swaptotal_mb

    显示总的swap内存

    ansible_swapfree_mb

    显示swap内存的可用内存

    ansible_mounts

    显示系统磁盘挂载情况

    ansible_processor

    显示cpu个数(具体显示每个cpu的型号)

    ansible_processor_vcpus

    显示cpu个数(只显示总的个数)

    ansible_python_version

    显示python版本

    以上列出的就是一些常用的系统信息变量参数,如果记不住,在过滤的时候也可以使用通配符:

    # 所限说有ipv4相关信息

    (sandboxMP) [root@sandboxmp ~]$ ansible 172.16.3.101 -m setup -a "filter=*ipv4*"   

    4 ansible-doc

    Ansible还提供了一些非常实用的命令行工具,例如:ansible-doc 可以用来查看一些帮助信息。

    1、列出所有模块:

    ansible-doc -l

    (sandboxMP) [root@sandboxmp ~]$ ansible-doc -l

    a10_server          Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' server object.                                                                     

    a10_server_axapi3   Manage A10 Networks AX/SoftAX/Thunder/vThunder devices                                                                                     

    a10_service_group   Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' service groups.                                                                   

    a10_virtual_server  Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' virtual servers.                                                                   

    aci_aaa_user        Manage AAA users (aaa:User)

    2、查看指定模块的用法

    ansible-doc -s [模块名称]

    (sandboxMP) [root@sandboxmp ~]$ ansible-doc -s copy

    - name: Copies files to remote locations

      copy:

          attributes:            # Attributes the file or directory should have. To get supported flags look at the man page for `chattr' on the target system. This string should contain the

                                   attributes in the same order as the one displayed by `lsattr'. `=' operator is assumed as default, otherwise `+' or `-' operators need

                                   to be included in the string.

          backup:                # Create a backup file including the timestamp information so you can get the original file back if you somehow clobbered it incorrectly.

          checksum:              # SHA1 checksum of the file being transferred. Used to validate that the copy of the file was successful. If this is not provided, ansible will use the local

                                   calculated checksum of the src file.

          content:               # When used instead of `src', sets the contents of a file directly to the specified value. For anything advanced or with formatting also look at the template module.

          decrypt:               # This option controls the autodecryption of source files using vault.

          dest:                  # (required) Remote absolute path where the file should be copied to. If `src' is a directory, this must be a directory too. If `dest' is a nonexistent path and if

                                   either `dest' ends with "/" or `src' is a directory, `dest' is created. If `src' and `dest' are files, the parent directory of `dest'

       '''省略'''

    作者:james

    -------------------------------------------

    个性签名:独学而无友,则孤陋而寡闻。做一个灵魂有趣的人!

    如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!

  • 相关阅读:
    洛谷P2466 [SDOI2008]Sue的小球 题解 区间DP+费用提前计算
    中国国家集训队论文集目录(1999-2008)
    洛谷P1726 上白泽慧音 题解 强连通分量
    洛谷P1410 子序列 题解 动态规划
    树堆(Treap)学习笔记 2020.8.12
    伸展树(Splay)学习笔记
    git操作
    yii 缓存探究
    yii之srbac详解
    一个PDO类
  • 原文地址:https://www.cnblogs.com/jameslove/p/10926749.html
Copyright © 2011-2022 走看看