zoukankan      html  css  js  c++  java
  • Ansible

    首先我们安装一个ansible。

    在7版本,直接用yum安装就可以

    yum -y install ansible

    然后清空ansible的配置文件,在里面写入自己需要管理的服务器的ip和相应的登陆密码

    [root@localhost ~]# cat /etc/ansi
    [root@localhost ~]# cat /etc/ansible/hosts 
    [test]
    web1 ansible_ssh_host=192.168.200.131 ansible_ssh_pass=mima 
    web2 ansible_ssh_host=192.168.200.133 ansible_ssh_pass=mima
    [root@localhost ~]# 

    ansible的批量运行的脚本

     

    [root@localhost scripts]# pwd
    /server/scripts
    [root@localhost scripts]# vim auto_nginx.sh


    #!/bin/bash dir=/media/cdrom anzhuang=/server/scripts [ -d $dir ] || mkdir -p $dir umount /dev/sr0 mount /dev/sr0 $dir &>/dev/null yum -y install gcc gcc-c++ make pcre pcre-devel zlib zlib-devel openssl openssl-devel &>/dev/null [ -d $anzhuang ] || mkdir -p $anzhuang cd /server/scripts/ tar xf nginx-1.10.2.tar.gz -C /usr/src/ cd /usr/src/nginx-1.10.2/ ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module &>/dev/null make &>/dev/null make install &>/dev/null
    exit 0
     

    写分发脚本

     
    [root@localhost scripts]# vim fenfa.sh

    #!/bin/bash
    Group=$1
    dir=/server/scripts/

    ansible $Group -m shell -a "mkdir -p $dir"
    ansible $Group -m copy -a "src=$dir dest=$dir"
    ansible $Group -m script -a "/server/scripts/auto_nginx.sh"

    然后激活脚本

    [root@localhost scripts]# sh fenfa.sh all 

     

    如果copy报错一下的语句

      "msg": "Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!"

    需要在备分发的服务器上安装支持包

    [root@www ~]# mount /dev/sr0 /media/cdrom/
    mount: block device /dev/sr0 is write-protected, mounting read-only
    [root@www ~]# yum -y install libselinux-python

    ansible的剧本playbook

     
    [root@ansible scripts]# cat test_shell.yaml  #playbook的执行模板
    ---         #开头三个小-开头
    - hosts: webB   
      tasks:        
      - name: test
        shell: echo "welcome to yunjisaun" >> /tmp/username
      - name: test2
        shell: echo "welcome to yunjisuan" >> /tmp/username
    模板说明:
    ---  #开头必须有三个小-,顶格写
    - hosts:   #正文配置代码的第一级,必须有两个空格(-占一个空格位)
    - host: webB   #webB是host参数的值,值和hosts:之间要有一个空格
      tasks:        #tasks:表示接下来要执行的具体任务
      - name:     #相对于tasks再多缩进两个格(-占一个空格位),表示属于tasks的下一级
      - name: test  #test只是要执行的具体命令的名字可以随便写。name:后还是有一个空格要注意
        shell:  #表示调用shell模块执行命令相对于tasks仍旧要多缩进两个空格
        shell: echo "xxx" >> xxx     #shell:后边还是要有个空格,需要注意。
     

    执行剧本

     
    [root@ansible scripts]# ansible-playbook test_shell.yaml #执行playbook配置文件
    PLAY [webB] ********************************************************************************************************
    TASK [Gathering Facts] *********************************************************************************************
    ok: [webB]
    TASK [test] ********************************************************************************************************
    changed: [webB]
    TASK [test2] *******************************************************************************************************
    changed: [webB]
    PLAY RECAP *********************************************************************************************************
    webB                       : ok=3    changed=2    unreachable=0    failed=0 
     

    简单的copy剧本

     
    [root@ansible scripts]# echo "welcom to yunjisuan" >> /tmp/test_copy
    [root@ansible scripts]# cat test_copy.yaml 
    ---
    - hosts: all
      tasks:
      - name: test copy
        copy: src=/tmp/copy_test dest=/tmp/
    [root@ansible scripts]# ansible-playbook /service/scripts/test_copy.yaml 
    PLAY [all] *********************************************************************************************************
    TASK [Gathering Facts] *********************************************************************************************
    ok: [webA]
    ok: [webB]
    TASK [test copy] ***************************************************************************************************
    changed: [webA]
    changed: [webB]
    PLAY RECAP *********************************************************************************************************
    webA                       : ok=2    changed=1    unreachable=0    failed=0   
    webB                       : ok=2    changed=1    unreachable=0    failed=0   
     

    剧本的查看输出的过程

    我们在用playbook进行ansible模块操作的时候,并没有命令的执行结果输出,默认被隐藏了。 
    我们可以通过register模块最加输出命令的执行结果

     
    [root@ansible scripts]# cat test_register.yaml 
    ---
    - hosts: all
      tasks:
      - name: test register
        shell: echo "welcome to yunjisuan"
        register: print_result          #将之前命令的输出结果保存在变量print_result里
      - debug: var=print_result         #将变量的值作为debug输出出来。
    [root@ansible scripts]# ansible-playbook test_register.yaml 
    PLAY [all] *********************************************************************************************************
    TASK [Gathering Facts] *********************************************************************************************
    ok: [webA]
    ok: [webB]
    TASK [test register] ***********************************************************************************************
    changed: [webA]
    changed: [webB]
    TASK [debug] *******************************************************************************************************
    ok: [webA] => {                                             #命令的执行结果有输出了
        "print_result": {
            "changed": true,
            "cmd": "echo "welcome to yunjisuan"",
            "delta": "0:00:00.002269",
            "end": "2018-06-15 10:28:14.693883",
            "failed": false,
            "rc": 0,
            "start": "2018-06-15 10:28:14.691614",
            "stderr": "",
            "stderr_lines": [],
            "stdout": "welcome to yunjisuan",
            "stdout_lines": [
                "welcome to yunjisuan"
            ]
        }
    }
    ok: [webB] => {
        "print_result": {
            "changed": true,
            "cmd": "echo "welcome to yunjisuan"",
            "delta": "0:00:00.002633",
            "end": "2018-06-15 10:28:14.710242",
            "failed": false,
            "rc": 0,
            "start": "2018-06-15 10:28:14.707609",
            "stderr": "",
            "stderr_lines": [],
            "stdout": "welcome to yunjisuan",
            "stdout_lines": [
                "welcome to yunjisuan"
            ]
        }
    }
    PLAY RECAP *********************************************************************************************************
    webA                       : ok=3    changed=1    unreachable=0    failed=0   
    webB                       : ok=3    changed=1    unreachable=0    failed=0   
     

    配置文件下发的简单剧本

     
    [root@ansible scripts]# cat test_nginx_conf.yaml 
    ---
    - hosts: all
      tasks:
      - name: copy nginx.conf
        copy: src=/tmp/nginx.conf dest=/usr/local/nginx/conf/ backup=yes
      - name:
        shell: /usr/local/nginx/sbin/nginx -t
        register: nginx_result
      - debug: var=nginx_result
     

    在剧本中使用自定义变量

     
    [root@localhost scripts]# cat test_vars.yaml 
    ---
    - hosts: all
      vars:         #定义变量
      - name: "yunjisuan"   #第一个name变量
        age: "3"            #第二个age变量
      tasks:
      - name: "{{ name }}"      #{{}}两对大括号引用变量,变量名两头空格
        shell: echo "myname {{ name }},myage {{ age }}"
        register: var_result
      - debug: var=var_result
    特别提示:
    引用变量需要在双引号中引用。
    [root@localhost scripts]# ansible-playbook /service/scripts/test_vars.yaml 
     [WARNING]: Found variable using reserved name: name        #这里提示,name是一个保留的内置变量,我们在自定义时不能用
    PLAY [all] *********************************************************************************************************
    TASK [Gathering Facts] *********************************************************************************************
    ok: [webA]
    ok: [webB]
    TASK [yunjisuan] ***************************************************************************************************
    changed: [webA]
    changed: [webB]
    TASK [debug] *******************************************************************************************************
    ok: [webA] => {
        "var_result": {
            "changed": true,
            "cmd": "echo "myname yunjisuan,myage 3"",
            "delta": "0:00:00.002320",
            "end": "2018-06-19 10:45:16.175728",
            "failed": false,
            "rc": 0,
            "start": "2018-06-19 10:45:16.173408",
            "stderr": "",
            "stderr_lines": [],
            "stdout": "myname yunjisuan,myage 3",
            "stdout_lines": [
                "myname yunjisuan,myage 3"
            ]
        }
    }
    ok: [webB] => {
        "var_result": {
            "changed": true,
            "cmd": "echo "myname yunjisuan,myage 3"",
            "delta": "0:00:00.002518",
            "end": "2018-06-19 10:45:10.552331",
            "failed": false,
            "rc": 0,
            "start": "2018-06-19 10:45:10.549813",
            "stderr": "",
            "stderr_lines": [],
            "stdout": "myname yunjisuan,myage 3",
            "stdout_lines": [
                "myname yunjisuan,myage 3"
            ]
        }
    }
    PLAY RECAP *********************************************************************************************************
    webA                       : ok=3    changed=1    unreachable=0    failed=0   
    webB                       : ok=3    changed=1    unreachable=0    failed=0   
    #我们修改一下name这个变量再发送,就不会出警告了
    [root@localhost scripts]# cat test_vars.yaml 
    ---
    - hosts: all
      vars:
      - names: "yunjisuan"
        age: "3"
      tasks:
      - name: "{{ names }}"
        shell: echo "myname {{ names }},myage {{ age }}"
        register: var_result
      - debug: var=var_result
    在使用自定义变量时,要特别注意不要和系统的内置保留变量同名,容易引发问题。
     

    使用内置的变量

    我们可以使用ansible all -m setup | less查看ansible内置变量
     
    [root@localhost scripts]# cat test_setupvars.yaml 
    ---
    - hosts: all
      gather_facts: True    #使用ansible内置变量
      tasks:
      - name: setup var
        shell: echo "ip {{ ansible_all_ipv4_addresses[0] }} cpu {{ ansible_processor_count }}"
        register: var_result
      - debug: var=var_result
    [root@localhost scripts]# 
    [root@localhost scripts]# ansible-playbook test_setupvars.yaml 
    PLAY [all] *********************************************************************************************************
    TASK [Gathering Facts] *********************************************************************************************
    ok: [webA]
    ok: [webB]
    TASK [setup var] ***************************************************************************************************
    changed: [webA]
    changed: [webB]
    TASK [debug] *******************************************************************************************************
    ok: [webA] => {
        "var_result": {
            "changed": true,
            "cmd": "echo "ip 192.168.200.132 cpu 1"",
            "delta": "0:00:00.002408",
            "end": "2018-06-19 11:32:44.540658",
            "failed": false,
            "rc": 0,
            "start": "2018-06-19 11:32:44.538250",
            "stderr": "",
            "stderr_lines": [],
            "stdout": "ip 192.168.200.132 cpu 1",
            "stdout_lines": [
                "ip 192.168.200.132 cpu 1"
            ]
        }
    }
    ok: [webB] => {
        "var_result": {
            "changed": true,
            "cmd": "echo "ip 192.168.200.138 cpu 1"",
            "delta": "0:00:00.002102",
            "end": "2018-06-19 11:32:44.526875",
            "failed": false,
            "rc": 0,
            "start": "2018-06-19 11:32:44.524773",
            "stderr": "",
            "stderr_lines": [],
            "stdout": "ip 192.168.200.138 cpu 1",
            "stdout_lines": [
                "ip 192.168.200.138 cpu 1"
            ]
        }
    }
    PLAY RECAP *********************************************************************************************************
    webA                       : ok=3    changed=1    unreachable=0    failed=0   
    webB                       : ok=3    changed=1    unreachable=0    failed=0   
     

    去内置变量的操作

     
    [root@localhost scripts]# cat test_setupvars.yaml
    ---
    - hosts: all
      gather_facts: True
      tasks:
      - name: setup var
        shell: echo "ip {{ ansible_all_ipv4_addresses[0] }} cpu {{ ansible_processor_count }}" >> /tmp/test
      - name: setup var2
        shell: echo "time {{ ansible_date_time["date"] }}" >> /tmp/test
        register: var_result
      - debug: var=var_result
     

    利用template模块下发可变的变量配置

     
    [root@localhost scripts]# cat /tmp/test 
    my name is {{ myname }} #自定义变量
    my name is {{ ansible_all_ipv4_addresses[0] }}  #系统变量
    [root@localhost scripts]# cat test_filevars.yaml 
    ---
    - hosts: all
      gather_facts: True    #开启系统变量
      vars:
      - myname: "yunjisuan" #自定义变量
      tasks:
      - name: template test
        template: src=/tmp/test dest=/root/test #使用template下发可变配置文件
    [root@localhost scripts]# ansible-playbook test_filevars.yaml
     

    下发的变量的判断的语法

     
    [root@localhost scripts]# cat /tmp/if.j2 
    {% if PORT %}       #if PORT存在
    ip=0.0.0.0:{{ PORT }}
    {% else %}          #否则的话
    ip=0.0.0.0:80
    {% endif %}         #结尾
    [root@localhost scripts]# cat test_ifvars.yaml 
    ---
    - hosts: all
      gather_facts: True    #开启系统内置变量
      vars:
      - PORT: 90        #自定义变量
      tasks:
      - name: jinja2 if test
        template: src=/tmp/if.j2 dest=/root/test
    [root@localhost scripts]# ansible-playbook test_ifvars.yaml 
     

    如果我们把PROT的值置空就会是假

     
    [root@localhost scripts]# cat test_ifvars.yaml 
    ---
    - hosts: all
      gather_facts: True
      vars:
      - PORT:       #置空
      tasks:
      - name: jinja2 if test
        template: src=/tmp/if.j2 dest=/root/test
    [root@localhost scripts]# ansible-playbook test_ifvars.yaml
     

    剧本的通知和下发机制

     
    #下发可执行动作的可变的nginx配置文件
    [root@localhost scripts]# head -1 /tmp/nginx.j2 
    worker_processes  {{ ansible_processor_count }};    #可变的参数
    [root@localhost scripts]# cat test_nginxvars.yaml 
    ---
    - hosts: all
      gather_facts: True    #开启系统内置变量
      tasks:
      - name: nginx conf
        template: src=/tmp/nginx.j2 dest=/usr/local/nginx/conf/nginx.conf
        notify:
        - reload nginx  #下发通知给handlers模块执行名字叫做reload nginx的动作
      handlers: #定义动作
      - name: reload nginx  #动作的名字
        shell: /usr/local/nginx/sbin/nginx -s reload
    [root@localhost scripts]# ansible-playbook test_nginxvars.yaml 
     

    用roles来模板换剧本,可以自己组合模板

     
    #创建roles基本原型的目录结构
    [root@ansible myroles]# tree /myroles/
    /myroles/
    ├── nginx.yaml  #入口触发配置文件
    └── roles       #playbook的原型配置目录
        └── nginx   #nginx相关模组配置目录
            ├── files   #copy模块和script模块的参数src默认会从这个文件夹查找
            ├── handlers    #用来存放notify的
            ├── tasks       #用来存放ansible模块任务的
            ├── templates   #用来存放j2的
            └── vars        #用来存放变量的
    7 directories, 1 file
    #入口触发配置文件
    [root@ansible myroles]# cat /myroles/nginx.yaml 
    ---
    - hosts: all    #执行的主机范围
      gather_facts: True    #开启系统内置变量
      roles:                #启用roles原型配置
      - nginx           #执行nginx原型模组
     

    tasks的任务编排模块

     
    #在nginx模组添加tasks任务配置文件
    [root@ansible myroles]# cat roles/nginx/tasks/main.yaml 
    ---
    - name: check alived    #任务1的名字
      ping:                 #执行ping模块
    - name:                 #任务2的名字
      shell: ls /           #执行shell模块
      register: ls_result   #将执行结果保存给变量
    - debug: var=ls_result  #变量的值赋值给debug进行输出
    #完成后的目录结构如下所示
    [root@ansible myroles]# tree /myroles/
    /myroles/
    ├── nginx.yaml  #nginx模组入口配置文件
    └── roles
        └── nginx   #nginx原型模组目录
            ├── files
            ├── handlers
            ├── tasks
            │   └── main.yaml   #nginx模组的tasks任务配置文件
            ├── templates
            └── vars
    7 directories, 2 files
     

    执行监督的模块

     
    [root@ansible myroles]# ansible-playbook nginx.yaml 
    PLAY [all] ****************************************************************************************************
    TASK [Gathering Facts] ****************************************************************************************
    ok: [webA]
    ok: [webB]
    TASK [nginx : check alived] ***********************************************************************************
    ok: [webA]
    ok: [webB]
    TASK [nginx : shell] ******************************************************************************************
    changed: [webA]
    changed: [webB]
    TASK [nginx : debug] ******************************************************************************************
    ok: [webA] => {
        "ls_result": {
            "changed": true,
            "cmd": "ls /",
            "delta": "0:00:00.002805",
            "end": "2018-06-21 11:52:29.343592",
            "failed": false,
            "rc": 0,
            "start": "2018-06-21 11:52:29.340787",
            "stderr": "",
            "stderr_lines": [],
            "stdout": "bin
    boot
    dev
    etc
    home
    lib
    lib64
    media
    mnt
    opt
    proc
    roo
    root
    run
    sbin
    service
    srv
    sys
    tmp
    usr
    var",
            "stdout_lines": [
                "bin",
                "boot",
                "dev",
                "etc",
                "home",
                "lib",
                "lib64",
                "media",
                "mnt",
                "opt",
                "proc",
                "roo",
                "root",
                "run",
                "sbin",
                "service",
                "srv",
                "sys",
                "tmp",
                "usr",
                "var"
            ]
        }
    }
    ok: [webB] => {
        "ls_result": {
            "changed": true,
            "cmd": "ls /",
            "delta": "0:00:00.002708",
            "end": "2018-06-21 11:52:29.359754",
            "failed": false,
            "rc": 0,
            "start": "2018-06-21 11:52:29.357046",
            "stderr": "",
            "stderr_lines": [],
            "stdout": "bin
    boot
    dev
    etc
    home
    lib
    lib64
    media
    mnt
    opt
    proc
    roo
    root
    run
    sbin
    service
    srv
    sys
    tmp
    usr
    var",
            "stdout_lines": [
                "bin",
                "boot",
                "dev",
                "etc",
                "home",
                "lib",
                "lib64",
                "media",
                "mnt",
                "opt",
                "proc",
                "roo",
                "root",
                "run",
                "sbin",
                "service",
                "srv",
                "sys",
                "tmp",
                "usr",
                "var"
            ]
        }
    }
    PLAY RECAP ****************************************************************************************************
    webA                       : ok=4    changed=1    unreachable=0    failed=0   
    webB                       : ok=4    changed=1    unreachable=0    failed=0   
     
    ansible-playbook执行入口配置文件nginx.yaml后,它会自动在roles目录下查找nginx目录并进入后查找tasks任务目录并执行main.yaml的任务配置文件。
    其实,这个roles的操作等效于以下配置
     
    #本配置和之前的roles配置等效
    [root@ansible myroles]# cat /service/scripts/test.yaml
    ---
    - hosts: all
      gather_facts: True
      tasks:                #其实roles的本质就是将tasks任务单独写了。
      - name: check alived  #并在入口文件里追加了roles去查找tasks配置文件路径
        ping:
      - name:
        shell: ls /
        register: ls_result
      - debug: var=ls_result
     

    roles下的自定义变量模块

     
    #创建自定义变量vars模组的配置文件
    [root@ansible myroles]# cat roles/nginx/vars/main.yaml 
    ---
    my_name: yunjisuan
    phone: 1800000000
    [root@ansible myroles]# cat roles/nginx/tasks/main.yaml 
    ---
    - name: check alived
      ping:
    - name:
      shell: ls /
      register: ls_result
    - debug: var=ls_result
    - name:         #添加对变量引用的任务编排
      shell: echo my phone is {{ phone }}
      register: echo_result
    - debug: var=echo_result
    [root@ansible myroles]# ansible-playbook nginx.yaml     #执行入口配置文件
     

    roles使用copy,和scripts模块

     
    [root@ansible myroles]# cat roles/nginx/files/test
    welcome to yunjisuan
    [root@ansible myroles]# cat roles/nginx/files/test.sh
    echo "aaa" >> /tmp/test
    [root@ansible myroles]# chmod +x roles/nginx/files/test.sh
    [root@ansible myroles]# cat roles/nginx/tasks/main.yaml 
    ---
    - name: check alived
      ping:
    - name:
      shell: ls /
      register: ls_result
    - debug: var=ls_result
    - name:
      shell: echo my phone is {{ phone }}
      register: echo_result
    - debug: var=echo_result
    - name:         #添加copy模块
      copy: src=test dest=/root/
    - name:         #添加script模块(自动在目标IP机器上执行脚本)
      script: test.sh
    [root@ansible myroles]# ansible-playbook nginx.yaml 
     

    roles中的template模块

     
    [root@ansible myroles]# cat roles/nginx/templates/test.j2 
    myname is {{ my_name }},my phone is {{ phone }} #引用自定义变量
    my ipaddress is {{ansible_all_ipv4_addresses[0]}}   #引用内置变量
    [root@ansible myroles]# cat roles/nginx/tasks/main.yaml 
    ---
    - name: check alived
      ping:
    - name:
      shell: ls /
      register: ls_result
    - debug: var=ls_result
    - name:
      shell: echo my phone is {{ phone }}
      register: echo_result
    - debug: var=echo_result
    - name:
      copy: src=test dest=/root/
    - name:
      script: test.sh
    - name:
      template: src=test.j2 dest=/root/test2    #下发可变配置文件
    [root@ansible myroles]# ansible-playbook nginx.yaml 
     

    roles的notify变动通知执行模块

     
    [root@ansible myroles]# cat roles/nginx/handlers/main.yaml 
    ---
    - name: start_nginx     #定义handlers的动作类型
      shell: /usr/local/nginx/sbin/nginx    
    - name: stop_nginx  #定义handlers的动作类型
      shell: /usr/local/nginx/sbin/nginx -s stop   
    - name: reload_nginx    #定义handlers的动作类型
      shell: /usr/local/nginx/sbin/nginx -s reload  
    [root@ansible myroles]# cat roles/nginx/tasks/main.yaml 
    ---
    - name: check alived
      ping:
    - name:
      shell: ls /
      register: ls_result
    - debug: var=ls_result
    - name:
      shell: echo my phone is {{ phone }}
      register: echo_result
    - debug: var=echo_result
    - name:
      copy: src=test dest=/root/
    - name:
      script: test.sh
    - name:
      template: src=test.j2 dest=/root/test2
      notify: start_nginx   #执行template任务后下发通知给handlers执行start_nginx
    [root@ansible myroles]# ansible-playbook nginx.yaml 
     

    特别提示: 
    notify下发通知只有当之前的任务造成了变化那么才会被执行,如果没有发生任何改变,则notify不会被执行。例如:

     
    #tasks任务造成改变,触发notify
    [root@ansible myroles]# cat /tmp/test.yaml 
    ---
    - hosts: webA
      gather_facts: True
      tasks:
      - name:
        copy: src=/tmp/test dest=/root/ #这步造成目标改变才能出发notify
        notify: start_nginx
      handlers:
      - name: start_nginx
        shell: /usr/local/nginx/sbin/nginx
    [root@ansible myroles]# ansible-playbook /tmp/test.yaml 
    PLAY [webA] ***************************************************************************************************
    TASK [Gathering Facts] ****************************************************************************************
    ok: [webA]
    TASK [copy] ***************************************************************************************************
    changed: [webA] #发生了改变
    RUNNING HANDLER [start_nginx]   #触发notify *********************************************************************************
    changed: [webA]
    PLAY RECAP ****************************************************************************************************
    webA                       : ok=3    changed=2    unreachable=0    failed=0   
    #我们再次执行/tmp/test.yaml
    [root@ansible myroles]# ansible-playbook /tmp/test.yaml 
    PLAY [webA] ***************************************************************************************************
    TASK [Gathering Facts] ****************************************************************************************
    ok: [webA]
    TASK [copy] ***************************************************************************************************
    ok: [webA]      #没有造成任务改变,未触发notify通知
    PLAY RECAP ****************************************************************************************************
    webA                       : ok=2    changed=0    unreachable=0    failed=0
     
  • 相关阅读:
    修复PLSQL Developer 与 Office 2010的集成导出Excel 功能
    Using svn in CLI with Batch
    mysql 备份数据库 mysqldump
    Red Hat 5.8 CentOS 6.5 共用 输入法
    HP 4411s Install Red Hat Enterprise Linux 5.8) Wireless Driver
    变更RHEL(Red Hat Enterprise Linux 5.8)更新源使之自动更新
    RedHat 5.6 问题简记
    Weblogic 9.2和10.3 改密码 一站完成
    ExtJS Tab里放Grid高度自适应问题,官方Perfect方案。
    文件和目录之utime函数
  • 原文地址:https://www.cnblogs.com/wangyinuo/p/9993399.html
Copyright © 2011-2022 走看看