Ansible介紹以及基於角色搭建LNMP和zabbix

来源:https://www.cnblogs.com/yan-linux/archive/2023/01/10/17039200.html
-Advertisement-
Play Games

1 ansible 常用指令總結,並附有相關示例。 /usr/bin/ansible 主程式,臨時命令執行工具 /usr/bin/ansible-doc 查看配置文檔,模塊功能查看工具,相當於man /usr/bin/ansible-playbook 定製自動化任務,編排劇本工具,相當於腳本 /us ...


1 ansible 常用指令總結,並附有相關示例。

  • /usr/bin/ansible 主程式,臨時命令執行工具
  • /usr/bin/ansible-doc 查看配置文檔,模塊功能查看工具,相當於man
  • /usr/bin/ansible-playbook 定製自動化任務,編排劇本工具,相當於腳本
  • /usr/bin/ansible-pull 遠程執行命令的工具
  • /usr/bin/ansible-vault 文件加密工具
  • /usr/bin/ansible-console 基於Console界面與用戶交互的執行工具
  • /usr/bin/ansible-galaxy 下載/上傳優秀代碼或Roles模塊的官網平臺

利用ansible實現管理的主要方式:

  • Ansible Ad-Hoc 即利用ansible命令,主要用於臨時命令使用場景
  • Ansible playbook 主要用於長期規劃好的,大型項目的場景,需要有前期的規划過程

ansible 使用前準備

ansible 相關工具大多數是通過ssh協議,實現對遠程主機的配置管理、應用部署、任務執行等功能

建議:使用此工具前,先配置ansible主控端能基於密鑰認證的方式聯繫各個被管理節點

1.1 ansible-doc

此工具用來顯示模塊幫助,相當於man

格式

ansible-doc [options] [module...]
-l, --list #列出可用模塊
-s, --snippet #顯示指定模塊的playbook片段

範例:

#列出所有模塊
ansible-doc -l
#查看指定模塊幫助用法
ansible-doc ping
#查看指定模塊幫助用法
ansible-doc -s ping

範例: 查看指定的插件

[13:38:40 root@ansible-rocky ~]$ ansible-doc -t connection -l
[13:39:08 root@ansible-rocky ~]$ ansible-doc -t lookup -l

1.2 ansible

1.2.1 Ansible Ad-Hoc 介紹

Ansible Ad-Hoc 的執行方式的主要工具就是 ansible
特點: 一次性的執行,不會保存執行命令信息,只適合臨時性或測試性的任務

1.2.2 ansible 命令用法

格式:

ansible <host-pattern> [-m module_name] [-a args]

選項說明:

--version                               #顯示版本
-m module                               #指定模塊,預設為command
-v                                      #詳細過程 -vv -vvv更詳細
--list-hosts                            #顯示主機列表,可簡寫 --list
-C, --check                             #檢查,並不執行
-T, --timeout=TIMEOUT                   #執行命令的超時時間,預設10s
-k, --ask-pass                          #提示輸入ssh連接密碼,預設Key驗證
-u, --user=REMOTE_USER                  #執行遠程執行的用戶,預設root
-b, --become                            #代替舊版的sudo實現通過sudo機制實現提升許可權
--become-user=USERNAME                  #指定sudo的run as用戶,預設為root
-K, --ask-become-pass                   #提示輸入sudo時的口令
-f FORKS, --forks FORKS                 #指定併發同時執行ansible任務的主機數
-i INVENTORY, --inventory INVENTORY     #指定主機清單文件

範例:

#先打通基於key驗證
#以yanlinux用戶執行ping存活檢測
[14:28:30 yanlinux@ansible-rocky ~]$ ansible all -m ping -u yanlinux
10.0.0.18 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.102 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.7 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}

#以yanlinux sudo至root執行命令
##沒有添加sudo授權之前
[14:36:46 yanlinux@ansible-rocky ~]$ ansible all -a 'ls /root'
10.0.0.18 | FAILED | rc=2 >>
ls: cannot open directory '/root': Permission deniednon-zero return code
10.0.0.102 | FAILED | rc=2 >>
ls: cannot open directory '/root': Permission deniednon-zero return code
10.0.0.7 | FAILED | rc=2 >>
ls: cannot open directory /root: Permission deniednon-zero return code
##在所有被控制主機上都加上suod授權
[14:30:46 root@ansible-rocky ~]$ echo "yanlinux    ALL=(ALL)   NOPASSWD: ALL" >> /etc/sudoers
[14:37:01 yanlinux@ansible-rocky ~]$ ansible all -a 'ls /root' -b
10.0.0.102 | CHANGED | rc=0 >>
init_os.sh
snap
10.0.0.7 | CHANGED | rc=0 >>
anaconda-ks.cfg
init_os.sh
10.0.0.18 | CHANGED | rc=0 >>
anaconda-ks.cfg
init_os.sh
##所有被管理主機上創建用戶magedu
[14:37:05 yanlinux@ansible-rocky ~]$ ansible all -a 'useradd magedu' -b
10.0.0.102 | CHANGED | rc=0 >>

10.0.0.18 | CHANGED | rc=0 >>

10.0.0.7 | CHANGED | rc=0 >>

[14:39:46 yanlinux@ansible-rocky ~]$ ansible all -a 'getent passwd magedu' -b
10.0.0.7 | CHANGED | rc=0 >>
magedu:x:1002:1002::/home/magedu:/bin/bash
10.0.0.102 | CHANGED | rc=0 >>
magedu:x:1001:1001::/home/magedu:/bin/sh
10.0.0.18 | CHANGED | rc=0 >>
magedu:x:1001:1001::/home/magedu:/bin/bash

範例: 併發執行控制

#併發是1一個主機一個主機的執行,一條條返回結果
[14:42:47 root@ansible-rocky ~]$ ansible all -a 'sleep 5' -f1
#併發是10,同時10個主機執行命令,返回結果
[14:42:47 root@ansible-rocky ~]$ ansible all -a 'sleep 5' -f10

範例: 使用普通用戶連接遠程主機執行代替另一個用戶身份執行操作

#在被管理主機上創建用戶並sudo授權
[14:34:00 root@ubuntu2004 ~]$ useradd magedu
[14:34:29 root@ubuntu2004 ~]$ echo magedu:centos1 |chpasswd

#以yanlinux的用戶連接用戶並利用sudo代表magedu執行whoami命令
[14:58:37 yanlinux@ansible-rocky ~]$ ansible all -a 'whoami' -b --become-user=magedu
10.0.0.18 | CHANGED | rc=0 >>
magedu
10.0.0.7 | CHANGED | rc=0 >>
magedu

1.3 ansible-console

此工具可交互執行命令,支持tab,ansible 2.0+新增
提示符格式:

執行用戶@當前操作的主機組 (當前組的主機數量)[f:併發數]$

常用子命令:

  • 設置併發數: forks n 例如: forks 10
  • 切換組: cd 主機組 例如: cd web
  • 列出當前組主機列表: list
  • 列出所有的內置命令: ?或help

範例

[15:24:28 root@ansible-rocky ~]$ ansible-console 
Welcome to the ansible console. Type help or ? to list commands.

root@all (3)[f:5]$ ping
10.0.0.18 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.102 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.7 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
root@all (3)[f:5]$ list
10.0.0.18
10.0.0.7
10.0.0.102
root@all (3)[f:5]$ cd websrvs
root@websrvs (2)[f:5]$ list
10.0.0.18
10.0.0.7
root@websrvs (2)[f:5]$ forks 10
root@websrvs (2)[f:10]$ cd appsrvs
root@appsrvs (2)[f:10]$ list
10.0.0.102
10.0.0.18

1.4 ansible-playbook

此工具用於執行編寫好的 playbook 任務
範例:

[15:27:57 root@ansible-rocky ~]$ vi hello.yml
---
#hello world yml file
- hosts: websrvs
  remote_user: root
  gather_facts: no

  tasks:
    - name: hello world
      command: /usr/bin/wall hello world
[15:30:12 root@ansible-rocky ~]$ ansible-playbook hello.yml 

PLAY [websrvs] ****************************************************************************************

TASK [hello world] ************************************************************************************
changed: [10.0.0.18]
changed: [10.0.0.7]

PLAY RECAP ********************************************************************************************
10.0.0.18                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
10.0.0.7                   : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

1.5 ansible-vault

此工具可以用於加密解密yml文件

格式:

ansible-vault [create|decrypt|edit|encrypt|rekey|view]

範例:

#1 加密
[15:31:01 root@ansible-rocky ~]$ ansible-vault encrypt hello.yml 
New Vault password: 
Confirm New Vault password: 
Encryption successful
##查看文件內容
[15:38:15 root@ansible-rocky ~]$ cat hello.yml 
$ANSIBLE_VAULT;1.1;AES256
65323766623831636563636132623333623932633461396563383764333037396563633766363231
3335646336346136626231353133623566626166626336380a306630643338353031353739353538
62373930306636633430653537363534376231323839643131376335653366656634616365663063
6236663364343461610a383365643534646564316261326166316233393039386134363436313138
63323939663537666462646233613262646637306130626336336239323737623833393735666364
36336334316666326265356166326163373039616533353564353964396266376637363037353338
37623639656262303966363766356630376466666463363338353535623635633137616335383333
65333263643762353264326563326362393663316538666530616664643438666435373162616164
30313761323030343165666330326537653430333764363834326566333666316133386465663334
63353035616266396366366662643839353431653736353465626261623433343735663534663831
32636632653730323465366531353531633761623930303138643337613162613062333237633566
39663562393535343165

#2 解密
[15:38:18 root@ansible-rocky ~]$ ansible-vault decrypt hello.yml 
Vault password: 
Decryption successful
[15:39:50 root@ansible-rocky ~]$ cat hello.yml 
---
#hello world yml file
- hosts: websrvs
  remote_user: root
  gather_facts: no

  tasks:
    - name: hello world
      command: /usr/bin/wall hello world
      
#3 查看加密後的yml文件內容
[15:41:44 root@ansible-rocky ~]$ ansible-vault view hello.yml 
Vault password: 
---
#hello world yml file
- hosts: websrvs
  remote_user: root
  gather_facts: no

  tasks:
    - name: hello world
      command: /usr/bin/wall hello world

#4 編輯加密文件
[15:41:50 root@ansible-rocky ~]$ ansible-vault edit hello.yml 
Vault password:             #輸入密碼後進入vim編輯器進行編輯

#5 修改口令
[15:44:53 root@ansible-rocky ~]$ ansible-vault rekey hello.yml 
Vault password:    #先前的口令
New Vault password:  #修改為的口令
Confirm New Vault password:  #再確認一遍
Rekey successful

#6 創建加密新文件
[15:46:31 root@ansible-rocky ~]$ ansible-vault create new.yml
New Vault password: 
Confirm New Vault password:

#7 互動式輸入密碼來執行加密文件
[15:46:46 root@ansible-rocky ~]$ ansible-playbook --ask-vault-pass hello.yml 
Vault password: 

PLAY [websrvs] ****************************************************************************************

TASK [hello world] ************************************************************************************
changed: [10.0.0.18]
changed: [10.0.0.7]

PLAY RECAP ********************************************************************************************
10.0.0.18                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
10.0.0.7                   : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

#8 從文件中讀取密碼
[15:52:56 root@ansible-rocky ~]$ ansible-playbook --vault-password-file pass.txt hello.yml 

PLAY [websrvs] ****************************************************************************************

TASK [hello world] ************************************************************************************
changed: [10.0.0.18]
changed: [10.0.0.7]

PLAY RECAP ********************************************************************************************
10.0.0.18                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
10.0.0.7                   : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

#9 從配置文件中添加密碼文件
[15:53:33 root@ansible-rocky ~]$ vi /etc/ansible/ansible.cfg
#添加以下一行信息
ault-password-file=pass.txt
[15:58:58 root@ansible-rocky ~]$ ansible-playbook hello.yml 

PLAY [websrvs] ****************************************************************************************

TASK [hello world] ************************************************************************************
changed: [10.0.0.18]
changed: [10.0.0.7]

PLAY RECAP ********************************************************************************************
10.0.0.18                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
10.0.0.7                   : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

1.6 ansible-galaxy

Galaxy 是一個免費網站, 類似於github網站, 網站上發佈了很多的共用的roles角色。

Ansible 提供了ansible-galaxy命令行工具連接 https://galaxy.ansible.com 網站下載相應的roles, 進行init(初始化、search( 查拘、install(安裝、 remove(移除)等操作。

範例

#搜索項目
[16:05:04 root@ansible-rocky ~]$ ansible-galaxy search lamp

Found 100 roles matching your search:

 Name                                      Description
 ----                                      -----------
 abhiarun_94.apache_lamp                   your role description
 adelaidearnauld.galaxy-lamp               your description
 adelaidearnauld.lamp_compose              your description
 ajish_antony.ansible_lamp                 your role description
 AlexanderAllen.Liara                      The sexiest toolkit for LAMP hackers.
 alphinaugustine.ansible_role              your description
 amtega.horde                              Setup horde
 ......
 

#2 列出所有已安裝的galaxy
[16:06:32 root@ansible-rocky ~]$ ansible-galaxy list
# /usr/share/ansible/roles
# /etc/ansible/roles


#3 安裝galaxy,預設下載到~/.ansible/roles
[16:14:06 root@ansible-rocky ~]$ ansible-galaxy install 想要安裝的galaxy

#刪除
ansible-galaxy remove 

2 總結ansible role目錄結構及文件用途。

roles目錄結構:

├── playbook1.yml
├── playbook2.yml
├── roles/
│   ├── project1/
│   │	├── tasks/
│   │	├── files/
│   │	├── vars/
│   │	├── templates/
│   │	├── handlers/
│   │	├── default/
│   │	└── meta/
│   ├── project2/
│   │	├── tasks/
│   │	├── files/
│   │	├── vars/
│   │	├── templates/
│   │	├── handlers/
│   │	├── default/
│   │	└── meta/

Roles各目錄作用

roles/project/ :項目名稱,有以下子目錄

  • files/ :存放由copyscript模塊等調用的文件
  • templates/template模塊查找所需要模板文件的目錄
  • tasks/:定義task,role的基本元素,至少應該包含一個名為main.yml的文件;其它的文件需要在此文件中通過include進行包含
  • handlers/:至少應該包含一個名為main.yml的文件;此目錄下的其它的文件需要在此文件中通過include進行包含
  • vars/定義變數,至少應該包含一個名為main.yml的文件;此目錄下的其它的變數文件需要在此文件中通過include進行包含,也可以通過項目目錄中的group_vars/all定義變數,從而實現角色通用代碼和項目數據的分離
  • meta/定義當前角色的特殊設定及其依賴關係,至少應該包含一個名為main.yml的文件,其它文件需在此文件中通過include進行包含
  • default/:設定預設變數時使用此目錄中的main.yml文件,比vars優先順序低

3 使用ansible playbook實現一個mysql角色。

#mysql角色目錄
[18:16:16 root@ansible-rocky opt]$ tree
.
├── ansible.cfg
├── hosts
├── mysql_role.yml
└── roles
    └── mysql
        ├── files
        │   └── mysql-8.0.31-linux-glibc2.12-x86_64.tar.xz
        ├── tasks
        │   └── main.yml
        └── templates
            └── my.cnf.j2
            
#定義主機及變數
[18:22:50 root@ansible-rocky opt]$ tail -n9 hosts 
[dbsrvs:vars]
db_group=mysql
db_gid=306
db_user=mysql
db_uid=306
db_version=8.0.31
db_file="mysql-{{db_version}}-linux-glibc2.12-x86_64.tar.xz"
db_data_dir="/data/mysql"
db_root_passwd="lgq123456**"

#下載準備mysql源文件包
[18:22:54 root@ansible-rocky opt]$ ls roles/mysql/files/
mysql-8.0.31-linux-glibc2.12-x86_64.tar.xz

#創建task文件
[18:24:40 root@ansible-rocky opt]$ cat roles/mysql/tasks/main.yml 
- name: install dependent package
  yum:
    name: "{{ item }}"
  loop:
    - libaio
    - numactl-libs

- name: create mysql group
  group: name={{db_group}} gid={{db_gid}}

- name: create mysql user
  user: name={{db_user}} uid={{db_uid}} system=yes shell="/sbin/nologin" create_home=no group={{db_group}}

- name: copy tar to remote host and file mode
  unarchive:
    src: "{{ db_file }}"
    dest: "/usr/local/"
    owner: root
    group: root

- name: create lingfile /usr/local/mysql
  file:
    src: "/usr/local/mysql-{{ db_version }}-linux-glibc2.12-x86_64"
    dest: "/usr/local/mysql"
    state: link

- name: path file
  copy:
    content: "PATH=/usr/local/mysql/bin:$PATH"
    dest: "/etc/profile.d/mysql.sh"

- name: config file
  template:
    src: my.cnf.j2
    dest: "/etc/my.cnf"

- name: create directory
  file:
    name: "/data"
    state: directory

- name: init mysql data
  shell:
    cmd: "/usr/local/mysql/bin/mysqld --initialize-insecure --user={{ db_user }} --datadir={{ db_data_dir }}"
  tags:
    - init

- name: service script
  copy:
    src: "/usr/local/mysql/support-files/mysql.server"
    dest: "/etc/init.d/mysqld"
    remote_src: yes
    mode: '+x'

- name: start service
  shell:
    cmd: chkconfig --add mysqld;chkconfig mysqld on;service mysqld start

- name: change root password
  shell:
    cmd: "/usr/local/mysql/bin/mysqladmin -uroot password {{ db_root_passwd }}"
    
    
#準備MySQL 配置文件模板
[18:25:25 root@ansible-rocky opt]$ cat roles/mysql/templates/my.cnf.j2 
[mysqld]
server-id=1
log-bin
datadir={{ db_data_dir }}
socket={{ db_data_dir }}/mysql.sock
log-error={{ db_data_dir }}/mysql.log
pid-file={{ db_data_dir }}/mysql.pid

[client]
socket={{ db_data_dir }}/mysql.sock

#準備MySQL角色playbook文件
[18:25:38 root@ansible-rocky opt]$ cat mysql_role.yml 
- hosts: dbsrvs
  remote_user: root
  gather_facts: no

  roles:
    - mysql
    
#部署MySQL
[18:26:34 root@ansible-rocky opt]$ ansible-playbook -i hosts mysql_role.yml
PLAY [dbsrvs] *****************************************************************************************

TASK [mysql : install dependent package] **************************************************************
ok: [10.0.0.38] => (item=libaio)
ok: [10.0.0.38] => (item=numactl-libs)

TASK [mysql : create mysql group] *********************************************************************
changed: [10.0.0.38]

TASK [mysql : create mysql user] **********************************************************************
changed: [10.0.0.38]

TASK [mysql : copy tar to remote host and file mode] **************************************************
changed: [10.0.0.38]

TASK [mysql : create lingfile /usr/local/mysql] *******************************************************
changed: [10.0.0.38]

TASK [mysql : path file] ******************************************************************************
changed: [10.0.0.38]

TASK [mysql : config file] ****************************************************************************
changed: [10.0.0.38]

TASK [mysql : create directory] ***********************************************************************
ok: [10.0.0.38]

TASK [mysql : init mysql data] ************************************************************************
changed: [10.0.0.38]

TASK [mysql : service script] *************************************************************************
changed: [10.0.0.38]

TASK [mysql : start service] **************************************************************************
changed: [10.0.0.38]

TASK [mysql : change root password] *******************************************************************
changed: [10.0.0.38]

PLAY RECAP ********************************************************************************************
10.0.0.38                  : ok=12   changed=10   unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

4 基於角色完成部署LNMP架構,並支持一鍵發佈,回滾應用。同時基於zabbix角色批量部署zabbix。

4.1 部署LNMP架構

4.1.1 目錄結構

[18:57:47 root@ansible-rocky opt]$ tree /opt/
/opt/
├── ansible.cfg
├── hosts
├── lnmp_role.yml
├── mysql_role.yml
├── nginx_role.yml
├── php-fpm_role.yml
├── roles
│   ├── mysql
│   │   ├── files
│   │   │   └── mysql-8.0.31-linux-glibc2.12-x86_64.tar.xz
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── templates
│   │       └── my.cnf.j2
│   ├── nginx
│   │   ├── handlers
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── templates
│   │       ├── nginx.conf.j2
│   │       └── nginx.service.j2
│   ├── php-fpm
│   │   ├── files
│   │   │   ├── test.php
│   │   │   └── www.conf
│   │   ├── handlers
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── templates
│   │       ├── php-fpm.conf.j2
│   │       └── php.ini.j2
│   └── wordpress
│       ├── files
│       │   └── wordpress-6.1.1-zh_CN.zip
│       └── tasks
│           └── main.yml
└── wordpress_role.yml

17 directories, 22 files

4.1.2 LNMP架構所需主機清單以及變數設置

[18:58:15 root@ansible-rocky opt]$ cat hosts 
[websrvs]
10.0.0.18
10.0.0.28

[websrvs:vars]
version="1.20.2"
url="http://nginx.org/download/nginx-{{ version }}.tar.gz"
install_dir="/apps/nginx"
fqdn="www.yanlinux.org"
root_path="/data/wordpress"
app="wordpress-6.1.1-zh_CN"

[dbsrvs]
10.0.0.38

[dbsrvs:vars]
db_group=mysql
db_gid=306
db_user=mysql
db_uid=306
db_version=8.0.31
db_file="mysql-{{db_version}}-linux-glibc2.12-x86_64.tar.xz"
db_data_dir="/data/mysql"
db_root_passwd="lgq123456**"

4.1.2 實現編譯安裝nginx角色

#task文件
[17:55:17 root@ansible-rocky roles]$ cat nginx/tasks/main.yml 
- name: add group nginx
  group: name=nginx system=yes gid=80

- name: add user nginx
  user: name=nginx group=nginx uid=80 system=yes shell="/sbin/nologin" create_home=no

- name: install dependent package
  yum: name={{item}} state=latest
  loop:
    - gcc
    - make
    - pcre-devel
    - openssl-devel
    - zlib-devel
    - perl-ExtUtils-Embed

- name: get nginx source
  unarchive:
    src: "{{ url }}"
    dest: "/usr/local/src"
    remote_src: yes

- name: compile and install
  shell:
    cmd: "./configure --prefix={{install_dir}} --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module && make && make install"
    chdir: "/usr/local/src/nginx-{{ version }}"
    creates: "{{install_dir}}/sbin/nginx"

- name: config file
  template:
    src: nginx.conf.j2
    dest: "{{install_dir}}/conf/nginx.conf"
    owner: nginx
    group: nginx
  notify: restart service
  tags:
    - config

- name: create directory
  file:
    path: "{{install_dir}}/conf/conf.d"
    state: directory
    owner: nginx
    group: nginx

- name: change install directory owner
  file:
    path: "{{install_dir}}"
    owner: nginx
    group: nginx
    recurse: yes

- name: copy service file
  template:
    src: nginx.service.j2
    dest: "/lib/systemd/system/nginx.service"

- name: check config
  shell:
    cmd: "{{install_dir}}/sbin/nginx -t"
  register: check_nginx_config
  changed_when:
    - check_nginx_config.stdout.find('successful')
    - false

- name: start service
  systemd:
    daemon_reload: yes
    name: nginx.service
    state: started
    enabled: yes
      
#創建handler文件
[17:59:27 root@ansible-rocky roles]$ cat nginx/handlers/main.yml 
- name: restart service
  service:
    name: nginx
    state: restarted

#準備兩個template文件
[17:59:51 root@ansible-rocky roles]$ cat nginx/templates/nginx.conf.j2 

#user  nobody;
user nginx;
worker_processes  {{ ansible_processor_vcpus*2 }};
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    log_format  access_json '{"@timestamp":"$time_iso8601",'
        '"host":"$server_addr",'
        '"clientip":"$remote_addr",'
        '"size":$body_bytes_sent,'
        '"responsetime":$request_time,'
        '"upstreamtime":"$upstream_response_time",'
        '"upstreamhost":"$upstream_addr",'
        '"http_host":"$host",'
        '"uri":"$uri",'
        '"xff":"$http_x_forwarded_for",'
        '"referer":"$http_referer",'
        '"tcp_xff":"$proxy_protocol_addr",'
        '"http_user_agent":"$http_user_agent",'
        '"status":"$status"}';
    # logging                                                                                          
    access_log {{install_dir}}/logs/access-json.log access_json;
    error_log {{install_dir}}/logs/error.log warn;

    keepalive_timeout  65;
    include {{install_dir}}/conf/conf.d/*.conf;
}
[18:00:28 root@ansible-rocky roles]$ cat nginx/templates/nginx.service.j2 
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile={{install_dir}}/logs/nginx.pid
ExecStartPre=/bin/rm -f {{install_dir}}/logs/nginx.pid
ExecStartPre={{install_dir}}/sbin/nginx -t
ExecStart={{install_dir}}/sbin/nginx
ExecReload=/bin/kill -s HUP \$MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true                                                                                        
LimitNOFILE=100000

[Install]
WantedBy=multi-user.target

#總入口playbook文件
[18:09:50 root@ansible-rocky opt]$ cat /opt/nginx_role.yml 
- hosts: websrvs
  remote_user: root

  roles:
    - nginx

4.1.4 實現php-fpm角色

#首先準備php.ini.j2和www.conf文件
#修改php上傳限制配置
[17:04:11 root@ansible-rocky ~]$ vi /opt/roles/php-fpm/templates/php.ini.j2
post_max_size = 100M #將次行從8M修改為100M
upload_max_filesize = 100M #將此行從2M改為100M

#修改配置文件
[17:14:03 root@proxy ~]$ vi /opt/roles/php-fpm/files/www.conf
user = nginx #修改為nginx
group = nginx #修改為nginx
;listen = /run/php-fpm/www.sock #註釋此行
listen = 127.0.0.1:9000 #添加此行,監控本機的9000埠

#準備網頁配置文件
[19:51:32 root@ansible-rocky opt]$ cat /opt/roles/php-fpm/templates/php-fpm.conf.j2 
server {
    listen 80;
    server_name {{ fqdn }};
    location / {
        root           {{ root_path  }};
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

#準備tasks文件
[19:40:32 root@ansible-rocky opt]$ cat /opt/roles/php-fpm/tasks/main.yml
- name: install package
  yum:
    name: "{{ item }}"
  loop:
    - php-fpm
    - php-mysqlnd
    - php-json
    - php-xml
    - php-gd
    - php-pecl-zip

- name: php path permissions
  file:
    path: /var/lib/php/
    owner: nginx
    group: nginx
    recurse: yes

- name: config php.ini
  template:
    src: php.ini.j2
    dest: /etc/php.ini

- name: config www.conf
  copy:
    src: www.conf
    dest: /etc/php-fpm.d/www.conf

- name: website config
  template:
    src: php-fpm.conf.j2
    dest: "{{ install_dir }}/conf/conf.d/php-fpm.conf"
    owner: nginx
    group: nginx
  notify: restart nginx

- name: start service
  service:
    name: php-fpm
    state: started
    enabled: yes
    
#準備handler文件
[19:53:47 root@ansible-rocky opt]$ cat /opt/roles/php-fpm/handlers/main.yml 
- name: restart nginx
  service:
    name: nginx
    state: restarted
    
#準備總入口playbook文件
[19:54:48 root@ansible-rocky opt]$ cat /opt/php-fpm_role.yml 
- hosts: websrvs
  remote_user: root

  roles:
    - php-fpm

4.1.5 實現MySQL角色

註意:ansible playbook調用mysql系列模塊需要依賴python3-mysql包和利用pip安裝pymysql

#下載準備mysql源文件包
[18:22:54 root@ansible-rocky opt]$ ls roles/mysql/files/
mysql-8.0.31-linux-glibc2.12-x86_64.tar.xz

#創建task文件
[18:24:40 root@ansible-rocky opt]$ cat roles/mysql/tasks/main.yml 
- name: install dependent package
  yum:
    name: "{{ item }}"
  loop:
    - libaio
    - numactl-libs
    - python39
    - python3-mysql

- name: install pymysql
  pip:
    name: pymysql
    state: present
    
- name: create mysql group
  group: name={{db_group}} gid={{db_gid}}

- name: create mysql user
  user: name={{db_user}} uid={{db_uid}} system=yes shell="/sbin/nologin" create_home=no group={{db_group}}

- name: copy tar to remote host and file mode
  unarchive:
    src: "{{ db_file }}"
    dest: "/usr/local/"
    owner: root
    group: root

- name: create lingfile /usr/local/mysql
  file:
    src: "/usr/local/mysql-{{ db_version }}-linux-glibc2.12-x86_64"
    dest: "/usr/local/mysql"
    state: link

- name: path file
  copy:
    content: "PATH=/usr/local/mysql/bin:$PATH"
    dest: "/etc/profile.d/mysql.sh"

- name: config file
  template:
    src: my.cnf.j2
    dest: "/etc/my.cnf"

- name: create directory
  file:
    name: "/data"
    state: directory

- name: init mysql data
  shell:
    cmd: "/usr/local/mysql/bin/mysqld --initialize-insecure --user={{ db_user }} --datadir={{ db_data_dir }}"
  tags:
    - init

- name: service script
  copy:
    src: "/usr/local/mysql/support-files/mysql.server"
    dest: "/etc/init.d/mysqld"
    remote_src: yes
    mode: '+x'

- name: start service
  shell:
    cmd: chkconfig --add mysqld;chkconfig mysqld on;service mysqld start

- name: change root password
  shell:
    cmd: "/usr/local/mysql/bin/mysqladmin -uroot password {{ db_root_passwd }}"
    
- name: create {{ wp_db_name }} database
  mysql_db:
    login_host: "localhost"
    login_user: "root"
    login_password: "{{ db_root_passwd }}"
    login_port: 3306
    login_unix_socket: "{{ db_data_dir }}/mysql.sock"
    name: "{{ wp_db_name }}"
    state: present
  when: "{{ wp_db_name }} is defined"

- name: create {{ wp_db_user }}
  mysql_user:
    login_host: "localhost"
    login_user: "root"
    login_password: "{{ db_root_passwd }}"
    login_port: 3306
    login_unix_socket: "{{ db_data_dir }}/mysql.sock"
    name: "{{ wp_db_user}}"
    password: "{{ wp_db_passwd }}"
    priv: "{{ wp_db_name }}.*:ALL"
    host: "10.0.0.%"
    state: present
  when: "{{ wp_db_user }} is defined"
    
    
#準備MySQL 配置文件模板
[18:25:25 root@ansible-rocky opt]$ cat roles/mysql/templates/my.cnf.j2 
[mysqld]
server-id=1
log-bin
datadir={{ db_data_dir }}
socket={{ db_data_dir }}/mysql.sock
log-error={{ db_data_dir }}/mysql.log
pid-file={{ db_data_dir }}/mysql.pid

[client]
socket={{ db_data_dir }}/mysql.sock

#準備總入口playbook文件
[18:25:38 root@ansible-rocky opt]$ cat mysql_role.yml 
- hosts: dbsrvs
  remote_user: root
  gather_facts: no

  roles:
    - mysql

4.2 基於zabbix角色批量部署zabbix

依賴上面搭建好的LNMP架構實現

4.2.1 部署zabbix-server

#總體目錄結構
[20:27:58 root@ansible-rocky opt]$ tree
.
├── ansible.cfg
├── hosts
├── hosts_zabbix
├── roles
│   ├── mysql
│   │   ├── files
│   │   │   ├── create.sql.gz
│   │   │   └── mysql-8.0.31-linux-glibc2.12-x86_64.tar.xz
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── templates
│   │       └── my.cnf.j2
│   ├── nginx
│   │   ├── files
│   │   ├── handlers
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── templates
│   │       ├── nginx.conf.j2
│   │       └── nginx.service.j2
│   ├── php-fpm
│   │   ├── files
│   │   │   ├── test.php
│   │   │   └── www.conf
│   │   ├── handlers
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── templates
│   │       ├── php-fpm.conf.j2
│   │       └── php.ini.j2
│   └── zabbix_server
│       ├── handlers
│       │   └── main.yml
│       ├── tasks
│       │   └── main.yml
│       └── templates
│           ├── zabbix.conf.j2
│           ├── zabbix_server.conf.j2
│           └── zabbix-server-ngx.conf.j2
└── zabbix_server.yml

29 directories, 26 files

#主入口playbook
[20:24:45 root@ansible-rocky opt]$ cat zabbix_server.yml 
- hosts: websrvs
  remote_user: root
  roles:
    - nginx
    - php-fpm

- hosts: dbsrvs
  remote_user: root
  roles:
    - mysql

- hosts: websrvs
  remote_user: root
  roles:
    - zabbix_server


#tasks文件
[20:30:01 root@ansible-rocky zabbix_server]$ cat /opt/roles/zabbix_server/tasks/main.yml 
- name: config zabbix yum repo
  yum_repository:
    name: "ansible_zabbix"
    description: "zabbix repo"
    baseurl: "https://mirrors.aliyun.com/zabbix/zabbix/{{ zabbix_version }}/rhel/{{ ansible_distribution_major_version }}/{{ ansible_architecture }}/"
    gpgcheck: yes
    gpgkey: "https://mirrors.aliyun.com/zabbix/zabbix-official-repo.key"

- name: install zabbix-server
  yum:
    name: "{{ item }}"
  loop:
    - zabbix-server-mysql
    - zabbix-agent2
    - zabbix-get
    - zabbix-web-mysql

- name: copy zabbix_server.conf 
  template:
    src: zabbix_server.conf.j2
    dest: /etc/zabbix/zabbix_server.conf
    mode: 0600
  notify:
    - restart zabbix-server
  tags: restart zabbix-server

- name: chown  zabbix-web
  file:
    path:  /etc/zabbix/web    
    state: directory
    owner: nginx
    group: nginx
    recurse: yes

- name: copy zabbix-server web conf
  template:
    src: zabbix-server-ngx.conf.j2
    dest: "{{ install_dir }}/conf/conf.d/zabbix_server_ngx.conf"
    owner: nginx
    group: nginx
  notify:
    - restart nginx

- name: copy zabbix.conf into php-fpm.d
  template:
    src: zabbix.conf.j2
    dest: "/etc/php-fpm.d/zabbix.conf"
  notify:
    - restart php-fpm

- name: start zabbix-server
  service:
    name: zabbix-server
    state: restarted
    enabled: yes
    
#查看handler
[20:34:11 root@ansible-rocky zabbix_server]$ cat /opt/roles/zabbix_server/handlers/main.yml 
- name: restart zabbix-server
  service:
    name: zabbix-server
    state: restarted

- name: restart nginx
  service:
    name: nginx
    state: restarted

- name: restart php-fpm
  service:
    name: php-fpm
    state: restarted
    
#查看template文件
[20:34:15 root@ansible-rocky zabbix_server]$ cat /opt/roles/zabbix_server/templates/zabbix.conf.j2 
[zabbix]
user = nginx
group = nginx

listen = /run/php-fpm/zabbix.sock
listen.acl_users = apache,nginx
listen.allowed_clients = 127.0.0.1

pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 200

php_value[session.save_handler] = files
php_value[session.save_path]    = /var/lib/php/session

php_value[max_execution_time] = 300
php_value[memory_limit] = 128M
php_value[post_max_size] = 80M
php_value[upload_max_filesize] = 80M
php_value[max_input_time] = 300
php_value[max_input_vars] = 10000
php_value[date.timezone] = Asia/Shanghai

[20:38:05 root@ansible-rocky zabbix_server]$ grep -Ev '^$|#' /opt/roles/zabbix_server/templates/zabbix_server.conf.j2 
LogFile=/var/log/zabbix/zabbix_server.log
LogFileSize=0
PidFile=/var/run/zabbix/zabbix_server.pid
SocketDir=/var/run/zabbix
DBHost=10.0.0.58
DBName=zabbix
DBUser=zabbix
DBPassword=lgq123456
SNMPTrapperFile=/var/log/snmptrap/snmptrap.log
Timeout=4
AlertScriptsPath=/usr/lib/zabbix/alertscripts
ExternalScripts=/usr/lib/zabbix/externalscripts
LogSlowQueries=3000
StatsAllowedIP=127.0.0.1
##zabbix網頁配置文件
[20:39:05 root@ansible-rocky zabbix_server]$ cat /opt/roles/zabbix_server/templates/zabbix-server-ngx.conf.j2
server {
    listen 80;
    server_name {{ zabbix_fqdn }};
    root /usr/share/zabbix;
    index index.php;
    location = /favicon.ico {
        log_not_found   off;
    }

    location / {
        try_files       $uri $uri/ =404;
    }

    location /assets {
         access_log      off;
         expires         10d;
    }

    location ~ /\.ht {
         deny            all;
    }

    location ~ /(api\/|conf[^\.]|include|locale|vendor) {
         deny            all;
         return          404;
    }
    location ~ [^/]\.php(/|$) {
        fastcgi_pass   127.0.0.1:9000;
        #fastcgi_pass    unix:/run/php-fpm/zabbix.sock;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_index   index.php;

        fastcgi_param   DOCUMENT_ROOT   /usr/share/zabbix;
        fastcgi_param   SCRIPT_FILENAME /usr/share/zabbix$fastcgi_script_name;
        fastcgi_param   PATH_TRANSLATED /usr/share/zabbix$fastcgi_script_name;

        include fastcgi_params;
        fastcgi_param   QUERY_STRING    $query_string;
        fastcgi_param   REQUEST_METHOD  $request_method;
        fastcgi_param   CONTENT_TYPE    $content_type;
        fastcgi_param   CONTENT_LENGTH  $content_length;

        fastcgi_intercept_errors        on;
        fastcgi_ignore_client_abort     off;
        fastcgi_connect_timeout         60;
        fastcgi_send_timeout            180;
        fastcgi_read_timeout            180;
        fastcgi_buffer_size             128k;
        fastcgi_buffers                 4 256k;
        fastcgi_busy_buffers_size       256k;
        fastcgi_temp_file_write_size    256k;
    }

}

4.2.2 部署zabbix-agent

#目錄結構
[22:59:31 root@ansible-rocky zabbix_agent2]$ tree
.
├── files
│   └── zabbix_agnet2.d
│       ├── login.conf
│       ├── mem.conf
│       ├── mysql.conf
│       ├── mysql_repl_status.sh
│       ├── mysql.sh
│       ├── nginx_status.conf
│       ├── nginx_status.sh
│       └── tcp_state.conf
├── handlers
│   └── main.yml
├── tasks
│   └── main.yml
└── templates
    └── zabbix_agent2.conf.j2

5 directories, 11 files

#task文件
[23:14:12 root@ansible-rocky opt]$ cat /opt/roles/zabbix_agent2/tasks/main.yml 
- name: install repo 
  yum_repository:
    name: "ansible_zabbix"
    description: "zabbix repo"
    baseurl: "https://mirrors.aliyun.com/zabbix/zabbix/{{ zabbix_version }}/rhel/{{ ansible_distribution_major_version }}/{{ ansible_architecture }}/"
    gpgcheck: yes
    gpgkey: "https://mirrors.aliyun.com/zabbix/zabbix-official-repo.key"

- name: install agent2 for centos or rocky
  yum:
    name: zabbix-agent2
  when: 
    - ansible_distribution == "Rocky" or ansible_distribution == "Centos"

- name: install agent2 for centos or ubuntu
  apt:
    name: zabbix-agent2
    update_cache: yes
  when:
    - ansible_distribution == "Ubuntu"

- name: config file
  template:
    src: zabbix_agent2.conf.j2
    dest: "/etc/zabbix/zabbix_agent2.conf"
    mode: 0644
  notify:
    - restart zabbix-agent2

- name: copy zabbix-agent2.d content
  copy:
    src: zabbix_agent2.d
    dest: "/etc/zabbix"
  notify:
    - restart zabbix-agent2
  tags: zabbix_agent2.d

- name: start zabbix-agent2
  service:
    name: zabbix-agent2
    state: started
    enabled: yes
    
#handler文件
[23:14:14 root@ansible-rocky opt]$ cat /opt/roles/zabbix_agent2/handlers/main.yml 
- name: restart zabbix_agent2
  service:
    name: zabbix-agent2
    state: restarted
    
#template文件
[23:14:43 root@ansible-rocky opt]$ cat /opt/roles/zabbix_agent2/templates/zabbix_agent2.conf.j2 
PidFile=/var/run/zabbix/zabbix_agent2.pid
LogFile=/var/log/zabbix/zabbix_agent2.log
LogFileSize=0
Server={{ zabbix_server_ip }}
ServerActive={{ zabbix_server_ip }}
Hostname={{ ansible_default_ipv4.address }}
Include=/etc/zabbix/zabbix_agent2.d/*.conf
ControlSocket=/tmp/agent.sock

4.2.3 測試

[23:15:29 root@rocky8 /etc/zabbix]$ zabbix_get -s 10.0.0.18 -k mem_use_percent
20.1886
[23:16:51 root@rocky8 /etc/zabbix]$ zabbix_get -s 10.0.0.18 -k tcp_state[ESTABLISHED]
32
[23:17:30 root@rocky8 /etc/zabbix]$ zabbix_get -s 10.0.0.28 -k tcp_state[ESTABLISHED]
28
[23:17:35 root@rocky8 /etc/zabbix]$ zabbix_get -s 10.0.0.58 -k tcp_state[ESTABLISHED]
55

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 互聯網世界里最流行的開源關係型資料庫之一就是MySQL/MariaDB了,由於高度的相似,故而直接使用mysql統一指稱。 ...
  • 項目地址:https://github.com/pikeduo/TXTReader PyQt5中文手冊:https://maicss.gitbook.io/pyqt-chinese-tutoral/pyqt5/ QtDesigner學習地址:https://youcans.blog.csdn.net ...
  • 14. 最長公共首碼 題目描述 編寫一個函數來查找字元串數組中的最長公共首碼。 如果不存在公共首碼,返回空字元串 ""。 方法 暴力演算法 先判斷字元串數組是否有為空,為空直接返回空 令第一個字元串作為基準進行比較 設置一個長度,作為最後最長公共首碼的長度 迴圈判斷,選取最小長度 代碼 package ...
  • 2023-01-09 一、在IDEA中創建Maven版的web工程 (1)步驟: ①創建一個maven模塊,命名為“maven_web_end”,之後需要創建web工程的目錄。在“maven_web_end.src.main”下創建“webapp”文件夾(命名必須為webapp,否則識別不了);在“ ...
  • 作者:小牛呼嚕嚕 | https://xiaoniuhululu.com 電腦內功、JAVA底層、面試相關資料等更多精彩文章在公眾號「小牛呼嚕嚕 」 大家好,我是呼嚕嚕,這次我們一起來看看Java記憶體區域,本文 基於HotSpot 虛擬機,JDK8, 乾貨滿滿 前言 Java 記憶體區域, 也叫運行 ...
  • Excelize 是 Go 語言編寫的用於操作 Office Excel 文檔基礎庫,支持 XLAM / XLSM / XLSX / XLTM / XLTX 等多種文檔格式。2023年1月9日,社區正式發佈了 2.7.0 版本,該版本包含了多項新增功能、錯誤修複和相容性提升優化。 ...
  • ThreadLocal是一個關於創建線程局部變數的類。 通常情況下,我們創建的變數是可以被任何一個線程訪問並修改的。而使用ThreadLocal創建的變數只能被當前線程訪問,其他線程則無法訪問和修改。ThreadLocal在設計之初就是為解決併發問題而提供一種方案,每個線程維護一份自己的數據,達到線... ...
  • 移動滑鼠到你想要的位置,然後進行點擊,某些時候是很有用的 using System; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms; private void button ...
一周排行
    -Advertisement-
    Play Games
  • GoF之工廠模式 @目錄GoF之工廠模式每博一文案1. 簡單說明“23種設計模式”1.2 介紹工廠模式的三種形態1.3 簡單工廠模式(靜態工廠模式)1.3.1 簡單工廠模式的優缺點:1.4 工廠方法模式1.4.1 工廠方法模式的優缺點:1.5 抽象工廠模式1.6 抽象工廠模式的優缺點:2. 總結:3 ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...