From 84e7334cc0a3119f98c19c490dcebadb342d8d2c Mon Sep 17 00:00:00 2001 From: dwe Date: Mon, 18 Mar 2024 23:48:45 +0800 Subject: [PATCH] ADD Notes --- ...5\222\214shell\346\250\241\345\235\227.md" | 75 + .../Ansible-copy\346\250\241\345\235\227.md" | 119 ++ .../Ansible-cron\346\250\241\345\235\227.md" | 90 + .../Ansible-fetch\346\250\241\345\235\227.md" | 45 + .../Ansible-file\346\250\241\345\235\227.md" | 295 +++ .../Ansible-group\346\250\241\345\235\227.md" | 78 + ...sible-hostname\346\250\241\345\235\227.md" | 29 + ...sible-playbook\345\211\247\346\234\254.md" | 239 +++ .../Ansible-role.md" | 238 +++ ...Ansible-script\346\250\241\345\235\227.md" | 160 ++ ...nsible-service\346\250\241\345\235\227.md" | 449 +++++ .../Ansible-setup\346\250\241\345\235\227.md" | 167 ++ .../Ansible-stat\346\250\241\345\235\227.md" | 67 + .../Ansible-user\346\250\241\345\235\227.md" | 127 ++ ...yum_repository\346\250\241\345\235\227.md" | 78 + .../Ansible-yum\346\250\241\345\235\227.md" | 92 + ...75\344\273\244\347\224\250\346\263\225.md" | 49 + ...63\345\217\260\351\203\250\347\275\262.md" | 387 ++++ ...63\345\217\260\345\210\235\350\257\206.md" | 111 ++ .../git \346\227\245\345\277\227.md" | 103 + .../gitlab\344\275\277\347\224\250.md" | 195 ++ ...75\344\270\216\350\277\230\345\216\237.md" | 79 + .../gitlab\351\203\250\347\275\262.md" | 145 ++ .../git\344\273\213\347\273\215.md" | 45 + ...23\345\272\223\347\211\271\346\200\247.md" | 191 ++ ...70\347\224\250\345\221\275\344\273\244.md" | 411 ++++ ...10\345\271\266\345\210\206\346\224\257.md" | 160 ++ ...47\345\210\266\347\263\273\347\273\237.md" | 23 + ...\210\260github\345\205\254\345\272\223.md" | 230 +++ ...16\345\210\235\345\247\213\345\214\226.md" | 93 + ...71\345\231\250\347\274\226\346\216\222.md" | 164 ++ ...73\346\234\272\347\274\226\346\216\222.md" | 195 ++ .../Docker \347\275\221\347\273\234.md" | 363 ++++ .../Dockerfile.md" | 383 ++++ .../Docker\345\256\211\350\243\205.md" | 128 ++ ...71\345\231\250\347\256\241\347\220\206.md" | 352 ++++ ...er\347\232\204\344\273\213\347\273\215.md" | 159 ++ ...01\346\234\211\344\273\223\345\272\223.md" | 514 +++++ ...34\345\203\217\347\256\241\347\220\206.md" | 244 +++ .../RHEL Podman\345\221\275\344\273\244.md" | 411 ++++ .../HPA.md" | 186 ++ ...23\345\272\223\351\203\250\347\275\262.md" | 174 ++ .../Helm.md" | 295 +++ .../Job \344\270\216 Cronjob.md" | 133 ++ ...241\214\345\267\245\345\205\267kubectl.md" | 72 + ...tes NameSpace \344\273\213\347\273\215.md" | 26 + ...02\345\277\265\344\273\213\347\273\215.md" | 124 ++ ...21\347\273\234\344\273\213\347\273\215.md" | 30 + ...01\344\271\246\344\273\213\347\273\215.md" | 41 + ...06\347\276\244\351\203\250\347\275\262.md" | 420 ++++ ...44\351\253\230\345\217\257\347\224\250.md" | 495 +++++ ...71\345\222\214\345\256\271\345\277\215.md" | 108 ++ ...d \344\272\262\345\222\214\346\200\247.md" | 228 +++ ...44\347\211\214\347\256\241\347\220\206.md" | 185 ++ ...03\345\272\246\344\273\213\347\273\215.md" | 52 + ...44\270\216 PVC\344\273\213\347\273\215.md" | 129 ++ .../Pod \344\273\213\347\273\215.md" | 163 ++ .../Pod \347\232\204 NameSpace.md" | 58 + ...2\204 Service \344\273\213\347\273\215.md" | 65 + .../Pod \347\232\204 init Containers.md" | 109 ++ ...0\346\237\245-\346\216\242\351\222\210.md" | 153 ++ ...5\230\345\202\250\344\271\213Configmap.md" | 213 ++ ...\255\230\345\202\250\344\271\213Secret.md" | 130 ++ ...\255\230\345\202\250\344\271\213volume.md" | 113 ++ ...66\345\231\250\347\261\273\345\236\213.md" | 32 + .../Service Ingress.md" | 363 ++++ ...e \347\232\204\345\272\224\347\224\250.md" | 161 ++ ...20\346\216\247\345\210\266\345\231\250.md" | 34 + ...01\351\207\217\347\256\241\347\220\206.md" | 203 ++ .../istio \351\203\250\347\275\262.md" | 157 ++ ...16\345\217\257\350\247\206\345\214\226.md" | 69 + ...06\344\270\216\346\237\245\350\257\242.md" | 81 + ...15\345\212\241\346\262\273\347\220\206.md" | 73 + ...200\344\271\210\346\230\257 Kubernetes.md" | 56 + ...0 Jenkins \345\256\236\347\216\260CICD.md" | 262 +++ ...344\271\205\345\214\226\344\271\213NFS.md" | 226 +++ ...72\345\256\232\350\212\202\347\202\271.md" | 70 + ...06\345\205\245\346\216\247\345\210\266.md" | 283 +++ .../\346\220\255\345\273\272 Dashboard.md" | 504 +++++ .../\346\220\255\345\273\272 Prometheus.md" | 232 +++ ...73\347\232\204\346\255\245\351\252\244.md" | 47 + ...01\347\247\273\347\244\272\344\276\213.md" | 595 ++++++ ...0\266\345\231\250\344\271\213DaemonSet.md" | 32 + ...\266\345\231\250\344\271\213Deployment.md" | 85 + ...\345\210\266\345\231\250\344\271\213RS.md" | 57 + ...06\346\236\220\347\263\273\347\273\237.md" | 225 +++ ...11\345\205\250\344\273\213\347\273\215.md" | 69 + .../DHCP\346\234\215\345\212\241.md" | 704 +++++++ .../DNS\346\234\215\345\212\241.md" | 702 +++++++ ...66\346\234\215\345\212\241\345\231\250.md" | 538 ++++++ ...14\346\234\272\347\203\255\345\244\207.md" | 211 ++ ...64\346\234\215\345\212\241\345\231\250.md" | 178 ++ ...05\346\234\215\345\212\241\345\231\250.md" | 354 ++++ ...57\345\212\250\346\265\201\347\250\213.md" | 302 +++ ...01\347\233\230\347\256\241\347\220\206.md" | 151 ++ ...21\345\215\267\344\273\213\347\273\215.md" | 35 + ...44\350\241\214\344\273\213\347\273\215.md" | 75 + ...72\346\234\254\344\274\230\345\214\226.md" | 123 ++ ...70\347\224\250\347\254\246\345\217\267.md" | 337 ++++ ...15\345\212\241\344\273\213\347\273\215.md" | 94 + ...71\346\256\212\346\235\203\351\231\220.md" | 59 + ...36\346\200\247\347\256\241\347\220\206.md" | 92 + ...16\247\345\267\245\345\205\267-glances.md" | 256 +++ ...57\347\232\204\344\275\277\347\224\250.md" | 65 + ...54\347\274\226\350\276\221\345\231\250.md" | 260 +++ .../linux acl\346\235\203\351\231\220.md" | 139 ++ ...75\344\273\244\350\257\246\350\247\243.md" | 148 ++ .../linux shadow\346\226\207\344\273\266.md" | 130 ++ ...06\347\240\201\347\256\241\347\220\206.md" | 80 + ...16\346\240\274\345\274\217\345\214\226.md" | 128 ++ ...x \347\273\204\347\256\241\347\220\206.md" | 85 + ...21\347\273\234\347\256\241\347\220\206.md" | 229 +++ ...32\345\220\210\351\223\276\350\267\257.md" | 238 +++ ...41\345\210\222\344\273\273\345\212\241.md" | 312 +++ ...57\347\224\261\347\256\241\347\220\206.md" | 66 + ...33\347\250\213\347\256\241\347\220\206.md" | 415 ++++ ...20\350\227\217\346\235\203\351\231\220.md" | 43 + ...06\345\214\272\346\214\202\350\275\275.md" | 193 ++ ...70\350\247\201\351\227\256\351\242\230.md" | 96 + ...72\346\234\254\346\235\203\351\231\220.md" | 137 ++ ...51\344\270\216\350\247\243\345\216\213.md" | 200 ++ ...41\345\231\250\351\203\250\347\275\262.md" | 87 + ...45\345\277\227\347\256\241\347\220\206.md" | 295 +++ ...15\345\212\241\347\256\241\347\220\206.md" | 405 ++++ ...50\346\210\267\347\256\241\347\220\206.md" | 232 +++ ...36\346\210\230\346\241\210\344\276\213.md" | 119 ++ ...72\346\234\254\347\256\241\347\220\206.md" | 204 ++ ...7\220\206-RAID\344\273\213\347\273\215.md" | 98 + ...05\351\232\234\346\216\222\346\237\245.md" | 180 ++ ...70\345\205\263\350\256\276\347\275\256.md" | 122 ++ ...66\345\214\205\347\256\241\347\220\206.md" | 510 +++++ ...60\346\215\256\345\244\204\347\220\206.md" | 820 ++++++++ ...50\275\257raid\351\230\265\345\210\227.md" | 309 +++ ...50\351\200\273\350\276\221\345\215\267.md" | 189 ++ ...06\346\234\215\345\212\241\345\231\250.md" | 201 ++ ...0\247\243linux\346\226\207\344\273\266.md" | 145 ++ ...4\276\213-swap\345\210\206\345\214\272.md" | 101 + ...70\350\247\201\346\223\215\344\275\234.md" | 104 + ...21\345\215\267\345\272\224\347\224\250.md" | 171 ++ ...21\345\215\267\346\211\251\345\256\271.md" | 90 + ...21\345\215\267\350\243\201\345\211\252.md" | 116 ++ ...70\347\224\250\345\221\275\344\273\244.md" | 131 ++ ...04\346\272\220\351\231\220\345\210\266.md" | 189 ++ .../DDL\350\257\255\345\217\245.md" | 627 ++++++ .../DML\350\257\255\345\217\245.md" | 261 +++ .../DQL-limit\345\210\206\351\241\265.md" | 106 + ...41\347\263\212\346\237\245\350\257\242.md" | 192 ++ ...32\345\220\210\345\207\275\346\225\260.md" | 224 +++ .../DQL\350\257\255\345\217\245.md" | 606 ++++++ ...17\344\270\216\345\210\206\347\273\204.md" | 213 ++ .../MySQL AB\345\244\215\345\210\266.md" | 398 ++++ .../MySQL DCL\350\257\255\345\217\245.md" | 239 +++ ...30\345\202\250\350\277\207\347\250\213.md" | 1065 ++++++++++ .../MySQL \347\264\242\345\274\225.md" | 554 ++++++ .../MySQL\344\272\213\345\212\241.md" | 869 +++++++++ ...41\345\236\213\345\256\236\346\210\230.md" | 102 + ...QL\345\255\220\346\237\245\350\257\242.md" | 242 +++ ...70\347\224\250\345\207\275\346\225\260.md" | 1411 ++++++++++++++ ...75\344\270\216\350\277\230\345\216\237.md" | 92 + .../MySQL\347\272\246\346\235\237.md" | 1066 ++++++++++ .../MySQL\350\247\206\345\233\276.md" | 520 +++++ ...05\344\270\216\344\275\277\347\224\250.md" | 255 +++ ...ql\345\256\242\346\210\267\347\253\257.md" | 141 ++ .../SQL\344\273\213\347\273\215.md" | 51 + ...36\346\216\245\346\237\245\350\257\242.md" | 282 +++ ...56\345\272\223\344\273\213\347\273\215.md" | 65 + ...56\345\272\223\350\256\276\350\256\241.md" | 130 ++ ...13\351\227\264\345\205\263\347\263\273.md" | 315 +++ ...73\344\273\216\345\244\215\345\210\266.md" | 352 ++++ ...75\344\273\244\346\223\215\344\275\234.md" | 339 ++++ ...50\345\205\265\346\250\241\345\274\217.md" | 317 +++ ...56\346\214\201\344\271\205\345\214\226.md" | 506 +++++ ...60\346\215\256\347\261\273\345\236\213.md" | 1721 +++++++++++++++++ .../Redis \351\233\206\347\276\244.md" | 391 ++++ ...41\345\231\250\351\203\250\347\275\262.md" | 223 +++ ...06\345\217\221\347\256\227\346\263\225.md" | 269 +++ ...64\347\232\204\345\210\206\345\217\221.md" | 237 +++ ...06\347\276\244\344\273\213\347\273\215.md" | 44 + ...350\257\206LVS\351\233\206\347\276\244.md" | 141 ++ ...\275\262LVS DR\351\233\206\347\276\244.md" | 163 ++ ...275\262LVS NAT\351\233\206\347\276\244.md" | 131 ++ ...275\262LVS TUN\351\233\206\347\276\244.md" | 117 ++ ...5\262nginx web\351\233\206\347\276\244.md" | 207 ++ ...06\347\276\244\344\273\213\347\273\215.md" | 74 + ...13\345\212\233\346\265\213\350\257\225.md" | 111 ++ ...RL\351\207\215\345\256\232\345\220\221.md" | 170 ++ .../Apache \344\273\213\347\273\215.md" | 71 + ...67\347\253\257\347\274\223\345\255\230.md" | 60 + ...6-\351\225\277\350\277\236\346\216\245.md" | 69 + ...32\346\213\237\344\270\273\346\234\272.md" | 238 +++ ...30\350\256\244\347\275\221\347\253\231.md" | 1047 ++++++++++ ...73\345\275\225\351\252\214\350\257\201.md" | 72 + ...77\351\227\256\346\216\247\345\210\266.md" | 52 + ...13\350\275\275\351\231\220\351\200\237.md" | 97 + ...60\346\215\256\345\216\213\347\274\251.md" | 77 + ...41\345\235\227\344\274\230\345\214\226.md" | 331 ++++ ...31\347\202\271\344\270\212\347\272\277.md" | 100 + ...he\346\234\215\345\212\241\345\231\250.md" | 200 ++ ...\262lamp-MySQL\345\256\211\350\243\205.md" | 138 ++ ...11\350\243\205\346\214\207\345\215\227.md" | 391 ++++ ...63\345\217\260\351\233\206\346\210\220.md" | 141 ++ .../Nginx url \351\207\215\345\206\231.md" | 230 +++ .../Nginx\344\273\213\347\273\215.md" | 33 + .../Nginx\344\274\230\345\214\226.md" | 112 ++ ...11\350\243\205\351\203\250\347\275\262.md" | 82 + ...13\350\275\275\351\231\220\351\200\237.md" | 151 ++ ...15\345\220\221\344\273\243\347\220\206.md" | 100 + ...32\346\213\237\344\270\273\346\234\272.md" | 107 + ...30\350\256\244\347\275\221\347\253\231.md" | 118 ++ ...50\346\200\201\351\241\265\351\235\242.md" | 50 + ...15\347\275\256\346\226\207\344\273\266.md" | 141 ++ .../Tomcat\344\273\213\347\273\215.md" | 47 + ...13\345\212\233\346\265\213\350\257\225.md" | 100 + ...31\346\200\201\351\241\265\351\235\242.md" | 79 + ...at\345\244\232\345\256\236\344\276\213.md" | 60 + .../Tomcat\350\260\203\344\274\230.md" | 168 ++ ...ux\346\234\215\345\212\241\345\231\250.md" | 103 + ...ws\346\234\215\345\212\241\345\231\250.md" | 51 + ...\270\203tomcat\347\253\231\347\202\271.md" | 126 ++ .../for\345\265\214\345\245\227.md" | 77 + ...4\270\216shell\350\277\220\347\256\227.md" | 166 ++ ...30\347\272\247\347\224\250\346\263\225.md" | 67 + ...60\347\273\204\350\257\246\350\247\243.md" | 170 ++ .../shell\345\207\275\346\225\260.md" | 141 ++ ...30\351\207\217\350\257\246\350\247\243.md" | 342 ++++ ...66\347\232\204\346\223\215\344\275\234.md" | 618 ++++++ ...11\344\270\216\345\244\204\347\220\206.md" | 612 ++++++ ...44\346\226\255\350\257\255\345\217\245.md" | 425 ++++ ...75\344\273\244\345\244\215\344\271\240.md" | 450 +++++ ...32\346\234\254\344\273\213\347\273\215.md" | 51 + ...30\345\210\235\345\247\213\345\214\226.md" | 115 ++ ...17\345\214\226\350\276\223\345\207\272.md" | 162 ++ ...11\350\243\205\350\204\232\346\234\254.md" | 95 + ...07\344\273\275\350\204\232\346\234\254.md" | 99 + ...11\350\243\205\350\204\232\346\234\254.md" | 110 ++ ...21\346\216\247\350\204\232\346\234\254.md" | 88 + ...15\345\212\241\347\212\266\346\200\201.md" | 71 + ...44\346\226\255\351\227\260\345\271\264.md" | 57 + ...30\344\275\277\347\224\250\347\216\207.md" | 68 + ...21\346\216\247\346\216\245\345\217\243.md" | 82 + ...30\344\275\277\347\224\250\347\216\207.md" | 68 + ...21\345\215\241\346\265\201\351\207\217.md" | 95 + ...56\345\275\225\345\210\244\346\226\255.md" | 37 + ...50\346\210\267\344\272\244\344\272\222.md" | 68 + ...71\351\244\220\347\263\273\347\273\237.md" | 79 + ...20\347\256\227\350\257\246\350\247\243.md" | 640 ++++++ ...47\345\210\266\350\257\255\345\217\245.md" | 174 ++ ...31\350\241\250\350\276\276\345\274\217.md" | 282 +++ ...5\210\266-case\350\257\255\345\217\245.md" | 150 ++ ...52\347\216\257\350\257\255\345\217\245.md" | 219 +++ ...\210\266-until\350\257\255\345\217\245.md" | 51 + ...\210\266-while\345\276\252\347\216\257.md" | 352 ++++ ...4\270\216shell\350\204\232\346\234\254.md" | 228 +++ .../Zabbix web\347\233\221\346\265\213,md" | 51 + ...53\345\212\250\347\233\221\346\216\247.md" | 33 + ...41\346\235\277\347\256\241\347\220\206.md" | 132 ++ ...50\346\210\267\347\256\241\347\220\206.md" | 55 + ...22\344\273\266\345\256\211\350\243\205.md" | 89 + ...21\346\216\247\346\212\245\350\255\246.md" | 116 ++ ...21\346\216\247\347\263\273\347\273\237.md" | 251 +++ ...21\346\216\247\344\273\213\347\273\215.md" | 39 + ...76\345\203\217\345\261\225\347\244\272.md" | 47 + ...21\346\216\247\344\273\213\347\273\215.md" | 71 + ...41\346\234\215\345\212\241\345\231\250.md" | 93 + ...32\345\212\241\346\234\272\345\231\250.md" | 156 ++ ...76\345\256\232\351\230\210\345\200\274.md" | 27 + ...52\347\233\221\346\216\247\351\241\271.md" | 104 + ...21\346\216\247\345\271\263\345\217\260.md" | 191 ++ .../Grafana\346\212\245\350\255\246.md" | 47 + ...21\346\216\247\344\273\213\347\273\215.md" | 50 + ...60\346\215\256\345\261\225\347\244\272.md" | 231 +++ ...00\344\270\252\344\270\232\345\212\241.md" | 76 + ...52\344\270\232\345\212\241\346\234\272.md" | 63 + ...21\346\216\247\345\271\263\345\217\260.md" | 65 + ...66\346\234\215\345\212\241\345\231\250.md" | 316 +++ ...66\346\234\215\345\212\241\345\231\250.md" | 844 ++++++++ ...\217\345\255\230\345\202\250-GlusterFS.md" | 810 ++++++++ ...45\345\277\227\346\224\266\351\233\206.md" | 387 ++++ ...60\346\215\256\351\207\207\351\233\206.md" | 258 +++ ...60\346\215\256\345\261\225\347\244\272.md" | 213 ++ ...2\351\203\250\347\275\262Elasticsearch.md" | 317 +++ ...206mysql slow \346\227\245\345\277\227.md" | 546 ++++++ ...60\346\215\256\347\256\241\347\220\206.md" | 105 + ...2Elasticsearch\351\233\206\347\276\244.md" | 117 ++ .../ELK\344\273\213\347\273\215.md" | 165 ++ ...inx access_log\346\227\245\345\277\227.md" | 110 ++ ...205\267ES-Head\345\272\224\347\224\250.md" | 124 ++ ...205\267ES-Head\351\203\250\347\275\262.md" | 359 ++++ ...34\347\250\213\346\241\214\351\235\242.md" | 89 + ...72\350\231\232\346\213\237\346\234\272.md" | 754 ++++++++ ...73\347\273\237\345\256\211\350\243\205.md" | 94 + ...37\346\234\272\345\205\213\351\232\206.md" | 132 ++ ...66\345\217\260\350\277\236\346\216\245.md" | 24 + ...37\345\214\226\351\203\250\347\275\262.md" | 295 +++ ...72\347\203\255\346\211\251\345\256\271.md" | 269 +++ ...37\346\234\272\347\256\241\347\220\206.md" | 279 +++ ...21\347\273\234\350\256\276\347\275\256.md" | 68 + ...37\346\234\272\350\277\201\347\247\273.md" | 110 ++ ...73\346\234\272\350\256\276\347\275\256.md" | 73 + ...344\270\216KVM\344\273\213\347\273\215.md" | 166 ++ .../IP\345\234\260\345\235\200.md" | 264 +++ ...21\347\273\234\346\250\241\345\236\213.md" | 82 + ...21\347\273\234\346\250\241\345\236\213.md" | 43 + ...23\345\261\202\345\215\217\350\256\256.md" | 41 + ...21\347\273\234\344\273\213\347\273\215.md" | 99 + ...41\345\231\250\351\203\250\347\275\262.md" | 107 + ...7\224\250nginx\351\233\206\347\276\244.md" | 230 +++ ...57\347\224\250\351\233\206\347\276\244.md" | 243 +++ Linux/zabbix.md | 138 ++ 309 files changed, 64342 insertions(+) create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-command\346\250\241\345\235\227\345\222\214shell\346\250\241\345\235\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-copy\346\250\241\345\235\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-cron\346\250\241\345\235\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-fetch\346\250\241\345\235\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-file\346\250\241\345\235\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-group\346\250\241\345\235\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-hostname\346\250\241\345\235\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-playbook\345\211\247\346\234\254.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-role.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-script\346\250\241\345\235\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-service\346\250\241\345\235\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-setup\346\250\241\345\235\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-stat\346\250\241\345\235\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-user\346\250\241\345\235\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-yum_repository\346\250\241\345\235\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-yum\346\250\241\345\235\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible\345\221\275\344\273\244\347\224\250\346\263\225.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260\351\203\250\347\275\262.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible\350\277\220\347\273\264\350\207\252\345\212\250\345\214\226\345\271\263\345\217\260\345\210\235\350\257\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/git \346\227\245\345\277\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/gitlab\344\275\277\347\224\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/gitlab\345\244\207\344\273\275\344\270\216\350\277\230\345\216\237.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/gitlab\351\203\250\347\275\262.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/git\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/git\344\273\223\345\272\223\351\205\215\347\275\256\345\217\212\344\273\223\345\272\223\347\211\271\346\200\247.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/git\345\270\270\347\224\250\345\221\275\344\273\244.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/\344\273\243\347\240\201\345\220\210\345\271\266\345\210\206\346\224\257.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/\344\273\243\347\240\201\347\211\210\346\234\254\346\216\247\345\210\266\347\263\273\347\273\237.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/\345\260\206\344\273\243\347\240\201\344\274\240\345\210\260github\345\205\254\345\272\223.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/\346\234\254\345\234\260git\345\256\211\350\243\205\344\270\216\345\210\235\345\247\213\345\214\226.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker Compose\345\256\271\345\231\250\347\274\226\346\216\222.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker Swarm\344\270\273\346\234\272\347\274\226\346\216\222.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker \347\275\221\347\273\234.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Dockerfile.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\345\256\211\350\243\205.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\345\256\271\345\231\250\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\347\232\204\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\351\225\234\345\203\217\347\247\201\346\234\211\344\273\223\345\272\223.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\351\225\234\345\203\217\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/RHEL Podman\345\221\275\344\273\244.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/HPA.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Harbor \351\225\234\345\203\217\344\273\223\345\272\223\351\203\250\347\275\262.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Helm.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Job \344\270\216 Cronjob.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kebetnetes\345\221\275\344\273\244\350\241\214\345\267\245\345\205\267kubectl.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes NameSpace \344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \346\246\202\345\277\265\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \347\275\221\347\273\234\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \350\257\201\344\271\246\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \351\233\206\347\276\244\351\203\250\347\275\262.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \351\233\206\347\276\244\351\253\230\345\217\257\347\224\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes\346\261\241\347\202\271\345\222\214\345\256\271\345\277\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes\350\212\202\347\202\271\344\270\216 Pod \344\272\262\345\222\214\346\200\247.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes\350\212\202\347\202\271\344\270\216\344\273\244\347\211\214\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes\351\233\206\347\276\244\350\260\203\345\272\246\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/PV \344\270\216 PVC\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204 NameSpace.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204 Service \344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204 init Containers.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\345\201\245\345\272\267\346\243\200\346\237\245-\346\216\242\351\222\210.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\345\255\230\345\202\250\344\271\213Configmap.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\345\255\230\345\202\250\344\271\213Secret.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\345\255\230\345\202\250\344\271\213volume.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250\347\261\273\345\236\213.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Service Ingress.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Service \347\232\204\345\272\224\347\224\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/StatefulSet\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/istio \346\265\201\351\207\217\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/istio \351\203\250\347\275\262.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/istio\345\210\206\345\270\203\345\274\217\350\277\275\350\270\252\344\270\216\345\217\257\350\247\206\345\214\226.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/istio\346\214\207\346\240\207\346\224\266\351\233\206\344\270\216\346\237\245\350\257\242.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/istio\351\233\206\347\276\244\346\234\215\345\212\241\346\262\273\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\344\273\200\344\271\210\346\230\257 Kubernetes.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\345\210\251\347\224\250 Jenkins \345\256\236\347\216\260CICD.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\214\201\344\271\205\345\214\226\344\271\213NFS.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\214\207\345\256\232pod\350\277\220\350\241\214\345\234\250\345\233\272\345\256\232\350\212\202\347\202\271.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\216\210\346\235\203\343\200\201\351\211\264\346\235\203\344\270\216\345\207\206\345\205\245\346\216\247\345\210\266.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\220\255\345\273\272 Dashboard.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\220\255\345\273\272 Prometheus.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\234\215\345\212\241\351\203\250\347\275\262\344\270\216\350\277\201\347\247\273\347\232\204\346\255\245\351\252\244.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\234\215\345\212\241\351\203\250\347\275\262\344\270\216\350\277\201\347\247\273\347\244\272\344\276\213.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250\344\271\213DaemonSet.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250\344\271\213Deployment.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250\344\271\213RS.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\351\203\250\347\275\262EFK pod\346\227\245\345\277\227\345\210\206\346\236\220\347\263\273\347\273\237.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\351\233\206\347\276\244\345\256\211\345\205\250\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/DHCP\346\234\215\345\212\241.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/DNS\346\234\215\345\212\241.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/FTP\346\226\207\344\273\266\346\234\215\345\212\241\345\231\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/Linux \345\217\214\346\234\272\347\203\255\345\244\207.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/Linux \346\227\266\351\227\264\346\234\215\345\212\241\345\231\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/\351\203\250\347\275\262linux\347\275\221\347\273\234\345\256\211\350\243\205\346\234\215\345\212\241\345\231\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/CentOS 8\345\220\257\345\212\250\346\265\201\347\250\213.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/GPT\347\243\201\347\233\230\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/LVM\351\200\273\350\276\221\345\215\267\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\345\221\275\344\273\244\350\241\214\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\345\237\272\346\234\254\344\274\230\345\214\226.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\345\237\272\346\234\254\345\221\275\344\273\244\344\270\216\345\270\270\347\224\250\347\254\246\345\217\267.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\346\234\215\345\212\241\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\347\211\271\346\256\212\346\235\203\351\231\220.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\347\233\256\345\275\225\347\273\223\346\236\204\345\222\214\346\226\207\344\273\266\345\261\236\346\200\247\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\347\263\273\347\273\237\347\233\221\346\216\247\345\267\245\345\205\267-glances.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\347\273\210\347\253\257\347\232\204\344\275\277\347\224\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/VIM\346\226\207\346\234\254\347\274\226\350\276\221\345\231\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux acl\346\235\203\351\231\220.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux nmcli\345\221\275\344\273\244\350\257\246\350\247\243.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux shadow\346\226\207\344\273\266.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \345\257\206\347\240\201\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \347\243\201\347\233\230\345\210\206\345\214\272\344\270\216\346\240\274\345\274\217\345\214\226.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \347\273\204\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \347\275\221\347\273\234\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \350\201\232\345\220\210\351\223\276\350\267\257.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \350\256\241\345\210\222\344\273\273\345\212\241.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \350\267\257\347\224\261\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \350\277\233\347\250\213\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \351\232\220\350\227\217\346\235\203\351\231\220.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\345\210\206\345\214\272\346\214\202\350\275\275.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\345\220\257\345\212\250\345\270\270\350\247\201\351\227\256\351\242\230.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\345\237\272\346\234\254\346\235\203\351\231\220.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\346\226\207\344\273\266\345\216\213\347\274\251\344\270\216\350\247\243\345\216\213.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\346\227\245\345\277\227\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\346\227\245\345\277\227\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\346\234\215\345\212\241\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\224\250\346\210\267\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\243\201\347\233\230\344\275\277\347\224\250\345\256\236\346\210\230\346\241\210\344\276\213.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\243\201\347\233\230\345\237\272\346\234\254\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\243\201\347\233\230\347\256\241\347\220\206-RAID\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\275\221\347\273\234\346\225\205\351\232\234\346\216\222\346\237\245.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\275\221\347\273\234\347\233\270\345\205\263\350\256\276\347\275\256.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\350\275\257\344\273\266\345\214\205\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/shell \346\225\260\346\215\256\345\244\204\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\345\210\233\345\273\272\344\270\200\344\270\252\350\275\257raid\351\230\265\345\210\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\345\210\233\345\273\272\351\253\230\345\217\257\347\224\250\351\200\273\350\276\221\345\215\267.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\227\245\345\277\227\347\256\241\347\220\206\346\234\215\345\212\241\345\231\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\346\267\261\345\205\245\347\220\206\350\247\243linux\346\226\207\344\273\266.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-swap\345\210\206\345\214\272.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-\345\205\266\344\273\226\345\270\270\350\247\201\346\223\215\344\275\234.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-\351\200\273\350\276\221\345\215\267\345\272\224\347\224\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-\351\200\273\350\276\221\345\215\267\346\211\251\345\256\271.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-\351\200\273\350\276\221\345\215\267\350\243\201\345\211\252.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\270\270\347\224\250\345\221\275\344\273\244.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\350\265\204\346\272\220\351\231\220\345\210\266\344\270\216\345\212\240\345\233\272/Cgroups\350\265\204\346\272\220\351\231\220\345\210\266.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DDL\350\257\255\345\217\245.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DML\350\257\255\345\217\245.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL-limit\345\210\206\351\241\265.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL-\346\250\241\347\263\212\346\237\245\350\257\242.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL-\350\201\232\345\220\210\345\207\275\346\225\260.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL\350\257\255\345\217\245.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL\350\257\255\345\217\245\346\216\222\345\272\217\344\270\216\345\210\206\347\273\204.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL AB\345\244\215\345\210\266.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL DCL\350\257\255\345\217\245.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL \345\255\230\345\202\250\350\277\207\347\250\213.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL \347\264\242\345\274\225.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\344\272\213\345\212\241.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\345\244\232\344\270\273\346\250\241\345\236\213\345\256\236\346\210\230.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\345\255\220\346\237\245\350\257\242.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\345\270\270\347\224\250\345\207\275\346\225\260.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\346\225\260\346\215\256\345\244\207\344\273\275\344\270\216\350\277\230\345\216\237.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\347\272\246\346\235\237.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\350\247\206\345\233\276.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySql\345\256\211\350\243\205\344\270\216\344\275\277\347\224\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySql\345\256\242\346\210\267\347\253\257.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/SQL\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/\345\244\232\350\241\250\350\277\236\346\216\245\346\237\245\350\257\242.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/\346\225\260\346\215\256\345\272\223\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/\346\225\260\346\215\256\345\272\223\350\256\276\350\256\241.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/\350\241\250\344\270\216\350\241\250\344\271\213\351\227\264\345\205\263\347\263\273.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \344\270\273\344\273\216\345\244\215\345\210\266.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \345\221\275\344\273\244\346\223\215\344\275\234.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \345\223\250\345\205\265\346\250\241\345\274\217.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \346\225\260\346\215\256\346\214\201\344\271\205\345\214\226.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \346\225\260\346\215\256\347\261\273\345\236\213.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \351\233\206\347\276\244.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/Nginx\345\210\206\345\217\221\347\256\227\346\263\225.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/Nginx\345\237\272\344\272\216\350\257\267\346\261\202\345\244\264\347\232\204\345\210\206\345\217\221.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/Nginx\351\233\206\347\276\244\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\350\256\244\350\257\206LVS\351\233\206\347\276\244.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\203\250\347\275\262LVS DR\351\233\206\347\276\244.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\203\250\347\275\262LVS NAT\351\233\206\347\276\244.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\203\250\347\275\262LVS TUN\351\233\206\347\276\244.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\203\250\347\275\262nginx web\351\233\206\347\276\244.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\233\206\347\276\244\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apacha\345\216\213\345\212\233\346\265\213\350\257\225.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache URL\351\207\215\345\256\232\345\220\221.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \347\253\231\347\202\271\344\274\230\345\214\226-\345\256\242\346\210\267\347\253\257\347\274\223\345\255\230.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \347\253\231\347\202\271\344\274\230\345\214\226-\351\225\277\350\277\236\346\216\245.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \350\231\232\346\213\237\344\270\273\346\234\272.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \351\273\230\350\256\244\347\275\221\347\253\231.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\345\256\211\345\205\250-\347\224\250\346\210\267\347\231\273\345\275\225\351\252\214\350\257\201.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\345\256\211\350\243\205-\347\224\250\346\210\267\350\256\277\351\227\256\346\216\247\345\210\266.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\347\253\231\347\202\271\344\274\230\345\214\226-\344\270\213\350\275\275\351\231\220\351\200\237.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\347\253\231\347\202\271\344\274\230\345\214\226-\346\225\260\346\215\256\345\216\213\347\274\251.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\347\253\231\347\202\271\344\274\230\345\214\226-\346\250\241\345\235\227\344\274\230\345\214\226.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/lamp\351\203\250\347\275\262-WordPress\347\253\231\347\202\271\344\270\212\347\272\277.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/\351\203\250\347\275\262Apache\346\234\215\345\212\241\345\231\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/\351\203\250\347\275\262lamp-MySQL\345\256\211\350\243\205.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/\351\203\250\347\275\262lamp-php\345\256\211\350\243\205\346\214\207\345\215\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/\351\203\250\347\275\262lamp-\345\271\263\345\217\260\351\233\206\346\210\220.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/Nginx url \351\207\215\345\206\231.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/Nginx\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/Nginx\344\274\230\345\214\226.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/Nginx\345\256\211\350\243\205\351\203\250\347\275\262.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/\344\270\213\350\275\275\351\231\220\351\200\237.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/\345\217\215\345\220\221\344\273\243\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/\350\231\232\346\213\237\344\270\273\346\234\272.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/\351\273\230\350\256\244\347\275\221\347\253\231.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat \345\217\221\345\270\203\345\212\250\346\200\201\351\241\265\351\235\242.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat \347\233\256\345\275\225\344\270\216\351\205\215\347\275\256\346\226\207\344\273\266.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\345\216\213\345\212\233\346\265\213\350\257\225.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\345\217\221\345\270\203\351\235\231\346\200\201\351\241\265\351\235\242.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\345\244\232\345\256\236\344\276\213.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\350\260\203\344\274\230.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\351\203\250\347\275\262\345\234\250linux\346\234\215\345\212\241\345\231\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\351\203\250\347\275\262\345\234\250windows\346\234\215\345\212\241\345\231\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/\344\275\277\347\224\250nginx\345\217\221\345\270\203tomcat\347\253\231\347\202\271.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/for\345\265\214\345\245\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/if\350\257\255\345\217\245\344\270\216shell\350\277\220\347\256\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/if\351\253\230\347\272\247\347\224\250\346\263\225.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell \346\225\260\347\273\204\350\257\246\350\247\243.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\345\207\275\346\225\260.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\345\217\230\351\207\217\350\257\246\350\247\243.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\345\257\271\346\226\207\344\273\266\347\232\204\346\223\215\344\275\234.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\346\225\260\346\215\256\347\255\233\351\200\211\344\270\216\345\244\204\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\346\265\201\347\250\213\346\216\247\345\210\266-if\345\210\244\346\226\255\350\257\255\345\217\245.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\344\270\255\345\270\270\347\224\250\345\221\275\344\273\244\345\244\215\344\271\240.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\345\256\236\346\210\230\346\241\210\344\276\213-\346\225\260\346\215\256\347\243\201\347\233\230\345\210\235\345\247\213\345\214\226.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\240\274\345\274\217\345\214\226\350\276\223\345\207\272.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-Python\345\256\211\350\243\205\350\204\232\346\234\254.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-mysql\345\244\207\344\273\275\350\204\232\346\234\254.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-nginx\345\256\211\350\243\205\350\204\232\346\234\254.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\344\270\273\346\234\272\347\212\266\346\200\201\347\233\221\346\216\247\350\204\232\346\234\254.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\345\210\244\346\226\255\346\234\215\345\212\241\347\212\266\346\200\201.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\345\210\244\346\226\255\351\227\260\345\271\264.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\221\346\216\247\345\206\205\345\255\230\344\275\277\347\224\250\347\216\207.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\221\346\216\247\346\216\245\345\217\243.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\221\346\216\247\347\243\201\347\233\230\344\275\277\347\224\250\347\216\207.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\221\346\216\247\347\275\221\345\215\241\346\265\201\351\207\217.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\256\345\275\225\345\210\244\346\226\255.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\347\224\250\346\210\267\344\272\244\344\272\222.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\277\220\347\256\227\345\256\236\346\210\230\346\241\210\344\276\213-KFC\347\202\271\351\244\220\347\263\273\347\273\237.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\277\220\347\256\227\350\257\246\350\247\243.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/\345\276\252\347\216\257\346\216\247\345\210\266\350\257\255\345\217\245.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/\346\265\201\347\250\213\346\216\247\345\210\266-case\350\257\255\345\217\245.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/\346\265\201\347\250\213\346\216\247\345\210\266-for\345\276\252\347\216\257\350\257\255\345\217\245.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/\346\265\201\347\250\213\346\216\247\345\210\266-until\350\257\255\345\217\245.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/\346\265\201\347\250\213\346\216\247\345\210\266-while\345\276\252\347\216\257.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/\347\274\226\347\250\213\350\257\255\350\250\200\344\270\216shell\350\204\232\346\234\254.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix web\347\233\221\346\265\213,md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \344\270\273\345\212\250\347\233\221\346\216\247\345\222\214\350\242\253\345\212\250\347\233\221\346\216\247.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \346\250\241\346\235\277\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \347\224\250\346\210\267\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \347\233\221\346\216\247\346\212\245\350\255\246-onealter\346\217\222\344\273\266\345\256\211\350\243\205.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \347\233\221\346\216\247\346\212\245\350\255\246.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix\345\210\206\345\270\203\345\274\217\347\233\221\346\216\247\347\263\273\347\273\237.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix\347\233\221\346\216\247\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix\347\233\221\346\216\247\345\233\276\345\203\217\345\261\225\347\244\272.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\346\234\215\345\212\241\345\231\250\347\233\221\346\216\247\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\347\233\221\346\216\247\346\241\210\344\276\213 \347\233\221\346\216\247\344\270\200\345\217\260\344\270\232\345\212\241\346\234\215\345\212\241\345\231\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\347\233\221\346\216\247\350\207\252\345\212\250\345\214\226-\350\207\252\345\212\250\346\267\273\345\212\240\344\270\232\345\212\241\346\234\272\345\231\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\347\273\231\347\233\221\346\216\247\351\241\271\350\256\276\345\256\232\351\230\210\345\200\274.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\350\207\252\345\256\232\344\271\211\344\270\200\344\270\252\347\233\221\346\216\247\351\241\271.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\351\203\250\347\275\262zabbix\347\233\221\346\216\247\345\271\263\345\217\260.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/Grafana\346\212\245\350\255\246.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/Prometheus\347\233\221\346\216\247\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/prometheus+Grafana\346\225\260\346\215\256\345\261\225\347\244\272.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/\344\275\277\347\224\250prometheus\347\233\221\346\216\247\344\270\200\344\270\252\344\270\232\345\212\241.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/\344\275\277\347\224\250prometheus\347\233\221\346\216\247\344\270\200\344\270\252\344\270\232\345\212\241\346\234\272.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/\351\203\250\347\275\262prometheus\347\233\221\346\216\247\345\271\263\345\217\260.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\225\260\346\215\256\345\256\211\345\205\250\344\271\213\344\274\201\344\270\232\345\255\230\345\202\250/NFS\346\226\207\344\273\266\346\234\215\345\212\241\345\231\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\225\260\346\215\256\345\256\211\345\205\250\344\271\213\344\274\201\344\270\232\345\255\230\345\202\250/Samba\346\226\207\344\273\266\346\234\215\345\212\241\345\231\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\225\260\346\215\256\345\256\211\345\205\250\344\271\213\344\274\201\344\270\232\345\255\230\345\202\250/\345\210\206\345\270\203\345\274\217\345\255\230\345\202\250-GlusterFS.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-Logstash\346\227\245\345\277\227\346\224\266\351\233\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-beats\346\225\260\346\215\256\351\207\207\351\233\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-kibana\346\225\260\346\215\256\345\261\225\347\244\272.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-\345\215\225\346\234\272\351\203\250\347\275\262Elasticsearch.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-\346\224\266\351\233\206mysql slow \346\227\245\345\277\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-\346\225\260\346\215\256\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-\351\203\250\347\275\262Elasticsearch\351\233\206\347\276\244.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK\346\224\266\351\233\206nginx access_log\346\227\245\345\277\227.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK\346\225\260\346\215\256\347\256\241\347\220\206\345\267\245\345\205\267ES-Head\345\272\224\347\224\250.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK\346\225\260\346\215\256\347\256\241\347\220\206\345\267\245\345\205\267ES-Head\351\203\250\347\275\262.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\231\232\346\213\237\345\214\226\344\271\213KVM/CentOS 8 VNC\350\277\234\347\250\213\346\241\214\351\235\242.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\231\232\346\213\237\345\214\226\344\271\213KVM/KVM \345\272\224\347\224\250-\345\210\233\345\273\272\350\231\232\346\213\237\346\234\272.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\231\232\346\213\237\345\214\226\344\271\213KVM/KVM \350\231\232\346\213\237\346\234\272\347\263\273\347\273\237\345\256\211\350\243\205.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\231\232\346\213\237\345\214\226\344\271\213KVM/KVM-\350\231\232\346\213\237\346\234\272\345\205\213\351\232\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\231\232\346\213\237\345\214\226\344\271\213KVM/KVM\346\216\247\345\210\266\345\217\260\350\277\236\346\216\245.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\231\232\346\213\237\345\214\226\344\271\213KVM/KVM\350\231\232\346\213\237\345\214\226\351\203\250\347\275\262.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\231\232\346\213\237\345\214\226\344\271\213KVM/KVM\350\231\232\346\213\237\346\234\272\347\203\255\346\211\251\345\256\271.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\231\232\346\213\237\345\214\226\344\271\213KVM/KVM\350\231\232\346\213\237\346\234\272\347\256\241\347\220\206.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\231\232\346\213\237\345\214\226\344\271\213KVM/KVM\350\231\232\346\213\237\346\234\272\347\275\221\347\273\234\350\256\276\347\275\256.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\231\232\346\213\237\345\214\226\344\271\213KVM/KVM\350\231\232\346\213\237\346\234\272\350\277\201\347\247\273.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\231\232\346\213\237\345\214\226\344\271\213KVM/KVM\351\203\250\347\275\262\345\217\212\345\272\224\347\224\250-\345\256\277\344\270\273\346\234\272\350\256\276\347\275\256.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\231\232\346\213\237\345\214\226\344\271\213KVM/\350\231\232\346\213\237\345\214\226\344\270\216KVM\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\345\237\272\347\241\200/IP\345\234\260\345\235\200.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\345\237\272\347\241\200/OSI\344\270\203\345\261\202\347\275\221\347\273\234\346\250\241\345\236\213.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\345\237\272\347\241\200/TCPIP\345\233\233\345\261\202\347\275\221\347\273\234\346\250\241\345\236\213.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\345\237\272\347\241\200/\344\274\240\350\276\223\345\261\202\345\215\217\350\256\256.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\345\237\272\347\241\200/\350\256\241\347\256\227\346\234\272\347\275\221\347\273\234\344\273\213\347\273\215.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\351\203\250\347\275\262\351\253\230\345\217\257\347\224\250\351\233\206\347\276\244/keepalived\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\351\203\250\347\275\262\351\253\230\345\217\257\347\224\250\351\233\206\347\276\244/\346\236\204\345\273\272\351\253\230\345\217\257\347\224\250nginx\351\233\206\347\276\244.md" create mode 100644 "Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\351\203\250\347\275\262\351\253\230\345\217\257\347\224\250\351\233\206\347\276\244/\351\203\250\347\275\262LVS\351\253\230\345\217\257\347\224\250\351\233\206\347\276\244.md" diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-command\346\250\241\345\235\227\345\222\214shell\346\250\241\345\235\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-command\346\250\241\345\235\227\345\222\214shell\346\250\241\345\235\227.md" new file mode 100644 index 0000000..51fce4d --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-command\346\250\241\345\235\227\345\222\214shell\346\250\241\345\235\227.md" @@ -0,0 +1,75 @@ +ansible command与shell模块 + +两个模块都是用于执行linux命令的,这对于命令熟悉的工程师来说,用起来非常high。 + +shell模块与command模块差不多(command模块不能执行一些类似$HOME,>,<,|等符号,但shell可以) + +https://docs.ansible.com/ansible/latest/modules/command_module.html + +https://docs.ansible.com/ansible/latest/modules/shell_module.html + +## 一、shell模块 + +``` +[root@manage01 ~]# ansible -m shell 192.168.98.201 -a "ls /root" +192.168.98.201 | CHANGED | rc=0 >> +公共 +模板 +视频 +图片 +文档 +下载 +音乐 +桌面 +anaconda-ks.cfg +initial-setup-ks.cfg +nginx.service +nginx_study + + +[root@manage01 ~]# ansible -m shell 192.168.98.201 -a "echo 'hello world' > /tmp/baishuming" +192.168.98.201 | CHANGED | rc=0 >> + + +[root@manage01 ~]# ansible -m shell 192.168.98.201 -a "cat /tmp/baishuming" +192.168.98.201 | CHANGED | rc=0 >> +hello world + + +注意shell模块不是什么命令都能使用,比如vim这样的交互命令,不建议大家去记忆哪些命令不可以,大家只要养成任何在生产环境里的命令都要先在测试环境里测试一下的习惯就好。 +``` + +## 二、command模块 + +``` +[root@manage01 ~]# ansible -m command 192.168.98.201 -a "ls /root" +192.168.98.201 | CHANGED | rc=0 >> +公共 +模板 +视频 +图片 +文档 +下载 +音乐 +桌面 +anaconda-ks.cfg +initial-setup-ks.cfg +nginx.service +nginx_study + +[root@manage01 ~]# ansible -m command 192.168.98.201 -a "echo 'baism hello' > /tmp/baism_123" +192.168.98.201 | CHANGED | rc=0 >> +baism hello > /tmp/baism_123 + +[root@manage01 ~]# ansible -m command 192.168.98.201 -a "cat /tmp/baism_123" +192.168.98.201 | FAILED | rc=1 >> +cat: /tmp/baism_123: 没有那个文件或目录non-zero return code + + + +发现没有/tmp/baism_123 证明上一条命令未能执行成功 +``` + +## 三、学习视频 + +[视频: command与shell模块](https://www.bilibili.com/video/BV19J41167sM?p=23) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-copy\346\250\241\345\235\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-copy\346\250\241\345\235\227.md" new file mode 100644 index 0000000..e32c4af --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-copy\346\250\241\345\235\227.md" @@ -0,0 +1,119 @@ +## 一、copy模块(重点) + +copy模块用于对文件的远程拷贝操作(如把本地的文件拷贝到远程的机器上) + +https://docs.ansible.com/ansible/latest/modules/copy_module.html#copy-module + +| 参数 | 说明 | +| -------- | ------------------------------------------------------ | +| src | 文件源路径 | +| dest | 目标路径 | +| content | 往目标文件输入内容 | +| force | 强制 yes or no | +| backup | 是否备份有冲突的源文件[文件名相同,内容不同] yes or no | +| checksum | 拷贝完整性校验,使用sha1sum生成校验码 | +| owner | 目标文件所有者 | +| group | 目标文件所属组 | +| mode | 目标文件权限 | + +**拷贝manage01机器/root/readme文件到group1组的机器。** + +1. 要求校验完整性,注意[checksum 是根据sha1算法做校验的] +2. 所有者、所属组都是sko +3. 权限0400 + +``` +[root@manage01 ~]# sha1sum readme +f8182e9ccdbe6efd13eb36a056a7db203fe66e40 readme +[root@manage01 ~]# ansible -m copy group1 -a "src=/root/readme dest=/opt checksum=f8182e9ccdbe6efd13eb36a056a7db203fe66e40 owner=sko group=sko mode=0400" +192.168.98.203 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "checksum": "f8182e9ccdbe6efd13eb36a056a7db203fe66e40", + "dest": "/opt/readme", + "gid": 1000, + "group": "sko", + "md5sum": "f8c2686842f9fa79361e8928867a1983", + "mode": "0400", + "owner": "sko", + "size": 1214, + "src": "/root/.ansible/tmp/ansible-tmp-1571366236.6664524-201027506158575/source", + "state": "file", + "uid": 1000 +} +192.168.98.202 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "checksum": "f8182e9ccdbe6efd13eb36a056a7db203fe66e40", + "dest": "/opt/readme", + "gid": 1001, + "group": "sko", + "md5sum": "f8c2686842f9fa79361e8928867a1983", + "mode": "0400", + "owner": "sko", + "size": 1214, + "src": "/root/.ansible/tmp/ansible-tmp-1571366236.6522918-97522631781022/source", + "state": "file", + "uid": 1001 +} +192.168.98.201 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "checksum": "f8182e9ccdbe6efd13eb36a056a7db203fe66e40", + "dest": "/opt/readme", + "gid": 1001, + "group": "sko", + "md5sum": "f8c2686842f9fa79361e8928867a1983", + "mode": "0400", + "owner": "sko", + "size": 1214, + "src": "/root/.ansible/tmp/ansible-tmp-1571366236.6274443-88161541412737/source", + "state": "file", + "uid": 1001 +} +``` + +copy模块拷贝时要注意拷贝目录后面是否带"/"符号 + +``` +/etc/yum.repos.d后面不带/符号,则表示把/etc/yum.repos.d整个目录拷贝到/tmp/目录下 +[root@manage01 ~]# ansible group1 -m copy -a 'src=/etc/yum.repos.d dest=/tmp/' +/etc/yum.repos.d/后面带/符号,则表示把/etc/yum.repos.d/目录里的所有文件拷贝到/tmp/目录下 +[root@manage01 ~]# ansible group1 -m copy -a 'src=/etc/yum.repos.d/ dest=/tmp/' +``` + +使用content参数直接往远程文件里写内容(会覆盖原内容) + +``` +[root@manage01 ~]# ansible -m file group1 -a "path=/tmp/zutuanxue_333 state=touch" +[root@manage01 ~]# ansible -m copy group1 -a "content='baism\nhello world\n' dest=/tmp/zutuanxue_333" +注意:ansible中-a后面的参数里也有引号时,记得要单引双引交叉使用,如果都为双引会出现问题 +``` + +使用force参数控制是否强制覆盖 + +``` +如果目标文件已经存在,则不覆盖 +[root@manage01 ~]# ansible group1 -m copy -a "src=/tmp/zutuanxue_222 dest=/tmp/zutuanxue_333 force=no" +如果目标文件已经存在,则会强制覆盖 +[root@manage01 ~]# ansible group1 -m copy -a "src=/tmp/zutuanxue_222 dest=/tmp/zutuanxue_333 force=yes" +``` + +使用backup参数控制是否备份文件 + +``` +backup=yes表示如果拷贝的文件内容与原内容不一样,则会备份一份 + +如果拷贝过来的文件本机存在,group1的机器上会将/tmp/333备份一份(备份文件命名加上时间),再远程拷贝新的文件为/tmp/333 +[root@manage01 ~]# ansible group1 -m copy -a "src=/etc/fstab dest=/tmp/zutuanxue_333 backup=yes" +``` + +## 二、学习视频 + +[视频:copy模块](https://www.bilibili.com/video/BV19J41167sM?p=14) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-cron\346\250\241\345\235\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-cron\346\250\241\345\235\227.md" new file mode 100644 index 0000000..236a3c6 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-cron\346\250\241\345\235\227.md" @@ -0,0 +1,90 @@ +## 一、cron模块 + +cron模块用于管理周期性时间任务。 + +https://docs.ansible.com/ansible/latest/modules/cron_module.html#cron-module + +| 参数 | 说明 | +| ------------ | ------------------------ | +| name | 计划任务的名称 | +| user | 执行计划任务的用户 | +| job | 计划任务命令 | +| minute | 执行计划任务的分 默认为* | +| hour | 执行计划任务的时 默认为* | +| day | 执行计划任务的日 默认为* | +| month | 执行计划任务的月 默认为* | +| week | 执行计划任务的周 默认为* | +| state absent | 删除计划任务 | + +创建一个cron任务,不指定user的话,默认就是root(因为我这里是用root操作的)。 +如果minute,hour,day,month,week不指定的话,默认都为* + +每天14:23 执行echo “haha”>/tmp/test + +``` +[root@manage01 ~]# ansible -m cron group1 -a 'name="cron test" user=root job="echo haha > /tmp/test" minute=23 hour=12' +192.168.98.203 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "envs": [], + "jobs": [ + "cron test" + ] +} +192.168.98.202 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "envs": [], + "jobs": [ + "cron test" + ] +} +192.168.98.201 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "envs": [], + "jobs": [ + "cron test" + ] +} +``` + +删除cron任务 + +``` +[root@manage01 ~]# ansible -m cron group1 -a 'name="cron test" state=absent' +192.168.98.203 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "envs": [], + "jobs": [] +} +192.168.98.202 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "envs": [], + "jobs": [] +} +192.168.98.201 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "envs": [], + "jobs": [] +} +``` + +## 二、学习视频 + +[视频:cron模块](https://www.bilibili.com/video/BV19J41167sM?p=18) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-fetch\346\250\241\345\235\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-fetch\346\250\241\345\235\227.md" new file mode 100644 index 0000000..f174955 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-fetch\346\250\241\345\235\227.md" @@ -0,0 +1,45 @@ +## 一、fetch模块 + +fetch模块与copy模块类似,但作用相反。用于把远程机器的文件拷贝到本地。 + +https://docs.ansible.com/ansible/latest/modules/fetch_module.html#fetch-module + +将group1组机器的/opt/readme 拷贝到manage01的/opt目录 + +注意:不管是拷贝多个机器还是一个机器的文件,在管理机本地目录都会按照 + + IP/路径/文件名 + +的方式命名,防止冲突 + +``` +[root@manage01 ~]# ansible -m fetch group1 -a "src=/opt/readme dest=/opt" +192.168.98.203 | CHANGED => { + "changed": true, + "checksum": "f8182e9ccdbe6efd13eb36a056a7db203fe66e40", + "dest": "/opt/192.168.98.203/opt/readme", + "md5sum": "f8c2686842f9fa79361e8928867a1983", + "remote_checksum": "f8182e9ccdbe6efd13eb36a056a7db203fe66e40", + "remote_md5sum": null +} +192.168.98.202 | CHANGED => { + "changed": true, + "checksum": "f8182e9ccdbe6efd13eb36a056a7db203fe66e40", + "dest": "/opt/192.168.98.202/opt/readme", + "md5sum": "f8c2686842f9fa79361e8928867a1983", + "remote_checksum": "f8182e9ccdbe6efd13eb36a056a7db203fe66e40", + "remote_md5sum": null +} +192.168.98.201 | CHANGED => { + "changed": true, + "checksum": "f8182e9ccdbe6efd13eb36a056a7db203fe66e40", + "dest": "/opt/192.168.98.201/opt/readme", + "md5sum": "f8c2686842f9fa79361e8928867a1983", + "remote_checksum": "f8182e9ccdbe6efd13eb36a056a7db203fe66e40", + "remote_md5sum": null +} +``` + +## 二、学习视频 + +[视频:fetch模块](https://www.bilibili.com/video/BV19J41167sM?p=15) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-file\346\250\241\345\235\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-file\346\250\241\345\235\227.md" new file mode 100644 index 0000000..3c7f838 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-file\346\250\241\345\235\227.md" @@ -0,0 +1,295 @@ +## 一、file模块(重点) + +file模块用于对文件或文件夹相关的操作,主要用来设置文件、链接、目录的属性,或者移除文件、链接、目录,很多其他的模块也会包含这种作用,例如copy,assemble和template。 + +https://docs.ansible.com/ansible/latest/modules/file_module.html#file-module + +| 参数 | 说明 | +| ------- | ------------------------------------------------------------ | +| path | 文件绝对路径 | +| state | 操作(touch文件新建、absent删除、link软连接、hard硬链接、directory目录创建) | +| owner | 设置所有者 | +| group | 设置所属的组 | +| mode | 权限 0000 | +| recurse | 递归 yes or no | + +**文件的创建** + +在所有的业务机器的/tmp下创建一个文件:zutuanxue + +``` +[root@manage01 ~]# ansible -m file group1 -a "path=/tmp/zutuanxue state=touch" +192.168.98.202 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "dest": "/tmp/zutuanxue", + "gid": 0, + "group": "root", + "mode": "0644", + "owner": "root", + "size": 0, + "state": "file", + "uid": 0 +} +192.168.98.203 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "dest": "/tmp/zutuanxue", + "gid": 0, + "group": "root", + "mode": "0644", + "owner": "root", + "size": 0, + "state": "file", + "uid": 0 +} +192.168.98.201 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "dest": "/tmp/zutuanxue", + "gid": 0, + "group": "root", + "mode": "0644", + "owner": "root", + "size": 0, + "state": "file", + "uid": 0 +} +``` + +**文件的删除** + +将node1(192.168.98.201)机器的/tmp/zutuanxue文件删除 + +``` +[root@manage01 ~]# ansible -m file 192.168.98.201 -a "path=/tmp/zutuanxue state=absent" +192.168.98.201 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "path": "/tmp/zutuanxue", + "state": "absent" +} +``` + +**文件权限** + +修改node2机器文件/tmp/zutuanxue: + +所有者:sko + +所属组:nobody + +权限:600 + +``` +[root@manage01 ~]# ansible -m file 192.168.98.202 -a "path=/tmp/zutuanxue owner=sko group=nobody mode=0600" +192.168.98.202 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "gid": 65534, + "group": "nobody", + "mode": "0600", + "owner": "sko", + "path": "/tmp/zutuanxue", + "size": 0, + "state": "file", + "uid": 1001 +} + +###执行前提:192.168.98.202 有sko用户 +``` + +**创建链接文件[软连接、硬链接]** + +为node2机器的/tmp/zutuanxue文件创建以下链接 + +软连接 /tmp/zutuanxue_com + +硬链接 /tmp/zutuanxue_com_cn + +``` +#软连接 +[root@manage01 ~]# ansible -m file 192.168.98.202 -a "src=/tmp/zutuanxue path=/tmp/zutuanxue_com state=link" +192.168.98.202 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "dest": "/tmp/zutuanxue_com", + "gid": 0, + "group": "root", + "mode": "0777", + "owner": "root", + "size": 13, + "src": "/tmp/zutuanxue", + "state": "link", + "uid": 0 +} + +#硬链接 +[root@manage01 ~]# ansible -m file 192.168.98.202 -a "src=/tmp/zutuanxue path=/tmp/zutuanxue_com_cn state=hard" +192.168.98.202 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "dest": "/tmp/zutuanxue_com_cn", + "gid": 65534, + "group": "nobody", + "mode": "0600", + "owner": "sko", + "size": 0, + "src": "/tmp/zutuanxue", + "state": "hard", + "uid": 1001 +} +``` + +**创建一个目录** + +为所有的业务机器创建一个目录: /tmp/zutuanxue123 + +``` +[root@manage01 ~]# ansible -m file group1 -a "path=/tmp/zutuanxue123 state=directory" +192.168.98.203 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "gid": 0, + "group": "root", + "mode": "0755", + "owner": "root", + "path": "/tmp/zutuanxue123", + "size": 6, + "state": "directory", + "uid": 0 +} +192.168.98.202 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "gid": 0, + "group": "root", + "mode": "0755", + "owner": "root", + "path": "/tmp/zutuanxue123", + "size": 6, + "state": "directory", + "uid": 0 +} +192.168.98.201 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "gid": 0, + "group": "root", + "mode": "0755", + "owner": "root", + "path": "/tmp/zutuanxue123", + "size": 6, + "state": "directory", + "uid": 0 +} +``` + +**修改目录及子文件权限** + +设置业务机器的/tmp/zutuanxue123目录及子文件的权限 + +所有者设置为sko + +权限为2775 + +``` +[root@manage01 ~]# ansible -m file group1 -a "path=/tmp/zutuanxue123 owner=sko mode=2755 recurse=yes" +192.168.98.203 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "gid": 0, + "group": "root", + "mode": "02755", + "owner": "sko", + "path": "/tmp/zutuanxue123", + "size": 19, + "state": "directory", + "uid": 1000 +192.168.98.202 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "gid": 0, + "group": "root", + "mode": "02755", + "owner": "sko", + "path": "/tmp/zutuanxue123", + "size": 19, + "state": "directory", + "uid": 1001 +} +192.168.98.201 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "gid": 0, + "group": "root", + "mode": "02755", + "owner": "sko", + "path": "/tmp/zutuanxue123", + "size": 19, + "state": "directory", + "uid": 1001 +} +``` + +**删除一个目录[包括子文件全部删除]** + +删除所有业务机器的/tmp/zutuanxue123目录 + +``` +[root@manage01 ~]# ansible -m file group1 -a "path=/tmp/zutuanxue123 state=absent" +192.168.98.203 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "path": "/tmp/zutuanxue123", + "state": "absent" +} +192.168.98.202 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "path": "/tmp/zutuanxue123", + "state": "absent" +} +192.168.98.201 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "path": "/tmp/zutuanxue123", + "state": "absent" +} +``` + +## 二、学习视频 + +[视频:file模块](https://www.bilibili.com/video/BV19J41167sM?p=13) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-group\346\250\241\345\235\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-group\346\250\241\345\235\227.md" new file mode 100644 index 0000000..145a693 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-group\346\250\241\345\235\227.md" @@ -0,0 +1,78 @@ +## 一、group模块 + +group模块用于管理用户组和用户组属性。 + +https://docs.ansible.com/ansible/latest/modules/group_module.html#group-module + +| 参数 | 说明 | +| ---------------------- | ------------ | +| name= | 组名 | +| state= persent\|absent | 创建\|删除 | +| system= yes\|no | 是否为系统组 | +| gid | gid | + +``` +#组创建 +[root@manage01 ~]# ansible -m group group1 -a "name=admin gid=4444 state=present" +192.168.98.203 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "gid": 4444, + "name": "admin", + "state": "present", + "system": false +} +192.168.98.202 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "gid": 4444, + "name": "admin", + "state": "present", + "system": false +} +192.168.98.201 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "gid": 4444, + "name": "admin", + "state": "present", + "system": false +} + +#删除组 +[root@manage01 ~]# ansible -m group group1 -a "name=admin state=absent" +192.168.98.203 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "name": "admin", + "state": "absent" +} +192.168.98.201 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "name": "admin", + "state": "absent" +} +192.168.98.202 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "name": "admin", + "state": "absent" +} +``` + +## 二、学习视频 + +[视频:group模块](https://www.bilibili.com/video/BV19J41167sM?p=17) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-hostname\346\250\241\345\235\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-hostname\346\250\241\345\235\227.md" new file mode 100644 index 0000000..3fdf3ea --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-hostname\346\250\241\345\235\227.md" @@ -0,0 +1,29 @@ +## 一、hostname模块 + +hostname模块用于修改主机名(**注意**: 它不能修改/etc/hosts文件) + +https://docs.ansible.com/ansible/latest/modules/hostname_module.html#hostname-module + +``` +将192.168.98.203机器的主机名修改为zutuanxue_node3 + +[root@manage01 ~]# ansible -m hostname -a "name=zutuanxue_node3" 192.168.98.203 +192.168.98.203 | CHANGED => { + "ansible_facts": { + "ansible_domain": "", + "ansible_fqdn": "zutuanxue_node3", + "ansible_hostname": "zutuanxue_node3", + "ansible_nodename": "zutuanxue_node3", + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "name": "zutuanxue_node3" +} + + +备注:批量修改需要使用playbook剧本 +``` + +## 二、学习视频 + +[视频:hostname模块](https://www.bilibili.com/video/BV19J41167sM?p=12) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-playbook\345\211\247\346\234\254.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-playbook\345\211\247\346\234\254.md" new file mode 100644 index 0000000..1013f63 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-playbook\345\211\247\346\234\254.md" @@ -0,0 +1,239 @@ +## 一、playbook介绍 + +playbook(剧本): 是ansible用于配置,部署,和管理被控节点的剧本。 + +参考:https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html + +使用的格式为**yaml**格式(saltstack,elk,docker等也都会用到yaml格式) + +``` +树明的理解: +playbook:ansible格式的脚本。将所有需要执行的操作按照ansible的编程语法,放到文件中执行。 + +playbook替代方案 +1)、完全可以用shell脚本来替代playbook + 将所有的ansible命令放入脚本 shell脚本中写的是ansible指令 +#!/bin/bash +for IP in `seq 201 203` + do + ansible -m hostname 192.168.98.$IP -a "name=node${IP}" +done + +2)、ansible+shell脚本 使用script模块 +ansible -m script group2 '/etc/ansible/srcipts/nginx_install.sh' +``` + +### 1.1、YAML格式规则 + +- 文件的第一行以 "—"开始,表明YMAL文件的开始. +- 以#号开头为注释 +- 列表中的所有成员都开始于相同的缩进级别, 并且使用一个 `"- "` 作为开头(一个横杠和一个空格) +- 一个字典是由一个简单的 `键: 值` 的形式组成(这个冒号后面必须是一个空格) +- **注意: 写这种文件不要使用tab键,都使用空格** + +参考: https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html#yaml-syntax + +下面看一个官方的示例感受一下 + +``` +--- +# 一位职工记录 +name: Example Developer +job: Developer +skill: Elite +employed: True +foods: + - Apple + - Orange + - Strawberry + - Mango +languages: + ruby: Elite + python: Elite + dotnet: Lame +``` + +### playbook实例 + +先直接来看一个实例 apache安装及业务初始化 + +**第1步: 创建一个存放playbook的目录(路径自定义)** + +``` +[root@manage01 ~]# mkdir -p /etc/ansible/playbook/web +``` + +**第2步: 准备httpd配置文件,并修改成你想要的配置** + +``` +[root@manage01 ~]# yum install httpd -y + +按需要修改你想要的配置(为了测试可以随意改动标记一下) +[root@manage01 ~]# vim /etc/httpd/conf/httpd.conf +``` + +**第3步: 写一个playbook文件(后缀为.yml或.yaml)** + +``` +[root@manage01 web]# cat apache.yaml +--- +- hosts: group1 + remote_user: root + vars: + - user: zutuanxue + tasks: + - name: create user use variable + user: user=zutuanxue state=present + + - name: install httpd server + yum: name={{item}} state=latest + with_items: + - httpd + - httpd-devel + + - name: start httpd service + service: name=httpd state=started enabled=yes + + - name: copy httpd.conf to group1:/etc/httpd/conf/ + copy: src=/etc/ansible/playbook/web/httpd.conf dest=/etc/httpd/conf + notify: + - restart httpd service + + handlers: + - name: restart httpd service + service: name=httpd state=restarted + + + +#tasks +#1、创建apache管理用户 +#2、安装httpd +#3、服务启动管理 +#4、拷贝配置文件,业务初始化 + #5、触发重启服务httpd +``` + +第4步: 执行写好的palybook + +- 会显示出执行的过程,并且执行的每一步都有ok,changed,failed等标识 +- 执行如果有错误(failed)会回滚,解决问题后,直接再执行这条命令即可,并会把failed改为changed(幂等性) + +``` +[root@manage01 web]# ansible-playbook /etc/ansible/playbook/web/apache.yaml +``` + +### 1.2、Playbook常见语法 + +**hosts:** 用于指定要执行任务的主机,其可以是一个或多个由冒号分隔主机组. + +**remote_user:** 用于指定远程主机上的执行任务的用户. + +``` +- hosts: group1 + remote_user: root +``` + +**tasks:** 任务列表, 按顺序执行任务. + +- 如果一个host执行task失败, 整个tasks都会回滚, 修正playbook 中的错误, 然后重新执行即可. + +``` +tasks: + - name: create user use variable + user: name={{user}} state=present + + - name: install httpd server + yum: name=httpd state=latest name=httpd-devel state=latest + + - name: start httpd service + service: name=httpd state=started enabled=yes + + - name: copy httpd.conf to group1:/etc/httpd/conf/ + copy: src=/opt/httpd.conf dest=/etc/httpd/conf/ + +``` + +**handlers:** 类似task,但需要使用notify通知调用,实现按需调用。 + +- 不管有多少个通知者进行了notify,等到play中的所有task执行完成之后,handlers也只会被执行一次. +- handlers最佳的应用场景是用来重启服务,或者触发系统重启操作.除此以外很少用到了. + +``` + notify: + - restart httpd service + + handlers: + - name: restart httpd service + service: name=httpd state=restarted + + #注意: handlers 需要notify调用,他和tasks不同的是 tasks每次都会调用,heandlers触发才调用,比如配置文件修改了,在执行playbook的时候,就会将管理机上的新改的copy到被管理机,那么就会触发headlers重启服务,否则不会执行heanlers +``` + +**练习:** 修改httpd的端口为8080,再执行playbook测试 + +**variables:** 变量 + +- 定义变量可以被多次方便调用 + +``` +vars: + - user: zutuanxue +``` + +**with_items**: 迭代列表 + +- 其使用格式为将需要迭代的内容定义为item变量引用,并通过with_items语句指明迭代的元素列表即可。 + +例如安装多个软件包 + +``` +yum: name={{item}} state=latest +with_items: + - httpd + - httpd-devel +``` + +执行后有如下警告 + +![警告.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601969382005.png) + +解决方法: + +在/etc/ansible/ansible.cfg配置文件里的[default]配置段下面加上deprecation_warnings=False参数即可 + +## 二、练习案例 + +写一个playbook实现 + +1. 配置yum +2. 安装vsftpd包 +3. 修改配置文件(要求拒绝匿名用户登录) +4. 启动服务并实现vsftpd服务开机自动启动 + +``` +--- +- hosts: group1 + remote_user: root + tasks: + - name: rm yum repository + file: path=/etc/yum.repos.d/ state=absent + + - name: 同步master上的yum源到group1 + copy: src=/etc/yum.repos.d dest=/etc/ + + - name: ensure vsftpd is at the latest version + yum: name=vsftpd state=latest + + - name: write the apache config file + copy: src=/etc/vsftpd/vsftpd.conf dest=/etc/vsftpd/vsftpd.conf + + notify: + - restart vsftpd + + - name: ensure vsftpd is running (and enable it at boot) + service: name=vsftpd state=started enabled=yes + + handlers: + - name: restart vsftpd + service: name=vsftpd state=restarted +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-role.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-role.md" new file mode 100644 index 0000000..6c8cd2b --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-role.md" @@ -0,0 +1,238 @@ +假设我们要写一个playbook来安装管理lamp环境,那么这个playbook就会写很长。所以我们希望把这个很大的文件分成多个功能拆分, 分成apache管理,php管理,mysql管理,然后在需要使用的时候直接调用就可以了,以免重复写。就类似编程里的模块化的概念,以达到代码复用的效果。 + +## 一、roles介绍 + +**roles:** ansible模块,类似于函数,完成一个任务的指令。每一个roles都有自己特定的目录结构,就是通过分别将variables, tasks及handlers等放置于单独的目录中,并可以便捷地调用它们的一种机制。 + +**roles优点:** + + 1)模块中指令较少,方便编写 + + 2)重复调用方便 + +3)排错方便 + +## 二、创建roles的目录结构 + +``` +files:用来存放由copy模块或script模块调用的文件。 +tasks:至少有一个main.yml文件,定义各tasks。 +handlers:有一个main.yml文件,定义各handlers。 +templates:用来存放jinjia2模板。 +vars:有一个main.yml文件,定义变量。 +meta:有一个main.yml文件,定义此角色的特殊设定及其依赖关系。 +``` + +**注意:** 在每个角色的目录中分别创建files, tasks,handlers,templates,vars和meta目录,用不到的目录可以创建为空目录. + +## 三、案例:通过roles实现lamp + +分析:需定制三个角色: httpd,mysql,php + +### 3.1) 创建roles目录及文件,并确认目录结构 + +roles/ +├── httpd +│ ├── files +│ ├── handlers +│ │ └── main.yml +│ ├── meta +│ │ └── main.yml +│ ├── tasks +│ │ └── main.yml +│ ├── templates +│ └── vars +│ └── main.yml +├── mysql +│ ├── files +│ ├── handlers +│ │ └── main.yml +│ ├── meta +│ │ └── main.yml +│ ├── tasks +│ │ └── main.yml +│ ├── templates +│ └── vars +│ └── main.yml +└── php +├── files +├── handlers +│ └── main.yml +├── meta +│ └── main.yml +├── tasks +│ └── main.yml +├── templates +└── vars +└── main.yml + +``` +[root@manage01 ansible]# mkdir -p roles/{httpd,mysql,php}/{files,tasks,handlers,templates,vars,meta} +[root@manage01 ansible]# touch roles/{httpd,mysql,php}/{tasks,handlers,vars,meta}/main.yml +[root@manage01 ansible]# tree roles/ +roles/ +├── httpd +│ ├── files +│ ├── handlers +│ │ └── main.yml +│ ├── meta +│ │ └── main.yml +│ ├── tasks +│ │ └── main.yml +│ ├── templates +│ └── vars +│ └── main.yml +├── mysql +│ ├── files +│ ├── handlers +│ │ └── main.yml +│ ├── meta +│ │ └── main.yml +│ ├── tasks +│ │ └── main.yml +│ ├── templates +│ └── vars +│ └── main.yml +└── php + ├── files + ├── handlers + │ └── main.yml + ├── meta + │ └── main.yml + ├── tasks + │ └── main.yml + ├── templates + └── vars + └── main.yml + +21 directories, 12 files +``` + +### 3.2)准备httpd服务器的主页文件,php测试页和配置文件等 + +``` +[root@manage01 files]# ls +httpd.conf phpinfo.php +``` + +### 3.3)编写httpd角色的main.yml文件 + +``` +[root@manage01 roles]# cat httpd/tasks/main.yml +- name: httpd httpd-devel httpd-manual软件包安装 + yum: name={{item}} state=latest + with_items: + - httpd + - httpd-devel + - httpd-manual + +- name: 创建apache管理用户 www + user: name={{user}} state=present + + +- name: 设置apache开机启动,并启动服务 + service: name=httpd enabled=yes state=started + +- name: 拷贝配置文件,初始化业务 + copy: src=/etc/ansible/roles/httpd/files/httpd.conf dest=/etc/httpd/conf/httpd.conf + #定义通知调用,当配置文件更新,需要重启服务 + notify: + - restart apache + +- name: 拷贝php测试页面 + copy: src=/etc/ansible/roles/httpd/files/phpinfo.php dest=/var/www/html/ + +[root@manage01 roles]# cat httpd/vars/main.yml +user: www + + +[root@manage01 roles]# cat httpd/handlers/main.yml +- name: restart apache + service: name=httpd state=restarted +``` + +### 3.4)编写mysql角色的main.yml文件 + +``` +[root@manage01 ansible]# ls roles/php/files/ +www.conf + +[root@manage01 roles]# cat mysql/tasks/main.yml +- name: mysql 用户创建 + user: name={{user}} state=present + +- name: mysql 软件安装 + yum: name={{item}} state=latest + with_items: + - mariadb + - mariadb-server + +- name: 启动服务,并设置开机启动 + service: name=mariadb enabled=yes state=started + +- name: 改变mysql文件的所有者为mysql + file: path='/usr/lib/mysql' owner={{user}} group={{user}} recurse=yes + + +[root@manage01 roles]# cat mysql/vars/main.yml +user: mysql +``` + +### 3.5):编写php角色的main.yml文件 + +``` +[root@manage01 ansible]# cat roles/php/tasks/main.yml +- name: 安装php + yum: name={{item}} state=latest + with_items: + - php + - php-mysqlnd + - php-gd + - php-ldap + - php-odbc + - php-pear + - php-xml + - php-xmlrpc + - php-mbstring + - php-snmp + - php-soap + - curl + - curl-devel + - php-bcmath + - php-fpm + +- name: copy www.conf to /etc/php-fpm.d + copy: src=/etc/ansible/roles/php/files/www.conf dest=/etc/php-fpm.d force=yes + notify: + - restart php-fpm + + +[root@manage01 ansible]# cat roles/php/handlers/main.yml +- name: restart php-fpm + service: name=php-fpm state=restarted + +``` + +### 3.6)编写lamp的playbook文件调用前面定义好的三个角色 + +``` +[root@manage01 yaml]# cat lamp.yml +--- +- hosts: group1 + remote_user: root + roles: + - httpd + - mysql + - php +``` + +### 3.7) 执行lamp的playbook文件 + +``` +[root@manage01 yaml]# ansible-playbook -C lamp.yml +[root@manage01 yaml]# ansible-playbook lamp.yml +``` + +### 3.8) 测试业务机器 + +![lamp_test.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601969569380.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-script\346\250\241\345\235\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-script\346\250\241\345\235\227.md" new file mode 100644 index 0000000..fcc222e --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-script\346\250\241\345\235\227.md" @@ -0,0 +1,160 @@ +## 一、script模块 + +**如何通过ansible执行一个脚本:lamp安装脚本** + +script模块:用于在远程机器上执行**本地**脚本。 + +https://docs.ansible.com/ansible/latest/modules/script_module.html#script-module + +``` +在manage01上创建脚本,通过ansible将脚本分发到被管理端 +[root@manage01 ~]# cat ansible_test.sh +#!/bin/bash +#ansible script module test script +mkdir /opt/log +find / -name "*.log" -exec cp -rpf {} /opt/log \; + + +#脚本不用给执行权限 +[root@manage01 ~]# ansible -m script group1 -a "/root/ansible_test.sh" + + +192.168.98.203 | CHANGED => { + "changed": true, + "rc": 0, + "stderr": "Shared connection to 192.168.98.203 closed.\r\n", + "stderr_lines": [ + "Shared connection to 192.168.98.203 closed." + ], + "stdout": "cp: '/opt/log/sssd.log' 与'/opt/log/sssd.log' 为同一文件\r\ncp: '/opt/log/sssd_implicit_files.log' 与'/opt/log/sssd_implicit_files.log' 为同一文件\r\ncp: '/opt/log/sssd_nss.log' 与'/opt/log/sssd_nss.log' 为同一文件\r\ncp: '/opt/log/tuned.log' 与'/opt/log/tuned.log' 为同一文件\r\ncp: '/opt/log/audit.log' 与'/opt/log/audit.log' 为同一文件\r\ncp: '/opt/log/anaconda.log' 与'/opt/log/anaconda.log' 为同一文件\r\ncp: '/opt/log/X.log' 与'/opt/log/X.log' 为同一文件\r\ncp: '/opt/log/program.log' 与'/opt/log/program.log' 为同一文件\r\ncp: '/opt/log/packaging.log' 与'/opt/log/packaging.log' 为同一文件\r\ncp: '/opt/log/storage.log' 与'/opt/log/storage.log' 为同一文件\r\ncp: '/opt/log/ifcfg.log' 与'/opt/log/ifcfg.log' 为同一文件\r\ncp: '/opt/log/lvm.log' 与'/opt/log/lvm.log' 为同一文件\r\ncp: '/opt/log/dnf.librepo.log' 与'/opt/log/dnf.librepo.log' 为同一文件\r\ncp: '/opt/log/hawkey.log' 与'/opt/log/hawkey.log' 为同一文件\r\ncp: '/opt/log/dbus.log' 与'/opt/log/dbus.log' 为同一文件\r\ncp: '/opt/log/ks-script-5r3m4old.log' 与'/opt/log/ks-script-5r3m4old.log' 为同一文件\r\ncp: '/opt/log/ks-script-h97m_bc_.log' 与'/opt/log/ks-script-h97m_bc_.log' 为同一文件\r\ncp: '/opt/log/journal.log' 与'/opt/log/journal.log' 为同一文件\r\ncp: '/opt/log/boot.log' 与'/opt/log/boot.log' 为同一文件\r\ncp: '/opt/log/vmware-vmsvc.log' 与'/opt/log/vmware-vmsvc.log' 为同一文件\r\ncp: '/opt/log/dnf.log' 与'/opt/log/dnf.log' 为同一文件\r\ncp: '/opt/log/dnf.rpm.log' 与'/opt/log/dnf.rpm.log' 为同一文件\r\ncp: '/opt/log/vmware-network.3.log' 与'/opt/log/vmware-network.3.log' 为同一文件\r\ncp: '/opt/log/vmware-network.2.log' 与'/opt/log/vmware-network.2.log' 为同一文件\r\ncp: '/opt/log/vmware-network.1.log' 与'/opt/log/vmware-network.1.log' 为同一文件\r\ncp: '/opt/log/vmware-network.log' 与'/opt/log/vmware-network.log' 为同一文件\r\ncp: '/opt/log/rpm.log' 与'/opt/log/rpm.log' 为同一文件\r\n", + "stdout_lines": [ + "cp: '/opt/log/sssd.log' 与'/opt/log/sssd.log' 为同一文件", + "cp: '/opt/log/sssd_implicit_files.log' 与'/opt/log/sssd_implicit_files.log' 为同一文件", + "cp: '/opt/log/sssd_nss.log' 与'/opt/log/sssd_nss.log' 为同一文件", + "cp: '/opt/log/tuned.log' 与'/opt/log/tuned.log' 为同一文件", + "cp: '/opt/log/audit.log' 与'/opt/log/audit.log' 为同一文件", + "cp: '/opt/log/anaconda.log' 与'/opt/log/anaconda.log' 为同一文件", + "cp: '/opt/log/X.log' 与'/opt/log/X.log' 为同一文件", + "cp: '/opt/log/program.log' 与'/opt/log/program.log' 为同一文件", + "cp: '/opt/log/packaging.log' 与'/opt/log/packaging.log' 为同一文件", + "cp: '/opt/log/storage.log' 与'/opt/log/storage.log' 为同一文件", + "cp: '/opt/log/ifcfg.log' 与'/opt/log/ifcfg.log' 为同一文件", + "cp: '/opt/log/lvm.log' 与'/opt/log/lvm.log' 为同一文件", + "cp: '/opt/log/dnf.librepo.log' 与'/opt/log/dnf.librepo.log' 为同一文件", + "cp: '/opt/log/hawkey.log' 与'/opt/log/hawkey.log' 为同一文件", + "cp: '/opt/log/dbus.log' 与'/opt/log/dbus.log' 为同一文件", + "cp: '/opt/log/ks-script-5r3m4old.log' 与'/opt/log/ks-script-5r3m4old.log' 为同一文件", + "cp: '/opt/log/ks-script-h97m_bc_.log' 与'/opt/log/ks-script-h97m_bc_.log' 为同一文件", + "cp: '/opt/log/journal.log' 与'/opt/log/journal.log' 为同一文件", + "cp: '/opt/log/boot.log' 与'/opt/log/boot.log' 为同一文件", + "cp: '/opt/log/vmware-vmsvc.log' 与'/opt/log/vmware-vmsvc.log' 为同一文件", + "cp: '/opt/log/dnf.log' 与'/opt/log/dnf.log' 为同一文件", + "cp: '/opt/log/dnf.rpm.log' 与'/opt/log/dnf.rpm.log' 为同一文件", + "cp: '/opt/log/vmware-network.3.log' 与'/opt/log/vmware-network.3.log' 为同一文件", + "cp: '/opt/log/vmware-network.2.log' 与'/opt/log/vmware-network.2.log' 为同一文件", + "cp: '/opt/log/vmware-network.1.log' 与'/opt/log/vmware-network.1.log' 为同一文件", + "cp: '/opt/log/vmware-network.log' 与'/opt/log/vmware-network.log' 为同一文件", + "cp: '/opt/log/rpm.log' 与'/opt/log/rpm.log' 为同一文件" + ] +} + + + +192.168.98.202 | CHANGED => { + "changed": true, + "rc": 0, + "stderr": "Shared connection to 192.168.98.202 closed.\r\n", + "stderr_lines": [ + "Shared connection to 192.168.98.202 closed." + ], + "stdout": "cp: '/opt/log/home-75a175cb.log' 与'/opt/log/home-75a175cb.log' 为同一文件\r\ncp: '/opt/log/root-648d48b0.log' 与'/opt/log/root-648d48b0.log' 为同一文件\r\ncp: '/opt/log/audit.log' 与'/opt/log/audit.log' 为同一文件\r\ncp: '/opt/log/sssd.log' 与'/opt/log/sssd.log' 为同一文件\r\ncp: '/opt/log/sssd_implicit_files.log' 与'/opt/log/sssd_implicit_files.log' 为同一文件\r\ncp: '/opt/log/sssd_nss.log' 与'/opt/log/sssd_nss.log' 为同一文件\r\ncp: '/opt/log/sssd_kcm.log' 与'/opt/log/sssd_kcm.log' 为同一文件\r\ncp: '/opt/log/tuned.log' 与'/opt/log/tuned.log' 为同一文件\r\ncp: '/opt/log/anaconda.log' 与'/opt/log/anaconda.log' 为同一文件\r\ncp: '/opt/log/X.log' 与'/opt/log/X.log' 为同一文件\r\ncp: '/opt/log/program.log' 与'/opt/log/program.log' 为同一文件\r\ncp: '/opt/log/packaging.log' 与'/opt/log/packaging.log' 为同一文件\r\ncp: '/opt/log/storage.log' 与'/opt/log/storage.log' 为同一文件\r\ncp: '/opt/log/ifcfg.log' 与'/opt/log/ifcfg.log' 为同一文件\r\ncp: '/opt/log/lvm.log' 与'/opt/log/lvm.log' 为同一文件\r\ncp: '/opt/log/dnf.librepo.log' 与'/opt/log/dnf.librepo.log' 为同一文件\r\ncp: '/opt/log/hawkey.log' 与'/opt/log/hawkey.log' 为同一文件\r\ncp: '/opt/log/dbus.log' 与'/opt/log/dbus.log' 为同一文件\r\ncp: '/opt/log/ks-script-fx6j2w7d.log' 与'/opt/log/ks-script-fx6j2w7d.log' 为同一文件\r\ncp: '/opt/log/ks-script-igqtd8i1.log' 与'/opt/log/ks-script-igqtd8i1.log' 为同一文件\r\ncp: '/opt/log/journal.log' 与'/opt/log/journal.log' 为同一文件\r\ncp: '/opt/log/boot.log' 与'/opt/log/boot.log' 为同一文件\r\ncp: '/opt/log/vmware-vmsvc.log' 与'/opt/log/vmware-vmsvc.log' 为同一文件\r\ncp: '/opt/log/Xorg.9.log' 与'/opt/log/Xorg.9.log' 为同一文件\r\ncp: '/opt/log/vmware-vmusr.log' 与'/opt/log/vmware-vmusr.log' 为同一文件\r\ncp: '/opt/log/dnf.log' 与'/opt/log/dnf.log' 为同一文件\r\ncp: '/opt/log/dnf.rpm.log' 与'/opt/log/dnf.rpm.log' 为同一文件\r\ncp: '/opt/log/vmware-network.3.log' 与'/opt/log/vmware-network.3.log' 为同一文件\r\ncp: '/opt/log/vmware-network.2.log' 与'/opt/log/vmware-network.2.log' 为同一文件\r\ncp: '/opt/log/vmware-network.1.log' 与'/opt/log/vmware-network.1.log' 为同一文件\r\ncp: '/opt/log/vmware-network.log' 与'/opt/log/vmware-network.log' 为同一文件\r\ncp: '/opt/log/rpm.log' 与'/opt/log/rpm.log' 为同一文件\r\n", + "stdout_lines": [ + "cp: '/opt/log/home-75a175cb.log' 与'/opt/log/home-75a175cb.log' 为同一文件", + "cp: '/opt/log/root-648d48b0.log' 与'/opt/log/root-648d48b0.log' 为同一文件", + "cp: '/opt/log/audit.log' 与'/opt/log/audit.log' 为同一文件", + "cp: '/opt/log/sssd.log' 与'/opt/log/sssd.log' 为同一文件", + "cp: '/opt/log/sssd_implicit_files.log' 与'/opt/log/sssd_implicit_files.log' 为同一文件", + "cp: '/opt/log/sssd_nss.log' 与'/opt/log/sssd_nss.log' 为同一文件", + "cp: '/opt/log/sssd_kcm.log' 与'/opt/log/sssd_kcm.log' 为同一文件", + "cp: '/opt/log/tuned.log' 与'/opt/log/tuned.log' 为同一文件", + "cp: '/opt/log/anaconda.log' 与'/opt/log/anaconda.log' 为同一文件", + "cp: '/opt/log/X.log' 与'/opt/log/X.log' 为同一文件", + "cp: '/opt/log/program.log' 与'/opt/log/program.log' 为同一文件", + "cp: '/opt/log/packaging.log' 与'/opt/log/packaging.log' 为同一文件", + "cp: '/opt/log/storage.log' 与'/opt/log/storage.log' 为同一文件", + "cp: '/opt/log/ifcfg.log' 与'/opt/log/ifcfg.log' 为同一文件", + "cp: '/opt/log/lvm.log' 与'/opt/log/lvm.log' 为同一文件", + "cp: '/opt/log/dnf.librepo.log' 与'/opt/log/dnf.librepo.log' 为同一文件", + "cp: '/opt/log/hawkey.log' 与'/opt/log/hawkey.log' 为同一文件", + "cp: '/opt/log/dbus.log' 与'/opt/log/dbus.log' 为同一文件", + "cp: '/opt/log/ks-script-fx6j2w7d.log' 与'/opt/log/ks-script-fx6j2w7d.log' 为同一文件", + "cp: '/opt/log/ks-script-igqtd8i1.log' 与'/opt/log/ks-script-igqtd8i1.log' 为同一文件", + "cp: '/opt/log/journal.log' 与'/opt/log/journal.log' 为同一文件", + "cp: '/opt/log/boot.log' 与'/opt/log/boot.log' 为同一文件", + "cp: '/opt/log/vmware-vmsvc.log' 与'/opt/log/vmware-vmsvc.log' 为同一文件", + "cp: '/opt/log/Xorg.9.log' 与'/opt/log/Xorg.9.log' 为同一文件", + "cp: '/opt/log/vmware-vmusr.log' 与'/opt/log/vmware-vmusr.log' 为同一文件", + "cp: '/opt/log/dnf.log' 与'/opt/log/dnf.log' 为同一文件", + "cp: '/opt/log/dnf.rpm.log' 与'/opt/log/dnf.rpm.log' 为同一文件", + "cp: '/opt/log/vmware-network.3.log' 与'/opt/log/vmware-network.3.log' 为同一文件", + "cp: '/opt/log/vmware-network.2.log' 与'/opt/log/vmware-network.2.log' 为同一文件", + "cp: '/opt/log/vmware-network.1.log' 与'/opt/log/vmware-network.1.log' 为同一文件", + "cp: '/opt/log/vmware-network.log' 与'/opt/log/vmware-network.log' 为同一文件", + "cp: '/opt/log/rpm.log' 与'/opt/log/rpm.log' 为同一文件" + ] +} + + +192.168.98.201 | CHANGED => { + "changed": true, + "rc": 0, + "stderr": "Shared connection to 192.168.98.201 closed.\r\n", + "stderr_lines": [ + "Shared connection to 192.168.98.201 closed." + ], + "stdout": "cp: '/opt/log/home-2b167fc1.log' 与'/opt/log/home-2b167fc1.log' 为同一文件\r\ncp: '/opt/log/root-836d3cf3.log' 与'/opt/log/root-836d3cf3.log' 为同一文件\r\ncp: '/opt/log/audit.log' 与'/opt/log/audit.log' 为同一文件\r\ncp: '/opt/log/sssd_implicit_files.log' 与'/opt/log/sssd_implicit_files.log' 为同一文件\r\ncp: '/opt/log/sssd_kcm.log' 与'/opt/log/sssd_kcm.log' 为同一文件\r\ncp: '/opt/log/sssd_nss.log' 与'/opt/log/sssd_nss.log' 为同一文件\r\ncp: '/opt/log/sssd.log' 与'/opt/log/sssd.log' 为同一文件\r\ncp: '/opt/log/tuned.log' 与'/opt/log/tuned.log' 为同一文件\r\ncp: '/opt/log/anaconda.log' 与'/opt/log/anaconda.log' 为同一文件\r\ncp: '/opt/log/X.log' 与'/opt/log/X.log' 为同一文件\r\ncp: '/opt/log/program.log' 与'/opt/log/program.log' 为同一文件\r\ncp: '/opt/log/packaging.log' 与'/opt/log/packaging.log' 为同一文件\r\ncp: '/opt/log/storage.log' 与'/opt/log/storage.log' 为同一文件\r\ncp: '/opt/log/ifcfg.log' 与'/opt/log/ifcfg.log' 为同一文件\r\ncp: '/opt/log/lvm.log' 与'/opt/log/lvm.log' 为同一文件\r\ncp: '/opt/log/dnf.librepo.log' 与'/opt/log/dnf.librepo.log' 为同一文件\r\ncp: '/opt/log/hawkey.log' 与'/opt/log/hawkey.log' 为同一文件\r\ncp: '/opt/log/dbus.log' 与'/opt/log/dbus.log' 为同一文件\r\ncp: '/opt/log/ks-script-ai28ecf4.log' 与'/opt/log/ks-script-ai28ecf4.log' 为同一文件\r\ncp: '/opt/log/ks-script-k4vgo8wr.log' 与'/opt/log/ks-script-k4vgo8wr.log' 为同一文件\r\ncp: '/opt/log/journal.log' 与'/opt/log/journal.log' 为同一文件\r\ncp: '/opt/log/boot.log' 与'/opt/log/boot.log' 为同一文件\r\ncp: '/opt/log/vmware-vmsvc.log' 与'/opt/log/vmware-vmsvc.log' 为同一文件\r\ncp: '/opt/log/Xorg.9.log' 与'/opt/log/Xorg.9.log' 为同一文件\r\ncp: '/opt/log/vmware-vmusr.log' 与'/opt/log/vmware-vmusr.log' 为同一文件\r\ncp: '/opt/log/dnf.log' 与'/opt/log/dnf.log' 为同一文件\r\ncp: '/opt/log/dnf.rpm.log' 与'/opt/log/dnf.rpm.log' 为同一文件\r\ncp: '/opt/log/vmware-network.6.log' 与'/opt/log/vmware-network.6.log' 为同一文件\r\ncp: '/opt/log/vmware-network.5.log' 与'/opt/log/vmware-network.5.log' 为同一文件\r\ncp: '/opt/log/vmware-network.4.log' 与'/opt/log/vmware-network.4.log' 为同一文件\r\ncp: '/opt/log/vmware-network.3.log' 与'/opt/log/vmware-network.3.log' 为同一文件\r\ncp: '/opt/log/vmware-network.2.log' 与'/opt/log/vmware-network.2.log' 为同一文件\r\ncp: '/opt/log/vmware-network.1.log' 与'/opt/log/vmware-network.1.log' 为同一文件\r\ncp: '/opt/log/vmware-network.log' 与'/opt/log/vmware-network.log' 为同一文件\r\ncp: '/opt/log/rpm.log' 与'/opt/log/rpm.log' 为同一文件\r\ncp: '/opt/log/error.log' 与'/opt/log/error.log' 为同一文件\r\ncp: '/opt/log/access.log' 与'/opt/log/access.log' 为同一文件\r\n", + "stdout_lines": [ + "cp: '/opt/log/home-2b167fc1.log' 与'/opt/log/home-2b167fc1.log' 为同一文件", + "cp: '/opt/log/root-836d3cf3.log' 与'/opt/log/root-836d3cf3.log' 为同一文件", + "cp: '/opt/log/audit.log' 与'/opt/log/audit.log' 为同一文件", + "cp: '/opt/log/sssd_implicit_files.log' 与'/opt/log/sssd_implicit_files.log' 为同一文件", + "cp: '/opt/log/sssd_kcm.log' 与'/opt/log/sssd_kcm.log' 为同一文件", + "cp: '/opt/log/sssd_nss.log' 与'/opt/log/sssd_nss.log' 为同一文件", + "cp: '/opt/log/sssd.log' 与'/opt/log/sssd.log' 为同一文件", + "cp: '/opt/log/tuned.log' 与'/opt/log/tuned.log' 为同一文件", + "cp: '/opt/log/anaconda.log' 与'/opt/log/anaconda.log' 为同一文件", + "cp: '/opt/log/X.log' 与'/opt/log/X.log' 为同一文件", + "cp: '/opt/log/program.log' 与'/opt/log/program.log' 为同一文件", + "cp: '/opt/log/packaging.log' 与'/opt/log/packaging.log' 为同一文件", + "cp: '/opt/log/storage.log' 与'/opt/log/storage.log' 为同一文件", + "cp: '/opt/log/ifcfg.log' 与'/opt/log/ifcfg.log' 为同一文件", + "cp: '/opt/log/lvm.log' 与'/opt/log/lvm.log' 为同一文件", + "cp: '/opt/log/dnf.librepo.log' 与'/opt/log/dnf.librepo.log' 为同一文件", + "cp: '/opt/log/hawkey.log' 与'/opt/log/hawkey.log' 为同一文件", + "cp: '/opt/log/dbus.log' 与'/opt/log/dbus.log' 为同一文件", + "cp: '/opt/log/ks-script-ai28ecf4.log' 与'/opt/log/ks-script-ai28ecf4.log' 为同一文件", + "cp: '/opt/log/ks-script-k4vgo8wr.log' 与'/opt/log/ks-script-k4vgo8wr.log' 为同一文件", + "cp: '/opt/log/journal.log' 与'/opt/log/journal.log' 为同一文件", + "cp: '/opt/log/boot.log' 与'/opt/log/boot.log' 为同一文件", + "cp: '/opt/log/vmware-vmsvc.log' 与'/opt/log/vmware-vmsvc.log' 为同一文件", + "cp: '/opt/log/Xorg.9.log' 与'/opt/log/Xorg.9.log' 为同一文件", + "cp: '/opt/log/vmware-vmusr.log' 与'/opt/log/vmware-vmusr.log' 为同一文件", + "cp: '/opt/log/dnf.log' 与'/opt/log/dnf.log' 为同一文件", + "cp: '/opt/log/dnf.rpm.log' 与'/opt/log/dnf.rpm.log' 为同一文件", + "cp: '/opt/log/vmware-network.6.log' 与'/opt/log/vmware-network.6.log' 为同一文件", + "cp: '/opt/log/vmware-network.5.log' 与'/opt/log/vmware-network.5.log' 为同一文件", + "cp: '/opt/log/vmware-network.4.log' 与'/opt/log/vmware-network.4.log' 为同一文件", + "cp: '/opt/log/vmware-network.3.log' 与'/opt/log/vmware-network.3.log' 为同一文件", + "cp: '/opt/log/vmware-network.2.log' 与'/opt/log/vmware-network.2.log' 为同一文件", + "cp: '/opt/log/vmware-network.1.log' 与'/opt/log/vmware-network.1.log' 为同一文件", + "cp: '/opt/log/vmware-network.log' 与'/opt/log/vmware-network.log' 为同一文件", + "cp: '/opt/log/rpm.log' 与'/opt/log/rpm.log' 为同一文件", + "cp: '/opt/log/error.log' 与'/opt/log/error.log' 为同一文件", + "cp: '/opt/log/access.log' 与'/opt/log/access.log' 为同一文件" + ] +} +``` + +## 二、学习视频 + +[视频:script模块](https://www.bilibili.com/video/BV19J41167sM?p=22) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-service\346\250\241\345\235\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-service\346\250\241\345\235\227.md" new file mode 100644 index 0000000..6a89152 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-service\346\250\241\345\235\227.md" @@ -0,0 +1,449 @@ +## 一、service模块 + +service模块:用于控制服务的启动,关闭,开机自启动等。 + +https://docs.ansible.com/ansible/latest/modules/service_module.html#service-module + +| 参数 | 说明 | +| ------------------------------------------- | ------------ | +| name | 服务名称 | +| state reloaded, restarted, started, stopped | 服务管理 | +| enabled yes\|no | 开启是否启动 | + +启动vsftpd服务,并设为开机自动启动 + +``` +[root@manage01 ~]# ansible -m service 192.168.98.202 -a "name=vsftpd state=started enabled=on" +192.168.98.202 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "enabled": true, + "name": "vsftpd", + "state": "started", + "status": { + "ActiveEnterTimestampMonotonic": "0", + "ActiveExitTimestampMonotonic": "0", + "ActiveState": "inactive", + "After": "network.target systemd-journald.socket system.slice basic.target sysinit.target", + "AllowIsolate": "no", + "AmbientCapabilities": "", + "AssertResult": "no", + "AssertTimestampMonotonic": "0", + "Before": "shutdown.target", + "BlockIOAccounting": "no", + "BlockIOWeight": "[not set]", + "CPUAccounting": "no", + "CPUQuotaPerSecUSec": "infinity", + "CPUSchedulingPolicy": "0", + "CPUSchedulingPriority": "0", + "CPUSchedulingResetOnFork": "no", + "CPUShares": "[not set]", + "CPUUsageNSec": "[not set]", + "CPUWeight": "[not set]", + "CacheDirectoryMode": "0755", + "CanIsolate": "no", + "CanReload": "no", + "CanStart": "yes", + "CanStop": "yes", + "CapabilityBoundingSet": "cap_chown cap_dac_override cap_dac_read_search cap_fowner cap_fsetid cap_kill cap_setgid cap_setuid cap_setpcap cap_linux_immutable cap_net_bind_service cap_net_broadcast cap_net_admin cap_net_raw cap_ipc_lock cap_ipc_owner cap_sys_module cap_sys_rawio cap_sys_chroot cap_sys_ptrace cap_sys_pacct cap_sys_admin cap_sys_boot cap_sys_nice cap_sys_resource cap_sys_time cap_sys_tty_config cap_mknod cap_lease cap_audit_write cap_audit_control cap_setfcap cap_mac_override cap_mac_admin cap_syslog cap_wake_alarm cap_block_suspend", + "CollectMode": "inactive", + "ConditionResult": "no", + "ConditionTimestampMonotonic": "0", + "ConfigurationDirectoryMode": "0755", + "Conflicts": "shutdown.target", + "ControlPID": "0", + "DefaultDependencies": "yes", + "Delegate": "no", + "Description": "Vsftpd ftp daemon", + "DevicePolicy": "auto", + "DynamicUser": "no", + "ExecMainCode": "0", + "ExecMainExitTimestampMonotonic": "0", + "ExecMainPID": "0", + "ExecMainStartTimestampMonotonic": "0", + "ExecMainStatus": "0", + "ExecStart": "{ path=/usr/sbin/vsftpd ; argv[]=/usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", + "FailureAction": "none", + "FileDescriptorStoreMax": "0", + "FragmentPath": "/usr/lib/systemd/system/vsftpd.service", + "GID": "[not set]", + "GuessMainPID": "yes", + "IOAccounting": "no", + "IOSchedulingClass": "0", + "IOSchedulingPriority": "0", + "IOWeight": "[not set]", + "IPAccounting": "no", + "IPEgressBytes": "18446744073709551615", + "IPEgressPackets": "18446744073709551615", + "IPIngressBytes": "18446744073709551615", + "IPIngressPackets": "18446744073709551615", + "Id": "vsftpd.service", + "IgnoreOnIsolate": "no", + "IgnoreSIGPIPE": "yes", + "InactiveEnterTimestampMonotonic": "0", + "InactiveExitTimestampMonotonic": "0", + "JobRunningTimeoutUSec": "infinity", + "JobTimeoutAction": "none", + "JobTimeoutUSec": "infinity", + "KeyringMode": "private", + "KillMode": "control-group", + "KillSignal": "15", + "LimitAS": "infinity", + "LimitASSoft": "infinity", + "LimitCORE": "infinity", + "LimitCORESoft": "infinity", + "LimitCPU": "infinity", + "LimitCPUSoft": "infinity", + "LimitDATA": "infinity", + "LimitDATASoft": "infinity", + "LimitFSIZE": "infinity", + "LimitFSIZESoft": "infinity", + "LimitLOCKS": "infinity", + "LimitLOCKSSoft": "infinity", + "LimitMEMLOCK": "16777216", + "LimitMEMLOCKSoft": "16777216", + "LimitMSGQUEUE": "819200", + "LimitMSGQUEUESoft": "819200", + "LimitNICE": "0", + "LimitNICESoft": "0", + "LimitNOFILE": "4096", + "LimitNOFILESoft": "1024", + "LimitNPROC": "7741", + "LimitNPROCSoft": "7741", + "LimitRSS": "infinity", + "LimitRSSSoft": "infinity", + "LimitRTPRIO": "0", + "LimitRTPRIOSoft": "0", + "LimitRTTIME": "infinity", + "LimitRTTIMESoft": "infinity", + "LimitSIGPENDING": "7741", + "LimitSIGPENDINGSoft": "7741", + "LimitSTACK": "infinity", + "LimitSTACKSoft": "8388608", + "LoadState": "loaded", + "LockPersonality": "no", + "LogLevelMax": "-1", + "LogsDirectoryMode": "0755", + "MainPID": "0", + "MemoryAccounting": "yes", + "MemoryCurrent": "[not set]", + "MemoryDenyWriteExecute": "no", + "MemoryHigh": "infinity", + "MemoryLimit": "infinity", + "MemoryLow": "0", + "MemoryMax": "infinity", + "MemorySwapMax": "infinity", + "MountAPIVFS": "no", + "MountFlags": "", + "NFileDescriptorStore": "0", + "NRestarts": "0", + "Names": "vsftpd.service", + "NeedDaemonReload": "no", + "Nice": "0", + "NoNewPrivileges": "no", + "NonBlocking": "no", + "NotifyAccess": "none", + "OOMScoreAdjust": "0", + "OnFailureJobMode": "replace", + "PermissionsStartOnly": "no", + "Perpetual": "no", + "PrivateDevices": "no", + "PrivateMounts": "no", + "PrivateNetwork": "no", + "PrivateTmp": "no", + "PrivateUsers": "no", + "ProtectControlGroups": "no", + "ProtectHome": "no", + "ProtectKernelModules": "no", + "ProtectKernelTunables": "no", + "ProtectSystem": "no", + "RefuseManualStart": "no", + "RefuseManualStop": "no", + "RemainAfterExit": "no", + "RemoveIPC": "no", + "Requires": "sysinit.target system.slice", + "Restart": "no", + "RestartUSec": "100ms", + "RestrictNamespaces": "no", + "RestrictRealtime": "no", + "Result": "success", + "RootDirectoryStartOnly": "no", + "RuntimeDirectoryMode": "0755", + "RuntimeDirectoryPreserve": "no", + "RuntimeMaxUSec": "infinity", + "SameProcessGroup": "no", + "SecureBits": "0", + "SendSIGHUP": "no", + "SendSIGKILL": "yes", + "Slice": "system.slice", + "StandardError": "inherit", + "StandardInput": "null", + "StandardInputData": "", + "StandardOutput": "journal", + "StartLimitAction": "none", + "StartLimitBurst": "5", + "StartLimitIntervalUSec": "10s", + "StartupBlockIOWeight": "[not set]", + "StartupCPUShares": "[not set]", + "StartupCPUWeight": "[not set]", + "StartupIOWeight": "[not set]", + "StateChangeTimestampMonotonic": "0", + "StateDirectoryMode": "0755", + "StatusErrno": "0", + "StopWhenUnneeded": "no", + "SubState": "dead", + "SuccessAction": "none", + "SyslogFacility": "3", + "SyslogLevel": "6", + "SyslogLevelPrefix": "yes", + "SyslogPriority": "30", + "SystemCallErrorNumber": "0", + "TTYReset": "no", + "TTYVHangup": "no", + "TTYVTDisallocate": "no", + "TasksAccounting": "yes", + "TasksCurrent": "[not set]", + "TasksMax": "12386", + "TimeoutStartUSec": "1min 30s", + "TimeoutStopUSec": "1min 30s", + "TimerSlackNSec": "50000", + "Transient": "no", + "Type": "forking", + "UID": "[not set]", + "UMask": "0022", + "UnitFilePreset": "disabled", + "UnitFileState": "disabled", + "UtmpMode": "init", + "WatchdogTimestampMonotonic": "0", + "WatchdogUSec": "0" + } +} +``` + +关闭vsftpd服务,并设为开机不自动启动 + +``` +[root@manage01 ~]# ansible -m service 192.168.98.202 -a "name=vsftpd state=stopped enabled=false" +192.168.98.202 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "enabled": false, + "name": "vsftpd", + "state": "stopped", + "status": { + "ActiveEnterTimestamp": "Fri 2019-10-18 04:13:19 EDT", + "ActiveEnterTimestampMonotonic": "89286681247", + "ActiveExitTimestampMonotonic": "0", + "ActiveState": "active", + "After": "systemd-journald.socket sysinit.target basic.target system.slice network.target", + "AllowIsolate": "no", + "AmbientCapabilities": "", + "AssertResult": "yes", + "AssertTimestamp": "Fri 2019-10-18 04:13:19 EDT", + "AssertTimestampMonotonic": "89286676375", + "Before": "multi-user.target shutdown.target", + "BlockIOAccounting": "no", + "BlockIOWeight": "[not set]", + "CPUAccounting": "no", + "CPUQuotaPerSecUSec": "infinity", + "CPUSchedulingPolicy": "0", + "CPUSchedulingPriority": "0", + "CPUSchedulingResetOnFork": "no", + "CPUShares": "[not set]", + "CPUUsageNSec": "[not set]", + "CPUWeight": "[not set]", + "CacheDirectoryMode": "0755", + "CanIsolate": "no", + "CanReload": "no", + "CanStart": "yes", + "CanStop": "yes", + "CapabilityBoundingSet": "cap_chown cap_dac_override cap_dac_read_search cap_fowner cap_fsetid cap_kill cap_setgid cap_setuid cap_setpcap cap_linux_immutable cap_net_bind_service cap_net_broadcast cap_net_admin cap_net_raw cap_ipc_lock cap_ipc_owner cap_sys_module cap_sys_rawio cap_sys_chroot cap_sys_ptrace cap_sys_pacct cap_sys_admin cap_sys_boot cap_sys_nice cap_sys_resource cap_sys_time cap_sys_tty_config cap_mknod cap_lease cap_audit_write cap_audit_control cap_setfcap cap_mac_override cap_mac_admin cap_syslog cap_wake_alarm cap_block_suspend", + "CollectMode": "inactive", + "ConditionResult": "yes", + "ConditionTimestamp": "Fri 2019-10-18 04:13:19 EDT", + "ConditionTimestampMonotonic": "89286676375", + "ConfigurationDirectoryMode": "0755", + "Conflicts": "shutdown.target", + "ControlGroup": "/system.slice/vsftpd.service", + "ControlPID": "0", + "DefaultDependencies": "yes", + "Delegate": "no", + "Description": "Vsftpd ftp daemon", + "DevicePolicy": "auto", + "DynamicUser": "no", + "ExecMainCode": "0", + "ExecMainExitTimestampMonotonic": "0", + "ExecMainPID": "51752", + "ExecMainStartTimestamp": "Fri 2019-10-18 04:13:19 EDT", + "ExecMainStartTimestampMonotonic": "89286681239", + "ExecMainStatus": "0", + "ExecStart": "{ path=/usr/sbin/vsftpd ; argv[]=/usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf ; ignore_errors=no ; start_time=[Fri 2019-10-18 04:13:19 EDT] ; stop_time=[Fri 2019-10-18 04:13:19 EDT] ; pid=51751 ; code=exited ; status=0 }", + "FailureAction": "none", + "FileDescriptorStoreMax": "0", + "FragmentPath": "/usr/lib/systemd/system/vsftpd.service", + "GID": "[not set]", + "GuessMainPID": "yes", + "IOAccounting": "no", + "IOSchedulingClass": "0", + "IOSchedulingPriority": "0", + "IOWeight": "[not set]", + "IPAccounting": "no", + "IPEgressBytes": "18446744073709551615", + "IPEgressPackets": "18446744073709551615", + "IPIngressBytes": "18446744073709551615", + "IPIngressPackets": "18446744073709551615", + "Id": "vsftpd.service", + "IgnoreOnIsolate": "no", + "IgnoreSIGPIPE": "yes", + "InactiveEnterTimestampMonotonic": "0", + "InactiveExitTimestamp": "Fri 2019-10-18 04:13:19 EDT", + "InactiveExitTimestampMonotonic": "89286677130", + "InvocationID": "e326c69c138b430880f883b0bdb05f83", + "JobRunningTimeoutUSec": "infinity", + "JobTimeoutAction": "none", + "JobTimeoutUSec": "infinity", + "KeyringMode": "private", + "KillMode": "control-group", + "KillSignal": "15", + "LimitAS": "infinity", + "LimitASSoft": "infinity", + "LimitCORE": "infinity", + "LimitCORESoft": "infinity", + "LimitCPU": "infinity", + "LimitCPUSoft": "infinity", + "LimitDATA": "infinity", + "LimitDATASoft": "infinity", + "LimitFSIZE": "infinity", + "LimitFSIZESoft": "infinity", + "LimitLOCKS": "infinity", + "LimitLOCKSSoft": "infinity", + "LimitMEMLOCK": "16777216", + "LimitMEMLOCKSoft": "16777216", + "LimitMSGQUEUE": "819200", + "LimitMSGQUEUESoft": "819200", + "LimitNICE": "0", + "LimitNICESoft": "0", + "LimitNOFILE": "4096", + "LimitNOFILESoft": "1024", + "LimitNPROC": "7741", + "LimitNPROCSoft": "7741", + "LimitRSS": "infinity", + "LimitRSSSoft": "infinity", + "LimitRTPRIO": "0", + "LimitRTPRIOSoft": "0", + "LimitRTTIME": "infinity", + "LimitRTTIMESoft": "infinity", + "LimitSIGPENDING": "7741", + "LimitSIGPENDINGSoft": "7741", + "LimitSTACK": "infinity", + "LimitSTACKSoft": "8388608", + "LoadState": "loaded", + "LockPersonality": "no", + "LogLevelMax": "-1", + "LogsDirectoryMode": "0755", + "MainPID": "51752", + "MemoryAccounting": "yes", + "MemoryCurrent": "577536", + "MemoryDenyWriteExecute": "no", + "MemoryHigh": "infinity", + "MemoryLimit": "infinity", + "MemoryLow": "0", + "MemoryMax": "infinity", + "MemorySwapMax": "infinity", + "MountAPIVFS": "no", + "MountFlags": "", + "NFileDescriptorStore": "0", + "NRestarts": "0", + "Names": "vsftpd.service", + "NeedDaemonReload": "no", + "Nice": "0", + "NoNewPrivileges": "no", + "NonBlocking": "no", + "NotifyAccess": "none", + "OOMScoreAdjust": "0", + "OnFailureJobMode": "replace", + "PermissionsStartOnly": "no", + "Perpetual": "no", + "PrivateDevices": "no", + "PrivateMounts": "no", + "PrivateNetwork": "no", + "PrivateTmp": "no", + "PrivateUsers": "no", + "ProtectControlGroups": "no", + "ProtectHome": "no", + "ProtectKernelModules": "no", + "ProtectKernelTunables": "no", + "ProtectSystem": "no", + "RefuseManualStart": "no", + "RefuseManualStop": "no", + "RemainAfterExit": "no", + "RemoveIPC": "no", + "Requires": "system.slice sysinit.target", + "Restart": "no", + "RestartUSec": "100ms", + "RestrictNamespaces": "no", + "RestrictRealtime": "no", + "Result": "success", + "RootDirectoryStartOnly": "no", + "RuntimeDirectoryMode": "0755", + "RuntimeDirectoryPreserve": "no", + "RuntimeMaxUSec": "infinity", + "SameProcessGroup": "no", + "SecureBits": "0", + "SendSIGHUP": "no", + "SendSIGKILL": "yes", + "Slice": "system.slice", + "StandardError": "inherit", + "StandardInput": "null", + "StandardInputData": "", + "StandardOutput": "journal", + "StartLimitAction": "none", + "StartLimitBurst": "5", + "StartLimitIntervalUSec": "10s", + "StartupBlockIOWeight": "[not set]", + "StartupCPUShares": "[not set]", + "StartupCPUWeight": "[not set]", + "StartupIOWeight": "[not set]", + "StateChangeTimestamp": "Fri 2019-10-18 04:13:19 EDT", + "StateChangeTimestampMonotonic": "89286681247", + "StateDirectoryMode": "0755", + "StatusErrno": "0", + "StopWhenUnneeded": "no", + "SubState": "running", + "SuccessAction": "none", + "SyslogFacility": "3", + "SyslogLevel": "6", + "SyslogLevelPrefix": "yes", + "SyslogPriority": "30", + "SystemCallErrorNumber": "0", + "TTYReset": "no", + "TTYVHangup": "no", + "TTYVTDisallocate": "no", + "TasksAccounting": "yes", + "TasksCurrent": "1", + "TasksMax": "12386", + "TimeoutStartUSec": "1min 30s", + "TimeoutStopUSec": "1min 30s", + "TimerSlackNSec": "50000", + "Transient": "no", + "Type": "forking", + "UID": "[not set]", + "UMask": "0022", + "UnitFilePreset": "disabled", + "UnitFileState": "enabled", + "UtmpMode": "init", + "WantedBy": "multi-user.target", + "WatchdogTimestamp": "Fri 2019-10-18 04:13:19 EDT", + "WatchdogTimestampMonotonic": "89286681246", + "WatchdogUSec": "0" + } +} +``` + +## 二、学习视频 + +[视频:service模块](https://www.bilibili.com/video/BV19J41167sM?p=21) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-setup\346\250\241\345\235\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-setup\346\250\241\345\235\227.md" new file mode 100644 index 0000000..41ad7fe --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-setup\346\250\241\345\235\227.md" @@ -0,0 +1,167 @@ +## 一、setup模块 + +setup模块用于收集远程主机的基本信息(如操作系统类型,主机名,ip,cpu信息,内存信息等) + +``` +#打印192.168.98.201机器的所有信息 +[root@manage01 ~]# ansible -m setup 192.168.98.201 + +#使用filter过滤输出 +#打印192.168.98.201机器的CPU信息 +[root@manage01 ~]# ansible -m setup 192.168.98.201 -a "filter='ansible_processor'" +192.168.98.201 | SUCCESS => { + "ansible_facts": { + "ansible_processor": [ + "0", + "GenuineIntel", + "Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz", + "1", + "GenuineIntel", + "Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz", + "2", + "GenuineIntel", + "Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz", + "3", + "GenuineIntel", + "Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz" + ], + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": false +} +#打印192.168.98.201机器的内核信息 +[root@manage01 ~]# ansible -m setup 192.168.98.201 -a "filter='ansible_kernel'" +192.168.98.201 | SUCCESS => { + "ansible_facts": { + "ansible_kernel": "4.18.0-80.el8.x86_64", + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": false +} +#打印192.168.98.201机器的主机名 +[root@manage01 ~]# ansible -m setup 192.168.98.201 -a "filter='ansible_hostname'" +192.168.98.201 | SUCCESS => { + "ansible_facts": { + "ansible_hostname": "node1", + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": false +} +#打印192.168.98.201机器的网卡信息 +[root@manage01 ~]# ansible -m setup 192.168.98.201 -a "filter='ansible_ens*'" +192.168.98.201 | SUCCESS => { + "ansible_facts": { + "ansible_ens33": { + "active": true, + "device": "ens33", + "features": { + "esp_hw_offload": "off [fixed]", + "esp_tx_csum_hw_offload": "off [fixed]", + "fcoe_mtu": "off [fixed]", + "generic_receive_offload": "on", + "generic_segmentation_offload": "on", + "highdma": "off [fixed]", + "hw_tc_offload": "off [fixed]", + "l2_fwd_offload": "off [fixed]", + "large_receive_offload": "off [fixed]", + "loopback": "off [fixed]", + "netns_local": "off [fixed]", + "ntuple_filters": "off [fixed]", + "receive_hashing": "off [fixed]", + "rx_all": "off", + "rx_checksumming": "off", + "rx_fcs": "off", + "rx_gro_hw": "off [fixed]", + "rx_udp_tunnel_port_offload": "off [fixed]", + "rx_vlan_filter": "on [fixed]", + "rx_vlan_offload": "on", + "rx_vlan_stag_filter": "off [fixed]", + "rx_vlan_stag_hw_parse": "off [fixed]", + "scatter_gather": "on", + "tcp_segmentation_offload": "on", + "tls_hw_record": "off [fixed]", + "tls_hw_tx_offload": "off [fixed]", + "tx_checksum_fcoe_crc": "off [fixed]", + "tx_checksum_ip_generic": "on", + "tx_checksum_ipv4": "off [fixed]", + "tx_checksum_ipv6": "off [fixed]", + "tx_checksum_sctp": "off [fixed]", + "tx_checksumming": "on", + "tx_esp_segmentation": "off [fixed]", + "tx_fcoe_segmentation": "off [fixed]", + "tx_gre_csum_segmentation": "off [fixed]", + "tx_gre_segmentation": "off [fixed]", + "tx_gso_partial": "off [fixed]", + "tx_gso_robust": "off [fixed]", + "tx_ipxip4_segmentation": "off [fixed]", + "tx_ipxip6_segmentation": "off [fixed]", + "tx_lockless": "off [fixed]", + "tx_nocache_copy": "off", + "tx_scatter_gather": "on", + "tx_scatter_gather_fraglist": "off [fixed]", + "tx_sctp_segmentation": "off [fixed]", + "tx_tcp6_segmentation": "off [fixed]", + "tx_tcp_ecn_segmentation": "off [fixed]", + "tx_tcp_mangleid_segmentation": "off", + "tx_tcp_segmentation": "on", + "tx_udp_segmentation": "off [fixed]", + "tx_udp_tnl_csum_segmentation": "off [fixed]", + "tx_udp_tnl_segmentation": "off [fixed]", + "tx_vlan_offload": "on [fixed]", + "tx_vlan_stag_hw_insert": "off [fixed]", + "udp_fragmentation_offload": "off", + "vlan_challenged": "off [fixed]" + }, + "hw_timestamp_filters": [], + "ipv4": { + "address": "192.168.98.201", + "broadcast": "192.168.98.255", + "netmask": "255.255.255.0", + "network": "192.168.98.0" + }, + "ipv6": [ + { + "address": "fe80::357b:9443:2232:f0c0", + "prefix": "64", + "scope": "link" + } + ], + "macaddress": "00:0c:29:b8:d0:45", + "module": "e1000", + "mtu": 1500, + "pciid": "0000:02:01.0", + "promisc": false, + "speed": 1000, + "timestamping": [ + "tx_software", + "rx_software", + "software" + ], + "type": "ether" + }, + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": false +} + + +其它常见的过滤条件 +ansible_all_ipv4_addresses:显示ipv4的信息。 +ansible_devices:显示磁盘设备信息。 +ansible_distribution_major_version:显示是系统主版本。 +ansible_distribution_version:仅显示系统版本。 +ansible_machine:显示系统类型,例:32位,还是64位。 +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个数(只显示总的个数)。 +``` + +## 二、学习视频 + +[视频:setup模块](https://www.bilibili.com/video/BV19J41167sM?p=24) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-stat\346\250\241\345\235\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-stat\346\250\241\345\235\227.md" new file mode 100644 index 0000000..6b252fe --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-stat\346\250\241\345\235\227.md" @@ -0,0 +1,67 @@ +## 一、stat模块 + +stat模块类似linux的stat命令,用于获取文件的状态信息。 + +https://docs.ansible.com/ansible/latest/modules/stat_module.html#stat-module + +获取/etc/fstab文件的状态信息 + +``` +[root@manage01 ~]# ansible -m stat 192.168.98.201 -a "path=/etc/fstab" +192.168.98.201 | SUCCESS => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": false, + "stat": { + "atime": 1571386074.1020715, + "attr_flags": "", + "attributes": [], + "block_size": 4096, + "blocks": 8, + "charset": "us-ascii", + "checksum": "554e387b5bde93c05baa689312e9a8db5579629e", + "ctime": 1570636725.1020045, + "dev": 64768, + "device_type": 0, + "executable": false, + "exists": true, + "gid": 0, + "gr_name": "root", + "inode": 16777347, + "isblk": false, + "ischr": false, + "isdir": false, + "isfifo": false, + "isgid": false, + "islnk": false, + "isreg": true, + "issock": false, + "isuid": false, + "mimetype": "text/plain", + "mode": "0644", + "mtime": 1570636308.3990006, + "nlink": 1, + "path": "/etc/fstab", + "pw_name": "root", + "readable": true, + "rgrp": true, + "roth": true, + "rusr": true, + "size": 579, + "uid": 0, + "version": "1364475400", + "wgrp": false, + "woth": false, + "writeable": true, + "wusr": true, + "xgrp": false, + "xoth": false, + "xusr": false + } +} +``` + +## 二、学习视频 + +[视频:ansible常用模块知识图谱](https://www.bilibili.com/video/BV19J41167sM?p=25) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-user\346\250\241\345\235\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-user\346\250\241\345\235\227.md" new file mode 100644 index 0000000..df56890 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-user\346\250\241\345\235\227.md" @@ -0,0 +1,127 @@ +## 一、user模块 + +user模块用于管理用户账号和用户属性 + +https://docs.ansible.com/ansible/latest/modules/user_module.html#user-module + +| 常用参数 | 说明 | +| ------------------------- | ---------------------------------------------------------- | +| name="" | 指定用户名 | +| password="" | 指定密码,必须是密文 | +| state= absent\|present | 删除\|创建 | +| system= yes\|no | 是否为系统用户 | +| shell="" | 指定登陆shell | +| generate_ssh_key= yes\|no | 是否创建秘钥对 | +| uid= | 指定用户的uid | +| append= yes\|no | 用户是否追加到其他组 | +| group= | 用户属组 | +| groups= | 将现有用户加入到某个组,空值就会把该用户从所有所属组中删除 | +| create_home= yes\|no | 是否建立家目录 | +| remove= yes\|no | 删除家目录 | + +**创建一个用户sky,密码是123** + +**要求是系统用户** + +**非交互式登陆** + +**要求生成自己的秘钥对** + +**不创建家目录** + +``` +#密码必须是密文,所以先要把明文转换一下,生成md5密文 +[root@manage01 ~]# echo 123|openssl passwd -1 -stdin +$1$5V.qzSEd$Yr08MU8K.vXeBZcmavypk1 +[root@manage01 ~]# ansible -m user group1 -a 'name=sky password="$1$5V.qzSEd$Yr08MU8K.vXeBZcmavypk1" state=present system=yes shell=/sbin/nologin generate_ssh_key=yes' +192.168.98.203 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "comment": "", + "create_home": true, + "group": 991, + "home": "/home/sky", + "name": "sky", + "password": "NOT_LOGGING_PASSWORD", + "shell": "/sbin/nologin", + "ssh_fingerprint": "2048 SHA256:b2umG0XfPW0cGAFBFDBNBNbtgaY+s1X4cM334JCGGOo ansible-generated on node3 (RSA)", + "ssh_key_file": "/home/sky/.ssh/id_rsa", + "ssh_public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDIvVcTDxT4GotFYolpPPJUS2XYEmgaxCj/YLXfW2vllXJSfa3TwBLN6kJnPBabVFSYCiGRzci28f/rx4chm9TuVsNx6TozzUpolD+T3vzO/rcLdaIEzw+JYXGtqpaTapuuhm6pdQBx04TLmO3pVWBCdbJum0paMIXwPDcGPGz6JwGXWTdA5AXfvWmOZ5ChwwLDUau84R47FHfj9EisclYM3Yt3WfcVp+waSd23BBRj86jh+veL9BR7OnDmmj7YZkOxAqnU/TjuOW1uiGCB91Flgku7fPR3jmbXXrd+Ql9vWlGe22+xgYYjT4KVzlHAr3lE/HZQu49Vz/N78ZnJ1rX3 ansible-generated on node3", + "state": "present", + "system": true, + "uid": 994 +} +192.168.98.201 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "comment": "", + "create_home": true, + "group": 974, + "home": "/home/sky", + "name": "sky", + "password": "NOT_LOGGING_PASSWORD", + "shell": "/sbin/nologin", + "ssh_fingerprint": "2048 SHA256:D2ZhPJV9bdFMtf7EBo3Y5w023xqxDppZxqoe5Z3NVus ansible-generated on node1 (RSA)", + "ssh_key_file": "/home/sky/.ssh/id_rsa", + "ssh_public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD1swS5MAox4o2f3rxe9TPz+AFDnB5Jt+X6Yygpphfetfds37SHSP5K4QcAd1SO6OlHopB3x9FQklS3z6C4bfz5trbK/PR9RCzkkzLamC5BKhNXEV2ozj1m2J/F10umZLSvd3ElEJubkyzV383x7sVi5VtQycemoDLiJiWjHTEcKu/I0bSCliODe57nqgM9+5V+nfeih56Vs+vhTGIxqZ/6FZXKGM9iDiI8VokUlMjhOJz5MuFRr4XsgBvtGNyu/bCbjr8QPdDNX/Wl8IZDjLJNHDno8ixc7Bp6ME2hEr9pnpe+DuKJmsAwl+A52E7eAlm/0pp573mZ4ObHRTQwdgQT ansible-generated on node1", + "state": "present", + "system": true, + "uid": 976 +} +192.168.98.202 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "comment": "", + "create_home": true, + "group": 975, + "home": "/home/sky", + "name": "sky", + "password": "NOT_LOGGING_PASSWORD", + "shell": "/sbin/nologin", + "ssh_fingerprint": "2048 SHA256:/VBzZUWcHnLOpMNxq9OXIwD/5IkI9r7smp50s6lByZs ansible-generated on node2 (RSA)", + "ssh_key_file": "/home/sky/.ssh/id_rsa", + "ssh_public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDT/+8y3omHiWSOS9dX1AYcADRp7ZUszOBqZV0/77TZ7mV5X1/T+cdZrsnwAiNbXosjDQjKj0qtIJQR3rLuCv08DV6gjlP4bzDodSekfh1mbGu9EkDu0HD+qmW0/y5Mb4lJbBCMHCVJFrwBnH2+AfVezTVgcf4NHh4zJvASnSfmecmyfFEDEVZIozd0z8hw8NcgcYn8MeDrMhVN+y3xj0IXKwg6E0NindBuxkMYbwehcQo6Sscx9YdCv05SXVU+FjyPOQNzZZUQkmp+5GDy1dib1m5GJ5yIf8IzOh1FISoKz8/FqORRIEp55NRgrGw3ZU/weK0RL9SkXhUc29gcN1ON ansible-generated on node2", + "state": "present", + "system": true, + "uid": 977 +} + + + +创建用户baishuming 密码为123456 +[root@manage01 ~]# echo "123456"|openssl passwd -1 -stdin +$1$BMPgiHeV$GskMFnvqBL17gTe/us5yK. +[root@manage01 ~]# ansible -m user group1 -a 'name=baishuming password="$1$BMPgiHeV$GskMFnvqBL17gTe/us5yK." uid=4423' + +不创建家目录 +[root@manage01 ~]# ansible -m user 192.168.98.201 -a "name=baism create_home=no" + +要求属组为root +附加组为sko +``` + +用户删除 + +``` +[root@manage01 ~]# ansible -m user 192.168.98.201 -a "name=baishuming1 state=absent remove=yes" +192.168.98.201 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/bin/python" + }, + "changed": true, + "force": false, + "name": "baishuming1", + "remove": true, + "state": "absent" +} +``` + +## 二、学习视频 + +[视频:user模块](https://www.bilibili.com/video/BV19J41167sM?p=16) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-yum_repository\346\250\241\345\235\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-yum_repository\346\250\241\345\235\227.md" new file mode 100644 index 0000000..b03c488 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-yum_repository\346\250\241\345\235\227.md" @@ -0,0 +1,78 @@ +## 一、yum_repository模块 + +yum_repository模块用于配置yum仓库。 + +https://docs.ansible.com/ansible/latest/modules/yum_repository_module.html + +| 参数 | 说明 | +| ----------------- | -------------------------------- | +| name | 仓库名 name.repo 源的名称 [name] | +| description | 描述 | +| baseurl | 包下载路径 | +| gpgcheck= 1 or 0 | 包gpg验证 | +| enabled = yes\|no | 是否开启本源 | +| state= absent | 删除源 | + +增加一个/etc/yum.repos.d/dvd.repo配置文件 + +``` +[root@manage01 ~]# ansible -m yum_repository group1 -a "name=dvd description=BaseOS baseurl=file:///mnt/BaseOS gpgcheck=0 enabled=yes" +192.168.98.203 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "repo": "dvd", + "state": "present" +} +192.168.98.201 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "repo": "dvd", + "state": "present" +} +192.168.98.202 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "repo": "dvd", + "state": "present" +} +``` + +删除某个yum源 + +``` +[root@manage01 ~]# ansible -m yum_repository group1 -a "name=dvd state=absent" +192.168.98.203 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "repo": "dvd", + "state": "absent" +} +192.168.98.202 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "repo": "dvd", + "state": "absent" +} +192.168.98.201 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "repo": "dvd", + "state": "absent" +} +``` + +## 二、学习视频 + +[视频:yum_repository模块](https://www.bilibili.com/video/BV19J41167sM?p=19) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-yum\346\250\241\345\235\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-yum\346\250\241\345\235\227.md" new file mode 100644 index 0000000..e18af87 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible-yum\346\250\241\345\235\227.md" @@ -0,0 +1,92 @@ +## 一、yum模块 + +yum模块用于使用yum命令来实现软件包的安装与卸载。 + +https://docs.ansible.com/ansible/latest/modules/yum_module.html#yum-module + +| 参数 | 说明 | +| ---------------------------------------------- | -------------------------------------------- | +| name | 需要安装软件包的名称 | +| list= installed, updates, available and repos | 列出已安装 需要更新 可获得的 和 yum源 | +| state= absent removed installed present latest | 删除、删除、安装确认、安装确认、安装最新版本 | + +list:列出包信息 + +``` +[root@manage01 ~]# ansible -m yum group1 -a "list=repos" +192.168.98.201 | FAILED! => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": false, + "msg": "同步仓库 'dvd' 缓存失败", + "rc": 1, + "results": [] +} + + +原因就是源不好用,这里是cdrom没有挂载光盘 +``` + +使用yum安装一个软件(前提:group1的机器上的yum配置都已经OK) + +``` +[root@manage01 ~]# ansible -m yum group1 -a "name=vsftpd" +192.168.98.203 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "msg": "", + "rc": 0, + "results": [ + "Installed: vsftpd", + "Installed: vsftpd-3.0.3-28.el8.x86_64" + ] +} +192.168.98.202 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "msg": "", + "rc": 0, + "results": [ + "Installed: vsftpd", + "Installed: vsftpd-3.0.3-28.el8.x86_64" + ] +} +192.168.98.201 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "msg": "", + "rc": 0, + "results": [ + "Installed: vsftpd", + "Installed: vsftpd-3.0.3-28.el8.x86_64" + ] +} +``` + +删除软件包 + +``` +[root@manage01 ~]# ansible -m yum 192.168.98.201 -a "state=absent name=vsftpd" +192.168.98.201 | CHANGED => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": true, + "msg": "", + "rc": 0, + "results": [ + "Removed: vsftpd-3.0.3-28.el8.x86_64" + ] +} +``` + +## 二、学习视频 + +[视频:yum模块](https://www.bilibili.com/video/BV19J41167sM?p=20) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible\345\221\275\344\273\244\347\224\250\346\263\225.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible\345\221\275\344\273\244\347\224\250\346\263\225.md" new file mode 100644 index 0000000..86ec843 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible\345\221\275\344\273\244\347\224\250\346\263\225.md" @@ -0,0 +1,49 @@ +ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。 + +ansible支持的模块非常的多,我们并不需要把每个模块都记住,而只需要熟悉一些常见的模块,其它的模块在需要用到时再查询即可。 + +## 一、ansible命令用法 + +``` +ansible 机器 -m 模块名称 -a '模块参数' +基本格式为: ansible 操作的机器名或组名 -m 模块名 -a "参数1=值1 参数2=值2" +``` + +**查看所有支持的模块** + +``` +# ansible-doc -l +a10_server Manage A10 Networks AX/SoftAX... +a10_server_axapi3 Manage A10 Networks AX/SoftAX... +a10_service_group Manage A10 Networks AX/SoftAX... +a10_virtual_server Manage A10 Networks AX/SoftAX... +aci_aaa_user Manage AAA users (aaa:User) +....... + +如果要查看ping模块的用法,使用下面命令(其它模块以此类推) +# ansible-doc ping +``` + +官网模块文档地址: https://docs.ansible.com/ansible/latest/modules/list_of_all_modules.html + +## 二、ansible常见模块 + +- hostname模块 +- file模块 +- copy模块 +- fetch模块 +- user模块 +- group模块 +- cron模块 +- yum_repository模块 +- yum模块 +- service模块 +- script模块 +- command模块 +- shell模块 +- setup模块 +- stat模块 + +## 三、学习视频 + +[视频:ansible 命令语法与常见模块介绍](https://www.bilibili.com/video/BV19J41167sM?p=11) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260\351\203\250\347\275\262.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260\351\203\250\347\275\262.md" new file mode 100644 index 0000000..98c89ca --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260\351\203\250\347\275\262.md" @@ -0,0 +1,387 @@ +## 一、部署前准备 + +- 部署机器准备 +- 计算机名解析 +- 关闭防火墙、selinux +- 时间同步 +- 软件包获得 +- ssh免密登陆 + +**约定事项:** + +1. 所有服务器全部采用静态ip + + | 主机名称 | IP地址 | + | -------- | ----------------- | + | manage01 | 192.168.98.200/24 | + | node1 | 192.168.98.201/24 | + | node2 | 192.168.98.202/24 | + | node3 | 192.168.98.203/24 | + +2. 主机名及主机名互相绑定 + + ``` + [root@manage01 ~]# cat /etc/hosts + 127.0.0.1 localhost + ::1 localhost + 192.168.98.200 manage01 + 192.168.98.201 node1 + 192.168.98.202 node2 + 192.168.98.203 node3 + + 其他机器同理 + ``` + +3. 关闭防火墙, selinux + + ``` + [root@manage01 ~]# systemctl disable firewalld + [root@manage01 ~]# sed -i -r '/SELINUX=/c\SELINUX=disabled' /etc/selinux/config + [root@manage01 ~]# reboot + + + 其他机器同理 + ``` + +4. 采用时间服务器,时间同步 + + ``` + 1、修改配置文件,配置时间服务器为阿里云的时间服务器 + [root@manage01 ~]# egrep "^server" /etc/chrony.conf + server ntp1.aliyun.com + server ntp2.aliyun.com + server ntp3.aliyun.com + server ntp4.aliyun.com + + #注释 + # pool 2.centos.pool.ntp.org iburst + + 2、重启服务chronyd + [root@manage01 ~]# systemctl restart chronyd.service + + 3、查看源信息 + #chronyc chrony的命令行客户端 + [root@manage01 ~]# chronyc sources -v + 210 Number of sources = 2 + + .-- Source mode '^' = server, '=' = peer, '#' = local clock. + / .- Source state '*' = current synced, '+' = combined , '-' = not combined, + | / '?' = unreachable, 'x' = time may be in error, '~' = time too variable. + || .- xxxx [ yyyy ] +/- zzzz + || Reachability register (octal) -. | xxxx = adjusted offset, + || Log2(Polling interval) --. | | yyyy = measured offset, + || \ | | zzzz = estimated error. + || | | \ + MS Name/IP address Stratum Poll Reach LastRx Last sample + =============================================================================== + ^? 120.25.115.20 2 6 1 3 +663us[ +663us] +/- 23ms + ^? 203.107.6.88 2 6 1 2 -1326us[-1326us] +/- 17ms + ``` + +5. 确认和配置yum源(需要epel源) + + ``` + [root@manage01 ~]# yum -y install epel-* + ``` + + 6.ssh远程连接 + + 管理端和被管理端连接时基于ssh的,所以有两种连接方式 + + 1)基于ssh口令 + + 2)基于ssh证书(重点讲解) + + 如果想不需要运维人员干预,被管理端必须允许管理端证书免密登陆。 + +6. ``` + #管理端manage01生成ssh公私钥 + [root@manage01 ~]# ssh-keygen + Generating public/private rsa key pair. + Enter file in which to save the key (/root/.ssh/id_rsa): + Enter passphrase (empty for no passphrase): + Enter same passphrase again: + Your identification has been saved in /root/.ssh/id_rsa. + Your public key has been saved in /root/.ssh/id_rsa.pub. + The key fingerprint is: + SHA256:aufJno2QjPK/V63/PVW13h5oWlKu0jk7HesXYTho0gM root@manage01 + The key's randomart image is: + +---[RSA 2048]----+ + | | + | E .| + | o . . o| + | . = + +.| + | S o.+ = +| + | o o ...* +o| + | . . * ....O o.+| + | o . =.*.B o +.| + | ..o+B oo*oo o| + +----[SHA256]-----+ + + #将公钥传给node1 + [root@manage01 ~]# ssh-copy-id -i .ssh/id_rsa.pub root@192.168.98.201 + /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: ".ssh/id_rsa.pub" + The authenticity of host '192.168.98.201 (192.168.98.201)' can't be established. + ECDSA key fingerprint is SHA256:u+yOQz+E+eF7Oixdz/vClLXlAEu/7K8jy783gzk20dQ. + ECDSA key fingerprint is MD5:c0:80:1b:ae:93:32:c2:66:f5:da:2f:1c:26:1e:7e:f8. + Are you sure you want to continue connecting (yes/no)? yes + /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed + /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys + root@192.168.98.201's password: + + Number of key(s) added: 1 + + Now try logging into the machine, with: "ssh 'root@192.168.98.201'" + and check to make sure that only the key(s) you wanted were added. + + #将公钥传给node2 + [root@manage01 ~]# ssh-copy-id -i .ssh/id_rsa.pub root@192.168.98.202 + /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: ".ssh/id_rsa.pub" + The authenticity of host '192.168.98.202 (192.168.98.202)' can't be established. + ECDSA key fingerprint is SHA256:X4JeiiFuwV0cja81veAyGCosriEfZm/zv34cfYkuxmU. + ECDSA key fingerprint is MD5:7d:17:0f:80:d5:2b:30:ec:2c:62:f9:79:6b:fb:5f:bc. + Are you sure you want to continue connecting (yes/no)? yes + /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed + /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys + root@192.168.98.202's password: + + Number of key(s) added: 1 + + Now try logging into the machine, with: "ssh 'root@192.168.98.202'" + and check to make sure that only the key(s) you wanted were added. + + #将公钥传给node3 + [root@manage01 ~]# ssh-copy-id -i .ssh/id_rsa.pub root@192.168.98.203 + /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: ".ssh/id_rsa.pub" + The authenticity of host '192.168.98.203 (192.168.98.203)' can't be established. + ECDSA key fingerprint is SHA256:PtpsYBjaXkE+o3j8QYU5Ju8uPgcW2lVW8wsx4X1PV/c. + ECDSA key fingerprint is MD5:50:a1:63:a0:ef:e7:61:26:11:25:ae:06:ec:93:cb:18. + Are you sure you want to continue connecting (yes/no)? yes + /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed + /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys + root@192.168.98.203's password: + + Number of key(s) added: 1 + + Now try logging into the machine, with: "ssh 'root@192.168.98.203'" + and check to make sure that only the key(s) you wanted were added. + + + + + 小窍门 + 免交互创建公私钥 + [root@manage01 ansible]# ssh-keygen -f /root/.ssh/id_rsa -N "" + -f 指定密钥存放路径 + -N "" 新密码设置问空 + -P "" 老密码是什么 + + + 如何可以非交互式传公钥呢 + [root@manage01 ansible]# yum -y install sshpass + [root@manage01 ansible]# sshpass -p111111 ssh-copy-id -o StrictHostKeyChecking=no -i /root/.ssh/id_rsa.pub root@192.168.98.202 + + + StrictHostKeyChecking 严厉的主机监测=no 就不会问你yes|no了 + sshpass 非交互式传密码 + + + 测试证书是否生效 + [root@manage01 ~]# for i in `seq 201 203`;do + > ssh root@192.168.98.$i "hostname" + > done + node1 + node2 + node3 + + 看到返回客户端的计算机名称 + ``` + +## 二、ansible管理端部署 + +### 2.1)管理端安装ansible + +安装方式: + +1)yum + +``` +[root@manage01 ~]# yum -y install ansible +[root@manage01 ~]# ansible --version +ansible 2.8.5 + config file = /etc/ansible/ansible.cfg + configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] + ansible python module location = /usr/lib/python3.6/site-packages/ansible + executable location = /usr/bin/ansible + python version = 3.6.8 (default, May 21 2019, 23:51:36) [GCC 8.2.1 20180905 (Red Hat 8.2.1-3)] +``` + +2) 源码 + +``` +1、官网下载地址:https://releases.ansible.com/ansible +[root@manage01 ~]# wget https://releases.ansible.com/ansible/ansible-2.9.3.tar.gz +2、安装ansible +[root@manage01 ~]# tar xf ansible-2.9.3.tar.gz +[root@manage01 ~]# mv ansible-2.9.3 /opt/ansible +[root@manage01 ~]# cd /opt/ansible-2.9.3 +#python软件包安装--1、安装依赖 +[root@manage01 ansible-2.9.0rc3]# pip3 install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/ +[root@manage01 ansible]# ln -s /usr/bin/pip3 /usr/bin/pip +#python软件包安装--2、安装软件 +[root@manage01 ansible-2.9.0rc3]# pip install --user ansible -i https://pypi.tuna.tsinghua.edu.cn/simple/ + +#安装后设置 +[root@manage01 ~]# ln -s /usr/bin/python3 /usr/bin/python +[root@manage01 ~]# ln -s /opt/ansible/bin/* /usr/bin/ +[root@manage01 ~]# cp /opt/ansible/examples/ansible.cfg /etc/ansible/ +[root@manage01 ~]# cp /opt/ansible/examples/hosts /etc/ansible/ +``` + +**FAQ1** + +``` +[root@manage01 ansible-2.9.0rc3]# ./bin/ansible -m ping 192.168.98.201 + [WARNING]: No inventory was parsed, only implicit localhost is available + + [WARNING]: provided hosts list is empty, only localhost is available. Note that +the implicit localhost does not match 'all' + + [WARNING]: Could not match supplied host pattern, ignoring: 192.168.98.201 + + 触发原因 + 执行ansible的时候回去读取客户端文件hosts,如果没有把客户端加入到hosts文件,就说明无法ansible无法管理。 + + 解决方案 + [root@manage01 ansible]# mkdir /etc/ansible + [root@manage01 ansible]# cp examples/hosts /etc/ansible/ + #将需要管理的客户端IP地址写入hosts文件,可以分组或者直接写 + [root@manage01 ~]# cat /etc/ansible/hosts + 192.168.98.[201:203] + + 分组 + [group1] +192.168.98.[201:203] +``` + +### 2.2)ansible管理服务器部署 + +管理端ansible目录:/etc/ansible + +``` +[root@manage01 ansible]# tree +. +├── ansible.cfg #ansible配置文件,不需要配置 +├── hosts #主机列表 +└── roles #角色列表 + +1 directory, 2 files +``` + +### 2.3)部署主机列表,定义被监控机 + +``` +[root@manage01 ansible]# egrep -v "(^#|^$)" /etc/ansible/hosts +[group1] #名字可以随便起 后面跟上业务机器的IP地址或者域名 +192.168.98.201 +192.168.98.202 +192.168.98.203 +``` + +**关于业务机器分组** + +``` +分组中使用范围 +[nginx] 组名 +apache[1:10].aaa.com 表示apache1.aaa.com到apache10.aaa.com这10台机器 +nginx[a:z].aaa.com 表示nginxa.aaa.com到nginxz.aaa.com共26台机器 +10.1.1.[11:15] 表示10.1.1.11到10.1.1.15这5台机器 + + + +如果业务机器的SSH端口不是22 +10.1.1.13:2222 表示10.1.1.13这台,但ssh端口为2222 + + +指定业务机器别名,未做免密登陆的机器可以通过下面的机器设置账号密码 +nginx1 ansible_ssh_host=10.1.1.13 ansible_ssh_port=2222 ansible_ssh_user=root ansible_ssh_pass="123456" + +ansible_ssh_host 指定业务机器的IP或域名 +ansible_ssh_port 指定业务机器的ssh端口 +ansible_ssh_user 指定业务机器的ssh用户名 +ansible_ssh_pass 指定业务机器的ssh用户名密码 + + +利用机器别名分组 +nginx1 ansible_ssh_host=10.1.1.13 ansible_ssh_port=2222 ansible_ssh_user=root ansible_ssh_pass="123456" +nginx2 ansible_ssh_host=10.1.1.12 + +[nginx] +nginx1 #写服务器别名 +nginx2 + + +[root@manage01 ansible]# egrep -v "(^#|^$)" /etc/ansible/hosts +#别名定义 +web1 ansible_ssh_host=192.168.98.203 ansible_ssh_port=12121 + +#分组 +[group1] +192.168.98.201 +#未做免密登陆机器 +192.168.98.202:12121 ansible_ssh_user=sko ansible_ssh_pass='123' +#别名机器 +web1 ansible_ssh_user=sko ansible_ssh_pass='123' +``` + +### 2.4)测试管理机和业务机器的联通性 + +``` +我们可以使用ansible通过调用ping模块来测试分组机器或某个机器 +-m 指定使用的模块 group1 业务机器分组 +#测试单个机器 +#测试主机列表中的机器 + + +#测试单个机器方法 +[root@manage01 ~]# ansible -m ping 192.168.98.201 +192.168.98.201 | SUCCESS => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": false, + "ping": "pong" +} + +#测试主机列表中的机器方法 +[root@manage01 ~]# ansible -m ping group1 +192.168.98.201 | SUCCESS => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": false, + "ping": "pong" +} +192.168.98.203 | SUCCESS => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": false, + "ping": "pong" +} +192.168.98.202 | SUCCESS => { + "ansible_facts": { + "discovered_interpreter_python": "/usr/libexec/platform-python" + }, + "changed": false, + "ping": "pong" +} +``` + +## 三、学习视频 + +[视频:部署前准备](https://www.bilibili.com/video/BV19J41167sM?p=6) +[视频:ssh证书互信设置](https://www.bilibili.com/video/BV19J41167sM?p=7) +[视频:ansible平台部署](https://www.bilibili.com/video/BV19J41167sM?p=8) +[视频:主机列表文件hosts文件](https://www.bilibili.com/video/BV19J41167sM?p=9) +[视频:ansible自动化平台部署知识图谱](https://www.bilibili.com/video/BV19J41167sM?p=10) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible\350\277\220\347\273\264\350\207\252\345\212\250\345\214\226\345\271\263\345\217\260\345\210\235\350\257\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible\350\277\220\347\273\264\350\207\252\345\212\250\345\214\226\345\271\263\345\217\260\345\210\235\350\257\206.md" new file mode 100644 index 0000000..b2e1ee7 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Ansible\350\207\252\345\212\250\345\214\226\350\277\220\347\273\264\345\271\263\345\217\260/Ansible\350\277\220\347\273\264\350\207\252\345\212\250\345\214\226\345\271\263\345\217\260\345\210\235\350\257\206.md" @@ -0,0 +1,111 @@ +## 一、运维自动化平台介绍 + +### 1.1、自动化运维平台介绍 + +运维自动化平台是由管理机器[S]和业务机器[C]组成的,C/S。 + +管理机器:任务定制及发布; + +业务机器:接收任务并执行任务。 + +![运维自动化平台组成.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601965978453.png) + +### 1.2、运维自动化平台的优势: + +- 一次性任务定制:任务一次性发布给所有机器 +- 节省任务执行时间:任务主机并发完成任务,节省部署时间 +- 错误率低:避免重复,保证一次任务定制准确即可 + +## 二、常见的自动化运维工具 + +### 2.1、常见的运维自动化工具 + +- **Puppet** +- **Ansible** +- **SaltStack** + +``` +puppet: +基于Ruby开发,有产品线已经在用,优点是历史悠久,比较成熟,在可远程可本地,功能强劲,批量执行需要写专门的配置文件,费力费时。而且有客户端在,和授权系统结合比较麻烦。 + +saltstack: +saltstack和ansible都是python流的,而且就功能上来讲,两者也极为相似,不同之处是salt stack是有客户端的,并且execution模块还用0MQ实现了pub-sub,命令和执行结果因此可以高效并行传输,不过成也萧何败也萧何,第一个sub阶段(将querystring下发到所有机器,然后收集机器响应的阶段)太依赖与客户端返回了,如果客户端未能及时返回或未响应的话,playbook执行阶段可能会直接漏掉这部分机器而没有任何提示,这对于运维来说是不可接受的。 + +ansible: +与前两者比起来,在特性上似乎并不抢眼,配置管理方面(playbook)绝对比不过老大哥puppet,批量执行方面也只是多线程,不像saltstack那么高大上,不过ansible搜索热度高出saltstack三倍多,显然靠的不是吹牛,至少,ansible至少不会悄悄的丢机器,这给了我们一个定心丸,而且仅依赖ssh,与登录授权管理系统天然集成,简单即有效,没有比这更美妙的事情了。 +``` + +### 2.2、ansible介绍 + +ansible是一种由Python开发的自动化运维工具,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。**ansible是基于模块工作的,本身没有批量部署的能力**。**真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架**。主要包括: + +1. 连接插件connection plugins:负责和被监控端实现通信;**ansible管理端和客户端基于ssh协议通信** +2. host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;**提供主机管理列表,定义管理谁** +3. 各种模块核心模块、command模块、自定义模块;**提供了日常模块** +4. 借助于插件完成记录日志邮件等功能; **根据需求后续添加模块,邮件、日志模块** +5. playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。**一次发布多条指令给客户端** + +**特性** + +1. no agents:不需要在被管控主机上安装任何客户端; +2. no server:无服务器端,使用时直接运行命令即可; +3. modules in any languages:基于模块工作,可使用任意语言开发模块; +4. yaml,not code:使用yaml语言定制剧本playbook; +5. ssh by default:基于SSH工作; +6. strong multi-tier solution:可实现多级指挥。 + +**优点** + +1. 轻量级,无需在客户端安装agent,更新时,只需在操作机上进行一次更新即可; +2. 批量任务执行可以写成脚本,而且不用分发到远程就可以执行; +3. 使用python编写,维护更简单,ruby语法过于复杂; +4. 支持sudo + +**基本架构** + +![ansible3.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601966026674.png) + +``` +· 核心引擎:即ansible +· 核心模块(core modules):这些都是ansible自带的模块,ansible模块资源分发到远程节点使其执行特定任务或匹配一个特定的状态。 +· 自定义模块(custom modules):如果核心模块不足以完成某种功能,可以添加自定义模块。 +· 插件(plugins):完成模块功能的补充,借助于插件完成记录日志、邮件等功能 +· 剧本(playbook):定义ansible任务的配置文件,可以将多个任务定义在一个剧本中,由ansible自动执行,剧本执行支持多个任务,可以由控制主机运行多个任务,同时对多台远程主机进行管理。 +· playbook是ansible的配置、部署和编排语言,可以描述一个你想要的远程系统执行策略,或一组步骤的一般过程。如果ansible模块作为你的工作室工具,playbook就是设计方案。在基本层面上,剧本可以用于管理配置和部署远程机器。在更高级的应用中,可以序列多层应用及滚动更新,并可以把动作委托给其他主机,与监控服务器和负载平衡器交互。 +· 连接插件(connection plugins):ansible基于连接插件连接到各个主机上,负责和被管理节点实现通信。虽然ansible是使用ssh连接到各被管理节点,但它还支持其他的连接方法,所以需要有连接插件。 +· 主机清单(host inventory):定义ansible管理的主机策略,默认是在ansible的hosts配置文件中定义被管节点,同时也支持自定义动态主机清单和指定配置文件路径。 + +``` + +ansible采用paramiko协议库(Fabric也使用这个,基于python开发,支持SSHV2),通过ssh或者ZeroMQ等连接主机。ansible在控制主机主机将ansible模块通过ssh协议(或者Kerberos、LDAP)推送到被管节点执行,执行完之后自动删除。控制主机与被管理节点之间支持local、SSH、ZeroMQ三种连接方式,默认使用基于SSH的连接。在规模较大的情况下使用ZeroMQ连接方式会明显改善执行速度。 + +## 三、ansible运行原理 + +ansible是如何工作的呢?我们通过一个图片来说明一下 + +![ansible工作原理1132928.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601966060853.png) + +``` +工作原理: +1、用户登录管理机器:通过ansible剧本或者单行命令针对业务机器组或者单个机器部署任务 + +2、管理机器读取用户的部署任务:根据自己hosts文件中定义的业务机器组查找对应的机器地址(ip或者域名) + +3、管理机下发任务:管理机通过ssh免密连接业务机器,下发任务给业务机器 + +4、业务机器执行任务 + +5、业务机器将执行结果发送给ansible管理机器 + 反馈字体颜色 + 绿色 未发生变化 + 黄色 更改生效 + 红色 执行错误 +``` + +## 四、学习视频 + +[视频:ansible课程介绍](https://www.bilibili.com/video/BV19J41167sM/) +[视频:自动化运维平台课程介绍](https://www.bilibili.com/video/BV19J41167sM?p=2) +[视频:自动化运维平台介绍](https://www.bilibili.com/video/BV19J41167sM?p=3) +[视频:ansible介绍](https://www.bilibili.com/video/BV19J41167sM?p=4) +[视频:ansible工作原理](https://www.bilibili.com/video/BV19J41167sM?p=5) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/git \346\227\245\345\277\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/git \346\227\245\345\277\227.md" new file mode 100644 index 0000000..6a44a67 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/git \346\227\245\345\277\227.md" @@ -0,0 +1,103 @@ +## git log + +查看历史的git commit快照操作 + +``` +[root@zutuanxue git_data]# git log +commit 326e57a3f87de546c8c17774f174192e280e36fc (HEAD -> master) +#哈希字符串的描述信息 HEAD->master表示当前工作目录所对应的commit,会随着新的commit变化(在个别版本中使用git log不会显示HEAD字样内容,需要使用git log --decorate) +Author: aaa +#作者 +Date: Mon Apr 6 01:00:27 2020 -0400 +#时间 + + v2 a #git commit -m添加的描述信息 + +commit 8f01c62906ee7c06489aae7afb42adaa3da90fdc +Author: aaa +Date: Mon Apr 6 00:43:55 2020 -0400 + + version2 a + +commit a714e37d98c3ab77cfa27f0d0a1ca773c6e4ce57 +Author: aaa +Date: Sun Apr 5 06:26:53 2020 -0400 + + a + +commit 47a267cc489a93f8fab100d7f945a15209f61240 +Author: aaa +Date: Sun Apr 5 06:25:51 2020 -0400 + + a.txt + +commit 6ac34be689eda430ffefc12114fde40759d536b0 +Author: aaa +Date: Sun Apr 5 06:21:02 2020 -0400 + + a +[root@zutuanxue git_data]# git log --oneline #简单的形式展示内容,只显示哈希标识符的前几位 +326e57a (HEAD -> master) v2 a +8f01c62 version2 a +a714e37 a +47a267c a.txt +6ac34be a + +############################ +[root@zutuanxue git_data]# echo 123 >> a +[root@zutuanxue git_data]# git add a +[root@zutuanxue git_data]# git commit -m "test head" +[master 644d678] test head + 1 file changed, 1 insertion(+) +[root@zutuanxue git_data]# git log --oneline --decorate +644d678 (HEAD -> master) test head #产生变化 +326e57a v2 a +8f01c62 version2 a +a714e37 a +47a267c a.txt +6ac34be a +``` + +## git log -p + +``` +[root@zutuanxue git_data]# git log -p #显示具体变化的内容,调用了git diff +commit 644d6785e33714f8f21a3767e39e2013540e1ee2 (HEAD -> master) +Author: aaa +Date: Mon Apr 6 01:12:02 2020 -0400 + + test head + +diff --git a/a b/a +index b989558..864e0ba 100644 +--- a/a ++++ b/a +@@ -1,3 +1,4 @@ + hello + test + test1 ++123 +``` + +## git log -n + +``` +[root@zutuanxue git_data]# git log -1 #只显示最近几条内容 +commit 644d6785e33714f8f21a3767e39e2013540e1ee2 (HEAD -> master) +Author: aaa +Date: Mon Apr 6 01:12:02 2020 -0400 + + test head +[root@zutuanxue git_data]# git log -2 +commit 644d6785e33714f8f21a3767e39e2013540e1ee2 (HEAD -> master) +Author: aaa +Date: Mon Apr 6 01:12:02 2020 -0400 + + test head + +commit 326e57a3f87de546c8c17774f174192e280e36fc +Author: aaa +Date: Mon Apr 6 01:00:27 2020 -0400 + + v2 a +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/gitlab\344\275\277\347\224\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/gitlab\344\275\277\347\224\250.md" new file mode 100644 index 0000000..80ac26b --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/gitlab\344\275\277\347\224\250.md" @@ -0,0 +1,195 @@ +## 一、外观 + +![image20200407163624225.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182691026.png) + +设置完成后保存,返回登录页面查看 + +![image20200407163659051.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182709215.png) + +关于注册,有些公司是不允许打开的,,有些人数非常多的公司就需要打开注册的功能,让人员自己注册,我们来给他特定的权限就可以,毕竟人非常多的时候还由我们来给她们注册就非常不现实了,工作量会很大 + +## 二、自动注册 + +![image20200407163952391.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182748085.png) + +![image20200407164026831.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182759100.png) + +## 三、组&用户&项目 + +**创建组** + +![image20200407164306707.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182786418.png) + +**设置组名称、描述等创建群组** + +![image20200407164514878.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182817607.png) + +**创建用户** + +![image20200407164550662.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182834630.png) + +![image20200407164640254.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182846078.png) + +**设置密码** + +![image20200407164723320.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182867689.png) + +![image20200407164835369.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182878730.png) + +**把用户添加到组里面** + +![image20200407164948977.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182902807.png) + +![image20200407165031097.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182914223.png) + +``` +Guest:可以创建issue、发表评论,不能读写版本库 +Reporter:可以克隆代码,不能提交,QA、PM可以赋予这个权限 +Developer:可以克隆代码、开发、提交、push,RD可以赋予这个权限 +Maintainer:可以创建项目、添加tag、保护分支、添加项目成员、编辑项目,核心RD负责人可以赋予这个权限 +Owner:可以设置项目访问权限 - Visibility Level、删除项目、迁移项目、管理组成员,开发组leader可以赋予这个权限 +Gitlab中的组和项目有三种访问权限:Private、Internal、Public + +Private:只有组成员才能看到 +Internal:只要登录的用户就能看到 +Public:所有人都能看到 +``` + +**创建仓库** + +管理区域-创建仓库 + +![image20200407165129307.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182932716.png) + +![image20200407170517512.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182945051.png) + +也可以导入项目 + +![image20200407170805432.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182973580.png) + +创建仓库以后,网页下面有操作步骤的提醒 + +![image20200407170918038.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182994629.png) + +## 四、登陆用户测试 + +是否能看到空的gitlabtest仓库,修改完密码后再次登录 + +![image20200407171108761.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603183012414.png) + +## 五、添加ssh‐keys + +注 :一个服务器的key只能添加到一个gitlab服务器上 ,一个用户可以添加多个key,切换到管理员用户 + +ssh‐keygen ‐t rsa + +![image20200408093838255.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603183025594.png) + +![image20200407171928443.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603183049076.png) + +## 六、添加、推送到远程仓库 + +默认master是不允许developer权限的成员执行推送操作的 + +``` +[root@zutuanxue git_data]# git remote rm origin +或者 +[root@zutuanxue git_data]# git remote rename origin old‐origin 也可以重命名 +[root@zutuanxue git_data]# git remote add origin git@192.168.2.100:gitlabtest/gitlabtest.git +[root@zutuanxue git_data]# git push -u origin --all +``` + +## 七、克隆 + +切换到另外一台主机 + +``` +[root@zutuanxue ~]# dnf install git -y +[root@zutuanxue work]# ssh-keygen -t rsa +[root@zutuanxue work]# cat /root/.ssh/id_rsa.pub +``` + +使用test用户登录gitlab并添加ssh秘钥 + +``` +[root@zutuanxue work]# git clone git@192.168.2.100:gitlabtest/gitlabtest.git +正克隆到 'gitlabtest'... +The authenticity of host '192.168.2.100 (192.168.2.100)' can't be established. +ECDSA key fingerprint is SHA256:CDlvaoOre2O1oLbKC4umHcPZ/AfHk37sEZGZakepDd0. +Are you sure you want to continue connecting (yes/no)? yes +Warning: Permanently added '192.168.2.100' (ECDSA) to the list of known hosts. +remote: Enumerating objects: 3, done. +remote: Counting objects: 100% (3/3), done. +remote: Compressing objects: 100% (2/2), done. +remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 +接收对象中: 100% (3/3), 完成. +[root@zutuanxue ~]# cd gitlabtest/ +[root@zutuanxue gitlabtest]# ls +a b c +[root@zutuanxue gitlabtest]# git config --global user.name test +[root@zutuanxue gitlabtest]# git config --global user.email "test@aa.com" +[root@zutuanxue gitlabtest]# git branch usertest +[root@zutuanxue gitlabtest]# git checkout usertest +切换到分支 'usertest' +[root@zutuanxue gitlabtest]# touch file4test +[root@zutuanxue gitlabtest]# ls +a b c file4test +[root@zutuanxue gitlabtest]# git add . +[root@zutuanxue gitlabtest]# git commit -m "touch file4test" +[root@zutuanxue gitlabtest]# git push -u origin usertest +``` + +创建合并请求 + +![image20200408111919102.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603183258414.png) + +![image20200408112004021.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603183278448.png) + +切换到管理员账号,处理请求 + +![image20200408112235898.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603183299410.png) + +![image20200408112327012.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603183318121.png) + +切换到test用户或者直接使用管理员查看,内容已合并,之前的usertest分支已经被删除 + +![image20200408112446861.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603183329790.png) + +**设置保护主分支** + +![image20200407181236004.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603183355905.png) + +![image20200407181310037.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603183370367.png) + +![image20200407182219612.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603183384145.png) + +默认情况下为了保证master分支的稳定是被保护的,只有维护者可以执行push的操作,所以,当一个开发者身份的用户在针对master分支进行操作的时候会出现被拒绝的提示 + +``` +[root@zutuanxue gitlabtest]# git push -u origin master +To 192.168.2.100:gitlabtest/gitlabtest.git + ! [rejected] master -> master (fetch first) +error: 无法推送一些引用到 'git@192.168.2.100:gitlabtest/gitlabtest.git' +提示:更新被拒绝,因为远程仓库包含您本地尚不存在的提交。这通常是因为另外 +提示:一个仓库已向该引用进行了推送。再次推送前,您可能需要先整合远程变更 +提示:(如 'git pull ...')。 +提示:详见 'git push --help' 中的 'Note about fast-forwards' 小节。 +``` + +同样我们也可以利用上述功能去保护某些不想被修改的分支。 + +**解决内容不一致** + +除了分支被保护会出现上述提示之外,有些时候在你返回master端测试推送 ,由于其他分支进行推送 ,和master端内容不一致 ,所以无法进行推送 ,这个时候可以使用git pull把代码拉取到本地 ,或者git fetch 把代码拉取到本地仓库后进行合并 (注意 :git pull = git + +fetch+git merge ) + +``` +[root@zutuanxue git_data]# git fetch +[root@zutuanxue git_data]# ls +a b c README.md +[root@zutuanxue git_data]# git merge origin/master +[root@zutuanxue git_data]# ls +a b c file4test README.md +[root@zutuanxue git_data]# git push -u origin +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/gitlab\345\244\207\344\273\275\344\270\216\350\277\230\345\216\237.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/gitlab\345\244\207\344\273\275\344\270\216\350\277\230\345\216\237.md" new file mode 100644 index 0000000..4c0356c --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/gitlab\345\244\207\344\273\275\344\270\216\350\277\230\345\216\237.md" @@ -0,0 +1,79 @@ +由于gitlab中存放的都是开发人员的工作成果,所以为了保证数据安全,我们会定期对数据进行备份,对gitlab进行备份将会创建一个包含所有库和附件的归档文件。对备份的恢复只能恢复到与备份时的gitlab相同的版本。将gitlab迁移到另一台服务器上的最佳方法就是通过备份和还原。gitlab提供了一个简单的命令行来备份整个gitlab ,并且能灵活的满足需求。 + +## 一、备份 + +备份路径: + +备份文件将保存在配置文件中定义的backup_path中 ,文件名为TIMESTAMP_gitlab_backup.tar,TIMESTAMP为备份时的时间戳。TIMESTAMP的格式为 :EPOCH_YYYY_MM_DD_Gitlab‐version。 + +**备份配置:** + +``` +[root@zutuanxue git_data]# vim /etc/gitlab/gitlab.rb +gitlab_rails['backup_path'] = "/opt/backups" +#备份路径 +gitlab_rails['backup_keep_time'] = 604800 +#备份周期-秒(7x24x3600) +[root@zutuanxue git_data]# gitlab-ctl reconfigure +``` + +**手动备份:** + +``` +[root@zutuanxue git_data]# gitlab-backup create +或者 +[root@zutuanxue git_data]# gitlab-rake gitlab:backup:create +[root@zutuanxue git_data]# ls /opt/backups/ +``` + +**定时备份:** + +在定时任务里添加: + +``` +0 2 * * * /opt/gitlab/bin/gitlab-rake gitlab:backup:create +或 +0 2 * * * /opt/gitlab/bin/gitlab-backup create +``` + +## 二、还原操作 + +只能还原到与备份文件相同的gitlab版本。执行恢复操作时,需要gitlab处于运行状态,备份文件位于gitlab_rails[‘backup_path’]。需要先停掉两个服务,停止连接到数据库的进程(也就是停止数据写入服务,如果是空主机,没有任何操作的话,可以不停止服务,停止相应服务的目的是为了保证数据移植),但是保持GitLab是运行的。 + +在web中删除项目 + +``` +[root@zutuanxue backups]# gitlab-ctl stop unicorn +[root@zutuanxue backups]# gitlab-ctl stop sidekiq +``` + +指定时间戳你要从那个备份恢复: + +``` +[root@zutuanxue git_data]# cd /opt/backups/ +[root@zutuanxue backups]# gitlab-ctl stop unicorn +ok: down: unicorn: 0s, normally up +[root@zutuanxue backups]# gitlab-ctl stop sidekiq +ok: down: sidekiq: 1s, normally up +[root@zutuanxue backups]# gitlab-rake gitlab:backup:restore BACKUP=1586328114_2020_04_08_12.9.2 +(有的版本执行gitlab-rake gitlab:backup:restore BACKUP=1586328114即可) +Unpacking backup ... done +Before restoring the database, we will remove all existing +tables to avoid future upgrade problems. Be aware that if you have +custom tables in the GitLab database these tables and all data will be +removed. +Do you want to continue (yes/no)? yes +#提示移除所有存在的表 +. +. +. +This task will now rebuild the authorized_keys file. +You will lose any data stored in the authorized_keys file. +Do you want to continue (yes/no)? yes +#提示移除所有验证秘钥 +[root@zutuanxue backups]# gitlab-ctl restart#重启gitlab + +注意:也可使用gitlab-rake gitlab:check SANITIZE=true验证下gitlab服务 +``` + +浏览器重新打开gitlab页面,重新登录后查看到被还原的项目内容 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/gitlab\351\203\250\347\275\262.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/gitlab\351\203\250\347\275\262.md" new file mode 100644 index 0000000..20f35b1 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/gitlab\351\203\250\347\275\262.md" @@ -0,0 +1,145 @@ +## 一、GitLab简介 + +GitLab 是一个用于仓库管理系统的开源项目。使用Git作为代码管理工具,并在此基础上搭建起来的web服务。可通过Web界面进行访问公开的或者私人项目。它拥有与Github类似的功能,能够浏览源代码,管理缺陷和注释。可以管理团队对仓库的访问,它非常易于浏览提交过的版本并提供一个文件历史库。团队成员可以利用内置的简单聊天程序(Wall)进行交流。它还提供一个代码片段收集功能可以轻松实现代码复用。 + +gitlab主要用于私用,github主要用于公网,都可看成web版的git + +Community Edition or Enterprise Edition,ce和ee分别指的是社区版和企业版,毫无疑问社区版已经能满足我们的需求了。 + +**常用的网站** + +官网 : https://about.gitlab.com/ + +https://packages.gitlab.com/gitlab/gitlab-ce CE版下载地址 + +https://packages.gitlab.com/gitlab/gitlab-ee EE版下载地址 + +国内镜像 :https://mirrors.tuna.tsinghua.edu.cn/gitlab‐ce/yum/ + +![image20200407140627737.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182391691.png) + +![image20200407140745198.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182403362.png) + +## 二、安装与配置 + +- 环境:CentOS 8 +- 关闭selinux和防火墙 + +**2.1、** 安装依赖包 + +``` +dnf install -y curl policycoreutils openssh-server postfix +systemctl enable sshd +systemctl start sshd +systemctl enable postfix +systemctl start postfix +``` + +**2.2、** 联网安装 + +``` +[root@zutuanxue ~]# vim /etc/yum.repos.d/gitlab-ce.repo +[gitlab-ce] +name=Gitlab CE Repository +baseurl=https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el$releasever/ +gpgcheck=0 +enabled=1 + +[root@zutuanxue ~]# dnf install gitlab-ce -y + + +( +如果安装比较慢的话也可以从https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el8/下载rpm包到本地进行安装 +[root@zutuanxue ~]# yum localinstall gitlab-ce-12.9.2-ce.0.el8.x86_64.rpm +) +``` + +**2.3**、配置 + +``` +[root@zutuanxue ~]# vim /etc/gitlab/gitlab.rb +external_url 'http://192.168.2.100' + + +#修改为本机的名称或者IP地址 + +###( +GitLab默认会占用80、8080和9090端口,如果服务器上还有tomcat、Jenkins等其他服务,可能会遇到端口冲突,如果想修改端口的话可以 +external_url 'http://192.168.2.100:自定义端口' +unicorn['port'] = xxx +prometheus['listen_address'] = 'localhost:xxx' +将xxx更换成自己需要使用的端口 +###) +[root@zutuanxue ~]# gitlab-ctl reconfigure +#修改完成之后重新配置gitlab +``` + +#### 命令和目录 + +/opt/gitlab/ # gitlab的程序安装目录 + +/var/opt/gitlab # gitlab数据目录 + +/var/opt/gitlab/git‐data # 存放仓库数据 + +| 命令 | function | +| :------------ | :------------------------- | +| start | 启动所有服务 | +| stop | 关闭所有服务 | +| restart | 重启所有服务 | +| status | 查看所有服务状态 | +| tail | 查看日志信息 | +| service-list | 查看所有启动服务 | +| graceful-kill | 平稳停止一个服务 | +| help | 帮助 | +| reconfigure | 修改配置文件之后,重新加载 | +| show-config | 查看所有服务配置文件信息 | +| uninstall | 卸载这个软件 | +| cleanse | 清空gitlab数据 | + +``` +[root@zutuanxue ~]# gitlab-ctl start +ok: run: alertmanager: (pid 1564) 3804s +ok: run: gitaly: (pid 1550) 3804s +[root@zutuanxue ~]# gitlab-ctl start nginx +ok: run: nginx: (pid 1531) 3823s + +#这些操作指令,如果不指定名称的话,默认会操作所有 +``` + +#### Gitlab的服务构成 + +``` +[root@zutuanxue ~]# gitlab-ctl service-list +gitaly* git RPC服务,用于处理gitlab发出的git调用 +gitlab-workhorse* 轻量级的反向代理服务器 +logrotate* 日志文件管理工具 +nginx* 静态web服务 +postgresql* 数据库 +redis* 缓存数据库 +sidekiq* 用于在后台执行队列任务 +unicorn* 用Ruby编写的web server,GitLab Rails应用是托管在这个服务器上面 +alertmanager*,gitlab-exporter*,grafana*,node-exporter*,postgres-exporter*,prometheus*,redis-exporter* #与监控相关的插件 +``` + +在浏览器中访问本机,就可以打开登录界面,初次登录必须修改密码(不能少于8位),更改完成后可以使用管理员账号登录,用户名为root + +**2.4**、gitlab汉化 + +1、浏览器设置中文后重新打开 + +2、点击右上角头像,选择设置(settings) + +3、左边选择preferences–>languages—>save + +4、刷新页面 + +如果还是有问题 + +``` +[root@zutuanxue ~]# dnf groupinstall chinese-support#安装中文支持 +[root@zutuanxue ~]# dnf install ibus* #安装输入法 +#重启后在系统设置更改语言环境为中文 +``` + +![image20200407163323541.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182523810.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/git\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/git\344\273\213\347\273\215.md" new file mode 100644 index 0000000..4862a08 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/git\344\273\213\347\273\215.md" @@ -0,0 +1,45 @@ +## git介绍 + +简单来说git就是一个分布式的版本控制软件,直接记录快照,而非差异比较Git 和其它版本控制系统(包括 Subversion 和近似工具)的主要差别在于 Git 对待数据的方法。 从概念上来说,其它大部分系统以文件变更列表的方式存储信息(基于差异的版本控制)。Git 不按照以上方式对待或保存数据。反之,Git 更像是把数据看作是对小型文件系统的一系列快照。 在 Git 中,每当你提交更新或保存项目状态时,它基本上就会对当时的全部文件创建一个快照并保存这个快照的索引。 为了效率,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。 Git 对待数据更像是一个快照流。 + +## git的优势 + +**近乎所有操作都是本地执行** + +在 Git 中的绝大多数操作都只需要访问本地文件和资源,一般不需要来自网络上其它计算机的信息。因为你在本地磁盘上就有项目的完整历史,所以大部分操作看起来瞬间完成。这也意味着你在离线或者没有 VPN 时,几乎可以进行任何操作, 直到有网络连接时再上传。 + +**保证完整性** + +Git 中所有的数据在存储前都计算校验和,然后以校验和来引用。 这意味着不可能在 Git 不知情时更改任何文件 内容或目录内容。 这个功能建构在 Git 底层,是构成 Git 哲学不可或缺的部分。 若你在传送过程中丢失信息或损 坏文件,Git 就能发现。 + +**很难丢失数据** + +你执行的 Git 操作,几乎只往 Git 数据库中添加数据。 你很难让 Git 执行任何不可逆操作,或者让它以任何方式清除数据。虽然未提交更新时有可能丢失或弄乱修改的内容。但是一旦你提交快照到 Git 中, 就难以再丢失数据,特别是如果你定期的推送数据库到其它仓库的话。 + +### git的三种状态 + +- **已修改(modified)** 表示修改了文件,但还没保存到数据库中。 +- **已暂存(staged)** 表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。 +- **已提交(committed)** 表示数据已经安全地保存在本地数据库中。 + +由于有这三种状态,所以Git 项目拥有三个阶段:工作区、暂存区以及 Git 目录。 + +![image20200405153608934.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603165978451.png) + +- **工作区**:是对项目的某个版本独立提取出来的内容。 这些从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。 +- **暂存区**:是一个文件,保存了下次将要提交的文件列表信息,一般在 Git 仓库目录中。 按照 Git 的术语叫做“索引”,不过一般说法还是叫“暂存区”。 +- **Git 仓库目录**:是 Git 用来保存项目的元数据和对象数据库的地方。 这是 Git 中最重要的部分,从其它计算机克隆仓库时,复制的就是这里的数据。 + +基本的 Git 工作流程如下: + +``` +1. 在工作区中修改文件。 +2. 将你想要下次提交的更改选择性地暂存,这样只会将更改的部分添加到暂存区。 +3. 提交更新,找到暂存区的文件,将快照永久性存储到 Git 目录。 +``` + +如果Git目录中保存着特定版本的文件,就属于已提交状态。 + +如果文件已修改并放入暂存区,就属于已暂存状态。 + +如果作了修改但还没有放到暂存区域,就是已修改状态。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/git\344\273\223\345\272\223\351\205\215\347\275\256\345\217\212\344\273\223\345\272\223\347\211\271\346\200\247.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/git\344\273\223\345\272\223\351\205\215\347\275\256\345\217\212\344\273\223\345\272\223\347\211\271\346\200\247.md" new file mode 100644 index 0000000..fdf6871 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/git\344\273\223\345\272\223\351\205\215\347\275\256\345\217\212\344\273\223\345\272\223\347\211\271\346\200\247.md" @@ -0,0 +1,191 @@ +## 一、git仓库初始化 + +``` +git init 把当前所在目录变成git工作目录 +git config + ‐‐global 使用全局配置文件 + ‐‐system 使用系统级配置文件 + ‐‐local 使用版本库级配置文件 + +#定义git用户 +[root@zutuanxue ~]# git config --global user.name "hello" + +#定义git使用的邮箱 +[root@zutuanxue ~]# git config --global user.email "hello@localhost + +#定义语法高亮 +[root@zutuanxue ~]# git config --global color.ui true + + +#查看定义的信息 +[root@zutuanxue ~]# git config --list +user.name=hello +user.email=hello@localhost +color.ui=true +``` + +**git 配置文件管理** + +``` +1、新建配置文件 +git config --global --add configName configValue +解释:给指定的级别的指定config增加一个值 +示例: +[root@zutuanxue git_data]# git config --global --add user.name test +[root@zutuanxue git_data]# git config --global --list +user.name=hello +user.email=hello@localhost +user.name=test +color.ui=true + + +2、删除配置文件 +git config --global --unset configName (只针对存在唯一值的情况) +为了测试先增加一个 +[root@zutuanxue git_data]# git config --global --add alias.test "aaaaa" +[root@zutuanxue git_data]# git config --global --list +user.name=hello +user.email=hello@localhost +user.name=test +color.ui=true +alias.test=aaaaa + +删除这个唯一值,查看效果 +[root@zutuanxue git_data]# git config --global --unset alias.test +[root@zutuanxue git_data]# git config --global --list +user.name=hello +user.email=hello@localhost +user.name=test +color.ui=true + + +3、修改配置文件 +git config --global configName configValue +[root@zutuanxue git_data]# git config --global --list +user.name=hello +user.email=hello@localhost +user.name=test +color.ui=true +[root@zutuanxue git_data]# git config --global user.name aaa +warning: user.name 有多个取值 +error: 无法用一个值覆盖多个值 + 使用一个正则表达式、--add 或 --replace-all 来修改 user.name。 +[root@zutuanxue git_data]# git config --global --replace-all user.name aaa +[root@zutuanxue git_data]# git config --global --list +user.email=hello@localhost +user.name=aaa +color.ui=true + + +4、查看配置文件 +git config --global configName +查询指定级别下: 实际生效的配置值 +[root@zutuanxue git_data]# git config --global user.name +aaa +``` + +## 二、git仓库数据管理机状态 + +**创建数据-提交数据** + +![image20200405175817262.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603166365630.png) + +本地仓库可以理解为工作目录下.git/objects + +- git提交数据到仓库流程: + +``` +1. 先git add把新文件提交到暂存区 +2. 再git commit 存到仓库 +3. 最后使用git push提交到远程仓库; +``` + +- 用户使用则通过以下命令拉取到本地 + +``` +1. 使用git clone/git pull将数据同步到本地仓库,再使用相关命令进行操作 +``` + +**git四种状态** + +![image20200405165323247.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603166335306.png) + +- untracked:未跟踪的,也就是一个文件没有被git管理、监控起来 +- unmodified:未修改的 +- modified:已修改的 +- staged:已暂存的 + +你工作目录下的每一个文件都不外乎这两种状态:已跟踪 或 未跟踪。 已跟踪的文件是指那些被纳入了版本控制的文件,在上一次快照中有它们的记录,在工作一段时间后, 它们的状态可能是未修改,已修改或已放入暂存区。简而言之,已跟踪的文件就是 Git 已经知道的文件。 + +工作目录中除已跟踪文件外的其它所有文件都属于未跟踪文件,它们既不存在于上次快照的记录中,也没有被放 入暂存区。 初次克隆某个仓库的时候,工作目录中的所有文件都属于已跟踪文件,并处于未修改状态,因为 Git 刚刚检出了它们, 而你尚未编辑过它们。 + +编辑过某些文件之后,由于自上次提交后你对它们做了修改,Git 将它们标记为已修改文件。 在工作时,你可以 选择性地将这些修改过的文件放入暂存区,然后提交所有已暂存的修改,如此反复。 + +**检查当前文件状态** + +我们可以使用git status检查文件的状态 + +``` +[root@zutuanxue git]# git status +位于分支 master +尚无提交 +无文件要提交(创建/拷贝文件并使用 "git add" 建立跟踪) + +#这说明你现在的工作目录相当干净。换句话说,所有已跟踪文件在上次提交后都未被更改过。 此外,上面的信 息还表明,当前目录下没有出现任何处于未跟踪状态的新文件,否则 Git 会在这里列出来。 +``` + +在项目下创建一个新的 README 文件。 如果之前并不存在这个文件,使用 git status 命令,你将看到一个新的未跟踪文件: + +``` +[root@zutuanxue git]# echo test > README +[root@zutuanxue git]# git status +位于分支 master +尚无提交 +未跟踪的文件: + (使用 "git add <文件>..." 以包含要提交的内容) + README +提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪) +``` + +在状态报告中可以看到新建的 README 文件出现在 “未跟踪的文件” 下面。 未跟踪的文件意味着 Git 在之前 的快照(提交)中没有这些文件;Git 不会自动将之纳入跟踪范围,除非你明明白白地告诉它“我需要跟踪该文件”。 + +**跟踪新文件** + +``` +[root@zutuanxue git]# git add README +[root@zutuanxue git]# git status +位于分支 master +尚无提交 +要提交的变更: + (使用 "git rm --cached <文件>..." 以取消暂存) + 新文件: README +``` + +只要在 Changes to be committed 或者“要提交的变更”这行下面的,就说明是已暂存状态。 如果此时提交,那么该文件在你运 行git add时的版本将被留存在后续的历史记录中。 + +**暂存已修改的文件** + +``` +[root@zutuanxue git]# echo aaa >> README +[root@zutuanxue git]# git status +位于分支 master +尚无提交 +要提交的变更: + (使用 "git rm --cached <文件>..." 以取消暂存) + 新文件: README +尚未暂存以备提交的变更: + (使用 "git add <文件>..." 更新要提交的内容) + (使用 "git checkout -- <文件>..." 丢弃工作区的改动) + 修改: README +``` + +现在我们来修改一个已被跟踪的文件。出现在Changes not staged for commit或者“尚未暂存以备提交的变更”这行下面,说明已跟踪文件的内容发生了变化,但还没有放到暂存区。 要暂存这次更新,需要运行 git add 命令。 这是个多功能命令:可以用它开 始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等。再次使用git status -s查看 + +``` +[root@zutuanxue git]# git status -s +A README +################ +?? 新添加的未跟踪文件 +A 新添加到暂存区中的文件 +M 修改过的文件 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/git\345\270\270\347\224\250\345\221\275\344\273\244.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/git\345\270\270\347\224\250\345\221\275\344\273\244.md" new file mode 100644 index 0000000..ace4664 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/git\345\270\270\347\224\250\345\221\275\344\273\244.md" @@ -0,0 +1,411 @@ +## git status/git status -s + +查看状态 + +``` +[root@zutuanxue git_data]# git status +位于分支 master +尚无提交 +无文件要提交(创建/拷贝文件并使用 "git add" 建立跟踪) +[root@zutuanxue git_data]# touch a b c +[root@zutuanxue git_data]# ls +a b c +[root@zutuanxue git_data]# git status +位于分支 master +尚无提交 +未跟踪的文件: + (使用 "git add <文件>..." 以包含要提交的内容) + a + b + c +提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪) +``` + +## git add + +暂存内容 + +``` +[root@zutuanxue git_data]# git add a +[root@zutuanxue git_data]# git status +位于分支 master +尚无提交 +要提交的变更: + (使用 "git rm --cached <文件>..." 以取消暂存) + 新文件: a +未跟踪的文件: + (使用 "git add <文件>..." 以包含要提交的内容) + b + c +[root@zutuanxue git_data]# ll .git/ +总用量 16 +drwxr-xr-x 2 root root 6 4月 3 05:34 branches +-rw-r--r-- 1 root root 92 4月 3 05:34 config +-rw-r--r-- 1 root root 73 4月 3 05:34 description +-rw-r--r-- 1 root root 23 4月 3 05:34 HEAD +drwxr-xr-x 2 root root 301 4月 3 05:34 hooks +-rw-r--r-- 1 root root 96 4月 5 06:05 index +#你会发现index的时间产生了变化,这意味着,我们使用git add命令将文件提交到了暂存区域 +drwxr-xr-x 2 root root 21 4月 3 05:34 info +drwxr-xr-x 5 root root 40 4月 5 06:05 objects +drwxr-xr-x 4 root root 31 4月 3 05:34 refs +[root@zutuanxue git_data]# ll .git/objects/ +总用量 0 +drwxr-xr-x 2 root root 52 4月 5 06:05 e6 +drwxr-xr-x 2 root root 6 4月 3 05:34 info +drwxr-xr-x 2 root root 6 4月 3 05:34 pack +[root@zutuanxue objects]# ls e6 +9de29bb2d1d6434b8b29ae775ad8c2e48c5391 +[root@zutuanxue objects]# cat e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 +#在objects目录中可以看到已元数据形式存储的a文件,这个我们看不懂,我们可以将数据都添加 + + +[root@zutuanxue git_data]# git add . #可以使用.也可以使用* +[root@zutuanxue git_data]# git status +位于分支 master +尚无提交 +要提交的变更: + (使用 "git rm --cached <文件>..." 以取消暂存) + 新文件: a + 新文件: b + 新文件: c +``` + +## git rm + +将文件从暂存区撤回到工作区(变成未跟踪的)、然后再删除文件;也可以直接从暂存区删除 + +``` +[root@zutuanxue git_data]# git rm --cached c +rm 'c' +[root@zutuanxue git_data]# git status +位于分支 master +尚无提交 +要提交的变更: + (使用 "git rm --cached <文件>..." 以取消暂存) + 新文件: a + 新文件: b +未跟踪的文件: + (使用 "git add <文件>..." 以包含要提交的内容) + c +[root@zutuanxue git_data]# rm -fr c +[root@zutuanxue git_data]# git status +位于分支 master +尚无提交 +要提交的变更: + (使用 "git rm --cached <文件>..." 以取消暂存) + 新文件: a + 新文件: b +[root@zutuanxue git_data]# git rm -f b +rm 'b' +[root@zutuanxue git_data]# git status +位于分支 master +尚无提交 +要提交的变更: + (使用 "git rm --cached <文件>..." 以取消暂存) + 新文件: a +[root@zutuanxue git_data]# git commit -m " new a" #提交到本地仓库 +[master(根提交) 6ac34be] a + 1 file changed, 0 insertions(+), 0 deletions(-) + create mode 100644 a +[root@zutuanxue git_data]# git status +位于分支 master +无文件要提交,干净的工作区 +``` + +## git mv + +将暂存区里的数据改名或移动 + +``` +1.使用mv命令配合git +[root@zutuanxue git_data]# mv a a.txt +[root@zutuanxue git_data]# git status +位于分支 master +尚未暂存以备提交的变更: + (使用 "git add/rm <文件>..." 更新要提交的内容) + (使用 "git checkout -- <文件>..." 丢弃工作区的改动) + + 删除: a + +未跟踪的文件: + (使用 "git add <文件>..." 以包含要提交的内容) + + a.txt + +修改尚未加入提交(使用 "git add" 和/或 "git commit -a") +[root@zutuanxue git_data]# git rm --cached a ###从暂存区删除a +rm 'a' +[root@zutuanxue git_data]# git status +位于分支 master +要提交的变更: + (使用 "git reset HEAD <文件>..." 以取消暂存) + + 删除: a + +未跟踪的文件: + (使用 "git add <文件>..." 以包含要提交的内容) + + a.txt + +[root@zutuanxue git_data]# git add a.txt +[root@zutuanxue git_data]# git status +位于分支 master +要提交的变更: + (使用 "git reset HEAD <文件>..." 以取消暂存) + + 重命名: a -> a.txt ########识别到a和a.txt是重命名的文件 +[root@zutuanxue git_data]# git commit -m "rename a to a.txt" +#提交到本地仓库 +[master 47a267c] a.txt + 1 file changed, 0 insertions(+), 0 deletions(-) + rename a => a.txt (100%) + + +2.使用git mv直接重命名 +[root@zutuanxue git_data]# git mv a.txt a #将工作区域和暂存区域的文件同时重命名 +[root@zutuanxue git_data]# git status +位于分支 master +要提交的变更: + (使用 "git reset HEAD <文件>..." 以取消暂存) + + 重命名: a.txt -> a + +[root@zutuanxue git_data]# git commit -m "rename a.txt to a" +[master a714e37] a + 1 file changed, 0 insertions(+), 0 deletions(-) + rename a.txt => a (100%) +``` + +## git diff + +git status 只能查看区域状态的不同 ,不能查看文件内容的变化。 + +git diff 查看内容的不同 + +``` +[root@zutuanxue git_data]# git diff #没有变化时不显示内容 +[root@zutuanxue git_data]# vim a +hello +abc +[root@zutuanxue git_data]# git add a +[root@zutuanxue git_data]# vim a +hello +test +test1 +[root@zutuanxue git_data]# git diff a #调整完成文件后,对比本地工作目录和暂存区文件的差异 +diff --git a/a b/a +#git格式的diff命令,进行比较的是a版本的a文件和b版本的a文件 +index e69de29..ce01362 100644 +#两个版本的哈希值,100644表示是对象是普通文件,权限是644 +--- a/a #---表示变动前,也就是a版本的a文件 ++++ b/a #+++表示变动后,也就是b版本的a文件 +@@ -1,2 +1,3 @@ ## 以@符号开始和结束“-1,2”表示前一个文件从第一行开始的连续两行;“+1,3”表示后一个文件的从第一行开始连续的3行(-表示前一个文件,+表示后一个文件) +hello +-abc #-表示去掉的内容 ++test ++test1 #+表示新增的内容 + +[root@zutuanxue git_data]# git diff --cached a #对比暂存区和本地仓库的差异 +diff --git a/a b/a +index e69de29..0e3af97 100644 +--- a/a ++++ b/a +@@ -0,0 +1,2 @@ ++hello ++abc +``` + +## git commit -m + +将暂存区内容提交到本地仓库-m后面是描述信息 + +``` +[root@zutuanxue git_data]# git commit -m "version2 a" +[master 8f01c62] version2 a + 1 file changed, 2 insertions(+) +[root@zutuanxue git_data]# git diff --cached a +git commit # 相当于虚拟机的镜像、任何操作都被做了一次快照 ,可恢复到任意一个位置 +``` + +## git commit -am + +快速提交到本地仓库 + +``` +[root@zutuanxue git_data]# cat a +haha +[root@zutuanxue git_data]# git diff +[root@zutuanxue git_data]# echo hello >> a +[root@zutuanxue git_data]# git diff +diff --git a/a b/a +index 5ad28e2..5c06d49 100644 +--- a/a ++++ b/a +@@ -1 +1,2 @@ + haha ++hello +[root@zutuanxue git_data]# git status +位于分支 master +尚未暂存以备提交的变更: + (使用 "git add <文件>..." 更新要提交的内容) + (使用 "git checkout -- <文件>..." 丢弃工作区的改动) + + 修改: a + +修改尚未加入提交(使用 "git add" 和/或 "git commit -a") +[root@zutuanxue git_data]# git add a +[root@zutuanxue git_data]# git commit -m "add hello" +[master 2add75e] add hello + 1 file changed, 1 insertion(+) +[root@zutuanxue git_data]# git diff +######在a文件中添加hello并提交到仓库 +[root@zutuanxue git_data]# echo haha >> a +[root@zutuanxue git_data]# git commit -am "add haha"#也可以使用-am直接提交到仓库,相当于先git add再git commit -m,但必须是跟踪状态的文件,参数a必须在m前面,否则会报错,无法提交。 +[master f3d6391] add haha + 1 file changed, 1 insertion(+) +[root@zutuanxue git_data]# git diff +[root@zutuanxue git_data]# git status +位于分支 master +无文件要提交,干净的工作区 +[root@zutuanxue git_data]# git log --oneline +f3d6391 (HEAD -> master) add haha +2add75e add hello +``` + +## git checkout – + +检出,重写工作区数据 + +``` +[root@zutuanxue git_data]# echo haha >> a +[root@zutuanxue git_data]# cat a +hello +test +test1 +123 +haha +[root@zutuanxue git_data]# git status +位于分支 master +尚未暂存以备提交的变更: + (使用 "git add <文件>..." 更新要提交的内容) + (使用 "git checkout -- <文件>..." 丢弃工作区的改动) + + 修改: a + +修改尚未加入提交(使用 "git add" 和/或 "git commit -a") +[root@zutuanxue git_data]# git checkout -- a +[root@zutuanxue git_data]# git status +位于分支 master +无文件要提交,干净的工作区 +[root@zutuanxue git_data]# cat a +hello +test +test1 +123 +``` + +## git reset HEAD + +本地仓库覆盖暂存区域 + +``` +[root@zutuanxue git_data]# echo "" > a #将a的内容清空 +[root@zutuanxue git_data]# git add a #提交到暂存区 +[root@zutuanxue git_data]# git commit -m "test head" #提交到仓库 +[master dd7925f] test head + 1 file changed, 1 insertion(+), 1 deletion(-) +[root@zutuanxue git_data]# echo haha > a #添加内容到a +[root@zutuanxue git_data]# git add a #提交到暂存区 +[root@zutuanxue git_data]# git diff a #确认没有差异 +[root@zutuanxue git_data]# git reset HEAD a #用本地仓库的数据将暂存区数据覆盖 +重置后取消暂存的变更: +M a +[root@zutuanxue git_data]# git diff a #比较工作区和暂存区的数据差异 +diff --git a/a b/a +index 8b13789..5ad28e2 100644 +--- a/a ++++ b/a +@@ -1 +1 @@ +- ++haha +``` + +## git reset --hard 哈希头名 + +Git服务程序中有一个叫做HEAD的版本指针,当用户申请还原数据时,其实就是将HEAD指针指向到某个特定的提交版本,但是因为Git是分布式版本控制系统,为了避免历史记录冲突,故使用了SHA‐1计算出十六进制的哈希字串来区分每个提交版本,另外默认的HEAD版本指针会指向到最近的一次提交版本记录,,注意恢复版本后代表的是在这个版本之前的内容全在(包括工作目录和暂存),本版本之后的都没了 + +``` +[root@zutuanxue git_data]# git log --oneline +f3d6391 (HEAD -> master) add haha +2add75e add hello +ff77333 aaa +dd7925f test head +e2e2131 head test +644d678 test head +326e57a v2 a +8f01c62 version2 a +a714e37 a +47a267c a.txt +6ac34be a +[root@zutuanxue git_data]# git reset --hard e2e2 +HEAD 现在位于 e2e2131 head test +[root@zutuanxue git_data]# git log --oneline +2add75e (HEAD -> master) add hello +ff77333 aaa +dd7925f test head +e2e2131 head test +644d678 test head +326e57a v2 a +8f01c62 version2 a +a714e37 a +47a267c a.txt +6ac34be a +[root@zutuanxue git_data]# cat a +test + + +#git reset --mixed:此为默认方式,不带任何参数的git reset,即是这种方式,移动head指针,改变暂存区内容,但不会改变工作区 +#git reset --soft:回退到某个版本,仅移动当前Head指针,不会改变工作区和暂存区的内容 +#git reset --hard:彻底回退到某个版本,head指针、工作区和暂存区内容全部改变 + +--soft用处不是很多;当执行git commit之后想撤回,但还不想覆盖工作区内容时,使用--mixed;当想完全回滚时,使用--hard来覆盖工作区。 +``` + +## git reflog + +``` +[root@zutuanxue git_data]# cat a #查看文件内容,发现恢复错了,本来是想恢复到“add haha”这个位置的 +test +[root@zutuanxue git_data]# git log --oneline #使用log查看,发现没有“add haha”的内容了 +e2e2131 (HEAD -> master) head test +644d678 test head +326e57a v2 a +8f01c62 version2 a +a714e37 a +47a267c a.txt +6ac34be a +#原因很简单,因为我们当前的工作版本是历史的一个提交点,这个历史提交点还没有发生过add bbb更新记录,所以当然就看不到了 ,要是想”还原到未来”的历史更新点 ,可以用git reflog命令来查看所有的历史记录 +[root@zutuanxue git_data]# git reflog +# 使用git reflog 可查看总历史内容(注意这里面也是所有的commit之后,也就是放到本地仓后的记录)再结合git reset --hard 哈希头部恢复版本快照 ,所有的数据根本就不可能丢失,随便删除,随便恢复(前提是已提交仓库的的内容) + +e2e2131 (HEAD -> master) HEAD@{0}: reset: moving to e2e2 +2add75e HEAD@{1}: reset: moving to 2add75e +f3d6391 HEAD@{2}: commit: add haha +2add75e HEAD@{3}: commit: add hello +ff77333 HEAD@{4}: commit: aaa +dd7925f HEAD@{5}: commit: test head +e2e2131 (HEAD -> master) HEAD@{6}: commit: head test +644d678 HEAD@{7}: commit: test head +326e57a HEAD@{8}: commit: v2 a +8f01c62 HEAD@{9}: commit: version2 a +a714e37 HEAD@{10}: commit: a +47a267c HEAD@{11}: commit: a.txt +6ac34be HEAD@{12}: commit (initial): a +[root@zutuanxue git_data]# git reset --hard f3d6 #使用reset恢复到“add haha”的版本 +HEAD 现在位于 f3d6391 add haha +[root@zutuanxue git_data]# cat a +haha +hello +haha +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/\344\273\243\347\240\201\345\220\210\345\271\266\345\210\206\346\224\257.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/\344\273\243\347\240\201\345\220\210\345\271\266\345\210\206\346\224\257.md" new file mode 100644 index 0000000..7d5ca87 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/\344\273\243\347\240\201\345\220\210\345\271\266\345\210\206\346\224\257.md" @@ -0,0 +1,160 @@ +合并分支 ,A分支上合并另一分支B,则B的所有内容都合并到了A上,如果分支和主干相差太多,合并就会容易报错,所以通常的操作就是分支合并后就删除分支然后再重新创建分支(完全拷贝主支信息)后再进行后续的合并,依次循环 + +``` +[root@zutuanxue git_data]# git branch + master +* test +[root@zutuanxue git_data]# git checkout master +切换到分支 'master' +[root@zutuanxue git_data]# git branch +* master + test +[root@zutuanxue git_data]# git merge test #提示输入描述信息 +Merge made by the 'recursive' strategy. + test | 0 + 1 file changed, 0 insertions(+), 0 deletions(-) + create mode 100644 test +[root@zutuanxue git_data]# git log --oneline +e96f03c (HEAD -> master) Merge branch 'test' +a6302d6 touch master +003e619 (test) touch test +f3d6391 add haha +2add75e add hello +ff77333 aaa +dd7925f test head +e2e2131 head test +644d678 test head +326e57a v2 a +8f01c62 version2 a +a714e37 a +47a267c a.txt +6ac34be a +[root@zutuanxue git_data]# ls +a master test +``` + +冲突合并 + +``` +[root@zutuanxue git_data]# echo master >> a +[root@zutuanxue git_data]# git commit -am "add master to a" +[master 801ff9a] add master to a + 1 file changed, 1 insertion(+) +[root@zutuanxue git_data]# git checkout test +切换到分支 'test' +[root@zutuanxue git_data]# git branch + master +* test +[root@zutuanxue git_data]# cat a +haha +hello +haha +[root@zutuanxue git_data]# echo test >> a +[root@zutuanxue git_data]# git commit -am "add test to a" +[test 1cab1b9] add test to a + 1 file changed, 1 insertion(+) +[root@zutuanxue git_data]# git checkout master +切换到分支 'master' +[root@zutuanxue git_data]# git merge -m "master&test" test#提示冲突 +自动合并 a +冲突(内容):合并冲突于 a +自动合并失败,修正冲突然后提交修正的结果。 +[root@zutuanxue git_data]# cat a +haha +hello +haha +<<<<<<< HEAD +master +======= +test +>>>>>>> test +[root@zutuanxue git_data]# vim a #手动更改冲突内容 +haha +hello +haha +master +test +[root@zutuanxue git_data]# git commit -am "merge test to master" #再次提交 +[master d8aeb13] merge test to master +[root@zutuanxue git_data]# cat a +haha +hello +haha +master +test +[root@zutuanxue git_data]# git log --oneline +d8aeb13 (HEAD -> master) merge test to master +1cab1b9 (test) add test to a +801ff9a add master to a +e96f03c Merge branch 'test' +a6302d6 touch master +003e619 touch test +f3d6391 add haha +2add75e add hello +ff77333 aaa +``` + +如果分支和主干相差太多,合并就会容易报错,所以通常的操作就是分支合并后就删除分支然后再重新创建分支(完全拷贝主支信息)后再进行后续的合并,依次循环 + +### 删除分支git branch -d + +``` +[root@zutuanxue git_data]# git branch -d test +已删除分支 test(曾为 1cab1b9)。 +[root@zutuanxue git_data]# git branch +* master +``` + +### git tag 标签 + +标签也是指向了一次commit提交,是一个里程碑式的标签,回滚打标签直接加标签号,不需要加唯一字符串,不用记唯一字符串,与指针的变动(reset)原理相似,也能通用git reset --hard命令 + +``` +[root@zutuanxue git_data]# git log --oneline +d8aeb13 (HEAD -> master) merge test to master +1cab1b9 add test to a +801ff9a add master to a +e96f03c Merge branch 'test' +a6302d6 touch master +003e619 touch test +f3d6391 add haha +2add75e add hello +[root@zutuanxue git_data]# git tag -a V1.0 f3d6 -m "add haha to V1.0" +#为“add haha”加上一个V1.0的标签 -a指定标签 f3d6为对应的哈希值,-m定义描述信息 +[root@zutuanxue git_data]# git tag -a V2.0 a630 -m "touch master to V2.0" +#为“touch master”定义一个V2.0的标签 +[root@zutuanxue git_data]# git tag #查看已有的标签 +V1.0 +V2.0 +[root@zutuanxue git_data]# git show V1.0 #查看指定标签的具体内容 +tag V1.0 +Tagger: aaa +Date: Mon Apr 6 04:35:18 2020 -0400 + +add haha to V1.0 + +commit f3d6391659db69a5c9fec610b94dd42f827b39e9 (tag: V1.0) +Author: aaa +Date: Mon Apr 6 02:56:34 2020 -0400 + + add haha + +diff --git a/a b/a +index 5c06d49..ec4f51e 100644 +--- a/a ++++ b/a +@@ -1,2 +1,3 @@ + haha + hello ++haha +[root@zutuanxue git_data]# git reset --hard V1.0 #数据回滚到V1.0标签的位置 +HEAD 现在位于 f3d6391 add haha +[root@zutuanxue git_data]# ls +a +[root@zutuanxue git_data]# cat a +haha +hello +haha +[root@zutuanxue git_data]# git tag -d V2.0 #删除标签 +已删除标签 'V2.0'(曾为 df79ae8) +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/\344\273\243\347\240\201\347\211\210\346\234\254\346\216\247\345\210\266\347\263\273\347\273\237.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/\344\273\243\347\240\201\347\211\210\346\234\254\346\216\247\345\210\266\347\263\273\347\273\237.md" new file mode 100644 index 0000000..cc4d8ac --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/\344\273\243\347\240\201\347\211\210\346\234\254\346\216\247\345\210\266\347\263\273\347\273\237.md" @@ -0,0 +1,23 @@ +## 版本控制介绍 + +vcs version control system 版本控制是指对软件开发过程中各种程序代码、配置文件及说明文档等文件变更的管理,是软件配置管理的核心思想之一。版本控制最主要的功能就是记录一个或若干个文件内容变化 ,以便将来查阅特定版本内容,并且记录文件的所有历史变化,随时可恢复到任何一个历史状态。除了记录版本变更外,版本控制的另一个重要功能是并行开发。软件开发往往是多人协同作业,版本控制可以有效地解决版本的同步以及不同开发者之间的开发通信问题,提高协同开发的效率。并行开发中最常见的不同版本软件的错误(Bug)修正问题也可以通过版本控制中分支与合并的方法有效地解决。这就类似于我们玩游戏的存档,或者写论文一样,刚写完的论文是版本1,提交上去不合格,修改之后叫版本2,再修改叫版本3,以此类推,版本控制的工具有很多,从SVN、VSS、CVS、Clearcase到现在使用的比较多的git(注意这个git是本地的库,网络的库是github)等 + +## 版本控制系统变迁 + +**本地版本控制系统(CVCS)** + +许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。 这么做唯一 的好处就是简单,但是特别容易犯错。 有时候会混淆所在的工作目录,一不小心会写错文件或者覆盖意想外的 文件。为了解决这个问题,人们很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文 件的历次更新差异。也就是在硬盘上保存补丁集(补丁是指文件修订前后的变化);通过应用所有的补丁,可以重新计算出各个版本的文件内容。 + +![image20200405145626878.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603165843979.png) + +**集中式的版本控制系统** + +只有一个中央数据仓库 ,如果中央数据仓库挂了或者不可访问 ,所有的使用者无法使用SVN ,无法进行提交或备份文件。本地版本控制 系统也存在类似问题,只要整个项目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。 + +![image20200405145221067.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603165860342.png) + +**分布式的版本控制(DVCS)** + +在这类系统中,像 Git、Mercurial、Bazaar 以及 Darcs 等,客户端并不只提取最新版本的文件快照, 而是把代码仓库完整地镜像 下来,包括完整的历史记录。 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。许多这类系统都可以指定和若干不同的远端代码仓库进行交互。籍此,你就可以在同一个项目中,分 别和不同工作小组的人相互协作。 你可以根据需要设定不同的协作流程,比如层次模型式的工作流,而这在以 前的集中式系统中是无法实现的。 + +![image20200405150812041.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603165876244.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/\345\260\206\344\273\243\347\240\201\344\274\240\345\210\260github\345\205\254\345\272\223.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/\345\260\206\344\273\243\347\240\201\344\274\240\345\210\260github\345\205\254\345\272\223.md" new file mode 100644 index 0000000..5d1d1d3 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/\345\260\206\344\273\243\347\240\201\344\274\240\345\210\260github\345\205\254\345\272\223.md" @@ -0,0 +1,230 @@ +## github使用 + +Github顾名思义是一个Git版本库的托管服务,是目前全球最大的软件仓库,拥有上百万的开发者用户,也是软件开发和寻找资源的最佳途径 ,Github不仅可以托管各种Git版本仓库,还拥有了更美观的Web界面,您的代码文件可以被任何人克隆 ,使得开发者为开源项贡献代码变得更加容易,当然也可以付费购买私有库,这样高性价比的私有库真的是帮助到了很多团队和企业 + +1、注册用户 + +2、配置ssh‐key + +3、创建项目 + +4、克隆项目到本地 + +5、推送新代码到github + +注册地址:https://github.com/ + +## 远程仓库 + +假设1:假设你准备开发一个新功能,但是需要两周才能完成。第一周写了50%,但是在第二周你的电脑粉碎了,并且还没有将上周工作代码存储到其他物理介质上,这样存在丢失的巨大风险 + +假设2:假设你是一个非常努力的程序员,除了在公司写代码外你还经常把代码用U盘拷贝回家继续工作,如果在通勤过程中U盘不小心丢了,回家之后你就不能工作了 + +- 配置Github + +- 创建SSH Key + + ``` + [root@zutuanxue ~]# ssh-keygen -t rsa + Generating public/private rsa key pair. + Enter file in which to save the key (/root/.ssh/id_rsa): + Enter passphrase (empty for no passphrase): + Enter same passphrase again: + Your identification has been saved in /root/.ssh/id_rsa. + Your public key has been saved in /root/.ssh/id_rsa.pub. + The key fingerprint is: + SHA256:UiiQi1grvAo9YFXFkuSHObA8XI2Jkpk07bUf1hSLXSw songs-wmx@163.com + The key's randomart image is: + +---[RSA 2048]----+ + |.o*o++B. .o. | + | =*==*o+oEo. | + |oo+Bo=+o+o. | + |=oo..oo+ . | + |.+. + S | + |..o o | + |o . | + |. | + | | + +----[SHA256]-----+ + [root@zutuanxue ~]# cd .ssh/ + [root@zutuanxue .ssh]# ls + id_rsa id_rsa.pub known_hosts + ``` + + .ssh/id_rsa:私钥 + + .ssh/id_res.pub:公钥 + + ``` + [root@zutuanxue .ssh]# cat id_rsa.pub + ``` + +- 添加公有秘钥到github + +![image20200407105944844.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603181654398.png) + +![image20200407110032231.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603181667320.png) + +![image20200407110138300.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603181678879.png) + +``` + [root@zutuanxue .ssh]# ssh git@github.com #测试秘钥是否有效 + Warning: Permanently added the RSA host key for IP address '52.74.223.119' to the list of known hosts. + PTY allocation request failed on channel 0 + Hi gongjunhe! You've successfully authenticated, but GitHub does not provide shell access. + Connection to github.com closed. +``` + +### 创建远程仓库 + +返回github首页 + +![image20200407110632002.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603181750178.png) + +![image20200407110822461.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603181782679.png) + +**关联本地仓库和远程仓库** + +在本地仓库中执行命令:`git remote add origin 远程仓库地址` + +``` +[root@zutuanxue git_data]# git remote add origin git@github.com:gongjunhe/gittest.git +``` + +![image20200407111123617.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603182093568.png) + +``` +[root@zutuanxue git_data]# git push -u origin master #将本地仓库的内容推送到远程仓库 +To github.com:gongjunhe/gittest.git + ! [rejected] master -> master (non-fast-forward) +error: 无法推送一些引用到 'git@github.com:gongjunhe/gittest.git' +提示:更新被拒绝,因为您当前分支的最新提交落后于其对应的远程分支。 +提示:再次推送前,先与远程变更合并(如 'git pull ...')。详见 +提示:'git push --help' 中的 'Note about fast-forwards' 小节。 +[root@zutuanxue git_data]# git fetch origin #获取远程更新 +[root@zutuanxue git_data]# git merge origin/master #将更新的内容合并到本地 +fatal: 拒绝合并无关的历史 +[root@zutuanxue git_data]# git merge origin/master --allow-unrelated-histories +Merge made by the 'recursive' strategy. + README.md | 2 ++ + 1 file changed, 2 insertions(+) + create mode 100644 README.md + +[root@zutuanxue git_data]# touch c +[root@zutuanxue git_data]# git add . +[root@zutuanxue git_data]# git commit -m "touch c" +[master 2ec770e] touch c + 1 file changed, 0 insertions(+), 0 deletions(-) + create mode 100644 c +[root@zutuanxue git_data]# git push -u origin master +枚举对象: 3, 完成. +对象计数中: 100% (3/3), 完成. +Delta compression using up to 4 threads. +压缩对象中: 100% (2/2), 完成. +写入对象中: 100% (2/2), 274 bytes | 274.00 KiB/s, 完成. +Total 2 (delta 0), reused 0 (delta 0) +To github.com:gongjunhe/gittest.git + e5d1eba..2ec770e master -> master +分支 'master' 设置为跟踪来自 'origin' 的远程分支 'master'。 +``` + +![image20200407113836692.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603181724025.png) + +``` +[root@zutuanxue git_data]# git log --oneline +2ec770e (HEAD -> master, origin/master) touch c +e5d1eba Merge remote-tracking branch 'origin/master' +3964bca touch d +c2a2158 Initial commit +f3d6391 (tag: V1.0) add haha +2add75e add hello +[root@zutuanxue git_data]# git reset --hard f3d6 +HEAD 现在位于 f3d6391 add haha +[root@zutuanxue git_data]# ls +a +[root@zutuanxue git_data]# git log --oneline +f3d6391 (HEAD -> master, tag: V1.0) add haha +2add75e add hello +ff77333 aaa +dd7925f test head +e2e2131 head test +644d678 test head +326e57a v2 a +8f01c62 version2 a +a714e37 a +47a267c a.txt +6ac34be a +[root@zutuanxue git_data]# git pull origin +更新 f3d6391..2ec770e +Fast-forward + README.md | 2 ++ + c | 0 + d | 0 + 3 files changed, 2 insertions(+) + create mode 100644 README.md + create mode 100644 c + create mode 100644 d +[root@zutuanxue git_data]# ls +a c d README.md +删除本地仓库与远程仓库的关联 +在本地仓库中执行命令:git remote rm origin + +推送本地仓库内容到远程仓库 +命令:git push origin 分支 +注意:关联后第一次推到远程库前需要先拉取内容,否则报错 + +拉取远程仓库内容到本地仓库 +命令:git pull origin 分支 +存在本地库与远程库不一致情况:git pull origin 分支 --allow-unrelated-histories + +克隆远程仓库到本地电脑形成本地仓库 +格式:git clone 远程库地址 +示例:[root@zutuanxue git_data]# git clone git@github.com:gongjunhe/gittest.git +``` + +## .gitignore文件 + +作用:忽略特殊文件。当工程中有些文件已经确定基本不会改变,所以不用每次推送时都推送,git在推送时会忽略.gitignore文件中列举的内容,可以提升推送效率 +注意:文件名必须叫做.gitignore,.gitignore和.git文件夹是同一目录; +一定要push之前创建.gitignore文件,push之后创建.gitignore不用被git使用,因为git已经开始了版本控制。 + +``` +文件内容说明 + +# 开头的行为注释,不生效 + +支持正则表达(简化的) + +可以以(/)开头防止递归 + +最后有斜杠(/)的代表要忽略的是目录 + +加感叹号(!)表示取反 +``` + +**支持的正则表达规范** + +``` +* 零个或多个字符 +[] 匹配括号中的任意字符 +? 匹配一字符 + [n-m] 匹配一个范围内的字符,[abc] 匹配 任何一个列在方括号中的字符 (这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c) + +[^n-m] 不要匹配一个范围内的字符 + +** 表示匹配任意中间目录,比如 a/**/z 可以 匹配 a/z 、 a/b/z 或 a/b/c/z 等。 + +例如 + +a/:忽略任何目录下名为a的目录 + +/a.txt:只忽略当前目录下的a.txt,不忽略其它目录下的a.txt + + *.exe:忽略所有以.exe结尾的文件 + + !/a/a.jpg:不忽略a目录下的a.jpg文件 + + a/*.txt:忽略a目录下的以.txt结尾的文件,但不忽略其子目录下包含的以.txt结尾的文件 + + *.[ao]: 忽略.a或.o结尾的文件 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/\346\234\254\345\234\260git\345\256\211\350\243\205\344\270\216\345\210\235\345\247\213\345\214\226.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/\346\234\254\345\234\260git\345\256\211\350\243\205\344\270\216\345\210\235\345\247\213\345\214\226.md" new file mode 100644 index 0000000..5042baa --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/CI\345\222\214CD\344\273\243\347\240\201\347\256\241\347\220\206\345\271\263\345\217\260/\346\234\254\345\234\260git\345\256\211\350\243\205\344\270\216\345\210\235\345\247\213\345\214\226.md" @@ -0,0 +1,93 @@ +## 系统环境准备 + +系统:CentOS8 + +``` +[root@zutuanxue ~]# sestatus -v +SELinux status: disabled +[root@zutuanxue ~]# systemctl status firewalld +● firewalld.service - firewalld - dynamic firewall daemon + Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled) + Active: inactive (dead) + Docs: man:firewalld(1) +[root@zutuanxue ~]# dnf repolist +上次元数据过期检查:6:26:44 前,执行于 2020年04月02日 星期四 23时17分37秒。 +仓库标识 仓库名称 状态 +app app 4,681 +os os 1,655 +``` + +### Git安装部署 + +``` +[root@zutuanxue ~]# dnf install git +Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量。 这些变量存储在三个不同的位置: +[root@zutuanxue ~]# git config +--system 系统配置文件 配置内容会存放在/etc/gitconfig中,包含系统上每一个用户及他们的仓库的通用配置,需要管理员权限 +--global 全局配置文件 配置内容会存放在~/.gitconfig或者~/.config/git/gitconfig中 +--local 本地的配置文件 配置文件存放在git工作目录的.git/config中 + +注:配置文件的优先级local>global>system,可以使用git config -h去获取相关帮助,也可以使用git config --list --show-origin查看所有的配置及所在的文件。 + + +[root@zutuanxue ~]# git config --global user.name "hello" +#定义git用户 +[root@zutuanxue ~]# git config --global user.email "hello@localhost +#定义git使用的邮箱 +[root@zutuanxue ~]# git config --global color.ui true +#定义语法高亮 +[root@zutuanxue ~]# git config --list +user.name=hello +user.email=hello@localhost +color.ui=true +#查看定义的信息 + +[root@zutuanxue ~]# pwd +/root +[root@zutuanxue ~]# cat .gitconfig +[user] + name = hello + email = hello@localhost +[color] + ui = true +``` + +### git初始化 + +初始化工作目录、主要用来初始化一个空的git本地仓库。执行完上面的命令,当前目录下会自动生成.git隐藏文件夹, + +``` +#建立工作目录 +mkdir git_data +cd git_data/ + +#初始化 +git init + +#查看工作区状态 +git status +[root@zutuanxue git_data]# pwd +/root/git_data +[root@zutuanxue git_data]# git status +位于分支 master +尚无提交 +无文件要提交(创建/拷贝文件并使用 "git add" 建立跟踪) +隐藏文件介绍: +[root@zutuanxue git_data]# pwd +/root/git_data +[root@zutuanxue git_data]# ls -a +. .. .git +[root@zutuanxue git_data]# cd .git/ +[root@zutuanxue .git]# ls +branches config description HEAD hooks info objects refs + +branches # 分支目录 +config # 保存配置信息 +description # 仅供git web程序使用 +HEAD # 记录当前的分支指向 +hooks # 包含脚本文件 +info # 包含一个全局排除文件(exclude文件),可以将不想被git处理的文件定义到exclude文件中 +objects # 存放所有数据内容 ,有info和pack两个子文件夹(实际也就是本地仓库的目录) +refs # 这个目录一般包括三个子文件夹,heads、remotes和tags,heads中的文件标识了项目中的各个分支指向的当前哪一个提交记录 +index # 保存暂存区信息 ,在执行git init的时候 ,这个文件还没有(也就是暂存区的内容) +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker Compose\345\256\271\345\231\250\347\274\226\346\216\222.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker Compose\345\256\271\345\231\250\347\274\226\346\216\222.md" new file mode 100644 index 0000000..227f36b --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker Compose\345\256\271\345\231\250\347\274\226\346\216\222.md" @@ -0,0 +1,164 @@ +## 一、 Docker-Compose + +### 1.1、 什么是Docker Compose + +Compose 项目是 Docker 官方的开源项目,负责实现 Docker 容器集群的快速编排,开源代码在 **https://github.com/docker/compose** 上 + +我们知道使用 Dockerfile 模板文件可以让用户很方便的定义一个单独的应用容器,其实在工作中,经常会碰到需要多个容器相互配合来完成的某项任务情况,例如工作中的 web 服务容器本身,往往会在后端加上数据库容器,甚至会有负责均衡器,比如 LNMP 服务 + +Compose 就是来做这个事情的,它允许用户通过一个单独的 docker-compose.yml 模板文件 YAML格式 来定义一组相关联的应用容器为一个项目 project + +Compose 中有两个重要的概念: + +**服务 service :一个应用的容器,实际上可以包括若干运行相同镜像的容器实例** +**项目 project :由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml中定义** + +### 1.2、 安装 + +``` +# docker-compose版本选择:https://github.com/docker/compose/releases +# curl -L https://github.com/docker/compose/releases/download/1.25.4/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose +# chmod +x /usr/local/bin/docker-compose +``` + +### 1.3、 命令 + +``` +Compose 大部分命令的对象即可以是项目的本身,也可以是指定为项目中的服务或者容器 +执行docker-compose [COMMAND] --help 或者docker-compose help [COMMAND]可以查看命令的帮助信息 +具体的使用格式 +docker-compose [-f=...] [options] [COMMAND] [ARGS] +参数选项 +-f,--file file指定模板文件,默认是docker-compose.yml模板文件,可以多次指定 +-p,--project-name name指定项目名称,默认使用所在目录名称作为项目名称 +--x-networking 使用Docker的后端可插拔网络特性 +--x-networking-driver driver指定网络的后端驱动,默认使用bridge +--verbose 输入更多的调试信息 +-v,--version 输出版本信息 + + +Compose所支持的命令: + +build 构建项目中的服务容器 +bundle 从Compose文件生成分布式应用程序包 +config 验证并查看Compose文件 +create 为服务创建容器 +down 停止容器并删除由其创建的容器,网络,卷和图像up +events 为项目中的每个容器流式传输容器事件 +exec 这相当于docker exec。 +help 获得一个命令的帮助 +kill 通过发送SIGKILL信号来强制停止服务容器 +logs 查看服务容器的输出 +pause 暂停一个容器 +port 打印某个容器端口所映射的公共端口 +ps 列出项目中目前所有的容器 +pull 拉取服务依赖镜像 +push 推送服务镜像 +restart 重启项目中的服务 +rm 删除所有停止状态的服务容器 +run 在指定服务上执行一个命令 +scale 设置指定服务执行的容器个数 +start 启动已存在的服务容器 +stop 停止已存在的服务容器 +top 显示容器正在运行的进程 +unpause 恢复处于暂停状态的容器 +up 自动完成包括构建镜像、创建服务、启动服务并关联服务相关容器的一系列操作 +version 输出版本 +``` + +### 1.4、模板文件 + +排版问题,请看单独的文件。 +官网链接:https://docs.docker.com/compose/compose-file/#compose-file-structure-and-examples + +### 1.5、 示例 + +``` +举个简单的例子来具有的说明一下 Compose 的使用 + +1. 创建一个目录(里面包含需要的文件) + +[root@zutuanxue] mkdir compose-py + +2. 创建一个 Python 应用, 使用 Flask ,将数值记入 Redis + +[root@zutuanxue compose-py] cat app.py + +import time + +import redis +from flask import Flask + + +app = Flask(__name__) +cache = redis.Redis(host='redis', port=6379) + + +def get_hit_count(): + retries = 5 + while True: + try: + return cache.incr('hits') + except redis.exceptions.ConnectionError as exc: + if retries == 0: + raise exc + retries -= 1 + time.sleep(0.5) + + +@app.route('/') +def hello(): + count = get_hit_count() + return 'Hello World! I have been seen {} times.\n'.format(count) + +if __name__ == "__main__": + app.run(host="0.0.0.0", debug=True) + +3. 创建 requirements.txt 文件,里面是需要安装的 Python 包 + +[root@zutuanxue compose-py] cat requirements.txt +flask +redis + +4. 创建 Dockerfile 文件 + +[root@zutuanxue compose-py] cat Dockerfile +FROM python +ADD . /code +WORKDIR /code +RUN pip install -r requirements.txt +CMD ["python", "app.py"] + +# 这告诉Docker: + 从 Python 开始构建镜像 + 将当前目录 . 添加到 /code 镜像中的路径 + 将工作目录设置为 /code + 安装 Python 依赖项 + 将容器的默认命令设置为 python app.py + +5. 创建 docker-compose.yml 文件 + +[root@zutuanxue compose-py] cat docker-compose.yml +version: '3' +services: + web: + build: . + ports: + - "5000:5000" + volumes: + - .:/code + redis: + image: "redis" + +此 Compose 文件定义了两个服务,web 和 redis +该web服务: + 使用从 Dockerfile 当前目录中构建的镜像 + 将容器上的公开端口 5000 转发到主机上的端口 5000 我们使用 Flask Web 服务器的默认端口 5000 + 该 redis 服务使用从 Docker Hub 中提取的公共 Redis 映像 + +6. 使用 Compose 构建并运行您的应用程序 + +[root@zutuanxue compose-py] docker-compose up + +7. 测试访问,在浏览器访问 IP:5000 每刷新一次就会加一 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker Swarm\344\270\273\346\234\272\347\274\226\346\216\222.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker Swarm\344\270\273\346\234\272\347\274\226\346\216\222.md" new file mode 100644 index 0000000..539619f --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker Swarm\344\270\273\346\234\272\347\274\226\346\216\222.md" @@ -0,0 +1,195 @@ +## 一、 什么是Docker Swarm + +Swarm 是 Docker 公司推出的用来管理 docker 集群的平台,几乎全部用GO语言来完成的开发的,代码开源在https://github.com/docker/swarm, 它是将一群 Docker 宿主机变成一个单一的虚拟主机,Swarm 使用标准的 Docker API 接口作为其前端的访问入口,换言之,各种形式的Docker Client (compose,docker-py等) 均可以直接与 Swarm 通信,甚至 Docker 本身都可以很容易的与 Swarm 集成,这大大方便了用户将原本基于单节点的系统移植到 Swarm 上,同时 Swarm 内置了对 Docker 网络插件的支持,用户也很容易的部署跨主机的容器集群服务。 + +Docker Swarm 和 Docker Compose 一样,都是 Docker 官方容器编排项目,但不同的是,Docker Compose 是一个在单个服务器或主机上创建多个容器的工具,而 Docker Swarm 则可以在多个服务器或主机上创建容器集群服务,对于微服务的部署,显然 Docker Swarm 会更加适合。 + +从 Docker 1.12.0 版本开始,Docker Swarm 已经包含在 Docker 引擎中(docker swarm),并且已经内置了服务发现工具,我们就不需要像之前一样,再配置 Etcd 或者 Consul 来进行服务发现配置了。 + +Swarm deamon 只是一个调度器(Scheduler)加路由器(router), Swarm 自己不运行容器,它只是接受 Docker 客户端发来的请求,调度适合的节点来运行容器,这就意味着,即使 Swarm 由于某些原因挂掉了,集群中的节点也会照常运行,当 Swarm 重新恢复运行之后,他会收集重建集群信息。 + +## 二、 Swarm的几个关键概念 + +**Swarm** +集群的管理和编排是使用嵌入docker引擎的SwarmKit,可以在docker初始化时启动swarm模式或者加入已存在的swarm + +**Node** +一个节点是docker引擎集群的一个实例。您还可以将其视为Docker节点。您可以在单个物理计算机或云服务器上运行一个或多个节点,但生产群集部署通常包括分布在多个物理和云计算机上的Docker节点。 +要将应用程序部署到swarm,请将服务定义提交给 管理器节点。管理器节点将称为任务的工作单元分派 给工作节点。 +Manager节点还执行维护所需群集状态所需的编排和集群管理功能,Manager节点选择单个领导者来执行编排任务,工作节点接收并执行从管理器节点分派的任务。默认情况下,管理器节点还将服务作为工作节点运行,但您可以将它们配置为仅运行管理器任务并且是仅管理器节点。代理程序在每个工作程序节点上运行,并报告分配给它的任务。工作节点向管理器节点通知其分配的任务的当前状态,以便管理器可以维持每个工作者的期望状态。 + +**Service** +一个服务是任务的定义,管理机或工作节点上执行。它是群体系统的中心结构,是用户与群体交互的主要根源。创建服务时,你需要指定要使用的容器镜像。 + +**Task** +任务是在docekr容器中执行的命令,Manager节点根据指定数量的任务副本分配任务给worker节点 + +## 三、相关命令 + +``` +docker swarm: + 集群管理,子命令有init, ``join``, leave, update。(docker swarm --help查看帮助) + +docker service: + 服务创建,子命令有create, inspect, update, remove, tasks。(docker service--help查看帮助) + +docker node: + 节点管理,子命令有accept, promote, demote, inspect, update, tasks, ``ls``, ``rm``。 +(docker node --help查看帮助) +``` + +## 四、swarm集群部署 + +### 4.1、 部署前准备 + +``` +以下操作在所有节点上进行: + +| IP地址 | 计算机名 | 角色 | +| ------------- | ----------- ---- | ------------ | +| 192.168.1.150 | zutuanxue-manage01 | swarm_manager | +| 192.168.1.151 | zutuanxue-node-1 | swarm_node | +| 192.168.1.152 | zutuanxue-node-2 | swarm_node | + +安装 docker + +hosts 解析 + +[root@zutuanxue-manage01 ~]# cat /etc/hosts + +192.168.1.150 zutuanxue-manage01 +192.168.1.151 zutuanxue-node-1 +192.168.1.152 zutuanxue-node-2 + +[root@zutuanxue-manage01 ~]# systemctl disable firewalld +[root@zutuanxue-manage01 ~]# systemctl stop firewalld +[root@zutuanxue-manage01 ~]# iptables -F + +关闭 selinux + +#设置为 disabled 后需要重启计算机生效 +SELINUX=disabled +``` + +### 4.2、 创建swarm集群 + +``` +初始化集群-init + +[root@zutuanxue-manage01 ~]# docker swarm init --advertise-addr 192.168.1.150 + +#--advertise-addr参数表示其它swarm中的worker节点使用此ip地址与manager联系 + + +Swarm initialized: current node (dh6qthwwctbrl0y3hx1k41icl) is now a manager. + +To add a worker to this swarm, run the following command: + + docker swarm join --token SWMTKN-1-0vdbyxq80uk8sf9nlnahsnkv6w3gaf5necl992ia0g8dmc5x8c-bkenoigc7kwizoch08r3fc4wq 192.168.1.150:2377 + +To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions. +``` + +### 4.3、添加worker(node工作节点)到swarm + +``` +[root@zutuanxue-node-1 ~]# docker swarm join --token SWMTKN-1-0vdbyxq80uk8sf9nlnahsnkv6w3gaf5necl992ia0g8dmc5x8c-bkenoigc7kwizoch08r3fc4wq 192.168.1.150:2377 +This node joined a swarm as a worker. + +[root@zutuanxue-node-2 ~]# docker swarm join --token SWMTKN-1-0vdbyxq80uk8sf9nlnahsnkv6w3gaf5necl992ia0g8dmc5x8c-bkenoigc7kwizoch08r3fc4wq 192.168.1.150:2377 +This node joined a swarm as a worker. +``` + +### 4.4、 验证加入情况 + +``` + [root@zutuanxue-manage01 ~]# docker node ls +``` + +### 4.5、 在Swarm中部署服务(nginx为例) + +``` +创建网络在部署服务 +# 创建网络 +[root@zutuanxue-manage01 ~]# docker network create -d overlay nginx_net +a52jy33asc5o0ts0rq823bf0m + +[root@zutuanxue-manage01 ~]# docker network ls | grep nginx_net +a52jy33asc5o nginx_net overlay swarm + +# 部署服务 +[root@zutuanxue-manage01 ~]# docker service create --replicas 1 --network nginx_net --name my_nginx -p 80:80 nginx # 就创建了一个具有一个副本(--replicas 1 )的nginx服务,使用镜像nginx + +olexfmtdf94sxyeetkchwhehg +overall progress: 1 out of 1 tasks +1/1: running [==================================================>] +verify: Service converged + +在 manager与node 节点上使用上面这个覆盖网络创建 nginx 服务 +其中,--replicas 参数指定服务由几个实例组成 +注意:不需要提前在节点上下载 nginx 镜像,这个命令执行后会自动下载这个容器镜像 + +# 使用 docker service ls 查看正在运行服务的列表 +[root@zutuanxue-manage01 ~]# docker service ls +ID NAME MODE REPLICAS IMAGE PORTS +olexfmtdf94s my_nginx replicated 1/1 nginx:latest *:80->80/tcp + +2) 查询Swarm中服务的信息 -pretty 使命令输出格式化为可读的格式,不加 --pretty 可以输出更详细的信息: + +[root@zutuanxue-manage01 ~]# docker service inspect --pretty my_nginx + +ID: zs7fw4ereo5w7ohd4n9ii06nt +Name: my_nginx +Service Mode: Replicated + Replicas: 1 +Placement: +UpdateConfig: + Parallelism: 1 + On failure: pause + Monitoring Period: 5s + Max failure ratio: 0 + Update order: stop-first +RollbackConfig: + Parallelism: 1 + On failure: pause + Monitoring Period: 5s + Max failure ratio: 0 + Rollback order: stop-first +ContainerSpec: + Image: nginx:latest@sha256:b73f527d86e3461fd652f62cf47e7b375196063bbbd503e853af5be16597cb2e + Init: false +Resources: +Networks: nginx_net +Endpoint Mode: vip +Ports: + PublishedPort = 80 + Protocol = tcp + TargetPort = 80 + PublishMode = ingress + +# 查询到哪个节点正在运行该服务 +[root@zutuanxue-manage01 ~]# docker service ps my_nginx + + +在 Swarm 中动态扩展服务 (scale) 当然,如果只是通过 service 启动容器,swarm 也算不上什么新鲜东西了。Service 还提供了复制(类似 kubernetes 里的副本)功能。可以通过 docker service scale 命令来设置服务中容器的副本数,比如将上面的 my_nginx 容器动态扩展到 4 个 + +[root@manager43 ~]# docker service scale my_nginx=4 +my_nginx scaled to 4 +overall progress: 4 out of 4 tasks +1/4: running [==================================================>] +2/4: running [==================================================>] +3/4: running [==================================================>] +4/4: running [==================================================>] +verify: Service converged + +和创建服务一样,增加 scale 数之后,将会创建新的容器,这些新启动的容器也会经历从准备到运行的过程,过一分钟左右,服务应该就会启动完成,这时候可以再来看一下 nginx 服务中的容器 + +[root@manager43 ~]# docker service ps my_nginx + + +升级镜像/升级业务/回滚业务 +docker service update --image nginx:new my_nginx + +删除服务 +[root@manager43 ~]# docker service rm my_nginx +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker \347\275\221\347\273\234.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker \347\275\221\347\273\234.md" new file mode 100644 index 0000000..a408634 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker \347\275\221\347\273\234.md" @@ -0,0 +1,363 @@ +# 一、Docker 网络 + +docker网络主要是解决容器联网问题,也是我们使用容器中最重要的一个环节,如果容器没有网络则无法向网络中提供服务。 + +### 网络管理命令:docker network + +``` +[root@zutuanxue ~]# docker network --help + +Usage: docker network COMMAND + +Manage networks + +Commands: + connect Connect a container to a network + create Create a network + disconnect Disconnect a container from a network + inspect Display detailed information on one or more networks + ls List networks + prune Remove all unused networks + rm Remove one or more networks + +Run 'docker network COMMAND --help' for more information on a command. +``` + +# 二、docker网络类型 + +创建容器的时候可以通过—network命令来指定容器的网络,网络类型有以下四种 + +- bridge +- host +- none +- 容器网络或联盟网络 + +### bridge + +桥接网络是指容器通过桥接的方式将容器网卡桥接到宿主机的docker0网桥,然后在通过宿主机防火墙的NAT表实现与外网的联系。 + +##### 宿主机docker0网桥 + +``` +[root@zutuanxue ~]# ifconfig +#docker0网桥 +docker0: flags=4163 mtu 1500 + inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 + inet6 fe80::42:c7ff:fe37:8e8 prefixlen 64 scopeid 0x20 + ether 02:42:c7:37:08:e8 txqueuelen 0 (Ethernet) + RX packets 6618 bytes 277975 (271.4 KiB) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 8152 bytes 24675021 (23.5 MiB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +.....省略了本机的网卡信息 +#容器网卡,每创建一个桥接网络的容器就会生成一个对应的网卡 +vethf75a942: flags=4163 mtu 1500 + inet6 fe80::9085:f5ff:fe34:77b5 prefixlen 64 scopeid 0x20 + ether 92:85:f5:34:77:b5 txqueuelen 0 (Ethernet) + RX packets 2850 bytes 158484 (154.7 KiB) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 3397 bytes 11613136 (11.0 MiB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + + + +如果想看更清楚一下 可以使用 ip add show命令 +[root@zutuanxue ~]# ip add show + +4: docker0: mtu 1500 qdisc noqueue state UP group default + link/ether 02:42:c7:37:08:e8 brd ff:ff:ff:ff:ff:ff + inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 + valid_lft forever preferred_lft forever + inet6 fe80::42:c7ff:fe37:8e8/64 scope link + valid_lft forever preferred_lft forever + +容器网卡 +14: vethf75a942@if13: mtu 1500 qdisc noqueue master docker0 state UP group default + link/ether 92:85:f5:34:77:b5 brd ff:ff:ff:ff:ff:ff link-netnsid 1 + inet6 fe80::9085:f5ff:fe34:77b5/64 scope link + valid_lft forever preferred_lft forever + + +注意: +这里的vethf75a942@if13指的就是容器网卡,V代表虚拟网卡的意思,eth 以太网卡,f75a942网卡编号,if13指的是宿主机网桥(docekr0)的一个端口,对应容器的网卡编号加一。 +所以容器内的网卡编号应该是 eth0@if14 + +通过在容器中执行命令 ip add show 也可以看到 +[root@zutuanxue ~]# docker exec centos1 ip add show +1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 + link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 + inet 127.0.0.1/8 scope host lo + valid_lft forever preferred_lft forever +13: eth0@if14: mtu 1500 qdisc noqueue state UP group default + link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0 + inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0 + valid_lft forever preferred_lft forever +``` + +### 防火墙的NAT表内容 + +``` +[root@zutuanxue ~]# iptables -t nat -L +Chain PREROUTING (policy ACCEPT) +target prot opt source destination +DOCKER all -- anywhere anywhere ADDRTYPE match dst-type LOCAL + +Chain INPUT (policy ACCEPT) +target prot opt source destination + +Chain OUTPUT (policy ACCEPT) +target prot opt source destination +DOCKER all -- anywhere !loopback/8 ADDRTYPE match dst-type LOCAL + +Chain POSTROUTING (policy ACCEPT) +target prot opt source destination +MASQUERADE all -- 172.17.0.0/16 anywhere + +Chain DOCKER (2 references) +target prot opt source destination +RETURN all -- anywhere anywhere +``` + +### docker0 与容器网卡桥接 + +``` +通过brctl show命令可以看到容器网卡和docker0网卡的桥接信息 +[root@zutuanxue ~]# brctl show +bridge name bridge id STP enabled interfaces +docker0 8000.0242c73708e8 no vethf75a942 +``` + +**创建一个网络为bridge类型的容器,不指定默认也是这个类型** + +``` +[root@zutuanxue ~]# docker run -d --network bridge --name centos1 baishuming2020/centos_nginx +``` + +### host + +**容器和真机共用网卡及对应的端口,缺点就是同一个端口只能宿主机或者某个容器使用,其他容器不能用。** + +``` +创建一个网络类型host的容器 +[root@zutuanxue ~]# docker run -d --network host --name centos2 baishuming2020/centos_nginx +``` + +### none + +**容器仅有lo网卡,是一个不能联网的本地容器** + +``` +创建一个网络类型为lo的容器 +[root@zutuanxue ~]# docker run -d --network none --name centos3 baishuming2020/centos_nginx +``` + +### 2.1、实现网桥网络 + +目的:不同的服务容器组应用不同的网桥,避免同一网络内容器太多,保持容器网络独立性。 + +关于新网桥联网问题:创建网桥后,宿主机会自动帮你做NAT,所以不用担心联网问题 + +#### 查看网络-ls + +``` +[root@zutuanxue ~]# docker network ls +NETWORK ID NAME DRIVER SCOPE +80982d2613cd bridge bridge local +40c179ab420a docker1 bridge local +04aadb7475c0 docker100 bridge local +ce79e9d7525a host host local +8f0358469e57 none null local + +NETWORK ID 网桥ID +NAME 名称 +DRIVER 网络类型 +SCOPE 作用范围 +``` + +#### 创建网桥-create + +``` +[root@zutuanxue ~]# docker network create -d bridge --subnet 192.168.1.0/24 --gateway 192.168.1.1 mydocker0 +6a410e27b66ea587142d967f7dff6f36c04ced3c27116a79831412f3743aba56 + +[root@zutuanxue ~]# docker network ls +NETWORK ID NAME DRIVER SCOPE +6ee1e928b710 bridge bridge local +ce79e9d7525a host host local +6a410e27b66e mydocker0 bridge local +8f0358469e57 none null local + + +修改docker网桥名字 +1、关闭新建网桥 +[root@zutuanxue ~]# ip link set dev br-6a410e27b66e down +2、修改名字 +[root@zutuanxue ~]# ip link set dev br-6a410e27b66e name mydocker0 +3、启动网桥 +[root@zutuanxue ~]# ip link set dev mydocker0 up +4、重启docker服务 +[root@zutuanxue ~]# systemctl restart docker +``` + +#### 删除未使用的网桥-prune + +``` +[root@zutuanxue ~]# docker network prune +WARNING! This will remove all networks not used by at least one container. +Are you sure you want to continue? [y/N] y +Deleted Networks: +docker1 +``` + +#### 删除某个网桥-rm + +``` +[root@zutuanxue ~]# docker network rm docker100 +docker100 + +注意: +不能被活动容器占用 +``` + +#### 容器连接到网桥 + +前提是该容器是桥接网络 + +``` +[root@zutuanxue ~]# docker network connect docker1 centos1 +[root@zutuanxue ~]# docker exec centos1 ifconfig +eth0: flags=4163 mtu 1500 + inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255 + ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet) + RX packets 8 bytes 656 (656.0 B) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 0 bytes 0 (0.0 B) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 +发现centos1容器多了一块网卡,使用的正是docker1的网段 +eth1: flags=4163 mtu 1500 + inet 192.168.1.2 netmask 255.255.255.0 broadcast 192.168.1.255 + ether 02:42:c0:a8:01:02 txqueuelen 0 (Ethernet) + RX packets 16 bytes 1312 (1.2 KiB) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 0 bytes 0 (0.0 B) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +lo: flags=73 mtu 65536 + inet 127.0.0.1 netmask 255.0.0.0 + loop txqueuelen 1000 (Local Loopback) + RX packets 0 bytes 0 (0.0 B) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 0 bytes 0 (0.0 B) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 +``` + +#### 容器断开网桥 + +``` +将centos1容器的网络从docker1网桥断开 +[root@zutuanxue ~]# docker network disconnect docker1 centos1 +``` + +### 常见故障 + +### FAQ1:使用改名后的新网桥的容器可能无法解析域名 + +原因:没有配置新网桥的DNS + +解决方法:为容器手动配置一个DNS地址即可 + +### FAQ2:Networking will not work + +``` +[root@zutuanxue ~]# docker run -d --network docker100 --name centos4 baishuming2020/centos_nginx +WARNING: IPv4 forwarding is disabled. Networking will not work. +67f2c276123c993cd66b9d7a99ba22402331a13f9ea8817e57324a934896b805 + +解决方案 +1、打开转发 +[root@zutuanxue ~]# echo "net.ipv4.ip_forward=1" >> /usr/lib/sysctl.d/00-system.conf + +2、重启网络 +[root@zutuanxue ~]# systemctl restart network +``` + +## 三、不同主机间的容器通信 + +### 3.1、 macvlan + +在 Docker 中,macvlan 是众多 Docker 网络模型中的一种,并且是一种跨主机的网络模型,作为一种驱动启用,Docker macvlan 只支持 bridge 模式 + +``` +#macvlan 需要一块独立的网卡来进行使用,所以我们需要新添加一块网卡 + +docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1 -o parent=ens224 mtacvlan-1 + +-o parent=网卡名称 指定用来给 macvlan 网络使用的物理网卡 + +注意,要在所有需要运行 macvlan 的主机上执行这条命令,但是要记得更改网关的地址,避免造成IP冲突 + +docker run -itd --network macvlan-1 centos /bin/bash +``` + +### 3.2、 overlay + +在 Docker 中,overlay 是众多 Docker 网络模型中的一种,并且是一种跨主机的全局网络模型,有一个数据库专门的来存储网络分配信息,避免 IP 冲突,同时内部还有一个小型的 DNS 我们可以直接通过主机名进行访问 + +``` +consul 服务端: +docker run -itd -h consul --name consul --restart=always -p 8500:8500 progrium/consul -server -bootstrap + +-h 主机名 +–name 容器名 +–restart=always 重启策略 +progrium/consul 镜像名称 +-server 以服务节点启动 +-bootstrap 预期的启动节点数:自举 + +在浏览器内输入 IP地址+端口号 可以看到 web 页面 + +在所有主机上编辑 daemon.json 文件: +{ +"hosts": ["tcp://0.0.0.0:2375","unix:///var/run/docker.sock"], 监听相关端口 +"cluster-store":"consul://192.168.1.150:8500", 集群的主机地址 +"cluster-advertise":"192.168.1.150:2375” 宣告自己的地址 +} + +重启 docker 服务 + +创建 overlay 网络(全局网络):一台主机上创建自动同步 + + docker network create -d overlay overlay-1 + +启动容器测试: + + docker run -it --name docker-1 --network=overlay-1 centos /bin/bash + + docker run -it --name docker-2 --network=overlay-1 centos /bin/bash + +验证:ping docker-1 +``` + +### 常见故障 + +如发现各容器内分配的ip之间相互ping不通 + +``` +原因:可能由于防火墙问题引起的,默认forward链是drop状态,需要打开才可以 + + +解决方案: +执行下面操作,保证INPUT FORWARD链都是ACCEPT状态 +清除其他规则 +[root@zutuanxue_node1 ~]# iptables -P INPUT ACCEPT +[root@zutuanxue_node1 ~]# iptables -P FORWARD ACCEPT +[root@zutuanxue_node1 ~]# iptables -F +[root@zutuanxue_node1 ~]# iptables -L -n + + +[root@zutuanxue_node2 ~]# iptables -P INPUT ACCEPT +[root@zutuanxue_node2 ~]# iptables -P FORWARD ACCEPT +[root@zutuanxue_node2 ~]# iptables -F +[root@zutuanxue_node2 ~]# iptables -L -n +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Dockerfile.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Dockerfile.md" new file mode 100644 index 0000000..b17e7e2 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Dockerfile.md" @@ -0,0 +1,383 @@ +## 一、什么是镜像? + +镜像可以看成是由多个镜像层叠加起来的一个文件系统(通过UnionFS与AUFS文件联合系统实现),镜像层也可以简单理解为一个基本的镜像,而每个镜像层之间通过指针的形式进行叠加。 + +![1.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/29/1601374665130.png) + +![2.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/29/1601374678766.png) + +根据上图,镜像层的主要组成部分包括镜像层 ID、镜像层指针 「指向父层」、元数据「 Layer Metadata,包含了 Docker 构建和运行的信息和父层的层次信息」。只读层和读写层「Top Layer」的组成部分基本一致,同时读写层可以转换成只读层「 通过docker commit 操作实现」。 + +元数据(metadata)就是关于这个层的额外信息,它不仅能够让Docker获取运行和构建时的信息,还包括父层的层次信息。需要注意,只读层和读写层都包含元数据。 + +![3.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/29/1601374695966.png) + +每一层都包括了一个指向父层的指针。如果一个层没有这个指针,说明它处于最底层。 + +![4.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/29/1601374711947.png) + +在docker主机中镜像层(image layer)的元数据被保存在名为”json”的文件中,一个容器的元数据好像是被分成了很多文件,但或多或少能够在/var/lib/docker/containers/目录下找到,就是一个可读层的id。这个目录下的文件大多是运行时的数据,比如说网络,日志等等。 + +镜像是一堆只读层的统一视角,除了最底层没有指向外,每一层都指向它的父层。统一文件系统( Union File System)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在。在用户的角度看来,只存在一个文件系统。镜像每一层都是不可写的,都是只读层。 + +![5.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/29/1601374727228.png) + +我们可以看到镜像包含多个只读层,它们重叠在一起。除了最下面一层,其它层都会有一个指针指向下一层。这些层是Docker内部的实现细节,并且能够在docker主机的文件系统上访问到。统一文件系统(union file system,升级版为AUFS)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。 + +## 二、什么是Dockerfile + +Dockerfile 是由一系列命令和参数构成的脚本,这些命令应用于基础镜像并最终创建一个新的镜像。它们简化了从头到尾的流程并极大的简化了部署工作。Dockerfile 从 FROM 命令开始,紧接着跟随着各种方法,命令和参数。其产出为一个新的可以用于创建容器的镜像。 + +Dockerfile 语法由两部分构成,注释和命令+参数,注释是不能少的,因为明天可能就忘记写的是什么了。说白了, Dockerfile 是告诉 docker 怎么样制作一个镜像,就像我们写代码告诉应用怎么执行一条逻辑,这样应该好理解了,所以可以在 Dockerfile 中写明,我们需要怎么个执行方式的某个镜像,最后执行 docker build 命令构建写好的Dockerfile 成镜像。 + +## 三、 Dockerfile基础命令 + +### 3.1、 FROM: + +功能为指定基础镜像,并且必须是第一条指令。 + +如果不以任何镜像为基础,写法为:FROM scratch。 + +同时意味着接下来所写的指令将作为镜像的第一层开始 + +语法: + +FROM ![img]() + +FROM ![img](): + +其中 是可选项,如果没有选择,那么默认值为latest + +### 3.2、 MAINTAINER + +指定作者 + +语法: + +MAINTAINER + +### 3.3、 LABEL + +功能是为镜像指定标签 + +语法: + +LABEL = = = … + +一个Dockerfile种可以有多个LABEL,如下: + +``` +LABEL "com.example.vendor"="ACME Incorporated" + +LABEL com.example.label-with-value="foo" + +LABEL version="1.0" + +LABEL description="This text illustrates \ +that label-values can span multiple lines." + +但是并不建议这样写,最好就写成一行,如太长需要换行的话则使用\符号 + +如下: + +LABEL multi.label1="value1" \ +multi.label2="value2" \ +other="value3" + +注意:LABEL会继承基础镜像种的LABEL,如遇到key相同,则值覆盖 +``` + +### 3.4、 RUN + +功能为运行指定的命令 + +RUN命令有两种格式 + +RUN + +RUN [“executable”, “param1”, “param2”] + +第一种后边直接跟shell命令 + +在linux操作系统上默认 /bin/sh -c + +第二种是类似于函数调用。 + +可将executable理解成为可执行文件,后面就是两个参数。 + +两种写法比对: + +RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME + +RUN ["/bin/bash", “-c”, “echo hello”] + +注意:多行命令不要写多个RUN,原因是Dockerfile中每一个指令都会建立一层. RUN书写时的换行符是 \ 多少个RUN就构建了多少层镜像,会造成镜像的臃肿、多层,不仅仅增加了构件部署的时间,还容易出错。 + +### 3.5、 ADD + +一个复制命令,把文件复制到镜像中 + +如果把虚拟机与容器想象成两台linux服务器的话,那么这个命令就类似于scp,只是scp需要加用户名和密码的权限验证,而ADD不用 + +``` +语法如下: + +ADD ... + +可以是一个本地文件或者是一个本地压缩文件,还可以是一个url +路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径 + +ADD test1.txt test1.txt + +ADD test1.txt test1.txt.bak + +ADD test1.txt /mydir/ + +ADD data1 data1 + +ADD zip.tar /myzip + +有如下注意事项: + +1、如果源路径是个文件,且目标路径是以 / 结尾, 则docker会把目标路径当作一个目录,会把源文件拷贝到该目录下。如果目标路径不存在,则会自动创建目标路径。 + +2、如果源路径是个文件,且目标路径不是以 / 结尾,则docker会把目标路径当作一个文件。 + +3、如果目标路径不存在,会以目标路径为名创建一个文件,内容同源文件; + +4、如果目标文件是个存在的文件,会用源文件覆盖它,当然只是内容覆盖,文件名还是目标文件名。 + +5、如果目标文件实际是个存在的目录,则会源文件拷贝到该目录下。 注意,这种情况下,最好显示的以 / 结尾,以避免混淆。 + +6、如果源路径是个目录,且目标路径不存在,则docker会自动以目标路径创建一个目录,把源路径目录下的文件拷贝进来。如果目标路径是个已经存在的目录,则docker会把源路径目录下的文件拷贝到该目录下。 + +7、如果源文件是个归档文件(压缩文件),则docker会自动帮解压。尽量不要把写成一个文件夹,如果是一个文件夹了,复制整个目录的内容,包括文件系统元数据 +``` + +### 3.6、COPY + +复制命令 + +语法如下: + +COPY … + +COPY ["",… “”] + +与ADD的区别, COPY的只能是本地文件,其他用法一致 + +### 3.7、 VOLUME + +可实现挂载功能,可以将内地文件夹或者其他容器种得文件夹挂在到这个容器种 + +语法为: + +VOLUME ["/data"] + +说明: + +["/data"]可以是一个JsonArray ,也可以是多个值。所以如下几种写法都是正确的 + +VOLUME ["/var/log/"] + +VOLUME /var/log + +VOLUME /var/log /var/db + +一般的使用场景为需要持久化存储数据时, 容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失,所以当数据需要持久化时用这个命令。 + +### 3.8、 EXPOSE + +功能为暴漏容器运行时的监听端口给外部 + +但是EXPOSE并不会使容器访问主机的端口 + +如果想使得容器与主机的端口有映射关系,必须在容器启动的时候加上 -P参数 + +### 3.9、 WORKDIR + +设置工作目录 + +语法: + +WORKDIR /usr/bin/ + +### 3.10、 ENV + +功能为设置环境变量 + +语法有两种 + +ENV + +ENV = … + +两者的区别就是第一种是一次设置一个,第二种是一次设置多个 + +### 3.11、 CMD + +功能为容器启动时要运行的命令 + +语法有三种写法 + +CMD [“executable”,“param1”,“param2”] + +CMD [“param1”,“param2”] + +CMD command param1 param2 + +第三种比较好理解了,就时shell这种执行方式和写法 + +第一种和第二种其实都是可执行文件加上参数的形式 + +举例说明两种写法: + +CMD [ “sh”, “-c”, “echo $HOME” + +CMD [ “echo”, “$HOME” ] + +注意: + +1、这里边包括参数的一定要用双引号,就是 " 不能是单引号, 原因是参数传递后,docker解析的是一个JSON Array + +2、不要把RUN和CMD搞混了。 + +RUN:是构件容器时就运行的命令以及提交运行结果 + +CMD:是容器启动时执行的命令,在构件时并不运行 + +### 3.12、 ENTRYPOINT + +功能是启动时的默认命令 + +语法如下: + +ENTRYPOINT [“executable”, “param1”, “param2”] + +ENTRYPOINT command param1 param2 + +如果从上到下看到这里的话,那么你应该对这两种语法很熟悉啦。 + +第一种就是可执行文件加参数 + +第二种就是写shell + +``` +与 CMD 比较说明: + +相同点: + +只能写一条,如果写了多条,那么只有最后一条生效,容器启动时才运行,运行时机相同 + +不同点: + +ENTRYPOINT 不会被运行的 command 覆盖,而 CMD 则会被覆盖 + + +如果我们在 Dockerfile 时同时写了 ENTRYPOINT 和 CMD ,并且 CMD 指令不是一个完整的可执行命令,那么CMD 指定的内容将会作为 ENTRYPOINT 的参数, 如下: + +FROM centos +ENTRYPOINT ["top", "-b"] +CMD ["-c"] + + + +如果我们在 Dockerfile 种同时写了 ENTRYPOINT 和 CMD ,并且 CMD 是一个完整的指令,那么它们两个会互相覆盖,谁在最后谁生效, 如下: + +FROM centos +ENTRYPOINT ["top", "-b"] +CMD ls -al + +那么将执行 ls -al , top -b 不会执行 +``` + +## 四、 Dockerfile 案例 + +``` +1、创建目录,用于存放 dockerfile 所使用的文件 +2、在此目录中创建 dockerfile 文件 +3、在此目录中使用 docker build 创建镜像 +4、使用创建的镜像启动容器 + +准备启动文件: +vim httpd-run.sh +#!/bash +rm -rf /run/httpd/* +exec /usr/sbin/httpd -D FOREGROUND + +准备网页测试文件 +vim index.html +hello welcome to zutuanxue!!! + +准备 dockerfile 文件 + +FROM centos:latest + +MAINTAINER "zutuanxue admin@163.com" + +ADD httpd-run.sh /httpd-run.sh + +ADD index.html /var/www/html/index.html + +RUN yum -y install httpd && chmod -v +x /httpd-run.sh + +EXPOSE 80 + +WORKDIR / + +CMD ["/bin/bash","/httpd-run.sh"] + +创建镜像: +docker build -t centos-httpd:v1 . + + -t: 镜像的名字及标签,通常 name:tag 或者 name 格式 +#定义基础镜像 FROM +FROM centos +#定义作者 MAINTAINER +MAINTAINER BaiShuming + +#上传文件到容器 COPY or ADD +#COPY 从当前目录复制文件到容器. 只是单纯地复制文件. 格式为 COPY 。 +#ADD 从当前目录复制文件到容器. 会自动处理目录, 压缩包等情况.格式为 ADD 。 +ADD nginx-1.17.6.tar.gz /root + + +#生成镜像时运行的命令 RUN +#shell 写法 +RUN yum -y install pcre-devel zlib-devel openssl lsof iproute net-tools gcc make +#exec写法 +#["命令","命令选项","参数"] + + +#解压压缩文件 +#RUN ["tar","xf","nginx-1.17.6.tar.gz"] + +#创建管理用户www +RUN useradd -r -s/sbin/nologin -M www + +#进入nginx源码文件WORKDIR +WORKDIR /root/nginx-1.17.6 + +#安装nginx +RUN ./configure --prefix=/usr/local/nginx --user=www --group=www && make && make install + +#定义变量 ENV +ENV PATH /usr/local/nginx/sbin:$PATH + +#业务初始化 +#COPY 从当前目录复制文件到容器. 只是单纯地复制文件. 格式为 COPY 。 +COPY nginx.conf /usr/local/nginx/conf +COPY index.html /usr/local/nginx/html + +#输出端口 EXPOSE +EXPOSE 80 + +#挂载本地目录VOLUME +#创建一个可以从本地主机或其他容器挂载的挂载点 +#一般用来存放数据库和需要保持同步的数据 +VOLUME ["/data"] + +#容器启动后执行的命令 CMD +#只能执行一个,如果有多个,同一时间只有最后一个生效 +CMD ["nginx","-g","daemon off;"] +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\345\256\211\350\243\205.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\345\256\211\350\243\205.md" new file mode 100644 index 0000000..b6a7f50 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\345\256\211\350\243\205.md" @@ -0,0 +1,128 @@ +# 一、docker安装 + +Docker 是管理容器的工具, Docker 不等于 容器。 + +### 1.1、docker yum源设置 + +``` +#step 1 download docker-ce.repo file + +[root@zutuanxue ~]# wget https://download.docker.com/linux/centos/docker-ce.repo -P /etc/yum.repos.d/ + +--2019-11-14 20:46:09-- https://download.docker.com/linux/centos/docker-ce.repo +正在解析主机 download.docker.com (download.docker.com)... 13.35.50.117, 13.35.50.10, 13.35.50.93, ... +正在连接 download.docker.com (download.docker.com)|13.35.50.117|:443... 已连接。 +已发出 HTTP 请求,正在等待回应... 200 OK +长度:2424 (2.4K) [binary/octet-stream] +正在保存至: “/etc/yum.repos.d/docker-ce.repo.1” + +100%[==================================================>] 2,424 --.-K/s 用时 0s + +2019-11-14 20:46:09 (210 MB/s) - 已保存 “/etc/yum.repos.d/docker-ce.repo.1” [2424/2424]) + +#step 2 change docker yum repo from tsinghua web + +[root@zutuanxue ~]# sed -i 's#download.docker.com#mirrors.tuna.tsinghua.edu.cn/docker-ce#g' /etc/yum.repos.d/docker-ce.repo +``` + +### 1.2、docker 安装 + +#### 1.2.1、卸载旧版本 + +``` +[root@zutuanxue ~]# yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine +``` + +#### 1.2.2、安装docker + +``` +[root@zutuanxue ~]# yum -y install https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm + +[root@zutuanxue ~]# yum -y install docker-ce +``` + +#### 1.2.3、启动docker + +``` +[root@zutuanxue ~]# systemctl enable docker + +Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service. + +[root@zutuanxue ~]# systemctl start docker +``` + +### 1.3、验证启动 + +``` +[root@zutuanxue ~]# systemctl status docker +● docker.service - Docker Application Container Engine + Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled) + Active: active (running) since 四 2019-11-14 20:53:12 EST; 14s ago + Docs: https://docs.docker.com + Main PID: 1584 (dockerd) + Tasks: 12 + Memory: 60.7M + CGroup: /system.slice/docker.service + └─1584 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock + +11月 14 20:53:12 zutuanxue dockerd[1584]: time="2019-11-14T20:53:12.366007531-05:00" level=info msg="scheme \"unix\" not registered, fallback to defau...odule=grpc +11月 14 20:53:12 zutuanxue dockerd[1584]: time="2019-11-14T20:53:12.366028377-05:00" level=info msg="ccResolverWrapper: sending update to cc: {[{unix:...odule=grpc +11月 14 20:53:12 zutuanxue dockerd[1584]: time="2019-11-14T20:53:12.366036593-05:00" level=info msg="ClientConn switching balancer to \"pick_first\"" module=grpc +11月 14 20:53:12 zutuanxue dockerd[1584]: time="2019-11-14T20:53:12.404043665-05:00" level=info msg="Loading containers: start." +11月 14 20:53:12 zutuanxue dockerd[1584]: time="2019-11-14T20:53:12.547472878-05:00" level=info msg="Default bridge (docker0) is assigned with an IP a...P address" +11月 14 20:53:12 zutuanxue dockerd[1584]: time="2019-11-14T20:53:12.588359436-05:00" level=info msg="Loading containers: done." +11月 14 20:53:12 zutuanxue dockerd[1584]: time="2019-11-14T20:53:12.733704268-05:00" level=info msg="Docker daemon" commit=a872fc2f86 graphdriver(s)=o...on=19.03.3 +11月 14 20:53:12 zutuanxue dockerd[1584]: time="2019-11-14T20:53:12.733826656-05:00" level=info msg="Daemon has completed initialization" +11月 14 20:53:12 zutuanxue systemd[1]: Started Docker Application Container Engine. +11月 14 20:53:12 zutuanxue dockerd[1584]: time="2019-11-14T20:53:12.753929596-05:00" level=info msg="API listen on /var/run/docker.sock" +Hint: Some lines were ellipsized, use -l to show in full. +``` + +### 1.4、验证版本 + +``` +[root@zutuanxue ~]# docker -v + +Docker version 19.03.1, build 74b1e89 +``` + +# 二、docker client 和 daemon分离 + +### docker client 与 daemon分离 + +``` +1、关闭docker + +[root@zutuanxue ~]# systemctl stop docker + +2、修改docker启动方式,要求加载配置文件启动 + +[root@zutuanxue ~]# sed -i.bak '/^ExecStart=/c\ExecStart=\/usr\/bin\/dockerd' /usr/lib/systemd/system/docker.service + +3、设置docker配置文件,默认没有 + +设置允许监听地址和端口,以及sock文件连接 + +默认是使用sock方式连接,加tcp://0.0.0.0:2375可实现远程管理 + +[root@zutuanxue ~]# cat /etc/docker/daemon.json +{ + "hosts": ["tcp://0.0.0.0:2375","unix:///var/run/docker.sock"] +} + +4、重载docker服务、重启docker生效配置 + +[root@zutuanxue ~]# systemctl daemon-reload + +[root@zutuanxue ~]# systemctl restart docker + +5、查看docker的监听地址和端口 + +[root@zutuanxue ~]# netstat -ntpl |grep 2375 + +tcp6 0 0 :::2375 :::* LISTEN 21219/dockerd + +6、客户端连接docker daemon,执行命令 + +[root@zutuanxue ~]# docker -H 192.168.98.240 images +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\345\256\271\345\231\250\347\256\241\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\345\256\271\345\231\250\347\256\241\347\220\206.md" new file mode 100644 index 0000000..9e54e53 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\345\256\271\345\231\250\347\256\241\347\220\206.md" @@ -0,0 +1,352 @@ +# 一、docker容器管理 + +### 1.1 容器查看-ps命令 + +显示本地容器列表,但是默认不显示关闭的容器,只显示运行中的容器,除非加上命令选项 -a + +用法: +**docker ps [-a 显示所有容器,默认只显示运行的]** + +``` +root@zutuanxue ~]# docker ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +8f4c3f823843 centos "/bin/bash" 3 seconds ago Exited(0) 3 seconds ago centos7_6 +``` + +### 1.2、容器详细信息-inspect命令 + +显示容器的详细信息 + +用法: +**docker inspect [容器名称或者ID]** + +``` +[root@zutuanxue ~]# docker inspect centos +[ + { + "Id": "sha256:0f3e07c0138fbe05abcb7a9cc7d63d9bd4c980c3f61fea5efa32e7c4217ef4da", + "RepoTags": [ + "centos:latest", + "zutuanxue_centos:v1" + ], + "RepoDigests": [], + "Parent": "", + "Comment": "", + "Created": "2019-10-01T23:19:57.105928163Z", + "Container": "711572e3c0c1ac06d5c13c4e668ec170b8ad8786b5f0949f884a5f7fd350d856", + "ContainerConfig": { + "Hostname": "711572e3c0c1", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "Cmd": [ + "/bin/sh", + "-c", + "#(nop) ", + "CMD [\"/bin/bash\"]" + ], + "ArgsEscaped": true, + "Image": "sha256:c0bda62fdbad65a3c6a1843d293a3a47d8233115cc6d384e3cb07c53580a2b43", + "Volumes": null, + "WorkingDir": "", + "Entrypoint": null, + "OnBuild": null, + "Labels": { + "org.label-schema.build-date": "20190927", + "org.label-schema.license": "GPLv2", + "org.label-schema.name": "CentOS Base Image", + "org.label-schema.schema-version": "1.0", + "org.label-schema.vendor": "CentOS" + } + }, + "DockerVersion": "18.06.1-ce", + "Author": "", + "Config": { + "Hostname": "", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "Cmd": [ + "/bin/bash" + ], + "ArgsEscaped": true, + "Image": "sha256:c0bda62fdbad65a3c6a1843d293a3a47d8233115cc6d384e3cb07c53580a2b43", + "Volumes": null, + "WorkingDir": "", + "Entrypoint": null, + "OnBuild": null, + "Labels": { + "org.label-schema.build-date": "20190927", + "org.label-schema.license": "GPLv2", + "org.label-schema.name": "CentOS Base Image", + "org.label-schema.schema-version": "1.0", + "org.label-schema.vendor": "CentOS" + } + }, + "Architecture": "amd64", + "Os": "linux", + "Size": 219583055, + "VirtualSize": 219583055, + "GraphDriver": { + "Data": { + "MergedDir": "/var/lib/docker/overlay2/7e9695593c24efc2b9e7cbe8ee2ce7c299e8cde85d73668b94f91284554d3e57/merged", + "UpperDir": "/var/lib/docker/overlay2/7e9695593c24efc2b9e7cbe8ee2ce7c299e8cde85d73668b94f91284554d3e57/diff", + "WorkDir": "/var/lib/docker/overlay2/7e9695593c24efc2b9e7cbe8ee2ce7c299e8cde85d73668b94f91284554d3e57/work" + }, + "Name": "overlay2" + }, + "RootFS": { + "Type": "layers", + "Layers": [ + "sha256:9e607bb861a7d58bece26dd2c02874beedd6a097c1b6eca5255d5eb0d2236983" + ] + }, + "Metadata": { + "LastTagTime": "2019-11-15T05:18:05.72378385-05:00" + } + } +] +``` + +### 1.3、容器创建-run命令 + +容器创建命令 + +用法: +**docker run [options] 镜像名称** + +``` +#后台执行容器 + +[root@zutuanxue ~]# docker run -d --name centos7_6 centos + +#前台执行的容器 + +[root@zutuanxue ~]# docker run -it --name centos7_5 centos /bin/bash + +[root@5a1f02b4041c /]# + +-i 交互式创建 +-t 创建一个伪终端 +-d 后台执行 +--name 容器名称 +/bin/bash 在伪终端中执行的命令 +``` + +### 1.4、容器删除-rm命令 + +删除一个本地容器 + +用法: +**docker rm [容器名称或者ID] [–force]** + +``` +[root@zutuanxue ~]# docker rm centos7_5 +centos7_5 + +默认删除的容器必须是关闭状态,建议如果希望删除一个运行的容器,可以先关闭在删除。 +当然也可以在后面直接加上--force 强制删除一个运行中的容器 +``` + +### 1.5、容器执行命令-exec命令 + +在运行容器中执行一个命令,如果想在容器中执行一个命令,那么这个exec命令就很有用了。 + +用法: +**docker exec [容器名称或者ID] 命令** + +``` +[root@zutuanxue ~]# docker exec centos7_6 ls / +bin +dev +etc +home +lib +lib64 +lost+found +media +mnt +opt +proc +root +run +sbin +srv +sys +tmp +usr +var +``` + +### 1.6、容器信息输出-attach命令 + +将一个运行容器的标准输出、错误输出、标准输入调入前台 +默认容器都会在后台运行,如果你想进入容器内,就可以使用该命令。这样你就可以交互式的在容器中执行命令了。 + +用法: +**docker attach [容器名称或者ID]** + +``` +[root@zutuanxue ~]# docker attach centos7_6 + +[root@128dc0ffc489 /]# +``` + +### 1.7、容器启动-start命令 + +启动一个容器 + +用法: +**docker start [容器名称或者ID]** + +``` +[root@zutuanxue ~]# docker start centos7_6 +centos7_6 +``` + +### 1.8、停止一个容器-stop命令 + +关闭一个容器 + +用法: +**docker stop [容器名称或者ID]** + +``` +[root@zutuanxue ~]# docker stop centos7_6 +centos7_6 +``` + +### 1.9、重启一个容器-restart命令 + +重启一个容器 + +用法: +**docker restart [容器名称或者ID]** + +``` +[root@zutuanxue ~]# docker restart centos7_6 +centos7_6 +``` + +### 1.10、容器挂起-pause命令 + +挂起运行中的容器 + +用法: +**docker pause [容器名称或者ID]** + +``` +[root@zutuanxue ~]# docker pause centos7_6 + +centos7_6 + +[root@zutuanxue ~]# docker ps + +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +128dc0ffc489 centos "/bin/bash" 19 minutes ago Up 14 minutes (Paused) centos7_6 +``` + +### 1.11、容器恢复-unpause命令 + +恢复挂起容器 + +用法: +**docker unpause [容器名称或者ID]** + +``` +[root@zutuanxue ~]# docker unpause centos7_6 +centos7_6 +``` + +### 1.12、容器重命名-rename命令 + +重命名容器 + +用法: +**docker rename 容器名称 容器新名称** + +``` +[root@zutuanxue ~]# docker rename centos7_6 centos76 +``` + +### 1.13、容器端口映射信息-port命令 + +显示容器与宿主机的端口隐射信息 + +用法: +**docker port [容器名称或者ID]** + +``` +[root@zutuanxue ~]# docker port 32fd02f05446 +5000/tcp -> 0.0.0.0:5000 + +容器的TCP 5000端口与宿主机的所有IP的5000端口绑定 +``` + +### 1.14、杀死一个或多个容器-kill命令 + +杀死运行的容器 + +用法: +**docker kill [镜像名称或者ID]** + +``` +[root@zutuanxue ~]# docker kill centos76 +centos76 +``` + +### 1.15、容器导出-export命令 + +将一个容器导出一个镜像为压缩文件 + +用法: +**docker export -o 导出后镜像文件名 [容器名称或者ID]** + +``` +[root@zutuanxue ~]# docker export -o zutuanxue_centos.tar centos76 + +[root@zutuanxue ~]# ls + +anaconda-ks.cfg centos_base.tar Docker zutuanxue_centos.tar +``` + +### 1.16、容器镜像导入到镜像库-import命令 + +将容器镜像导入到镜像库 + +用法: +**docker import 镜像文件名 镜像名:tag** + +``` +[root@zutuanxue ~]# docker import zutuanxue_centos.tar zutuanxue/centos7_6:latest +sha256:659fb2fca656430822627685ba4f29d09ae619cd9f2b42ef52d47003c8af8d11 +``` + +### 1.17、将容器生成镜像-commit命令 + +将改变后的容器直接变成镜像,一般指的是封装好业务的容器,直接封装成镜像 + +用法: +**docker commit [容器名称或者ID] 导出后镜像的名字:tag** + +``` +[root@zutuanxue ~]# docker commit centos76 zutuanxue/centos_7_6:v1 + +sha256:1f078c1d94dd641c65495bd91d3e471593c5ec60ecbb4492cfa18a161448dd3a +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\347\232\204\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\347\232\204\344\273\213\347\273\215.md" new file mode 100644 index 0000000..b929238 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\347\232\204\344\273\213\347\273\215.md" @@ -0,0 +1,159 @@ +# 一、虚拟化和容器 + +### 虚拟化介绍 + +操作系统层虚拟化是指通过划分一个宿主操作系统的特定部分,产生一个个隔离的操作执行环境。操作系统层的虚拟化是操作系统内核直接提供的虚拟化,虚拟出的操作系统之间共享底层宿主操作系统内核和底层的硬件资源。操作系统虚拟化的关键点在于将操作系统与上层应用隔离开,将对操作系统资源的访问进行虚报化,使上层应用觉得自己独占操作系统。 + +操作系统虚拟化的好处是实现了虚拟操作系统与物理操作系统的隔离并且有效避免物理操作系统的重复安装。比较有名的操作系统虚报化解决方案有Virtual Server、Zone、Virtuozzo 及虚拟专用服务器(Vital Pnvate Sever,VPS)。VPS是利用虚拟服务器软件在一台物理机上创建多个相互隔离的小服务器。这些小服务器本身就有自己的操作系统,其运行和管理与独立主机完全相。其可以保证用户独享资源,且可以节约成本。 + +### 虚拟化分类 + +1. 仿真虚拟化 [对系统硬件没有要求,性能最低] VMware +2. 半虚拟化 [虚拟机可以使用真机物理硬件,性能高,需要改内核] xen +3. 硬件辅助虚拟化 vmware kvm + - 需要硬件支持 【cpu 主板】 + - 不需要改内核 + - 可以直接使用真机硬件,性能最贴近宿主机 +4. 容器虚拟化 lxc docker + +### 主机虚拟化和容器虚拟化特点 + +##### 主机虚拟化 + +![vmachines.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/29/1601365927074.png) + +- 应用程序运行环境强隔离 +- 虚拟机操作系统与底层操作系统无关化 +- 虚拟机内部操作不会影响到物理机 +- 拥有操作系统会占用部署资源及存储 +- 网络传输效率低 +- 当应用程序需要调用硬件响应用户访问时间延迟大 + +##### 容器虚拟化 + +![container_virtual.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/29/1601365914972.png) + +- 可以实现应用程序的隔离 +- 直接使用物理机的操作系统可以快速响应用户请求 +- 不占用部署时间 +- 占用少量磁盘空间 + +容器虚拟化缺点:学习成本增加、操作控制麻烦、网络控制与主机虚拟化有所区别、服务治理。 + +### 容器的发展 + +- LXC + - 2008 + - 是第一套完整的容器管理解决方案 + - 不需要任何补丁直接运行在linux内核之上管理容器 + - 创建容器慢,不方便移置 +- Docker + - 2013 + - dotcloud + - 是在LXC基础上发展起来的 + - 拥有一套容器管理生态系统 + - 生态系统包含:容器镜像、注册表、RESTFul API及命令行操作界面 + - 属于容器管理系统 + +### Docker版本介绍 + +- 2017之前版本 + - 1.7 ,1.8,1.9,1.10,1.11,1.12,1.13 +- 2017年3月1日后 + - 把docker做商业开源 + - docker-ce + - docker-ee + - 17-03-ce + - 17-06-ce + - 18-03-ce + - 18-06-ce + - 18-09-ce + - 19.03-ce + +# 二、docker介绍 + +![docker.jpeg](https://www.zutuanxue.com:8000/static/media/images/2020/9/29/1601366234542.jpeg) + +Docker 是一个开源项目,诞生于 2013 年初,最初是 dotCloud 公司内部的一个业余项目。它基于 Google 公司推出的 Go 语言实现。 项目后来加入了 Linux 基金会,遵从了 Apache 2.0 协议,项目代码在 [GitHub](https://github.com/docker/docker) 上进行维护。 + +Docker 自开源后受到广泛的关注和讨论,以至于 dotCloud 公司后来都改名为 Docker Inc。Redhat 已经在其 RHEL6.5 中集中支持 Docker;Google 也在其 PaaS 产品中广泛应用。 + +Docker 项目的目标是实现轻量级的操作系统虚拟化解决方案。 Docker 的基础是 Linux 容器(LXC)等技术。 + +在 LXC 的基础上 Docker 进行了进一步的封装,让用户不需要去关心容器的管理,使得操作更为简便。用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单。 + +### 为什么要用 Docker + +作为一种新兴的虚拟化方式,Docker 跟传统的虚拟化方式相比具有众多的优势。 + +首先,Docker 容器的启动可以在秒级实现,这相比传统的虚拟机方式要快得多。 其次,Docker 对系统资源的利用率很高,一台主机上可以同时运行数千个 Docker 容器。 + +容器除了运行其中应用外,基本不消耗额外的系统资源,使得应用的性能很高,同时系统的开销尽量小。传统虚拟机方式运行 10 个不同的应用就要起 10 个虚拟机,而Docker 只需要启动 10 个隔离的应用即可。 + +具体说来,Docker 在如下几个方面具有较大的优势。 + +### 更快速的交付和部署 + +对开发和运维(devop)人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。开发者可以使用一个标准的镜像来构建一套开发容器,开发完成之后,运维人员可以直接使用这个容器来部署代码。 Docker 可以快速创建容器,快速迭代应用程序,并让整个过程全程可见,使团队中的其他成员更容易理解应用程序是如何创建和工作的。 Docker 容器很轻很快!容器的启动时间是秒级的,大量地节约开发、测试、部署的时间。 + +### 更高效的虚拟化 + +Docker 容器的运行不需要额外的 hypervisor 支持,它是内核级的虚拟化,因此可以实现更高的性能和效率。 + +### 更轻松的迁移和扩展 + +Docker 容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等。 这种兼容性可以让用户把一个应用程序从一个平台直接迁移到另外一个。 + +### 更简单的管理 + +使用 Docker,只需要小小的修改,就可以替代以往大量的更新工作。所有的修改都以增量的方式被分发和更新,从而实现自动化并且高效的管理。 + +### 对比传统虚拟机总结 + +| 特性 | 容器 | 虚拟机 | +| ---------- | ------------------ | ---------- | +| 启动 | 秒级 | 分钟级 | +| 硬盘使用 | 一般为 MB | 一般为 GB | +| 性能 | 接近原生 | 弱于 | +| 系统支持量 | 单机支持上千个容器 | 一般几十个 | + +### Docker基本架构 + +Docker 采用了 C/S架构,包括客户端和服务端。 Docker daemon 作为服务端接受来自客户的请求,并处理这些请求(创建、运行、分发容器)。 客户端和服务端既可以运行在一个机器上,也可通过 socket 或者 RESTful API 来进行通信。 + +![docker基本架构.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/29/1601366475829.png) + +docker daemon 一般在宿主主机后台运行,等待接收来自客户端的消息。 Docker 客户端则为用户提供一系列可执行命令,用户用这些命令实现跟 Docker daemon 交互。 + +**容器 — 镜像 — 仓库 — daemon — client 之间的关系** +![clientdaemon.jpg](https://www.zutuanxue.com:8000/static/media/images/2020/9/29/1601366499592.jpg) + +# 三、 Docker的名字空间 + +名字空间是 Linux 内核一个强大的特性。每个容器都有自己单独的名字空间,运行在其中的应用都像是在独立的操作系统中运行一样。名字空间保证了容器之间彼此互不影响。 + +![namespace.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/29/1601366525883.png) + +#### pid 名字空间 + + 不同用户的进程就是通过 pid 名字空间隔离开的,且不同名字空间中可以有相同 pid。所有的 LXC 进程在 Docker 中的父进程为Docker进程,每个 LXC 进程具有不同的名字空间。同时由于允许嵌套,因此可以很方便的实现嵌套的 Docker 容器。 + +#### net 名字空间 + + 有了 pid 名字空间, 每个名字空间中的 pid 能够相互隔离,但是网络端口还是共享 host 的端口。网络隔离是通过 net 名字空间实现的, 每个 net 名字空间有独立的 网络设备, IP 地址, 路由表, /proc/net 目录。这样每个容器的网络就能隔离开来。Docker 默认采用 veth 的方式,将容器中的虚拟网卡同 host 上的一 个Docker 网桥 docker0 连接在一起。 + +#### ipc 名字空间 + + 容器中进程交互还是采用了 Linux 常见的进程间交互方法(interprocess communication - IPC), 包括信号量、消息队列和共享内存等。然而同 VM 不同的是,容器的进程间交互实际上还是 host 上具有相同 pid 名字空间中的进程间交互,因此需要在 IPC 资源申请时加入名字空间信息,每个 IPC 资源有一个唯一的 32 位 id。 + +#### mnt 名字空间 + + 类似 chroot,将一个进程放到一个特定的目录执行。mnt 名字空间允许不同名字空间的进程看到的文件结构不同,这样每个名字空间 中的进程所看到的文件目录就被隔离开了。同 chroot 不同,每个名字空间中的容器在 /proc/mounts 的信息只包含所在名字空间的 mount point。 + +#### uts 名字空间 + + UTS(“UNIX Time-sharing System”) 名字空间允许每个容器拥有独立的 hostname 和 domain name, 使其在网络上可以被视作一个独立的节点而非 主机上的一个进程。 + +#### user 名字空间 + + 每个容器可以有不同的用户和组 id, 也就是说可以在容器内用容器内部的用户执行程序而非主机上的用户。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\351\225\234\345\203\217\347\247\201\346\234\211\344\273\223\345\272\223.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\351\225\234\345\203\217\347\247\201\346\234\211\344\273\223\345\272\223.md" new file mode 100644 index 0000000..7c5e6ec --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\351\225\234\345\203\217\347\247\201\346\234\211\344\273\223\345\272\223.md" @@ -0,0 +1,514 @@ +在Docker中,当我们执行 docker pull xxx 的时候 ,它实际上是从 hub.docker.com 这个地址去查找,这就是 Docker 公司为我们提供的公共仓库。在工作中,我们不可能把企业项目 push 到公有仓库进行管理。所以为了更好的管理镜像,Docker 不仅提供了一个中央仓库,同时也允许我们搭建本地私有仓库。 + +docker容器镜像仓库分类: + +- 公网仓库:docker hub +- 私网仓库: registry、harbor + +## 一、registry镜像仓库 + +### 1.1、 registry 仓库搭建 + +**搭建步骤** + +- 拉取 registry 容器镜像 +- 创建 registry 仓库容器 +- 测试容器应用 + +**搭建过程** +a、拉取registry容器镜像 + +``` +docker pull registry +``` + +b、创建registry仓库容器 + +``` +1、创建持久化存储,将容器镜像存储目录/var/lib/registry挂载到本地/opt/myregistry下: + +mkdir /opt/myregistry + +2、创建 registry 容器: + +docker run -d -p 5000:5000 -v /opt/myregistry:/var/lib/registry --restart=always registry:latest + +3、查看容器是否运行 + +docker ps + +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +6b20b55fe6f8 registry:latest "/entrypoint.sh /etc…" 2 minutes ago Up 2 minutes 0.0.0.0:5000->5000/tcp busy_mclean +``` + +c、测试容器应用 + +``` +[root@zutuanxue_manage01 ~]# curl http://192.168.1.150:5000/v2/_catalog +{"repositories":[]} + +显示仓库中没有任何镜像 +``` + +### 1.2、registry仓库应用-上传镜像 + +**上传镜像步骤** + +- 设置docker仓库为registry本地仓库 +- 给需要存储的镜像打tag +- 上传镜像到registry仓库 + +**演示案例** + +**将baishuming2020/centos_nginx:latest上传到仓库** + +**查看当前本地镜像** + +``` +[root@zutuanxue_manage01 ~]# docker images +REPOSITORY TAG IMAGE ID CREATED SIZE +baishuming2020/centos_nginx latest bcd9f28f6126 33 minutes ago 447MB +baishuming2020/centos_8_base latest 3e9f682f8459 47 minutes ago 200MB +centos latest 0f3e07c0138f 6 weeks ago 220MB +registry latest f32a97de94e1 8 months ago 25.8MB +``` + +a、设置docker仓库为registry本地仓库 + +``` +#1、修改docker进程启动文件,修改其启动方式,目的是为了让通过docker配置文件启动 +[root@zutuanxue_manage01 ~]# sed -i.bak '/^ExecStart=/c\ExecStart=\/usr\/bin\/dockerd' /usr/lib/systemd/system/docker.service + +#2、设置docker 守护进程的配置文件 /etc/docker/daemon.json,默认没有该文件 +[root@zutuanxue_manage01 ~]# cat /etc/docker/daemon.json +{ + "insecure-registries": ["http://192.168.1.150:5000"] +} + +insecure-registries 指定非安全的仓库地址,多个用逗号隔开 + +#3、重启docker生效配置文件 +[root@zutuanxue_manage01 ~]# systemctl daemon-reload +[root@zutuanxue_manage01 ~]# systemctl restart docker +``` + +b、给需要存储的镜像打tag + +``` +[root@zutuanxue_manage01 ~]# docker tag baishuming2020/centos_nginx:latest 192.168.1.150:5000/centos_nginx:v1 + +[root@zutuanxue_manage01 ~]# docker images +REPOSITORY TAG IMAGE ID CREATED SIZE +192.168.98.240:5000/centos_nginx v1 bcd9f28f6126 45 minutes ago 447MB +baishuming2020/centos_nginx latest bcd9f28f6126 45 minutes ago 447MB +baishuming2020/centos_8_base latest 3e9f682f8459 59 minutes ago 200MB +centos latest 0f3e07c0138f 6 weeks ago 220MB +registry latest f32a97de94e1 8 months ago 25.8MB +``` + +c、上传镜像到registry仓库 + +``` +#1、上传镜像 +[root@zutuanxue_manage01 ~]# docker push 192.168.98.240:5000/centos_nginx:v1 +The push refers to repository [192.168.98.240:5000/centos_nginx] +1da799aaf1ec: Pushed +f598357997c6: Pushed +630012d2d35b: Pushed +4dcde7ab808a: Pushed +64dc1b92ebb6: Pushed +7db2133dafb9: Pushed +fd05189e6e81: Pushed +ee645629aa71: Pushed +v1: digest: sha256:507a5ad9dd5771cdf461a6fa24c3fff6ea9eabd6945abf03e9264d3130fe816b size: 1996 + +#2、查看上传 +[root@zutuanxue_manage01 ~]# curl http://192.168.98.240:5000/v2/_catalog +{"repositories":["centos_nginx"]} + +#查看存储文件夹 +[root@zutuanxue_manage01 ~]# ls /opt/docker_repos/docker/registry/v2/repositories/centos_nginx/ +_layers _manifests _uploads +``` + +### 1.3、 registry仓库应用-客户端下载镜像 + +- 设置客户端docker仓库为registry仓库 +- 拉取镜像到本地 + +**演示案例** + +**要求192.168.98.241[hostname:zutuanxue_node1]机器的容器可以下载registry仓库中的镜像** + +a、设置192.168.1.151[hostname:zutuanxue_node1]机器的docker仓库为registry仓库 + +``` +#1、设置docker启动文件 +[root@zutuanxue_node1 ~]# sed -i.bak '/^ExecStart=/c\ExecStart=\/usr\/bin\/dockerd' /usr/lib/systemd/system/docker.service + +#2、设置docker配置文件 +[root@zutuanxue_node1 ~]# cat /etc/docker/daemon.json +{ + "insecure-registries": ["http://192.168.1.150:5000"] +} +``` + +b、下载镜像 +192.168.1.151[hostname:zutuanxue_node1]机器上的docker可以拉取registry仓库中的192.168.1.150:5000/centos_nginx:v1容器镜像 + +``` +[root@zutuanxue_node1 ~]# docker pull 192.168.1.150:5000/centos_nginx:v1 +v1: Pulling from centos_nginx +dcd04d454f16: Pull complete +5cb2e05aa6e1: Pull complete +870634eb98b4: Pull complete +0fae9697ee4b: Pull complete +18ad57cfcecb: Pull complete +64dd6f0d85c1: Pull complete +7178b0b4388e: Pull complete +34de8795cd41: Pull complete +Digest: sha256:507a5ad9dd5771cdf461a6fa24c3fff6ea9eabd6945abf03e9264d3130fe816b +Status: Downloaded newer image for 192.168.98.240:5000/centos_nginx:v1 +192.168.98.240:5000/centos_nginx:v1 + +#验证下载 +[root@zutuanxue_node1 ~]# docker images +REPOSITORY TAG IMAGE ID CREATED SIZE +192.168.1.150:5000/centos_nginx v1 bcd9f28f6126 4 hours ago 447MB +``` + +### 1.4、registry带basic认证的仓库 + +**实现步骤** + +- 安装需要认证的包 +- 创建存放认证信息的文件 +- 创建认证信息 +- 创建带认证的registry容器 +- 指定仓库地址 +- 登录认证 + +**实现过程** +a、安装需要认证的包 + +``` +yum -y install httpd-tools +``` + +b、创建存放认证信息的文件 + +``` +mkdir -p /opt/registry-var/auth +``` + +c、创建认证信息 + +``` +htpasswd -Bbn zutuanxue 123456 >> /opt/registry-var/auth/htpasswd +``` + +d、创建带认证的registry容器 + +``` +docker run -d -p 10000:5000 --restart=always --name registry \ +-v /opt/registry-var/auth:/auth \ +-v /opt/myregistry:/var/lib/registry \ +-e "REGISTRY_AUTH=htpasswd" \ +-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ +-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \ +registry:latest +``` + +e、指定仓库地址 + +``` +cat /etc/docker/daemon.json +{ + "insecure-registries": ["http://192.168.1.150:5000","http://192.168.1.150:10000"] +} +``` + +f、登录认证 + +``` +docker login 192.168.1.150:10000 +Username:zutuanxue +Password:123456 +``` + +### 二、 harbor镜像仓库 + +Harbor离线安装包下载地址:https://github.com/goharbor/harbor + +docker-compose版本选择:https://github.com/docker/compose/releases + +### 2.1 harbor下载 + +``` +[root@centos8_manage01 ~]# wget https://storage.googleapis.com/harbor-releases/release-1.9.0/harbor-offline-installer-v1.9.2-rc1.tgz +``` + +### 2.2 docker-compose安装 + +容器编排工具,执行./install.sh时需要。如果不安装,一会重启docker服务,相关的harbor容器会死掉,安装后就会被随着docker重启 + +``` +curl -L https://github.com/docker/compose/releases/download/1.25.4/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose +chmod +x /usr/local/bin/docker-compose +``` + +### 2.3 harbor安装 + +``` +[root@centos8_manage01 ~]# tar xf harbor-offline-installer-v1.9.2-rc1.tgz + +[root@centos8_manage01 ~]# mv harbor /opt/ +[root@centos8_manage01 ~]# /opt/harbor/prepare +prepare base dir is set to /opt/harbor +Unable to find image 'goharbor/prepare:v1.9.2' locally +v1.9.2: Pulling from goharbor/prepare +b950b5dd94ab: Pull complete +cc7bb94ca291: Pull complete +d6a642502e65: Pull complete +21510274066b: Pull complete +04998692a2c0: Pull complete +ae8f4647fe53: Pull complete +cee24c721c12: Pull complete +Digest: sha256:a647780bcd7f5fdcc9696332c9bca90f290912ecb41bd15c4c1a516450597bc2 +Status: Downloaded newer image for goharbor/prepare:v1.9.2 +Generated configuration file: /config/log/logrotate.conf +Generated configuration file: /config/log/rsyslog_docker.conf +Generated configuration file: /config/nginx/nginx.conf +Generated configuration file: /config/core/env +Generated configuration file: /config/core/app.conf +Generated configuration file: /config/registry/config.yml +Generated configuration file: /config/registryctl/env +Generated configuration file: /config/db/env +Generated configuration file: /config/jobservice/env +Generated configuration file: /config/jobservice/config.yml +Generated and saved secret to file: /secret/keys/secretkey +Generated certificate, key file: /secret/core/private_key.pem, cert file: /secret/registry/root.crt +Generated configuration file: /compose_location/docker-compose.yml +Clean up the input dir + + + +修改配置文件中的主机名为本机域名或IP +[root@centos8_manage01 ~]# grep "^hostname" /opt/harbor/harbor.yml +hostname: 192.168.98.240 + + + +[root@centos8_manage01 ~]# /opt/harbor/install.sh + +[Step 0]: checking installation environment ... + +Note: docker version: 19.03.1 +/usr/lib/python2.7/site-packages/requests/__init__.py:91: RequestsDependencyWarning: urllib3 (1.24.3) or chardet (2.2.1) doesn't match a supported version! + RequestsDependencyWarning) + +Note: docker-compose version: 1.24.1 + +[Step 1]: loading Harbor images ... +6ef530defbe4: Loading layer 63.49MB/63.49MB +55872518448e: Loading layer 54.42MB/54.42MB +070787ce276e: Loading layer 5.632kB/5.632kB +1ddc8ebef7e9: Loading layer 2.048kB/2.048kB +94ec70036213: Loading layer 2.56kB/2.56kB +87f88832870d: Loading layer 2.56kB/2.56kB +208968317bf9: Loading layer 2.56kB/2.56kB +ab6259c81a01: Loading layer 10.24kB/10.24kB +Loaded image: goharbor/harbor-db:v1.9.2 +92e51ca4c459: Loading layer 9.005MB/9.005MB +9e12eb4a5a82: Loading layer 3.072kB/3.072kB +913c064dae30: Loading layer 21.76MB/21.76MB +b28cae8255d8: Loading layer 3.072kB/3.072kB +890572f32fd2: Loading layer 8.661MB/8.661MB +6f00be7ade9a: Loading layer 30.42MB/30.42MB +Loaded image: goharbor/harbor-registryctl:v1.9.2 +51bada9a03ba: Loading layer 78.25MB/78.25MB +bdd423614a28: Loading layer 3.072kB/3.072kB +e44c809a7328: Loading layer 59.9kB/59.9kB +07d91c85aa68: Loading layer 61.95kB/61.95kB +Loaded image: goharbor/redis-photon:v1.9.2 +e0a372c4d5d3: Loading layer 10.84MB/10.84MB +Loaded image: goharbor/nginx-photon:v1.9.2 +99f324455426: Loading layer 115.7MB/115.7MB +dbde533bd1f2: Loading layer 12.29MB/12.29MB +32adabde1b24: Loading layer 2.048kB/2.048kB +cdedbb7b738d: Loading layer 48.13kB/48.13kB +60eb6ca8f5f9: Loading layer 3.072kB/3.072kB +05fadada21a7: Loading layer 12.34MB/12.34MB +Loaded image: goharbor/clair-photon:v2.0.9-v1.9.2 +fbe05936a49e: Loading layer 12.77MB/12.77MB +8dc691e9365f: Loading layer 55.38MB/55.38MB +c83233ecc176: Loading layer 5.632kB/5.632kB +de775c6f50f5: Loading layer 36.35kB/36.35kB +525709237f01: Loading layer 55.38MB/55.38MB +Loaded image: goharbor/harbor-core:v1.9.2 +734abd864add: Loading layer 12.77MB/12.77MB +74033d37bf08: Loading layer 48.13MB/48.13MB +Loaded image: goharbor/harbor-jobservice:v1.9.2 +6677f529d41e: Loading layer 9.005MB/9.005MB +019a95ff5e80: Loading layer 3.072kB/3.072kB +4b3792cedc69: Loading layer 2.56kB/2.56kB +274f5851694b: Loading layer 21.76MB/21.76MB +68e937b2af9e: Loading layer 21.76MB/21.76MB +Loaded image: goharbor/registry-photon:v2.7.1-patch-2819-2553-v1.9.2 +Loaded image: goharbor/prepare:v1.9.2 +0566b1894f2e: Loading layer 9.009MB/9.009MB +b99c86e48679: Loading layer 44.41MB/44.41MB +283ba1db5c52: Loading layer 2.048kB/2.048kB +701de676a8f6: Loading layer 3.072kB/3.072kB +c923d0b0255c: Loading layer 44.41MB/44.41MB +Loaded image: goharbor/chartmuseum-photon:v0.9.0-v1.9.2 +ef4a961407c7: Loading layer 9.004MB/9.004MB +7cf94e5011b7: Loading layer 6.239MB/6.239MB +5c984b34ecb2: Loading layer 16.4MB/16.4MB +f06fb877e324: Loading layer 29.21MB/29.21MB +ae07ec384ebd: Loading layer 22.02kB/22.02kB +864698f2b94d: Loading layer 51.85MB/51.85MB +Loaded image: goharbor/notary-server-photon:v0.6.1-v1.9.2 +c953b6400a8b: Loading layer 50.3MB/50.3MB +2ee784d17d84: Loading layer 3.584kB/3.584kB +c71f6b26fd01: Loading layer 3.072kB/3.072kB +bb6389098841: Loading layer 2.56kB/2.56kB +b63da553de9f: Loading layer 3.072kB/3.072kB +62a479d14974: Loading layer 3.584kB/3.584kB +aa3fee5917b8: Loading layer 12.29kB/12.29kB +Loaded image: goharbor/harbor-log:v1.9.2 +691af8d2c981: Loading layer 14.9MB/14.9MB +7878347ee491: Loading layer 29.21MB/29.21MB +433f16e7c539: Loading layer 22.02kB/22.02kB +ad0202306aed: Loading layer 50.34MB/50.34MB +Loaded image: goharbor/notary-signer-photon:v0.6.1-v1.9.2 +62247cb7cb19: Loading layer 337.8MB/337.8MB +d8b748aaf7dd: Loading layer 119.8kB/119.8kB +Loaded image: goharbor/harbor-migrator:v1.9.2 +d9705202f79f: Loading layer 7.036MB/7.036MB +3fdb77b47894: Loading layer 196.6kB/196.6kB +8901bb1db41e: Loading layer 172kB/172kB +baf9307d1844: Loading layer 15.36kB/15.36kB +1dcfba9b1bd1: Loading layer 3.584kB/3.584kB +90a90fef2f80: Loading layer 10.84MB/10.84MB +Loaded image: goharbor/harbor-portal:v1.9.2 + + +[Step 2]: preparing environment ... +prepare base dir is set to /opt/harbor +Clearing the configuration file: /config/log/logrotate.conf +Clearing the configuration file: /config/log/rsyslog_docker.conf +Clearing the configuration file: /config/nginx/nginx.conf +Clearing the configuration file: /config/core/env +Clearing the configuration file: /config/core/app.conf +Clearing the configuration file: /config/registry/config.yml +Clearing the configuration file: /config/registryctl/env +Clearing the configuration file: /config/registryctl/config.yml +Clearing the configuration file: /config/db/env +Clearing the configuration file: /config/jobservice/env +Clearing the configuration file: /config/jobservice/config.yml +Generated configuration file: /config/log/logrotate.conf +Generated configuration file: /config/log/rsyslog_docker.conf +Generated configuration file: /config/nginx/nginx.conf +Generated configuration file: /config/core/env +Generated configuration file: /config/core/app.conf +Generated configuration file: /config/registry/config.yml +Generated configuration file: /config/registryctl/env +Generated configuration file: /config/db/env +Generated configuration file: /config/jobservice/env +Generated configuration file: /config/jobservice/config.yml +loaded secret from file: /secret/keys/secretkey +Generated configuration file: /compose_location/docker-compose.yml +Clean up the input dir + +/usr/lib/python2.7/site-packages/requests/__init__.py:91: RequestsDependencyWarning: urllib3 (1.24.3) or chardet (2.2.1) doesn't match a supported version! + RequestsDependencyWarning) + + +[Step 3]: starting Harbor ... +/usr/lib/python2.7/site-packages/requests/__init__.py:91: RequestsDependencyWarning: urllib3 (1.24.3) or chardet (2.2.1) doesn't match a supported version! + RequestsDependencyWarning) +Creating network "harbor_harbor" with the default driver +Creating harbor-log ... done +Creating harbor-portal ... done +Creating redis ... done +Creating registryctl ... done +Creating registry ... done +Creating harbor-db ... done +Creating harbor-core ... done +Creating nginx ... done +Creating harbor-jobservice ... done + +✔ ----Harbor has been installed and started successfully.---- + +Now you should be able to visit the admin portal at http://192.168.98.240. +For more details, please visit https://github.com/goharbor/harbor . +``` + +### 2.4 docker设置仓库为harbor + +``` +1、docker服务启动文件 +#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock 注释或者将[-H fd:// --containerd=/run/containerd/containerd.sock]删除 +ExecStart=/usr/bin/dockerd +这样做的目的是让daemon.json管理docker进程 + +2、创建docker守护进程配置文件 +[root@centos8_manage01 harbor]# cat /etc/docker/daemon.json +{ + "insecure-registries": ["http://192.168.98.240"] +} +``` + +### 2.5 镜像上传到harbor + +``` +#登陆harbor +[root@centos8_manage01 harbor]# docker login http://192.168.98.240 -u admin -p Harbor12345 +WARNING! Using --password via the CLI is insecure. Use --password-stdin. +WARNING! Your password will be stored unencrypted in /root/.docker/config.json. +Configure a credential helper to remove this warning. See +https://docs.docker.com/engine/reference/commandline/login/#credentials-store + +Login Succeeded + + +#修改镜像name:tag为harbor仓库名 +[root@centos8_manage01 harbor]# docker tag baishuming2020:latest 192.168.98.240/library/centos_web:v1 + +#上传镜像 +[root@centos8_manage01 harbor]# docker push 192.168.98.240/library/centos_web:v1 +The push refers to repository [192.168.98.240/library/centos_web] +968786242e9d: Pushed +v1: digest: sha256:d204253a33c6c2c74273fbd003cf3e14a48bcdd5c7bc10f51ccbad9e4dd39699 size: 528 +``` + +## 常见问题 + +docker-compose命令无法使用 +[root@centos8_manage01 ~]# docker-compose ps +ERROR: +Can’t find a suitable configuration file in this directory or any +parent. Are you in the right directory? + +``` + Supported filenames: docker-compose.yml, docker-compose.yaml +``` + +原因: **当前目录没有配置文件** + +``` +正确执行路径 harbor安装目录 +[root@centos8_manage01 harbor]# docker-compose ps + Name Command State Ports +----------------------------------------------------------------------------------------- +harbor-core /harbor/harbor_core Up +harbor-db /docker-entrypoint.sh Up 5432/tcp +harbor-jobservice /harbor/harbor_jobservice ... Up +harbor-log /bin/sh -c /usr/local/bin/ ... Up 127.0.0.1:1514->10514/tcp +harbor-portal nginx -g daemon off; Up 8080/tcp +nginx nginx -g daemon off; Up 0.0.0.0:80->8080/tcp +redis redis-server /etc/redis.conf Up 6379/tcp +registry /entrypoint.sh /etc/regist ... Up 5000/tcp +registryctl /harbor/start.sh Exit 137 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\351\225\234\345\203\217\347\256\241\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\351\225\234\345\203\217\347\256\241\347\220\206.md" new file mode 100644 index 0000000..73f839b --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/Docker\351\225\234\345\203\217\347\256\241\347\220\206.md" @@ -0,0 +1,244 @@ +# 一、docker镜像管理 + +### 1.1、镜像搜索-search + +``` +从docker镜像仓库模糊搜索镜像 +用法: + docker search 镜像关键字 + +[root@zutuanxue ~]# docker search centos + +NAME DESCRIPTION STARS OFFICIAL AUTOMATED +centos The official build of CentOS. 5674 [OK] + + +#字段说明: +NAME:镜像名称 +DESCRIPTION:镜像描述 +STARS:镜像星级,数字越大表示用的人越多 +OFFICIAL:是否为官方 跟[OK]说明是官方 +AUTOMATED: 是否为自动化构建的镜像 +``` + +### 1.2、镜像下载-pull命令 + +从docker指定的仓库下载镜像到本地 +用法: +**docker pull 镜像名称** + +``` +[root@zutuanxue ~]# docker pull centos + +Using default tag: latest +latest: Pulling from library/centos +729ec3a6ada3: Pull complete +Digest: sha256:f94c1d992c193b3dc09e297ffd54d8a4f1dc946c37cbeceb26d35ce1647f88d9 +Status: Downloaded newer image for centos:latest +docker.io/library/centos:latest +``` + +### 1.3、本地镜像查看-images命令 + +查看本地存储的镜像 + +``` +[root@zutuanxue ~]# docker images +REPOSITORY TAG IMAGE ID CREATED SIZE +docker.io/gitlab/gitlab-ce latest 515ad1a75677 7 weeks ago 1.9 GB +docker.io/redis latest 1319b1eaa0b7 7 weeks ago 104 MB + +#字段说明: +REPOSITORY:镜像的名字 +TAG:镜像的标签 +IMAGE ID:镜像的ID号 +CREATED:镜像建立时间 +SIZE: 镜像大小 +``` + +### 1.4、镜像详细信息-inspect命令 + +显示镜像的详细导入由save保存出来的压缩文件镜像 + +用法: +**docker load -i 镜像压缩文件名称 [镜像名称或者ID]** + +``` +[root@zutuanxue ~]# docker load -i centos_base.tar + +Loaded image: centos:latest信息 + +用法: + docker inspect [镜像名称或者ID] + +[root@zutuanxue ~]# docker inspect 0f3e07c0138f +[ + { + "Id": "sha256:0f3e07c0138fbe05abcb7a9cc7d63d9bd4c980c3f61fea5efa32e7c4217ef4da", + "RepoTags": [ + "centos:latest" + ], + "RepoDigests": [ + "centos@sha256:f94c1d992c193b3dc09e297ffd54d8a4f1dc946c37cbeceb26d35ce1647f88d9" + ], + "Parent": "", + "Comment": "", + "Created": "2019-10-01T23:19:57.105928163Z", + "Container": "711572e3c0c1ac06d5c13c4e668ec170b8ad8786b5f0949f884a5f7fd350d856", + "ContainerConfig": { + "Hostname": "711572e3c0c1", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "Cmd": [ + "/bin/sh", + "-c", + "#(nop) ", + "CMD [\"/bin/bash\"]" + ], + "ArgsEscaped": true, + "Image": "sha256:c0bda62fdbad65a3c6a1843d293a3a47d8233115cc6d384e3cb07c53580a2b43", + "Volumes": null, + "WorkingDir": "", + "Entrypoint": null, + "OnBuild": null, + "Labels": { + "org.label-schema.build-date": "20190927", + "org.label-schema.license": "GPLv2", + "org.label-schema.name": "CentOS Base Image", + "org.label-schema.schema-version": "1.0", + "org.label-schema.vendor": "CentOS" + } + }, + "DockerVersion": "18.06.1-ce", + "Author": "", + "Config": { + "Hostname": "", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "Cmd": [ + "/bin/bash" + ], + "ArgsEscaped": true, + "Image": "sha256:c0bda62fdbad65a3c6a1843d293a3a47d8233115cc6d384e3cb07c53580a2b43", + "Volumes": null, + "WorkingDir": "", + "Entrypoint": null, + "OnBuild": null, + "Labels": { + "org.label-schema.build-date": "20190927", + "org.label-schema.license": "GPLv2", + "org.label-schema.name": "CentOS Base Image", + "org.label-schema.schema-version": "1.0", + "org.label-schema.vendor": "CentOS" + } + }, + "Architecture": "amd64", + "Os": "linux", + "Size": 219583055, + "VirtualSize": 219583055, + "GraphDriver": { + "Data": { + "MergedDir": "/var/lib/docker/overlay2/e84fb0b30e3f1cd4a40d2ee6ed522736aedad13fcfce3571075ebbbd665aab4a/merged", + "UpperDir": "/var/lib/docker/overlay2/e84fb0b30e3f1cd4a40d2ee6ed522736aedad13fcfce3571075ebbbd665aab4a/diff", + "WorkDir": "/var/lib/docker/overlay2/e84fb0b30e3f1cd4a40d2ee6ed522736aedad13fcfce3571075ebbbd665aab4a/work" + }, + "Name": "overlay2" + }, + "RootFS": { + "Type": "layers", + "Layers": [ + "sha256:9e607bb861a7d58bece26dd2c02874beedd6a097c1b6eca5255d5eb0d2236983" + ] + }, + "Metadata": { + "LastTagTime": "0001-01-01T00:00:00Z" + } + } +] +``` + +### 1.5、本地镜像删除-rmi命令 + +删除本地镜像库中的某个镜像 + +用法: +**docker rmi [镜像名称或者ID]** + +``` +[root@zutuanxue ~]# docker rmi centos + +Untagged: centos:latest +Untagged: centos@sha256:f94c1d992c193b3dc09e297ffd54d8a4f1dc946c37cbeceb26d35ce1647f88d9 +Deleted: sha256:0f3e07c0138fbe05abcb7a9cc7d63d9bd4c980c3f61fea5efa32e7c4217ef4da +Deleted: sha256:9e607bb861a7d58bece26dd2c02874beedd6a097c1b6eca5255d5eb0d2236983 +``` + +### 1.6、镜像保存-save命令 + +保存镜像为压缩文件 + +用法: +**docker save -o 压缩文件名称 [镜像名称或者ID]** + +``` +[root@zutuanxue ~]# docker save -o centos_base.tar centos + +[root@zutuanxue ~]# ls + +anaconda-ks.cfg centos_base.tar +``` + +### 1.7、镜像载入-load命令 + +导入由save保存出来的压缩文件镜像 + +用法: +**docker load -i 镜像压缩文件名称 [镜像名称或者ID]** + +``` +[root@zutuanxue ~]# docker load -i centos_base.tar + +Loaded image: centos:latest +``` + +### 1.8、镜像管理命令-image命令 + +镜像管理命令,和上面的命令相似 + +``` +[root@zutuanxue ~]# docker image --help +Usage: docker image COMMAND +Manage images + +Commands: + build Build an image from a Dockerfile + history Show the history of an image + import Import the contents from a tarball to create a filesystem image + inspect Display detailed information on one or more images + load Load an image from a tar archive or STDIN + ls List images + prune Remove unused images + pull Pull an image or a repository from a registry + push Push an image or a repository to a registry + rm Remove one or more images + save Save one or more images to a tar archive (streamed to STDOUT by default) + tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/RHEL Podman\345\221\275\344\273\244.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/RHEL Podman\345\221\275\344\273\244.md" new file mode 100644 index 0000000..cfc38c0 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Docker\345\256\271\345\231\250\345\256\236\346\210\230\351\203\250\347\275\262/RHEL Podman\345\221\275\344\273\244.md" @@ -0,0 +1,411 @@ +# Podman介绍 + +Podman 是一个开源的容器运行时项目,可在大多数 Linux 平台上使用。Podman 提供与 Docker 非常相似的功能。正如前面提到的那样,它不需要在你的系统上运行任何守护进程,并且它也可以在没有 root 权限的情况下运行。 +Podman 可以管理和运行任何符合 OCI(Open Container Initiative)规范的容器和容器镜像。Podman 提供了一个与 Docker 兼容的命令行前端来管理 Docker 镜像。 + +> 1. Podman 官网地址:https://podman.io/ +> 2. Podman 项目地址:https://github.com/containers/libpod + +#### Podman 和docker不同之处? + +1. docker 需要在我们的系统上运行一个守护进程(docker daemon),而podman 不需要 +2. 启动容器的方式不同: + `docker cli` 命令通过API跟 `Docker Engine(引擎)`交互告诉它我想创建一个container,然后`docker Engine`才会调用`OCI container runtime(runc)`来启动一个container。这代表container的process(进程)不会是`Docker CLI`的`child process(子进程)`,而是`Docker Engine`的`child process`。 + `Podman`是直接给`OCI containner runtime(runc)`进行交互来创建container的,所以`container process`直接是`podman`的`child process`。 +3. 因为docke有docker daemon,所以docker启动的容器支持`--restart`策略,但是podman不支持,如果在k8s中就不存在这个问题,我们可以设置pod的重启策略,在系统中我们可以采用编写systemd服务来完成自启动 +4. docker需要使用root用户来创建容器,但是podman不需要 + +## Podman安装 + +``` +# yum -y install podman +``` + +## Podman命令 + +### 镜像管理命令 + +#### 镜像搜索 podman search + +``` +[root@node4 ~]# podman search centos +INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED +Podman.io Podman.io/blacklabelops/centos CentOS Base Image! Built and Updates Daily! 1 [OK] + +INDEX +NAME 镜像名字 +DESCRIPTION 描述 +SATRS 星级 数字越大代表使用人数越多 +OFFICIAL 是否为官方镜像 +AUTOMATED + + +拓展知识: +根据本地的/etc/containers/registries.conf文件中定义的去搜索 +#默认情况下,使用podman搜索从容器仓库中搜索镜像时,基于registries.conf文件,podman按顺序在registry.redhat.io、registry.access.redhat.com、quay.io和docker.io中查找请求的镜像。 +[registries.search] +registries = ['registry.redhat.io', 'registry.access.redhat.com', 'quay.io', 'docker.io'] + +#要添加对不需要身份验证的容器仓库(不安全容器仓库)的访问,必须在[registries.Unsecure]部分下添加该容器仓库的名称。 +[registries.insecure] +registries = [] + +#要禁止从本地系统访问的任何容器仓库都需要添加到[registries.block]部分下。 +[registries.block] +registries = [] + + +关于配置容器容器仓库,您还应该了解以下几点: +1、确保每个容器仓库都用单引号括起来。 +2、如果为registries=值设置了多个仓库,则必须用逗号分隔这些仓库。 +3、仓库可以通过IP地址或主机名来标识。 +4、如果仓库使用非标准端口(即,安全端口不是TCP端口443,不安全端口不是80),则应使用仓库名输入该端口号。例如:host.example.com:9999 +5、按照Registries.conf文件每个部分的显示顺序搜索仓库。 +6、如果您是运行podman和相关工具的普通用户(无根),则可以创建自己的registries.conf文件来覆盖默认设置。 +``` + +#### 本地镜像查看 podman images + +``` +[root@node4 ~]# podman images +REPOSITORY TAG IMAGE ID CREATED SIZE +Podman.io/blacklabelops/centos latest 73f5fb57a402 13 months ago 391 MB +``` + +#### 从仓库镜像拉取 podman pull [imange_name] + +``` +[root@node4 ~]# podman pull Podman.io/blacklabelops/centos +Trying to pull Podman.io/blacklabelops/centos...Getting image source signatures +Copying blob 18b8eb7e7f01: 69.75 MiB / 69.96 MiB [=============================] +Copying blob 18b8eb7e7f01: 69.96 MiB / 69.96 MiB [=========================] 33s +Copying blob 18b8eb7e7f01: 69.96 MiB / 69.96 MiB [=========================] 33s +Copying blob 9d438d3ad7e8: 61.22 MiB / 61.22 MiB [=========================] 33s +Copying config 73f5fb57a402: 3.98 KiB / 3.98 KiB [==========================] 0s +Writing manifest to image destination +Storing signatures +73f5fb57a402c17df1a74ddb154c4d2e2cd30c366e224d9cb6087ab9c6339d58 +``` + +#### 本地镜像删除 podman rmi [IMAGE_ID|REPOSITORY] + +``` +方法一: podman rmi IMAGE_ID +[root@node4 ~]# podman rmi 73f5fb57a402 +73f5fb57a402c17df1a74ddb154c4d2e2cd30c366e224d9cb6087ab9c6339d58 +方法二: podman rmi REPOSITORY +[root@node4 ~]# podman rmi Podman.io/blacklabelops/centos +73f5fb57a402c17df1a74ddb154c4d2e2cd30c366e224d9cb6087ab9c6339d58 +``` + +#### 镜像上传到仓库 podman push + +#### 镜像管理综合命令 podman image + +``` +[root@node4 ~]# podman image +NAME: + podman image - Manage images + +USAGE: + podman image command [command options] [arguments...] + +COMMANDS: + build Build an image using instructions from Podmanfiles + #根据Podmanfiles创建image + history Show history of a specified image + #显示指定镜像的历史信息 + import Import a tarball to create a filesystem image + #导入一个文件系统压缩包 + exists Check if an image exists in local storage + #检查本地是否存在某个镜像 + inspect Displays the configuration of a container or image + #显示容器或镜像的详细信息 + load Load an image from Podman archive + #将镜像文件导入到镜像仓库 + list, ls list images in local storage + #列出本地存储中的镜像 + prune Remove unused images + #移除未使用的镜像 + pull Pull an image from a registry + #下载一个镜像到本地 + push Push an image to a specified destination + #上传一个镜像到仓库 + rm removes one or more images from local storage + #删除一个或多个本地镜像 + save Save image to an archive + #将一个镜像保存为一个镜像文件 + tag Add an additional name to a local image + #添加一个额外的名称给本地镜像 + trust Manage container image trust policy + #信任容器镜像 + sign Sign an image + #生成镜像签名,可以根据签名验证镜像的完整性 + +OPTIONS: + --help, -h show help + + +镜像历史信息 +[root@node4 ~]# podman image history 73f5fb57a402 +ID CREATED CREATED BY SIZE COMMENT +73f5fb57a402 13 months ago /bin/sh -c #(nop) LABEL maintainer=Steffen... 0B + 13 months ago |1 BUILD_DATE=06/10/2018-01:06+0200 /bin/s... 64.2MB + 13 months ago /bin/sh -c #(nop) ARG BUILD_DATE=undefined 64.2MB + 15 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 64.2MB + 15 months ago /bin/sh -c #(nop) LABEL name=CentOS Base I... 64.2MB + 15 months ago /bin/sh -c #(nop) ADD file:d6a1da927f0b7a7... 73.36MB + + +镜像导入来自系统压缩包 导入时文件越大越慢 +[root@node4 ~]# podman image import centos8.tar +Getting image source signatures +Copying blob 84d82847ae58: 1.29 GiB / 1.31 GiB [===============================] +Copying blob 84d82847ae58: 1.31 GiB / 1.31 GiB [===========================] 14s +Copying config 2d42f6c756bc: 419 B / 419 B [================================] 0s +Writing manifest to image destination +Storing signatures +2d42f6c756bc02640bbb77319b5f1b3a2c51f70fd64d4919d8eb5c0d078c87a7 + + +监测本地镜像是否存在,结合$? +[root@node4 ~]# podman image exists 2d42f6c756bc;echo $? +0 +[root@node4 ~]# podman image exists 2d42f6c756bcxxxx;echo $? +1 + + + +镜像下载 +[root@node4 ~]# podman image pull Podman.io/blacklabelops/centos +Trying to pull Podman.io/blacklabelops/centos...Getting image source signatures +Copying blob 18b8eb7e7f01: 69.92 MiB / 69.96 MiB [=============================] +Copying blob 18b8eb7e7f01: 69.96 MiB / 69.96 MiB [=========================] 23s +Copying blob 18b8eb7e7f01: 69.96 MiB / 69.96 MiB [=========================] 24s +Copying blob 9d438d3ad7e8: 61.22 MiB / 61.22 MiB [=========================] 24s +Copying config 73f5fb57a402: 3.98 KiB / 3.98 KiB [==========================] 0s +Writing manifest to image destination +Storing signatures +73f5fb57a402c17df1a74ddb154c4d2e2cd30c366e224d9cb6087ab9c6339d58 + +镜像查看 list +[root@node4 ~]# podman image list +REPOSITORY TAG IMAGE ID CREATED SIZE +Podman.io/blacklabelops/centos latest 73f5fb57a402 13 months ago 391 MB + +镜像查看 ls +[root@node4 ~]# podman image ls +REPOSITORY TAG IMAGE ID CREATED SIZE +Podman.io/blacklabelops/centos latest 73f5fb57a402 13 months ago 391 MB + +镜像删除 +[root@node4 ~]# podman image rm 73f5fb57a402 +73f5fb57a402c17df1a74ddb154c4d2e2cd30c366e224d9cb6087ab9c6339d58 + + + + +[root@node4 ~]# podman image tag 2d42f6c756bc tyschool_centos8_1905 +[root@node4 ~]# podman image list +REPOSITORY TAG IMAGE ID CREATED SIZE +localhost/tyschool_centos8_1905 latest 2d42f6c756bc 5 hours ago 1.4 GB + + +导出一个镜像到文件 -o output +[root@node4 ~]# podman image save -o centos_7_base Podman.io/blacklabelops/centos +Getting image source signatures +Copying blob 129b697f70e9: 194.43 MiB / 195.64 MiB [===========================] +Copying blob 129b697f70e9: 195.64 MiB / 195.64 MiB [========================] 6s +Copying blob 129b697f70e9: 195.64 MiB / 195.64 MiB [========================] 6s +Copying blob a39553b46393: 177.41 MiB / 177.41 MiB [========================] 6s +Copying config 73f5fb57a402: 3.98 KiB / 3.98 KiB [==========================] 0s +Writing manifest to image destination +Storing signatures + + +导入一个镜像文件到本地仓库 -i input +[root@node4 ~]# podman image load -i centos_7_base +Getting image source signatures +Copying blob 129b697f70e9: 183.88 MiB / 195.64 MiB [=========================>-] +Copying blob a39553b46393: 171.16 MiB / 177.41 MiB [===========================] +Copying blob 129b697f70e9: 195.64 MiB / 195.64 MiB [========================] 4s +Copying blob a39553b46393: 177.41 MiB / 177.41 MiB [========================] 4s +Copying config 73f5fb57a402: 3.98 KiB / 3.98 KiB [==========================] 0s +Writing manifest to image destination +Storing signatures +Loaded image(s): docker.io/blacklabelops/centos:latest + + +删除未使用的镜像 +[root@node4 ~]# podman image prune --all +2d42f6c756bc02640bbb77319b5f1b3a2c51f70fd64d4919d8eb5c0d078c87a7 +b9e394903cd716d89ca1fb6758bfa08dd6ec6a5966fa925c9cf58738062eba05 +73f5fb57a402c17df1a74ddb154c4d2e2cd30c366e224d9cb6087ab9c6339d58 +``` + +### 容器管理命令 + +#### 容器查看 ps + +``` +#显示开机容器 +[root@node4 ~]# podman ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES + +#显示所有容器,包括没开机的 +[root@node4 ~]# podman ps -a +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +344ce4a0a6b4 localhost/tyschool_centos8_1905:latest /bin/bash 54 seconds ago Exited (0) 50 seconds ago ty2 +78c97bb19bec docker.io/mcnaughton/centos-base:latest /bin/bash 3 minutes ago Exited (0) About a minute ago ty1 +``` + +#### 容器创建 run + +方法一:根据本地镜像创建容器 + +``` +[root@node4 ~]# podman images +REPOSITORY TAG IMAGE ID CREATED SIZE +localhost/tyschool_centos8_1905 latest 2d42f6c756bc 7 hours ago 1.4 GB +docker.io/blacklabelops/centos latest 73f5fb57a402 13 months ago 391 MB +[root@node4 ~]# podman run -it -name ty2 localhost/tyschool_centos8_1905 /bin/bash + +-i 开启容器交互 +-t 分配一个TTY终端[假的] + +拓展 +--privileged 扩展容器权限 +``` + +方法二: 容器创建的时候,优先从本地仓库找镜像,本地没有就回去远程仓库拉取到本地 + +``` +本地仓库没有镜像 +[root@node4 ~]# podman run --name ty1 -it docker.io/mcnaughton/centos-base /bin/bash +Trying to pull docker.io/mcnaughton/centos-base...Getting image source signatures +Copying blob a02a4930cb5d: 0 B / 71.68 MiB [-----------------------------------] +Copying blob a02a4930cb5d: 30.30 MiB / 71.68 MiB [============>----------------] +Copying blob a02a4930cb5d: 71.27 MiB / 71.68 MiB [=============================] +Copying blob a02a4930cb5d: 71.68 MiB / 71.68 MiB [=========================] 34s +Copying blob a02a4930cb5d: 71.68 MiB / 71.68 MiB [=========================] 34s +Copying blob f6168f316445: 23.45 MiB / 23.45 MiB [=========================] 34s +Copying blob cf55ab518523: 99.57 MiB / 99.57 MiB [=========================] 34s +Copying blob 68b1bf62d7e6: 1.19 KiB / 1.19 KiB [===========================] 34s +Copying config b9e394903cd7: 4.99 KiB / 4.99 KiB [==========================] 0s +Writing manifest to image destination +Storing signatures +``` + +#### 容器启动、关闭、重启、暂停、恢复 + +``` +#启动容器 start +[root@node4 ~]# podman start ty1 +ty1 +查看容器开启了 +[root@node4 ~]# podman ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +78c97bb19bec docker.io/mcnaughton/centos-base:latest /bin/bash 4 minutes ago Up 5 seconds ago ty1 + + +#关闭容器 stop +[root@node4 ~]# podman stop ty1 +78c97bb19bec488b8bf5a6f68cdff9ecc20980b3c2c9e2d4c56a0946f539bd02 +查看容器关闭了 +[root@node4 ~]# podman ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES + +#重启容器 restart +[root@node4 ~]# podman restart ty1 +78c97bb19bec488b8bf5a6f68cdff9ecc20980b3c2c9e2d4c56a0946f539bd02 +[root@node4 ~]# +[root@node4 ~]# podman ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +78c97bb19bec docker.io/mcnaughton/centos-base:latest /bin/bash 6 minutes ago Up 2 seconds ago ty1 + + +#暂停容器 pause +[root@node4 ~]# podman pause ty1 +78c97bb19bec488b8bf5a6f68cdff9ecc20980b3c2c9e2d4c56a0946f539bd02 +查看状态 +[root@node4 ~]# podman ps -a +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +344ce4a0a6b4 localhost/tyschool_centos8_1905:latest /bin/bash 4 minutes ago Exited (0) 4 minutes ago ty2 +78c97bb19bec docker.io/mcnaughton/centos-base:latest /bin/bash 6 minutes ago Paused ty1 + +#恢复暂停容器 unpause +[root@node4 ~]# podman unpause ty1 +78c97bb19bec488b8bf5a6f68cdff9ecc20980b3c2c9e2d4c56a0946f539bd02 +查看状态 +[root@node4 ~]# podman ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +78c97bb19bec docker.io/mcnaughton/centos-base:latest /bin/bash 6 minutes ago Up 25 seconds ago ty1 +``` + +#### 容器性能查看 top + +``` +podman top 容器名称 + +[root@node4 ~]# podman top ty1 +USER PID PPID %CPU ELAPSED TTY TIME COMMAND +root 1 0 0.000 6m9.377354027s pts/0 0s /bin/bash +``` + +#### 容器连接 exec + +``` +连接一个运行容器,执行/bin/bash命令 +[root@node4 ~]# podman exec -it ty1 /bin/bash +[root@78c97bb19bec /]# +``` + +#### 容器连接 attach + +``` +将一个运行容器的标准输出、标准错误输出、标准输入调到前台 +[root@node4 ~]# podman attach ty1 +[root@78c97bb19bec /]# +``` + +#### 根据容器生成镜像 export + +``` +[root@node4 ~]# podman export -o ty1.tar ty1 + +[root@node4 ~]# podman import ty1.tar baism:ty1 +Getting image source signatures +Copying blob 854836d1c5c3: 491.28 MiB / 505.18 MiB [===========================] +Copying blob 854836d1c5c3: 505.18 MiB / 505.18 MiB [========================] 5s +Copying config 25581780c97b: 419 B / 419 B [================================] 0s +Writing manifest to image destination +Storing signatures +25581780c97b41ed62e0d6a9e41f8725cfaa93653e32adbb65369d3e527d235c + + + +podman import ty1.tar baism:ty1 + +baism:ty1 自定义仓库的名称:标签 +``` + +#### 打包更改过的容器为镜像 commit + +``` +[root@node4 ~]# podman commit ty1 baism:latest +Getting image source signatures +Skipping blob 071d8bd76517 (already present): 200.44 MiB / 200.44 MiB [=====] 0s +Skipping blob 3c8ab5053a82 (already present): 57.01 MiB / 57.01 MiB [=======] 0s +Skipping blob ba3cdff1294c (already present): 286.14 MiB / 286.14 MiB [=====] 0s +Skipping blob e25e400e5c38 (already present): 28.50 KiB / 28.50 KiB [=======] 0s +Skipping blob 071d8bd76517 (already present): 200.44 MiB / 200.44 MiB [=====] 1s +Skipping blob 071d8bd76517 (already present): 200.44 MiB / 200.44 MiB [=====] 1s +Skipping blob 3c8ab5053a82 (already present): 57.01 MiB / 57.01 MiB [=======] 1s +Skipping blob ba3cdff1294c (already present): 286.14 MiB / 286.14 MiB [=====] 1s +Skipping blob e25e400e5c38 (already present): 28.50 KiB / 28.50 KiB [=======] 1s +Copying blob 83e9209f930c: 114.44 MiB / 114.44 MiB [========================] 1s +Copying config d558217acef1: 4.08 KiB / 4.08 KiB [==========================] 0s +Writing manifest to image destination +Storing signatures +d558217acef109e465d5ce65d60de7c8619cc3c8cbbcde57e418555516ba3ec0 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/HPA.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/HPA.md" new file mode 100644 index 0000000..871e44a --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/HPA.md" @@ -0,0 +1,186 @@ +**Horizontal Pod Autoscaling 可以根据 CPU 利用率自动伸缩一个 ReplicaSet、Deployment 或者中的 Pod 数量** + +``` +cat hpa-deploy.yaml + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: hpa-web +spec: + selector: + matchLabels: + app: hpa-web + replicas: 1 + template: + metadata: + labels: + app: hpa-web + spec: + containers: + - name: hpa-web + image: gcr.io/google_containers/hpa-example + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + resources: + limits: + cpu: 200m + memory: 200Mi + requests: + cpu: 100m + memory: 100Mi +--- +apiVersion: v1 +kind: Service +metadata: + name: hpa-web +spec: + type: ClusterIP + selector: + app: hpa-web + ports: + - name: http + port: 80 + targetPort: 80 +``` + +![179.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486845597.png) + +![180.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486852393.png) + +**创建 HPA 控制器 - 相关算法的详情请参阅这篇文档:http://git.k8s.io/community/contributors/design-proposals/horizontal-pod-autoscaler.md#autoscaling-algorithm** + +``` +kubectl autoscale deployment hpa-web --cpu-percent=50 --min=1 --max=10 +``` + +![181.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486866224.png) + +**增加负载,查看负载节点数目** + +``` +两种方式: + +1.命令行创建: + +创建测试POD: +kubectl run -i --tty zutuanxue --image=busybox --image-pull-policy='IfNotPresent' /bin/sh + +执行命令: +while true; do wget -q -O- http://hpa-web.default.svc.cluster.local; done + +2.副本控制器创建: + +cat test.yaml + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ceshi +spec: + selector: + matchLabels: + app: ceshi + replicas: 1 + template: + metadata: + labels: + app: ceshi + spec: + containers: + - name: ceshi + image: docker.io/busybox + imagePullPolicy: IfNotPresent + command: ['sh', '-c', 'while true; do wget -q -O- http://hpa-web.default.svc.cluster.local; done'] +``` + +![182.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486877651.png) + +![183.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486883664.png) + +![184.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486889305.png) + + **资源限制 - Pod** + + **Kubernetes 对资源的限制实际上是通过 cgroup 来控制的,cgroup 是容器的一组用来控制内核如何运行进程的相关属性集合。针对内存、CPU 和各种设备都有对应的 cgroup** + + **默认情况下,Pod 运行没有 CPU 和内存的限额。 这意味着系统中的任何 Pod 将能够像执行该 Pod 所在的节点一样,消耗足够多的 CPU 和内存 。一般会针对某些应用的 pod 资源进行资源限制,这个资源限制是通过resources 的 requests 和 limits 来实现** + +``` +spec: + containers: + - image: xxxx + imagePullPolicy: Always + name: auth + ports: + - containerPort: 8080 + protocol: TCP + resources: + limits: + cpu: "4" + memory: 2Gi + requests: + cpu: 250m + memory: 250Mi +``` + + **requests 要分配的资源,limits 为最高请求的资源值。可以简单理解为初始值和最大值** + + **资源限制 - 名称空间** + + 1、计算资源配额 + +``` +apiVersion: v1 +kind: ResourceQuota +metadata: + name: compute-resources + namespace: zutuanxue +spec: + hard: + pods: "20" + requests.cpu: "20" + requests.memory: 100Gi + limits.cpu: "40" + limits.memory: 200Gi +``` + +2、配置对象数量配额限制 + +``` +apiVersion: v1 +kind: ResourceQuota +metadata: + name: object-counts + namespace: zutuanxue +spec: + hard: + configmaps: "10" + persistentvolumeclaims: "4" + ReplicaSet: "20" + secrets: "10" + services: "10" +``` + +**3、配置 CPU 和 内存 LimitRange** + +``` +apiVersion: v1 +kind: LimitRange +metadata: + name: mem-limit-range +spec: + limits: + - default: + memory: 50Gi + cpu: 5 + defaultRequest: + memory: 1Gi + cpu: 1 + type: Container +``` + +default 即 limit 的值 + +defaultRequest 即 request 的值 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Harbor \351\225\234\345\203\217\344\273\223\345\272\223\351\203\250\347\275\262.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Harbor \351\225\234\345\203\217\344\273\223\345\272\223\351\203\250\347\275\262.md" new file mode 100644 index 0000000..0d6d2a4 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Harbor \351\225\234\345\203\217\344\273\223\345\272\223\351\203\250\347\275\262.md" @@ -0,0 +1,174 @@ +## 一、创建自签证书: + +### 1.1、准备工作 + +- 检查是否已经安装 openssl: openssl version +- 创建存放证书目录并进入目录 + +``` +[root@zutuanxue ~]# mkdir /opt/harbor-ca-key +[root@zutuanxue ~]# cd /opt/harbor-ca-key +``` + +### 1.2、创建秘钥 + +**生成私钥** + +``` +[root@zutuanxue harbor-ca-key]# openssl genrsa -des3 -out server.pass.key 2048 + +# genra 生成RSA私钥 +# -des3 des3算法 +# -out server.key 生成的私钥文件名 +# 2048 私钥长度 +# 设置密码,密麻麻长度不能少于4位 +``` + +**去除私钥中的密码** + +``` +[root@zutuanxue harbor-ca-key]# openssl rsa -in server.pass.key -out server.key + +# 有密码的私钥是server.pass.key,没有密码的私钥是server.key +``` + +**生成CSR(证书签名请求)** + +``` +[root@zutuanxue harbor-ca-key]# openssl req -new -key server.key -out server.csr -subj "/C=CN/ST=bj/L=bj/O=zutuanxue/OU=zutuanxue/CN=www.zutuanxue.com" + +subj参数说明如下: + +/C=国家 +/ST=省 +/L=城市 +/O=组织或企业 +/OU=部门 +/CN=域名或IP + +第四步:生成自签名SSL证书 + +openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt + +# -days 证书有效期 + +# X.509证书包含三个文件:key,csr,crt。 + +# key是服务器上的私钥文件,用于对发送给客户端数据的加密,以及对从客户端接收到数据的解密 + +# csr是证书签名请求文件,用于提交给证书颁发机构(CA)对证书签名 + +# crt是由证书颁发机构(CA)签名后的证书,或者是开发者自签名的证书,包含证书持有人的信息,持有人的公钥,以及签署者的签名等信息 + +# 在密码学中,X.509是一个标准,规范了公开秘钥认证、证书吊销列表、授权凭证、凭证路径验证算法等。 +``` + +## 二、部署 Harbor + +**准备工作** + +- Harbor 离线安装包 +- docker-compose + +### 2.1、部署前准备 + +解压 Harboe 离线安装包后,进入解压后的目录,编辑 harbor.yaml 文件 + +- 修改 hostname 字段,改为自己的主机名 + +``` + hostname: www.zutuanxue.com +``` + +- 修改 certificate 与 private_key 字段如下,修改为你自己环境下的证书存放目录: + +``` + certificate: /opt/harbor-ca-key/server.crt + private_key: /opt/harbor-ca-key/server.key +``` + +- 修改 harbor_admin_password 字段,设置管理员用户的密码 + +``` +默认密码为 Harbor12345 ,如果配置文件内保持了默认密码的话,可以在搭建完成后在 web 页面进行密码修改操作。 +``` + +### 2.2、安装Harbor + +在解压后的 Harbor 目录内,有 “prepare” 初始化文件以及 ”install.sh“ 安装文件,先执行初始化操作 ./prepare 初始化完成以后执行安装操作 ./install.sh 然后等待安装完成即可。 + +``` +[root@zutuanxue Harbor]# ./prepare +[root@zutuanxue Harbor]# ./install.sh +``` + +### 2.3、验证Harbor仓库 + +使用docker客户端连接Harbor仓库,验证是否能够正确连接 + +**设置仓库URL** +因为我们使用的是自签证书,所以我们要在需要进行 docker login 的节点上编辑 daemon.json 文件,添加信任,否则话我们将无法正常进行 docker login 的操作: + +``` +[root@zutuanxue Harbor]# vim /etc/docker/daemon.json + +添加内容如下: + +{ + +"insecure-registries": ["https://www.zutuanxue.com"] + +} + +保存退出,重启 docker 服务即可。 +[root@zutuanxue docker]# systemctl restart docker +``` + +如果你 hostname 字段设置的是域名,记得在 /etc/hosts 文件内添加解析,示例如下: + +``` +vim /etc/hosts +192.168.1.150 www.zutuanxue.com + +添加完成后保存退出即可。 +``` + +**登录验证** + +``` +完成后可以进行验证: + +docker login www.zutuanxue.com + +Username:admin +Password:Harbor12345 + +输入完密码后显示如下信息 + +Authenticating with existing credentials... +WARNING! Your password will be stored unencrypted in /root/.docker/config.json. +Configure a credential helper to remove this warning. See +https://docs.docker.com/engine/reference/commandline/login/#credentials-store + +Login Succeeded + +证明登录成功。 +``` + +同样,如果你想 web 登录进行管理,那么你需要修改你宿主机的 hosts 文件,在里面添加对应的解析条目 + +**MAC 系统设置** + +``` +打开终端 → sudo vim /etc/hosts → 添加 IP 与 域名 的解析即可 +``` + +**Windows 系统设置** + +``` +1、打开计算机后,点击进入C盘,找到 windows 文件夹 +2、在windows文件中找到System32 → drivers → etc ,进入到 etc 文件夹中就能看到 hosts 文件 +3、在末尾添加对应解析即可,然后保存退出 +``` + +添加完解析后,打开浏览器,输入我们设置的域名即可访问,因为我们使用的是自签证书,所以浏览器会有安全提示,说我们访问的网站不安全,直接无视该信息,点击继续访问即可,然后输入我们的用户名 admin 密码 Harbor12345 即可成功登陆。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Helm.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Helm.md" new file mode 100644 index 0000000..056b84e --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Helm.md" @@ -0,0 +1,295 @@ +## 一、Helm 是什么 + +在没使用 helm 之前,向 kubernetes 部署应用,我们要依次部署 deployment、svc 等,步骤较繁琐。况且随着很多项目微服务化,复杂的应用在容器中部署以及管理显得较为复杂,helm 通过打包的方式,支持发布的版本管理和控制,很大程度上简化了 Kubernetes 应用的部署和管理。 + +Helm 本质就是让 K8s 的应用管理(Deployment,Service 等 ) 可配置,能动态生成。通过动态生成 K8s 资源清单文件(deployment.yaml,service.yaml)。然后调用 Kubectl 自动执行 K8s 资源部署。 + +Helm 是官方提供的类似于 YUM 的包管理器,是部署环境的流程封装。Helm 有两个重要的概念:chart 和release。 + +## 二、Helm 相关组件 + +**Helm 包含两个组件,分别是 helm 客户端 和 Tiller 服务器:** + +**helm :** 是一个命令行工具,用于本地开发及管理chart,chart仓库管理等 + +**Tiller:** 是 Helm 的服务端。Tiller 负责接收 Helm 的请求,与 k8s 的 apiserver 交互,根据chart来生成一个 release 并管理 release + +**chart:** Helm的打包格式叫做chart,所谓chart就是一系列文件, 它描述了一组相关的 k8s 集群资源 + +**release:** 使用 helm install 命令在 Kubernetes 集群中部署的 Chart 称为 Release + +## 三、Helm 原理 + +![150.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486104098.png) + +**创建 或 删除 release** + +helm 客户端从指定的目录或本地tar文件或远程repo仓库解析出chart的结构信息 + +helm 客户端指定的 chart 结构和 values 信息通过 gRPC 传递给 Tiller + +Tiller 服务端根据 chart 和 values 生成一个 release + +Tiller 将install release请求直接传递给 kube-apiserver + +**更新release** + +helm 客户端将需要更新的 chart 的 release 名称 chart 结构和 value 信息传给 Tiller + +Tiller 将收到的信息生成新的 release,并同时更新这个 release 的 history + +Tiller 将新的 release 传递给 kube-apiserver 进行更新 + +## 四、Helm 部署 + +``` +wget https://storage.googleapis.com/kubernetes-helm/helm-v2.16.7-linux-amd64.tar.gz + +tar zxvf helm-v2.16.7-linux-amd64.tar.gz + +cd linux-amd64/ + +ls +LICENSE README.md helm tiller + +cp helm /usr/local/bin/ + +安装好 helm 客户端后,就可以通过以下命令将 Tiller 安装在 kubernetes 集群中 : + +helm init + +# 这个地方默认使用 “https://kubernetes-charts.storage.googleapis.com” 作为缺省的 stable repository 的地址,但由于国内有一张无形的墙的存在,googleapis.com 是不能访问的。 + +可以使用阿里云的源来配置 : + +helm init --upgrade -i registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.16.7 --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts + +执行上面命令后,可以通过 kubectl get pod -n kube-system 来查看 tiller 的安装情况 : + +由于 kubernetes 从1.6 版本开始加入了 RBAC 授权。当前的 Tiller 没有定义用于授权的ServiceAccount, 访问 API Server 时会被拒绝,需要给 Tiller 加入授权: + +创建 Kubernetes 的服务帐号和绑定角色: + +kubectl create serviceaccount --namespace kube-system tiller +# serviceaccount "tiller" created + +kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller +# clusterrolebinding.rbac.authorization.k8s.io "tiller-cluster-rule" created + +给 Tiller 的 deployments 添加刚才创建的 ServiceAccount : + +kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}' +# deployment.extensions "tiller-deploy" patched + +查看 Tiller deployments 资源是否绑定 ServiceAccount : + +kubectl get deploy -n kube-system tiller-deploy -o yaml | grep serviceAccount +# serviceAccount: tiller +# serviceAccountName: tiller + +查看 Tiller 是否安装成功 : + +helm version +# Client: &version.Version{SemVer:"v2.16.7", +# Server: &version.Version{SemVer:"v2.16.7", + +helm 有很多子命令和参数,为了提高使用命令行的效率,通常建议安装 helm 的 bash 命令补全脚本: + +source <(helm completion bash) +echo "source <(helm completion bash)" >> ~/.bashrc + +添加 helm chart 仓库: + +helm repo add stable https://kubernetes-charts.storage.googleapis.com + +helm repo add aliyun https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts + +helm repo add alihub https://apphub.aliyuncs.com + +helm repo add svc-cat https://svc-catalog-charts.storage.googleapis.com + +helm repo add weiruan-1 http://mirror.azure.cn/kubernetes/charts + +helm repo add weiruan-2 http://mirror.azure.cn/kubernetes/charts-incubator + +helm repo add weiruan-3 http://mirror.azure.cn/kubernetes/svc-catalog-charts + +helm repo add bitnami https://charts.bitnami.com/bitnami + +helm repo add elastic https://helm.elastic.co + +helm repo add kiwigrid https://kiwigrid.github.io + +helm repo add jetstack https://charts.jetstack.io + +更新仓库: + +helm repo update +``` + +![149.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486127780.png) + +**Helm 常用命令** + +``` +# 创建一个chart范例 +helm create HELM-NAME + +# 检查chart语法 +helm lint ./HELM-NAME + +# 使用默认chart部署到k8s +helm install --name RELEASE-NAME ./HELM-NAME --set service.type=NodePort + +# 查看当前的部署列表 +helm ls + +# 查询一个特定的 Release 的状态 +helm status RELEASE-NAME + +# 打包chart +helm package ./HELM-NAME --debug + +# 使用包去做release部署 +helm install --name RELEASE-NAME HELM-NAME-0.1.0.tgz --set service.type=NodePort + +# 升级当前release +helm upgrade RELEASE-NAME ./HELM-NAME + +# 回滚当前release +helm rollback RELEASE-NAME 3(版本号) + +# 删除该release +helm delete RELEASE-NAME +helm del --purge RELEASE-NAME +``` + +## 五、Helm 自定义模板 + +``` +创建自描述文件 Chart.yaml , 这个文件必须有 name 和 version 定义: + +vim Chart.yaml + +name: hello-world +version: 1.0 + + +创建模板文件, 用于生成 Kubernetes 资源清单,模板文件名必须为 templates: + +mkdir templates + +vim templates/deployment.yaml + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: helm-nginx +spec: + selector: + matchLabels: + app: helm-nginx + replicas: 3 + template: + metadata: + labels: + app: helm-nginx + spec: + containers: + - name: helm-nginx + image: docker.io/nginx + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + + + +vim templates/service.yaml + +apiVersion: v1 +kind: Service +metadata: + name: helm-nginx-svc +spec: + type: NodePort + ports: + - port: 80 + targetPort: 80 + protocol: TCP + selector: + app: helm-nginx + + +使用命令 helm install RELATIVE_PATH_TO_CHART 创建一次Release + +helm install . +``` + +![151.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486151896.png) + +查看下我们创建以后的资源: + +![152.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486158573.png) + +访问测试: + +![153.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486165093.png) + +``` +通过 values.yaml 配置 helm 应用: + + +vim values.yaml + +image: + repository: docker.io/nginx + tag: latest + pullPolicy: IfNotPresent + + +vim templates/deployment.yaml + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: helm-nginx-1 +spec: + selector: + matchLabels: + app: helm-nginx-1 + replicas: 3 + template: + metadata: + labels: + app: helm-nginx-1 + spec: + containers: + - name: helm-nginx + image: {{ .Values.image.repository }}:{{ .Values.image.tag }} + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + +vim templates/service.yaml + +apiVersion: v1 +kind: Service +metadata: + name: helm-nginx-svc-1 +spec: + type: NodePort + ports: + - port: 80 + targetPort: 80 + protocol: TCP + selector: + app: helm-nginx-1 +``` + +使用模板动态生成K8s资源清单,非常需要能提前预览生成的结果,使用 --dry-run 选项来打印出生成的清单文件内容,而不执行部署: + +**helm install . --dry-run** + +![154.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486177990.png) + +这里看见报错了,这是因为,我们刚刚已经创了对应的资源,所以报错说 service “helm-nginx-svc” 已经存在了。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Job \344\270\216 Cronjob.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Job \344\270\216 Cronjob.md" new file mode 100644 index 0000000..9a18360 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Job \344\270\216 Cronjob.md" @@ -0,0 +1,133 @@ +## 一、Job + +Job 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束。 + +**特殊说明**: + +1、spec.template 格式同 Pod + +2、RestartPolicy 仅支持 Never 或 OnFailure + +3、单个 Pod 时,默认 Pod 成功运行后 Job 即结束 + +4、spec.completions 标志 Job 结束需要成功运行的 Pod 个数,默认为 1 + +5、spec.parallelism 标志并行运行的 Pod 的个数,默认为 1 + +6、spec.activeDeadlineSeconds 标志失败 Pod 的重试最大时间,超过这个时间不会继续重试 + +**Job 应用示例:** + +``` +vim job.yaml + +apiVersion: batch/v1 +kind: Job +metadata: + name: job +spec: + template: + metadata: + name: job + spec: + containers: + - name: job + image: docker.io/perl + command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] + restartPolicy: Never +``` + +**然后我们来看一下 Pod 的信息:** + +![63.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328807881.png) + +**我们在来看下日志信息:** + +![64.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328813948.png) + +**任务完成, π 的2000位信息。** + +## 二、Cronjob + +Cron Job 管理基于时间的 Job,即: + +在给定时间点只运行一次 + +周期性地在给定时间点运行 + +**使用条件:** 当前使用的 Kubernetes 集群,版本 >= 1.8 + +**典型的用法:** + +在给定的时间点调度 Job 运行 + +创建周期性运行的 Job,例如:数据库备份、发送邮件 + +**CronJob Spec:** + +**spec.template** 格式同 Pod + +**RestartPolicy** 仅支持 **Never** 或 **OnFailure** + +单个 Pod 时,默认 Pod 成功运行后 Job 即结束 + +**spec.schedule:** 调度,必需字段,指定任务运行周期,格式同 Cron + +**spec.jobTemplate:** Job 模板,必需字段,指定需要运行的任务,格式同 Job + +**spec.startingDeadlineSeconds:** 启动 Job 的期限(秒级别),该字段是可选的。如果因为任何原因而错过了被调度的时间,那么错过执行时间的 Job 将被认为是失败的。如果没有指定,则没有期限 + +**spec.concurrencyPolicy:** 并发策略,该字段也是可选的。它指定了如何处理被 Cron Job 创建的 Job 的并发执行。只允许指定下面策略中的一种: + +**Allow (默认):** 允许并发运行 Job + +**Forbid :** 禁止并发运行,如果前一个还没有完成,则直接跳过下一个 + +**Replace :** 取消当前正在运行的 Job,用一个新的来替换 + +**注意,当前策略只能应用于同一个 Cron Job 创建的 Job。如果存在多个 Cron Job,它们创建的 Job 之间总是允许并发运行。** + +**spec.suspend :** 挂起,该字段也是可选的。如果设置为 true ,后续所有执行都会被挂起。它对已经开始执行的 Job 不起作用,默认值为 false + +**spec.successfulJobsHistoryLimit** 和 **spec.failedJobsHistoryLimit :** 历史限制,是可选的字段。它们指定了可以保留多少完成和失败的 Job 。默认情况下,它们分别设置为 3 和 1 。设置限制的值为 0 ,相关类型的 Job 完成后将不会被保留。 + +Cronjob 应用示例: + +``` +vim cronjob.yaml + +apiVersion: batch/v1beta1 +kind: CronJob +metadata: + name: hello +spec: + schedule: "*/1 * * * *" + jobTemplate: + spec: + template: + spec: + containers: + - name: hello + image: docker.io/busybox + args: + - /bin/sh + - -c + - date; echo Hello from the Kubernetes cluster + restartPolicy: OnFailure +``` + +然后我们来运行我们的 Cronjob: + +![65.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328826945.png) + +我们来查看一下我们的 Pod : + +![66.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328833079.png) + +我们来查看一下我们的 Job : + +![67.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328839397.png) + +我们来查看一下我们的日志信息: + +![68.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328845724.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kebetnetes\345\221\275\344\273\244\350\241\214\345\267\245\345\205\267kubectl.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kebetnetes\345\221\275\344\273\244\350\241\214\345\267\245\345\205\267kubectl.md" new file mode 100644 index 0000000..b7c6e42 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kebetnetes\345\221\275\344\273\244\350\241\214\345\267\245\345\205\267kubectl.md" @@ -0,0 +1,72 @@ +为了方便在命令行下对集群、节点、pod进行管理,kubernetes官方提供了一个管理命令:kubectl + +kubectl作为客户端CLI工具,可以让用户通过命令行对Kubernetes集群进行操作。 + +## 一、kubectl介绍 + +### kubectl命令行的语法: + +``` +kubectl [command] [TYPE] [NAME] [flags] + + +command:子命令,用于操作Kubernetes集群资源对象的命令,例如create、delete、describe、get、apply等 + +TYPE:资源对象的类型,区分大小写,能以单数、复数或简写形式表示。例如以下3种TYPE是等价的 + + - kubectl get pod pod-name + + - kubectl get pods pod-name + + - kubectl get po pod-name + +NAME:资源对象的名称,区分大小写,如果不指定名称,系统将返回所有Pod的列表 + +flags:kubectl子命令的可选参数,比如可以使用 “-o wide“ 来显示更多的信息 +``` + +## 二、kubectl常用命令 + +- 新建资源:kubectl create -f pod.yaml + +![19.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602326563560.png) + +- 删除资源-根据YAML文件: kubectl delete -f pod.yaml + +![20.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602326585774.png) + +- 删除资源-根据pod名字: kubectl delete pod nginx + +![21.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602326600592.png) + +- 删除资源-删除所有pod: kubectl delete pod --all + +![22.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602326653562.png) + +- 查看node信息:kubectl get nodes + +![23.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602326678706.png) + +- 查看pod信息:kubectl get pod -o wide/yaml + +![24.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602326699622.png) + +- 查看所有信息:kubectl get all + +![25.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602326721496.png) + +- 查看pod详细信息:kubectl describe pod nginx + +![26.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602326742365.png) + +- 查看kube-system空间内的pod:kubectl get pod -n kube-system + +![9.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602326770788.png) + +## 三、帮助 + +如果在使用命令过程中出现问题,那么我们也可以通过使用 --help来获取 kubectl 命令的使用说明: + +- 获取 kubectl 的使用说明: kubectl --help +- 获取 kubectl 子命令的使用说明:kubectl get --help / kubectl delete --help +- 获取资源控制器说明: kubectl explain pod / rs / deployment / ····· \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes NameSpace \344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes NameSpace \344\273\213\347\273\215.md" new file mode 100644 index 0000000..6417fdb --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes NameSpace \344\273\213\347\273\215.md" @@ -0,0 +1,26 @@ +Kubernetes使用命名空间的概念帮助解决集群中在管理对象时的复杂性问题。命名空间允许将对象分组到一起,便于将它们作为一个单元进行筛选和控制。无论是应用自定义的访问控制策略,还是为了测试环境而分离所有组件,命名空间都是一个按照组来处理对象、强大且灵活的概念。 + +## 一、什么是命名空间,为什么它很重要 + +命名空间(namespace)是Kubernetes提供的组织机制,用于给集群中的任何对象组进行分类、筛选和管理,**每一个添加到Kubernetes集群的工作负载必须放在一个命名空间中。** + +**命名空间为集群中的对象名称赋予作用域** +虽然在命名空间中名称必须是唯一的,但是相同的名称可以在不同的命名空间中使用。这对于某些场景来说可能帮助很大。例如,如果使用命名空间来划分应用程序生命周期环境(如开发、staging、生产),则可以在每个环境中维护利用同样的名称维护相同对象的副本。 + +**命名空间还可以让用户轻松地将策略应用到集群的具体部分** +你可以通过定义ResourceQuota对象来控制资源的使用,该对象在每个命名空间的基础上设置了使用资源的限制。类似地,当在集群上使用支持网络策略的CNI(容器网络接口)时,比如Calico或Canal(calico用于策略,flannel用于网络)。你可以将NetworkPolicy应用到命名空间,其中的规则定义了pod之间如何彼此通信。不同的命名空间可以有不同的策略。 + +**使用命名空间最大的好处之一是能够利用Kubernetes RBAC(基于角色的访问控制)** + +RBAC允许您在单个名称下开发角色,这样将权限或功能列表分组。ClusterRole对象用于定义集群规模的使用模式,而角色对象类型(Role object type)应用于具体的命名空间,从而提供更好的控制和粒度。在角色创建后,RoleBinding可以将定义的功能授予单个命名空间上下文中的具体具体用户或用户组。通过这种方式,命名空间可以使得集群操作者能够将相同的策略映射到组织好的资源集合。 + +## 二、常见的命名空间使用模式 + +**将命名空间映射到团队或项目上:** +在设置命名空间时有一个惯例是,为每个单独的项目或者团队创建一个命名空间,通过给团队提供专门的命名空间,你可以用RBAC策略委托某些功能来实现自我管理和自动化。 + +**使用命名空间对生命周期环境进行分区:** +命名空间非常适合在集群中划分开发、staging以及生产环境。通常情况下我们会被建议将生产工作负载部署到一个完全独立的集群中,来确保最大程度的隔离。不过对于较小的团队和项目来说,命名空间会是一个可行的解决方案。 + +**使用命名空间隔离不同的使用者:** +根据使用者对工作负载进行分段。比如,如果你的集群为多个客户提供基础设施,那么按命名空间进行分段就能够实现管理每个客户,同时跟踪账单的去向。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \346\246\202\345\277\265\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \346\246\202\345\277\265\344\273\213\347\273\215.md" new file mode 100644 index 0000000..4859b60 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \346\246\202\345\277\265\344\273\213\347\273\215.md" @@ -0,0 +1,124 @@ +## 一、Master + + Master指的是集群控制节点,在每个Kubernetes集群里都需要有一个Master来负责整个集群的管理和控制,基本上Kubernetes的所有控制命令都发给它,它负责具体的执行过程,我们后面执行的所有命令基本都是在Master上运行的 + +**Master上运行的核心组件:** + +**Kubernetes API Server(kube-apiserver):** + +提供了HTTP Rest接口的关键服务进程,是Kubernetes里所有资源的增、删、改、查等操作的唯一入口,也是集群控制的入口进程。 + +**Kubernetes Controller Manager(kube-controller-manager):** + +Kubernetes里所有资源对象的自动化控制中心,可以将其理解为资源对象的“大总管”。 + +**Kubernetes Scheduler(kube-scheduler):** + +负责资源调度(Pod调度)的进程,相当于公交公司的“调度室”。 + +## 二、Node + + Node是Kubernetes集群中的工作负载节点,每个Node都会被Master分配一些工作负载(Docker容器),当某个Node宕机时,其上的工作负载会被Master自动转移到其他节点上。 + +**Node上运行的核心组件:** + +**kubelet:** 负责Pod对应的容器的创建、启停等任务,同时与Master密切协作,实现集群管理的基本功能。 + +**kube-proxy:** 实现Kubernetes Service的通信与负载均衡机制的重要组件。 + +## 三、Etcd + +etcd 的官方将它定位成一个可信赖的分布式键值存储服务,保存了整个集群的状态,它能够为整个分布式集群存储一些关键数据,协助分布式集群的正常运转。 + +## 四、Pod + +Pod是Kubernetes最重要的基本概念,我们看到每个Pod都有一个特殊的被称为“根容器”的Pause容器。Pause容器对应的镜像属于Kubernetes平台的一部分,除了Pause容器,每个Pod还包含一个或多个紧密相关的用户业务容器。 + +## 五、Label + + Label(标签)是Kubernetes系统中另外一个核心概念。一个Label是一个key=value的键值对,其中key与value由用户自己指定。Label可以被附加到各种资源对象上,例如Node、Pod、Service、RC等,一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上。Label通常在资源对象定义时确定,也可以在对象创建后动态添加或者删除。 + +#### 6、ReplicationController(RC) + +用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的 Pod 来替代;而如果异常多出来的容器也会自动回收。在新版本的 Kubernetes 中建议使用 ReplicaSet 来取代 ReplicationControlle。 + +## 七、ReplicaSet(RS) + +ReplicaSet 跟 ReplicationController 没有本质的不同,只是名字不一样,并且ReplicaSet 支持集合式的 selector虽然 ReplicaSet 可以独立使用,但一般还是建议使用 Deployment 来自动管理ReplicaSet ,这样就无需担心跟其他机制的不兼容问题(比如 ReplicaSet 不支持rolling-update 但 Deployment 支持)。 + +## 八、Deployment + +Deployment 为 Pod 和 ReplicaSet 提供了一个 声明式定义 (declarative) 方法,用来替代以前的 ReplicationController 来方便的管理应用。典型的应用场景包括: + +1、定义 Deployment 来创建 Pod 和 ReplicaSet + +2、滚动升级和回滚应用 + +3、扩容和缩容 + +4、暂停和继续 Deployment + +## 九、DaemonSet + +DaemonSet 确保全部(或者一些) Node 上运行一个 Pod 的副本。当有 Node 加入集群时,也会为他们新增一个 Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod,使用 DaemonSet 的一些典型用法: + +1、运行集群存储 daemon ,例如在每个 Node 上运行 glusterd 、 ceph 。 + +2、在每个 Node 上运行日志收集 daemon ,例如 fluentd 、 logstash 。 + +3、在每个 Node 上运行监控 daemon ,例如 Prometheus Node Exporter + +## 十、Horizontal Pod Autoscaling + +Horizontal Pod Autoscaling 仅适用于 Deployment 和 ReplicaSet ,在 V1 版本中仅支持根据 Pod的 CPU 利用率扩所容,在 v1alpha 版本中,支持根据内存和用户自定义的 metric 扩缩容。 + +## 十一、StatefulSet + +StatefulSet 是为了解决有状态服务的问题(对应 Deployments 和 ReplicaSets 是为无状态服务而设计),其应用场景包括: + +1、稳定的持久化存储,即 Pod 重新调度后还是能访问到相同的持久化数据,基于 PVC 来实现 + +2、稳定的网络标志,即 Pod 重新调度后其 PodName 和 HostName 不变,基于 Headless Service(即没有 Cluster IP 的 Service )来实现 + +3、有序部署,有序扩展,即 Pod 是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从 0 到 N-1 ,在下一个 Pod 运行之前所有之前的 Pod 必须都是 Running 和 Ready 状态),基于 init containers 来实现 + +4、有序收缩,有序删除(即从 N-1 到 0 0 ) + +## 十二、Job + +Job 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 。 + +## 十三、Cron Job + +Cron Job 管理基于时间的 Job ,即: + +1、在给定时间点只运行一次 +2、周期性地在给定时间点运行 + +## 十四、ConfigMap + +ConfigMap 功能在 Kubernetes1.2 版本中引入,许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。ConfigMap API 给我们提供了向容器中注入配置信息的机制,ConfigMap 可以被用来保存单个属性,也可以用来保存整个配置文件或者 JSON 二进制大对象。 + +## 十五、Secret + +Secret 解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者 Pod Spec中。Secret 可以以 Volume 或者环境变量的方式使用。 + +## 十六、Volume + +容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题。首先,当容器崩溃时,kubelet 会重启它,但是容器中的文件将丢失——容器以干净的状态(镜像最初的状态)重新启动。其次,在Pod 中同时运行多个容器时,这些容器之间通常需要共享文件。Kubernetes 中的 Volume 就很好的解决了这些问题 + +## 十七、PersistentVolume (PV) + +PersistentVolume是由管理员设置的存储,它是群集的一部分。就像节点是集群中的资源一样,PV 也是集群中的资源。 PV 是Volume 之类的卷插件,但具有独立于使用 PV 的 Pod 的生命周期。此 API 对象包含存储实现的细节,即 NFS、iSCSI 或特定于云供应商的存储系统。 + +## 十八、PersistentVolumeClaim (PVC) + +PersistentVolumeClaim是用户存储的请求。它与 Pod 相似。Pod 消耗节点资源,PVC 消耗 PV 资源。Pod 可以请求特定级别的资源(CPU 和内存)。声明可以请求特定的大小和访问模式(例如,可以以读/写一次或 只读多次模式挂载)。 + +## 十九、Service + +Service是Kubernetes的核心概念,通过创建Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。 + +## 二十、NameSpace + +Namespace(命名空间)是Kubernetes系统中的另一个非常重要的概念,Namespace在很多情况下用于实现多租户的资源隔离。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \347\275\221\347\273\234\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \347\275\221\347\273\234\344\273\213\347\273\215.md" new file mode 100644 index 0000000..08f1046 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \347\275\221\347\273\234\344\273\213\347\273\215.md" @@ -0,0 +1,30 @@ +Service是Kubernetes的核心概念,通过创建Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。 + +Kubernetes 的网络模型假定了所有 Pod 都在一个可以直接连通的扁平的网络空间中,这在GCE ( Google Compute Engine )里面是现成的网络模型, Kubernetes 假定这个网络已经存在。而在私有云里搭建Kubernetes 集群,就不能假定这个网络已经存在了。我们需要自己实现这个网络假设,将不同节点上的 Docker 容器之间的互相访问先打通,然后运行 Kubernetes。 + +## 一、Flannel 网络 + +Flannel 是 CoreOS 团队针对 Kubernetes 设计的一个网络规划服务,简单来说,它的功能是让集群中的不同节点主机创建的 Docker 容器都具有全集群唯一的虚拟 IP 地址。而且它还能在这些 IP 地址之间建立一个覆盖网络( Overlay Network ),通过这个覆盖网络,将数据包原封不动地传递到目标容器内。 + +ETCD 与 Flannel 之间的关系: + +- 存储管理 Flannel 可分配的 IP 地址段资源 +- 监控 ETCD 中每个 Pod 的实际地址,并在内存中建立维护 Pod + +### 1.1、Flannel 网络流程图: + +![4.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602262833553.png) + +### 1.2、 Service 不同情况下网络通信方式 + +同Pod内部通讯:同一个 Pod 共享同一个网络命名空间,共享同一个 Linux 协议栈。 + +**不同pod通讯:** + +不在同一台主机:docker0 网段与宿主机网卡是两个完全不同的 IP 网段,不同 Node 之间的通信只能通过宿主机的物理网卡进行 + +同一台机器:由 Docker0 网桥直接转发请求 + +Pod与Service: 目前基于性能考虑,全部为 iptables 维护和转发 + +Pod与外网:Pod 向外网发送请求,查找路由表 , 转发数据包到宿主机的网卡,宿主网卡完成路由选择后,iptables行Masquerade ,把源 IP 更改为宿主网卡的 IP ,然后向外网服务器发送请求。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \350\257\201\344\271\246\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \350\257\201\344\271\246\344\273\213\347\273\215.md" new file mode 100644 index 0000000..8065514 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \350\257\201\344\271\246\344\273\213\347\273\215.md" @@ -0,0 +1,41 @@ +## 一、证书机制说明 + +Kubernetes 作为一个分布式集群的管理工具,保证集群的安全性是其一个重要的任务。API Server 是集群内部各个组件通信的中介,也是外部控制的入口。所以 Kubernetes 的安全机制基本就是围绕保护 API Server 来设计的,Kubernetes 使用了认证(Authentication)、鉴权(Authorization)、准入控制(AdmissionControl)三步来保证API Server的安全 。 + +## 二、证书认证(Authentication) + +**HTTP Token 认证:** + +通过一个 Token 来识别合法用户,HTTP Token 的认证是用一个很长的特殊编码方式的并且难以被模仿的字符串 - Token 来表达客户的一种方式。Token 是一个很长的很复杂的字符串,每一个 Token 对应一个用户名存储在 API Server 能访问的文件中,当客户端发起 API 调用请求时,需要在 HTTP Header 里放入 Token。 + +**HTTP Base 认证:** + +通过用户名+密码的方式进行认证,用户名+密码用 BASE64 算法进行编码后的字符串放在 HTTP Request 中的 Heather Authorization 域里发送给服务端,服务端收到后进行编码,获取用户名及密码。 + +**HTTPS 证书认证:** + +HTTPS 证书认证是最严格的认证,基于 CA 根证书签名的客户端身份认证方式。 + +## 三、证书授权与鉴权(Authorization) + +AlwaysDeny:表示拒绝所有的请求,一般用于测试 + +AlwaysAllow:允许接收所有请求,如果集群不需要授权流程,则可以采用该策略 + +Webbook:**通过调用外部 REST 服务对用户进行授权 + +RBAC(Role-Based Access Control):基于角色的访问控制,现行默认规则 + +ABAC(Attribute-Based Access Control): 基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制 + +## 四、证书准入控制 + +准入控制是API Server的插件集合,通过添加不同的插件,实现额外的准入控制规则。甚至于API Server的一些主要的功能都需要通过 Admission Controllers 实现,这里我们列举几个插件的功能: + +NamespaceLifecycle:防止在不存在的 namespace 上创建对象,防止删除系统预置 namespace,删除namespace 时,连带删除它的所有资源对象 + +LimitRanger:确保请求的资源不会超过资源所在 Namespace 的 LimitRange 的限制。 + +ResourceQuota:确保请求的资源不会超过资源的 ResourceQuota 限制。 + +ServiceAccount:为Pod中的进程和外部用户提供身份信息。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \351\233\206\347\276\244\351\203\250\347\275\262.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \351\233\206\347\276\244\351\203\250\347\275\262.md" new file mode 100644 index 0000000..13d872d --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \351\233\206\347\276\244\351\203\250\347\275\262.md" @@ -0,0 +1,420 @@ +## 一、集群部署准备 + +Kubernetes有三种安装方式: + +1、通过yum进行安装 + +2、通过二进制文件进行安装 + +3、命令行工具kubeadm进行安装 + +kubeadm是Kubernetes官方提供的用于快速安装Kubernetes集群的工具,致力于简化集群的安装过程,并解决Kubernetes集群的高可用问题。 + +``` +安装 kubernetes 所需软件包: +链接:https://pan.baidu.com/s/1GoxSWAHkB3AVn9aRzGMjkQ +密码:az0o +``` + +## 二、部署kubernetes集群 + +### 2.1、环境准备 + +**准备好三台虚拟机分别做为 master、node-1、node-2** + +**虚拟机硬件配置:** + +master:2CPU、4G + +node-1:2CPU、2G +node-2:2CPU、2G + +![5.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602263258940.png) + +**网络配置:** +master:192.168.2.20 +node-1:192.168.2.21 +node-2:192.168.2.22 +**操作系统:** +Centos-8 最小化安装 + +**主机名设置:** + +``` +# hostnamectl set-hostname master + +# hostnamectl set-hostname node-1 + +# hostnamectl set-hostname node-2 +``` + +**设置Hosts文件的相互解析:** + +``` +# cat /etc/hosts + +192.168.2.20 master +192.168.2.21 node-1 +192.168.2.22 node-2 +``` + +![6.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602263331272.png) + +### 2.2、操作系统初始化 + +a、关闭swap + +``` +# swapoff -a && sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab +``` + +b、关闭Selinux + +``` +# setenforce 0 && sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config +``` + +c、关闭firewalld + +``` +# systemctl stop firewalld && systemctl disable firewalld +``` + +d、重置Iptables并设置空规则: + +``` +# yum -y install iptables-services && systemctl start iptables && systemctl enable iptables && iptables -F && service iptables save +``` + +e、关闭不需要的服务: + +``` +# systemctl stop postfix && systemctl disable postfix +``` + +### 2.3、配置网络源 + +``` +- 下载阿里云的yum源文件: +# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-8.repo + +- 安装epel源: +# yum install -y https://mirrors.aliyun.com/epel/epel-release-latest-8.noarch.rpm + +- 将repo 配置中的地址替换为阿里云镜像站地址: +# sed -i 's|^#baseurl=https://download.fedoraproject.org/pub|baseurl=https://mirrors.aliyun.com|' /etc/yum.repos.d/epel* +# sed -i 's|^metalink|#metalink|' /etc/yum.repos.d/epel* + +- 配置docker源: + +# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo + +- 设置kubernetes源: + +# cat < /etc/yum.repos.d/kubernetes.repo +[kubernetes] +name=Kubernetes +baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ +enabled=1 +gpgcheck=1 +repo_gpgcheck=1 +gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg +EOF +``` + +### 2.4、操作系统环境优化 + +``` +- 安装依赖包: + +# yum makecache && yum -y update + +# yum -y install conntrack ipvsadm ipset jq iptables curl sysstat libseccomp wget vim-enhanced lrzsz net-tools git net-tools psmisc bash-completion yum-utils.noarch nmap bind-utils + +- 设置系统时区:中国/上海 + +# timedatectl set-timezone Asia/Shanghai + +- 将当前的 UTC 时间写入硬件时钟: + +# timedatectl set-local-rtc 0 + +- 重启依赖于系统时间的服务: + +# systemctl restart rsyslog + +# systemctl restart crond +``` + +### 2.5、针对Kubernetes调整内核参数 + +``` +# cat > kubernetes.conf < /etc/systemd/journald.conf.d/99-prophet.conf < /etc/sysconfig/modules/ipvs.modules < /etc/docker/daemon.json < kubeadm-config.yaml + +进行如下修改: + +localAPIEndpoint: +advertiseAddress: 192.168.2.20 +··· +kubernetesVersion: v1.15.1 +··· +networking: +podSubnet: "10.244.0.0/16" +serviceSubnet: 10.96.0.0/12 +--- +apiVersion: kubeproxy.config.k8s.io/v1alpha1 +kind: KubeProxyConfiguration +featureGates: +SupportIPVSProxyMode: true +mode: ipvs +``` + +完整配置文件如下(注意格式): + +``` +apiVersion: kubeadm.k8s.io/v1beta2 +bootstrapTokens: +- groups: + - system:bootstrappers:kubeadm:default-node-token + token: abcdef.0123456789abcdef + ttl: 24h0m0s + usages: + - signing + - authentication +kind: InitConfiguration +localAPIEndpoint: + advertiseAddress: 192.168.2.20 + bindPort: 6443 +nodeRegistration: + criSocket: /var/run/dockershim.sock + name: master + taints: + - effect: NoSchedule + key: node-role.kubernetes.io/master +--- +apiServer: + timeoutForControlPlane: 4m0s +apiVersion: kubeadm.k8s.io/v1beta2 +certificatesDir: /etc/kubernetes/pki +clusterName: kubernetes +controllerManager: {} +dns: + type: CoreDNS +etcd: + local: + dataDir: /var/lib/etcd +imageRepository: k8s.gcr.io +kind: ClusterConfiguration +kubernetesVersion: v1.15.1 +networking: + dnsDomain: cluster.local + podSubnet: "10.244.0.0/16" + serviceSubnet: 10.96.0.0/12 +scheduler: {} +--- +apiVersion: kubeproxy.config.k8s.io/v1alpha1 +kind: KubeProxyConfiguration +featureGates: + SupportIPVSProxyMode: true +mode: ipvs +``` + +### 2.11、安装配置集群 + +```powersell +- 安装Master: +# kubeadm init --config=kubeadm-config.yaml --upload-certs | tee kubeadm-init.log + +- 添加 --upload-certs 参数可以在后续执行加入节点时自动分发证书文件。追加的 tee kubeadm-init.log 用以输出日志 + +# mkdir -p $HOME/.kube +# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config +# chown $(id -u):$(id -g) $HOME/.kube/config + +- 安装flannel网络: +(官网地址:https://github.com/coreos/flannel) + +# wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml + +# kubectl apply -f kube-flannel.yml + +- Node节点加入: 注意下面这条命令在安装完Master后会输出在屏幕上 + +# kubeadm join 192.168.2.20:6443 --token abcdef.0123456789abcdef \ +--discovery-token-ca-cert-hash sha256:424676564f3a33bc1d7d9451a322613188e39dcaa004386b453794d8135adaad + +- kubectl有很多子命令和参数,为了提高使用命令行的效率,通常建议安装 kebectl 的 bash 命令补全脚本: + +# source <(kubectl completion bash) +# echo "source <(kubectl completion bash)" >> ~/.bashrc +``` + +![7.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602263691236.png) + +2.12、查看集群状态 + +``` +# kuberctl get nodes -o wide +``` + +**集群可用性验证** + +``` +# cat pod.yaml + +apiVersion: v1 +kind: Pod +metadata: + name: nginx + labels: + app: web +spec: + containers: + - name: nginx + image: docker.io/nginx + ports: + - containerPort: 80 + + +# kubectl create -f pod.yaml +``` + +通过命令查看是否创建成功: kubectl get pod -o wide + +![10.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602263894333.png) + +通过修改容器名称将nginx修改为nginx-1后,创建第二个pod资源后查看: + +![11.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602263911832.png) + +通过curl命令查看服务是否可以正常被访问: + +![12.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602263931169.png) + +## 三、集群版本更新 + +这里演示的是以 K8S 1.15版本为例,具体的版本升级以你们自己实验机上安装的版本号为准!!! + +kubeadm提供了upgrade命令用于对kubeadm安装的Kubernetes集群进行升级,但是开始之前需要注意,虽然kubeadm的升级不会触及工作负载,但还是要在升级之前做好备份,升级过程可能会因为Pod的变化而造成容器重启。 + +首先执行 kubeadm upgrade plan 命令: + +![13.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602263954459.png) + +可以看到,我们当前使用的版本为1.15.1,最新的稳定版本为1.15.7,并且告知我们,如果想要进行升级操作,那么首先我们需要将kubeadm升级为1.15.7版本,然后执行升级命令。 + +执行命令 yum -y install kubeadm-1.15.7 进行升级 + +![14.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602263982064.png) + +将kubeadm升级完成后我们执行 kubeadm upgrade apply v1.15.7 升级命令,系统询问,是否进行更新输入 Y 回车 + +![15.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602263998442.png) + +等待片刻后,升级完成 + +![16.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602264017416.png) + +然后再将 kubectl 与 kubelet 进行升级,然后重启 kubelet 后,查看节点版本已经升级为1.15.7 + +![17.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602264037871.png) + +查看组件状态 + +![18.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602264052827.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \351\233\206\347\276\244\351\253\230\345\217\257\347\224\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \351\233\206\347\276\244\351\253\230\345\217\257\347\224\250.md" new file mode 100644 index 0000000..57cfbd0 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes \351\233\206\347\276\244\351\253\230\345\217\257\347\224\250.md" @@ -0,0 +1,495 @@ +## 一、Kubernetes 集群高可用 + +下载链接: + +链接:https://pan.baidu.com/s/1U3UWaZSA5b5bf3QnR_XZGw 密码:2flw + +### 1.1、环境准备 + +**准备好五台虚拟机分别做为 master、master-1、master-2、node-1、node-2** + +**虚拟机硬件配置:** + +master-1:2CPU、2G + +master-2:2CPU、2G + +master-3:2CPU、2G + +node-1:2CPU、2G + +node-2:2CPU、2G + +**网络配置:** + +master-1:192.168.1.160 + +master-2:192.168.1.161 + +master-3:192.168.1.162 + +node-1:192.168.1.163 + +node-2:192.168.1.164 + +**操作系统:** + +Centos-8.1 最小化安装 + +**主机名设置:** + +hostnamectl set-hostname zutuanxue-master-1 + +hostnamectl set-hostname zutuanxue-master-2 + +hostnamectl set-hostname zutuanxue-master-3 + +hostnamectl set-hostname zutuanxue-node-1 + +hostnamectl set-hostname zutuanxue-node-2 + +**设置Hosts文件的相互解析:** + +vim /etc/hosts + +192.168.1.160 zutuanxue-master-1 + +192.168.1.161 zutuanxue-master-2 + +192.168.1.162 zutuanxue-master-3 + +192.168.1.163 zutuanxue-node-1 + +192.168.1.164 zutuanxue-node-2 + +192.168.1.170 zutuanxue-master-vip + +### 1.2、操作系统初始化 (所有节点) + +> ``` +> 关闭swap: +> +> swapoff -a && sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab +> +> 关闭Selinux: +> +> setenforce 0 && sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config +> +> 关闭firewalld: +> +> systemctl stop firewalld && systemctl disable firewalld +> +> 重置Iptables并设置空规则: +> +> yum -y install iptables-services && systemctl start iptables && systemctl enable iptables && iptables -F && service iptables save +> +> 关闭不需要的服务: +> +> systemctl stop postfix && systemctl disable postfix +> ``` + +### 1.3、配置网络源 (所有节点) + +> ``` +> yum源: +> +> wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-8.repo +> +> repo源: +> +> yum install -y https://mirrors.aliyun.com/epel/epel-release-latest-8.noarch.rpm +> +> 将 repo 配置中的地址替换为阿里云镜像站地址: +> +> sed -i 's|^#baseurl=https://download.fedoraproject.org/pub|baseurl=https://mirrors.aliyun.com|' /etc/yum.repos.d/epel* +> +> sed -i 's|^metalink|#metalink|' /etc/yum.repos.d/epel* +> +> +> docker源: +> +> yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo +> +> kubernetes源: +> +> cat < /etc/yum.repos.d/kubernetes.repo +> [kubernetes] +> name=Kubernetes +> baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ +> enabled=1 +> gpgcheck=1 +> repo_gpgcheck=1 +> gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg +> EOF +> ``` + +### 1.4、操作系统环境优化 (所有节点) + +> ``` +> 11、安装依赖包: +> +> yum -y makecache && yum -y update +> +> yum -y install conntrack ipvsadm ipset jq iptables curl sysstat libseccomp wget vim-enhanced lrzsz net-tools git net-tools psmisc bash-completion yum-utils.noarch nmap bind-utils +> +> 12、设置系统时区:中国/上海 +> +> timedatectl set-timezone Asia/Shanghai +> +> 13、将当前的 UTC 时间写入硬件时钟: +> +> timedatectl set-local-rtc 0 +> +> 14、重启依赖于系统时间的服务: +> +> systemctl restart rsyslog +> +> systemctl restart crond +> ``` + +### 1.5、针对Kubernetes调整内核参数 (所有节点) + +> ``` +> cat > kubernetes.conf < net.bridge.bridge-nf-call-iptables=1 +> net.bridge.bridge-nf-call-ip6tables=1 +> net.ipv4.ip_forward=1 +> net.ipv4.tcp_tw_recycle=0 +> vm.swappiness=0 # 禁止使用 swap 空间,只有当系统 OOM 时才允许使用它 +> vm.overcommit_memory=1 # 不检查物理内存是否够用 +> vm.panic_on_oom=0 # 开启 OOM +> fs.inotify.max_user_instances=8192 +> fs.inotify.max_user_watches=1048576 +> fs.file-max=52706963 +> fs.nr_open=52706963 +> net.ipv6.conf.all.disable_ipv6=1 +> net.netfilter.nf_conntrack_max=2310720 +> EOF +> +> cp kubernetes.conf /etc/sysctl.d/kubernetes.conf +> +> sysctl -p /etc/sysctl.d/kubernetes.conf +> ``` + +### 1.6、设置 rsyslogd 和 systemd journald (所有节点) + +> ``` +> mkdir /var/log/journal # 持久化保存日志的目录 +> +> mkdir /etc/systemd/journald.conf.d +> +> cat > /etc/systemd/journald.conf.d/99-prophet.conf < [Journal] +> Storage=persistent # 持久化保存到磁盘 +> Compress=yes # 压缩历史日志 +> SyncIntervalSec=5m # 写入硬盘间隔 +> RateLimitInterval=30s # 限制日志的生成速率-时间段内 +> RateLimitBurst=1000 # 限制日志的生成速率-每个服务最多允许产生的日志数量(条数) +> SystemMaxUse=10G # 最大占用空间 10G +> SystemMaxFileSize=200M # 单日志文件最大 200M +> MaxRetentionSec=2week # 日志保存时间 2 周 +> ForwardToSyslog=no # 不将日志转发到 syslog +> EOF +> +> systemctl restart systemd-journald +> ``` + +### 1.7、关闭 NUMA (所有节点) + +``` +cp /etc/default/grub{,.bak} + +vim /etc/default/grub # 在 GRUB_CMDLINE_LINUX 一行添加 `numa=off` 参数,如下所示: + +GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rhgb quiet numa=off" + +cp /boot/grub2/grub.cfg{,.bak} + +grub2-mkconfig -o /boot/grub2/grub.cfg +``` + +### 1.8、设置kube-proxy开启ipvs的前置条件 (所有节点) + +``` +modprobe br_netfilter + +cat > /etc/sysconfig/modules/ipvs.modules < /etc/docker/daemon.json < mtu 1500 qdisc mq state UP group default qlen 1000 + link/ether fa:16:3e:c0:d5:a6 brd ff:ff:ff:ff:ff:ff + inet 192.168.1.160/24 brd 192.168.2.255 scope global noprefixroute eth0 + valid_lft forever preferred_lft forever + inet 192.168.1.170/24 scope global secondary eth0 + valid_lft forever preferred_lft forever +``` + +### 1.11、安装 Kubeadm (在主节点) + +``` +yum -y install kubeadm-1.18.1 kubectl-1.18.1 kubelet-1.18.1 + +systemctl enable kubelet.service +``` + +### 1.12、初始化Master节点 (主节点) + +``` +kubeadm config print init-defaults > kubeadm-config.yaml + +进行如下修改: + +localAPIEndpoint: +advertiseAddress: 192.168.1.160 +··· +controlPlaneEndpoint: "192.168.1.170:6444" +··· +kubernetesVersion: v1.18.1 +··· +networking: +podSubnet: "10.244.0.0/16" +serviceSubnet: 10.96.0.0/12 +--- +apiVersion: kubeproxy.config.k8s.io/v1alpha1 +kind: KubeProxyConfiguration +featureGates: +SupportIPVSProxyMode: true +mode: ipvs +``` + +完整配置如下: + +``` +apiVersion: kubeadm.k8s.io/v1beta2 +bootstrapTokens: +- groups: + - system:bootstrappers:kubeadm:default-node-token + token: abcdef.0123456789abcdef + ttl: 24h0m0s + usages: + - signing + - authentication +kind: InitConfiguration +localAPIEndpoint: + advertiseAddress: 192.168.1.160 + bindPort: 6443 +nodeRegistration: + criSocket: /var/run/dockershim.sock + name: zutuanxue-master-1 + taints: + - effect: NoSchedule + key: node-role.kubernetes.io/master +--- +apiServer: + timeoutForControlPlane: 4m0s +apiVersion: kubeadm.k8s.io/v1beta2 +certificatesDir: /etc/kubernetes/pki +clusterName: kubernetes +controlPlaneEndpoint: "192.168.1.170:6444" +controllerManager: {} +dns: + type: CoreDNS +etcd: + local: + dataDir: /var/lib/etcd +imageRepository: k8s.gcr.io +kind: ClusterConfiguration +kubernetesVersion: v1.18.1 +networking: + dnsDomain: cluster.local + podSubnet: "10.244.0.0/16" + serviceSubnet: 10.96.0.0/12 +scheduler: {} +--- +apiVersion: kubeproxy.config.k8s.io/v1alpha1 +kind: KubeProxyConfiguration +featureGates: +SupportIPVSProxyMode: true +mode: ipvs +``` + +### 1.13、安装配置集群 (主节点) + +``` +安装Master: + +kubeadm init --config=kubeadm-config.yaml --upload-certs | tee kubeadm-init.log + +mkdir -p $HOME/.kube + +cp -i /etc/kubernetes/admin.conf $HOME/.kube/config + +chown $(id -u):$(id -g) $HOME/.kube/config + +安装flannel网络: + +wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml + +kubectl apply -f kube-flannel.yml +``` + +![194.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602490973408.png) + +### 1.14、将从节点加入集群 + +``` +#---------------------Master 节点使用下面这条命令加入集群------------------------------# + kubeadm join 192.168.1.170:6444 --token abcdef.0123456789abcdef \ + --discovery-token-ca-cert-hash sha256:ec36d9832497453d5297e86f13928a3374e831da8861372f2086ea79c000bad7 \ + --control-plane --certificate-key 80847d457d198a8ce1483817e11de8a472ff68b94410db2574e55c2f56f1b7be +#----------------------------------------------------------------------------------# + +#------------------------Node 节点使用下面这条命令加入集群------------------------------# +kubeadm join 192.168.1.170:6444 --token abcdef.0123456789abcdef \ + --discovery-token-ca-cert-hash sha256:ec36d9832497453d5297e86f13928a3374e831da8861372f2086ea79c000bad7 +#---------------------------------------------------------------------------------# + + +在主服务器上将 /data 推送到从服务器上: + +scp -r /data root@192.168.1.161:/ + +scp -r /data root@192.168.1.162:/ + + +分别在每台从服务器上执行下列命令 + +cd /data/lb + +./start-haproxy.sh + +./start-keepalived.sh + +yum -y install kubeadm-1.18.1 kubectl-1.18.1 kubelet-1.18.1 + +systemctl enable kubelet.service + +# 注意,不要执行错命令,千万别复制成 Node 加入集群的命令在辅服务器上执行!!! + +kubeadm join 192.168.1.170:6444 --token abcdef.0123456789abcdef \ + --discovery-token-ca-cert-hash sha256:ec36d9832497453d5297e86f13928a3374e831da8861372f2086ea79c000bad7 \ + --control-plane --certificate-key 80847d457d198a8ce1483817e11de8a472ff68b94410db2574e55c2f56f1b7be + +mkdir -p $HOME/.kube + +cp -i /etc/kubernetes/admin.conf $HOME/.kube/config + +chown $(id -u):$(id -g) $HOME/.kube/config +``` + +![195.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602490985331.png) + +### 1.15、在所有节点执行 + +``` +vim /data/lb/etc/haproxy.cfg 在文件底部修改相关参数(要么自己补齐,要么将#号去掉): + +server rancher01 192.168.1.160:6443 +server rancher02 192.168.1.161:6443 +server rancher03 192.168.1.162:6443 + +删掉老的 HAProxy ,重新启动一个: + +docker rm -f HAProxy-K8S && bash /data/lb/start-haproxy.sh + +所有 Master 上执行下列命令: + +# kubectl有很多子命令和参数,为了提高使用命令行的效率,通常建议安装 kebectl 的 bash 命令补全脚本 +source <(kubectl completion bash) + +echo "source <(kubectl completion bash)" >> ~/.bashrc +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes\346\261\241\347\202\271\345\222\214\345\256\271\345\277\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes\346\261\241\347\202\271\345\222\214\345\256\271\345\277\215.md" new file mode 100644 index 0000000..460b0b9 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes\346\261\241\347\202\271\345\222\214\345\256\271\345\277\215.md" @@ -0,0 +1,108 @@ +## 一、Taint 和 Toleration介绍 + +节点亲和性,是 pod 的一种属性(偏好或硬性要求),它使 pod 被吸引到一类特定的节点。Taint 则相反,它使节点能够排斥一类特定的pod**,Taint 和 toleration 相互配合,可以用来避免 pod 被分配到不合适的节点上**。每个节点上都可以应用一个或多个taint ,这表示对于那些不能容忍这些 taint 的 pod,是不会被该节点接受的。如果将 toleration 应用于 pod上,则表示这些 pod 可以(但不要求)被调度到具有匹配 taint 的节点上。 + +## 二、污点(Taint) + +### 2.1、 污点 ( Taint ) 的组成 + +使用 kubectl taint 命令可以给某个Node节点设置污点,Node 被设置上污点之后就和 Pod 之间存在了一种相斥的关系,可以让 Node 拒绝 Pod 的调度执行,甚至将 Node 已经存在的 Pod 驱逐出去。 + +``` +污点的对象是: 节点 +``` + +**每个污点的组成: key=value:effect** + +每个污点有一个 key 和 value 作为污点的标签,其中 value 可以为空,effect 描述污点的作用。当前 taint effect 支持如下三个选项: + +- NoSchedule :表示 k8s 将不会将 Pod 调度到具有该污点的 Node 上。 +- PreferNoSchedule :表示 k8s 将尽量避免将 Pod 调度到具有该污点的 Node 上。 +- NoExecute :表示 k8s 将不会将 Pod 调度到具有该污点的 Node 上,同时会将 Node 上已经存在的 Pod 驱逐出去。 + +![124.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602324961878.png) + +我们的 Master 节点上本来就已经有了污点,所以我们在创建 Pod 的时候,才不会将 Pod 创建在 Master 节点上。 + +### 2.2、污点的设置、查看和去除 + +**设置污点** +kubectl taint nodes node1 key1=value1:NoSchedule +![125.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602325320975.png) +这里我们打了一个 NoExecute 的标签,这个时候我们可以看到,之前在 node-1 上的 Pod 已经被驱离,因为这是自助式的 Pod ,没有我们的资源管理器进行管理的 Pod ,所以被驱离以后没有在被创建出来。 + +**节点说明中,查找 Taints 字段** +kubectl describe pod pod-name + +![126.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602325420235.png) + +**去除污点** +kubectl taint nodes node1 key1:NoSchedule- + +![127.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602325509089.png) + +## 三、容忍(Tolerations) + +设置了污点的 Node 将根据 taint 的 effect:NoSchedule、PreferNoSchedule、NoExecute 和 Pod 之间产生互斥的关系,Pod 将在一定程度上不会被调度到 Node 上。 但我们可以在 Pod 上设置容忍 ( Toleration ) ,意思是设置了容忍的 Pod 将可以容忍污点的存在,可以被调度到存在污点的 Node 上。 + +``` +容忍的对象是: pod +``` + +比如,我们现在将 node-1 与 node-2 都标记上污点,这个时候我们来创建一个 Pod 看一下: + +![128.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602325621955.png) + +**pod.spec.tolerations** + +``` +tolerations: +- key: "key1" + operator: "Equal" + value: "value1" + effect: "NoSchedule" + tolerationSeconds: 3600 + +# 其中 key, vaule, effect 要与 Node 上设置的 taint 保持一致 +# operator 的值为 Exists 将会忽略 value 值 +# tolerationSeconds 用于描述当 Pod 需要被驱逐时可以在 node 上继续保留运行的时间 + +# 1、当不指定 key 值时,表示容忍所有的污点 key: +tolerations: +- operator: "Exists" + +# 2、当不指定 effect 值时,表示容忍所有的污点作用 +tolerations: +- key: "key" +operator: "Exists" + + +# 3、有多个 Master 存在时,防止资源浪费,可以如下设置 +kubectl taint nodes Node-Name node-role.kubernetes.io/master=:PreferNoSchedule +``` + +**这个时候我们来设置一下,看下效果:** + +``` +vim tole-pod.yaml + +apiVersion: v1 +kind: Pod +metadata: + name: pod-1 + labels: + app: pod-1 +spec: + containers: + - name: pod-1 + image: docker.io/busybox + command: [ "/bin/sh", "-c", "sleep 600s" ] + tolerations: + - key: "node" + operator: "Equal" + value: "zutuaxue" + effect: "NoExecute" + tolerationSeconds: 30 # 容忍时间,超过该时间后将其驱离 +``` + +![129.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602325779865.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes\350\212\202\347\202\271\344\270\216 Pod \344\272\262\345\222\214\346\200\247.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes\350\212\202\347\202\271\344\270\216 Pod \344\272\262\345\222\214\346\200\247.md" new file mode 100644 index 0000000..c8b6a62 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes\350\212\202\347\202\271\344\270\216 Pod \344\272\262\345\222\214\346\200\247.md" @@ -0,0 +1,228 @@ +## 一、节点亲和性策略介绍 + +**pod.spec.nodeAffinity** + +- preferredDuringSchedulingIgnoredDuringExecution:软策略 +- requiredDuringSchedulingIgnoredDuringExecution:硬策略 + +``` +preferred:首选,较喜欢 +required:需要,必修 +``` + +**键值运算关系:** + +- In:label 的值在某个列表中 +- NotIn:label 的值不在某个列表中 +- Gt:label 的值大于某个值 +- Lt:label 的值小于某个值 +- Exists:某个 label 存在 +- DoesNotExist:某个 label 不存在 + +## 二、节点与Pod硬亲和性 + +**requiredDuringSchedulingIgnoredDuringExecution** + +``` +#创建pod的模板yaml文件 +vim affinity.yaml + +apiVersion: v1 +kind: Pod +metadata: + name: affinity + labels: + app: node-affinity-pod +spec: + containers: + - name: with-node-affinity + image: docker.io/nginx + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/hostname + operator: NotIn + values: + - node-1 +``` + +通过修改 Pod 名称的方式多创建几个 Pod 查看结果: +![119.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602265359628.png) + +这个时候,我们将 operator 修改为 “In” ,node-1 修改为 node-3, + +``` +vim affinity.yaml + +apiVersion: v1 +kind: Pod +metadata: + name: affinity-3 + labels: + app: node-affinity-pod +spec: + containers: + - name: with-node-affinity + image: docker.io/nginx + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/hostname + operator: In + values: + - node-3 +``` + +查看下结果: +![120.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602265434289.png) + +这个时候可以看到,我们新创建的 Pod 一直处于 Pending 的状态,这是因为我们没有Node-3这个节点,且采用的是硬亲和性策略的原因所导致的。 + +## 三、节点与Pod软亲和性 + +**preferredDuringSchedulingIgnoredDuringExecution** +为了解决上述因为硬亲和性创建Pod不成功的问题,我们通过设置软亲和性策略后再次创建一个pod affinity-pod-a测试。 + +``` +vim affinity-1.yaml + +apiVersion: v1 +kind: Pod +metadata: + name: affinity-a + labels: + app: node-affinity-pod-a +spec: + containers: + - name: with-node-affinity-a + image: docker.io/nginx + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + preference: + matchExpressions: + - key: kubernetes.io/hostname + operator: In + values: + - node-3 +``` + +我们没有 node-3 节点,这个时候我们创建看一下: + +![121.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602265504683.png) + +我们再将 node-3 修改为 node-1 看一下: + +![122.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602265522269.png) + +**通过实验我们得出关于节点与pod亲和力策略** + +- 硬限制是:我必须在某个节点或我必须不在某个节点。 +- 软限制是:我想在某个节点或我不想在某个节点,实在不行,我也可以将就。 + +**软硬限制结合策略** +策略优先级:先满足硬限制,然后满足软限制 + +``` +软硬限制可以结合使用,先满足硬限制,然后满足软限制= + +apiVersion: v1 +kind: Pod +metadata: + name: affinity + labels: + app: node-affinity-pod +spec: + containers: + - name: with-node-affinity + image: docker.io/nginx + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/hostname + operator: NotIn + values: + - node-2 + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + preference: + matchExpressions: + - key: source + operator: In + values: + - zutuanxue_com +``` + +## 四、Pod 亲和性 + +pod.spec.affinity.podAffinity/podAntiAffinity + +- preferredDuringSchedulingIgnoredDuringExecution:软策略 +- requiredDuringSchedulingIgnoredDuringExecution:硬策略 + +``` +podAffinity: pod之间亲和,pod在同一网段 +podAntiAffinity:pod之间反亲和,pod在不同网段 +``` + +### 4.1、pod亲和性 + +``` +vim test-pod.yaml + +apiVersion: v1 +kind: Pod +metadata: + name: pod-1 + labels: + app: pod-1 +spec: + containers: + - name: pod-1 + image: docker.io/busybox + command: [ "/bin/sh", "-c", "sleep 600s" ] + +#-----------------------------# 分割线 #--------------------------------------# + +vim affinity-pod.yaml + +apiVersion: v1 +kind: Pod +metadata: + name: pod-3 + labels: + app: pod-3 +spec: + containers: + - name: pod-3 + image: docker.io/nginx + affinity: + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - pod-1 + topologyKey: kubernetes.io/hostname +``` + +我们来看一下结果: + +![123.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602265725369.png) + +## 五、关于亲和性总结 + +| 调度策略 | 匹配标签 | 操作符 | 拓扑域支持 | 调度目标 | +| --------------- | -------- | -------------------------------------- | ---------- | -------------------------- | +| nodeAffinity | 主机 | In, NotIn, Exists,DoesNotExist, Gt, Lt | 否 | 指定主机 | +| podAffinity | POD | In, NotIn, Exists,DoesNotExist | 是 | POD与指定POD同一拓扑域 | +| podAnitAffinity | POD | In, NotIn, Exists,DoesNotExist | 是 | POD与指定POD不在同一拓扑域 | \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes\350\212\202\347\202\271\344\270\216\344\273\244\347\211\214\347\256\241\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes\350\212\202\347\202\271\344\270\216\344\273\244\347\211\214\347\256\241\347\220\206.md" new file mode 100644 index 0000000..950928f --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes\350\212\202\347\202\271\344\270\216\344\273\244\347\211\214\347\256\241\347\220\206.md" @@ -0,0 +1,185 @@ +## 一、令牌管理 + +**查看令牌** + +``` +[root@master ~]# kubeadm token list +``` + +**删除令牌** + +``` +[root@master ~]# kubeadm token delete <令牌值> +``` + +**创建令牌-临时令牌** + +``` +临时 token 生成: +[root@master ~]# kubeadm token create +此 token 的有效期为 24 小时,过期后需要重新生成 token 。 +``` + +**创建令牌-临时令牌** + +``` +永久 token 生成: +[root@master ~]# kubeadm token create --ttl 0 +此 token 的有有效期为永久有效。 + +为了安全起见,建议使用临时 token ,而不要使用永久的 token 。 +``` + +## 二、K8S节点管理 + +### 2.1、查看节点 + +``` +查看当前的节点信息: +[root@master ~]# kubectl get nodes + +NAME STATUS ROLES AGE VERSION +master Ready master 4h40m v1.18.1 +node-1 Ready 4h39m v1.18.1 +node-2 Ready 3h58m v1.18.1 +``` + +### 2.2、删除节点 + +**驱逐即将删除node节点上的pod** + +如果需要从集群中移除 node-2 这个 Node ,在 master上执行下面的命令,安全驱逐节点上面所有的 pod,该命令执行成功后 node节点开始释放所有 pod ,并且不接收新的 pod 进程 + +``` +[root@master ~]# kubectl drain node-2 --delete-local-data --force --ignore-daemonsets +注:默认情况下,kubectl drain 会忽略那些不能杀死的系统类型的 pod + + +参数说明: + +--force:当一些pod不是经 ReplicationController, ReplicaSet, Job, DaemonSet 或者 StatefulSet 管理的时候 +就需要用 --force 来强制执行 (例如:kube-proxy) + +--ignore-daemonsets:无视 DaemonSet 管理下的 Pod + +--delete-local-data:如果有 mount local volumn 的 pod,会强制杀掉该 pod 并把料清除掉,另外如果跟本身的配置信息有冲突时,drain就不会执行 + +该命令会安全驱逐节点上面所有的 pod ,安全驱逐的方式将会允许 pod 里面的容器遵循指定的 Pod DisruptionBudgets 执行优雅的中止。 +``` + +kubectl drain 返回成功表明所有的 pod (除了前面排除的那些)已经被安全驱逐(遵循期望优雅的中止期,并且没有违反任何应用程序级别的中断预算)。然后,通过对物理机断电或者在云平台上删除节点所在的虚拟机,都能安全的将节点移除。 + +**恢复node,继续接收新pod** +节点上的pod被驱逐后,如果不删除node的话,进行完对应的升级或维护后可以恢复node,恢复接收新的pod进程 + +``` +[root@master ~]# kubectl uncordon node-2 +``` + +**删除节点** + +``` +[root@master ~]# kubectl delete node <节点名称> +``` + +**删除后进行查看** + +``` +[root@master ~]# kubectl get nodes + +NAME STATUS ROLES AGE VERSION +master Ready master 4h40m v1.18.1 +node-1 Ready 4h39m v1.18.1 +``` + +### 2.3、集群节点扩展 + +**Master 节点加入集群** + +``` + kubeadm join 192.168.2.100:6444 \ + --token abcdef.0123456789abcdef \ + --discovery-token-ca-cert-hash sha256:ec36d9832497453d5297e86f13928a3374e831da8861372f2086ea79c000bad7 \ + --control-plane --certificate-key 80847d457d198a8ce1483817e11de8a472ff68b94410db2574e55c2f56f1b7be +``` + +**Node节点加入集群** + +``` +kubeadm join 192.168.2.100:6444 --token abcdef.0123456789abcdef \ + --discovery-token-ca-cert-hash sha256:ec36d9832497453d5297e86f13928a3374e831da8861372f2086ea79c000bad7 + +``` + +以上信息为高可用的加入信息,这里所显示的 token 的有效期为 24 小时,在有效期内,可以直接使用命令加入我们的集群,如果超过了有效期的话,那么我们的 token 已经过期,就需要我们重新生成 token ,然后在进行加入。 + +### 2.4、token过期的解决方案 + +token 过期后,生成新的token + +**2.4.1、节点加入单master集群** + +- 创建新的token + +``` +[root@master ~]# kubeadm token create + +W0410 16:22:44.706213 11426 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io] +oqghzy.40dftxcaeegan10t < 这一条信息是我们新生成的 token > +``` + +- 获取ca证书的hash值 + token 生成完后,我们还需要获取 ca 证书 sha256 编码 hash 值,查看当前 k8s 集群的 ca 证书 sha256 编码 hash 值,我们的 ca 证书默认存放在 /etc/kubernetes/pki 目录下: + +``` +[root@master ~]# openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //' + +a5a41919d1200e21bcafe066a1423ca904aaa70a9dd1582ea668993e8e831fc7 < 这一条信息就是我们的 hash 值 > +``` + +- 将新master加入单master的集群 + 然后我们通过新生成的 token 和 ca 证书 sha256 编码 hash 值重新组装得到有效的 work node 加入集群命令: + +``` +[root@master ~]# kubeadm join 192.168.2.20:6443 --token oqghzy.40dftxcaeegan10t \ + --discovery-token-ca-cert-hash sha256:a5a41919d1200e21bcafe066a1423ca904aaa70a9dd1582ea668993e8e831fc7 + +这里需要注意一下,如果是加入单 master 集群,那么我们使用的 IP 地址为我们 master 的 IP 地址与 6443 端口。 + + +#或者我们也可以使用命令,直接生成出包含新的token与hash值的完整加入命令,这样更加轻松有效。 + +[root@master ~]# kubeadm token create --print-join-command + +kubeadm join 192.168.2.100:6444 --token 1kuag1.elna9kktnznxr50m --discovery-token-ca-cert-hash sha256:a5a41919d1200e21bcafe066a1423ca904aaa70a9dd1582ea668993e8e831fc7 +``` + +**2.4.2、节点加入高可用集群** + +高可用集群与单master集群不同的地方在于还要生成用于新master加入的证书 + +- 首先生成新的 token + +``` +[root@master ~]# kubeadm token create --print-join-command +``` + +- 生成新的用于 master 加入的证书 + +``` +[root@master ~]# kubeadm init phase upload-certs --upload-certs + +W0410 16:49:45.773081 21497 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io] +[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace +[upload-certs] Using certificate key: +1d57c7bbf579b9bdcf3441cd45dd01a2a066e75b45fe672a0f5295e07a337d0d < 这一条信息是用于 master 加入的证书信息 > +``` + +然后我们通过新生成的 token 和 ca 证书 sha256 编码 hash 值还有新生成的 master 证书的值,重新组装得到有效的 master 加入集群命令: + +``` +kubeadm join 192.168.2.100:6444 \ + --token 1kuag1.elna9kktnznxr50m \ + --discovery-token-ca-cert-hash sha256:a5a41919d1200e21bcafe066a1423ca904aaa70a9dd1582ea668993e8e831fc7 \ + --control-plane --certificate-key 1d57c7bbf579b9bdcf3441cd45dd01a2a066e75b45fe672a0f5295e07a337d0d +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes\351\233\206\347\276\244\350\260\203\345\272\246\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes\351\233\206\347\276\244\350\260\203\345\272\246\344\273\213\347\273\215.md" new file mode 100644 index 0000000..f33c5bc --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Kubernetes\351\233\206\347\276\244\350\260\203\345\272\246\344\273\213\347\273\215.md" @@ -0,0 +1,52 @@ +## 一、Kubernetes调度 + +Scheduler 是 kubernetes 的调度器,主要的任务是把定义的 pod 分配到集群的节点上。听起来非常简单,但有很多要考虑的问题: + +- 公平:如何保证每个节点都能被分配资源 +- 资源高效利用:集群所有资源最大化被使用 +- 效率:调度的性能要好,能够尽快地对大批量的 pod 完成调度工作 +- 灵活:允许用户根据自己的需求控制调度的逻辑 + +Sheduler 是作为单独的程序运行的,启动之后会一直监听 API Server,获取 PodSpec.NodeName 为空的 pod,对每个 pod 都会创建一个 binding,表明该 pod 应该放到哪个节点上。 + +### 1.1、调度过程 + +调度分为几个部分: + +- 首先是过滤掉不满足条件的节点,这个过程称为**预选(predicate)** ; +- 然后对通过的节点按照优先级排序,这个是**优选(priority)** ; +- 最后从中选择优先级最高的节点。如果中间任何一步骤有错误,就直接返回错误。 + +预选有一系列的算法可以使用: + +- PodFitsResources :节点上剩余的资源是否大于 pod 请求的资源 +- PodFitsHost :如果 pod 指定了 NodeName,检查节点名称是否和 NodeName 匹配 +- PodFitsHostPorts :节点上已经使用的 port 是否和 pod 申请的 port 冲突 +- PodSelectorMatches :过滤掉和 pod 指定的 label 不匹配的节点 +- NoDiskConflict :已经 mount 的 volume 和 pod 指定的 volume 不冲突,除非它们都是只读 + +如果在预选过程中没有合适的节点,pod 会一直在 pending 状态,不断重试调度,直到有节点满足条件。经过这个步骤,如果有多个节点满足条件,就继续优选过程,按照优先级大小对节点排序,优先级由一系列键值对组成,键是该优先级项的名称,值是它的权重(该项的重要性)。这些优先级选项包括: + +- LeastRequestedPriority :通过计算 CPU 和 Memory 的使用率来决定权重,使用率越低权重越高。换句话说,这个优先级指标倾向于资源使用比例更低的节点。 +- BalancedResourceAllocation :节点上 CPU 和 Memory 使用率越接近,权重越高。这个应该和上面的一起使用,不应该单独使用。 +- ImageLocalityPriority :倾向于已经有要使用镜像的节点,镜像总大小值越大,权重越高 + +通过算法对所有的优先级项目和权重进行计算,得出最终的结果。 + +### 1.2、自定义调度器 + +除了 kubernetes 自带的调度器,你也可以编写自己的调度器。通过 spec:schedulername 参数指定调度器的名字,可以为 pod 选择某个调度器进行调度。比如下面的 pod 选择 my-scheduler 进行调度,而不是默认的default-scheduler : + +``` +apiVersion: v1 +kind: Pod +metadata: + name: annotation-second-scheduler + labels: + name: multischeduler-example +spec: + schedulername: my-scheduler + containers: + - name: pod-with-second-annotation-container + image: gcr.io/google_containers/pause:2.0 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/PV \344\270\216 PVC\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/PV \344\270\216 PVC\344\273\213\347\273\215.md" new file mode 100644 index 0000000..f17d5ff --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/PV \344\270\216 PVC\344\273\213\347\273\215.md" @@ -0,0 +1,129 @@ +## 一、概念介绍 + +**PersistentVolume (PV)** 是由管理员设置的存储,它是群集的一部分。就像节点是集群中的资源一样,PV 也是集群中的资源。 PV 是Volume 之类的卷插件,但具有独立于使用 PV 的 Pod 的生命周期。此 API 对象包含存储实现的细节,即 NFS、iSCSI 或特定于云供应商的存储系统。 + +**PersistentVolumeClaim (PVC)** 是用户存储的请求。它与 Pod 相似。Pod 消耗节点资源,PVC 消耗 PV 资源。Pod 可以请求特定级别的资源(CPU 和内存)。声明可以请求特定的大小和访问模式(例如,可以以读/写一次或 只读多次模式挂载)。 + +**静态 pv** + +集群管理员创建一些 PV。它们带有可供群集用户使用的实际存储的细节。它们存在于 Kubernetes API 中,可用于消费。 + +**动态** + +当管理员创建的静态 PV 都不匹配用户的 PersistentVolumeClaim 时,集群可能会尝试动态地为 PVC 创建卷。此配置基于 StorageClasses :PVC 必须请求 [存储类],并且管理员必须创建并配置该类才能进行动态创建。声明该类为 “” 可以有效地禁用其动态配置 + +要启用基于存储级别的动态存储配置,集群管理员需要启用 API server 上的 DefaultStorageClass [准入控制器]。例如,通过确保 DefaultStorageClass 位于 API server 组件的 --admission-control 标志,使用逗号分隔的有序值列表中,可以完成此操作。 + +**绑定** + +master 中的控制环路监视新的 PVC,寻找匹配的 PV(如果可能),并将它们绑定在一起。如果为新的 PVC 动态调配 PV,则该环路将始终将该 PV 绑定到 PVC。否则,用户总会得到他们所请求的存储,但是容量可能超出要求的数量。一旦 PV 和 PVC 绑定后, PersistentVolumeClaim 绑定是排他性的,不管它们是如何绑定的。 PVC 跟PV 绑定是一对一的映射。 + +## 二、持久化卷 + +**持久化卷声明的保护** + +PVC 保护的目的是确保由 pod 正在使用的 PVC 不会从系统中移除,因为如果被移除的话可能会导致数据丢失 + +``` +# 注意 :当 pod 状态为 “pending” 并且 Pod 已经分配给节点 或者 Pod 为 “running” 状态时,pvc 处于活动状态。 +``` + +当启用PVC 保护 alpha 功能时,如果用户删除了一个 pod 正在使用的 PVC,则该 PVC 不会被立即删除。PVC 的删除将被推迟,直到 PVC 不再被任何 pod 使用。 + +**持久化卷类型** + +PersistentVolume 类型以插件形式实现。Kubernetes 目前支持以下插件类型: + +``` +GCEPersistentDisk、AWSElasticBlockStore、AzureFile、AzureDisk、FC(Fibre Channel)、FlexVolume、Flocker、NFS、iSCSI、RBD、(Ceph Block Device)、CephFS、Cinder、(OpenStack block storage)、Glusterfs、VsphereVolume、Quobyte、Volumes、HostPath等等** +``` + +**持久卷演示代码:** + +``` +apiVersion: v1 +kind: PersistentVolume +metadata: + name: pv0001 +spec: + capacity: + storage: 5Gi + volumeMode: Filesystem + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Recycle + storageClassName: slow + mountOptions: + - hard + - nfsvers=4.1 + nfs: + path: /tmp + server: 192.168.1.169 +``` + +## 三、访问模式 + +**PV 访问模式** + +PersistentVolume 可以以资源提供者支持的任何方式挂载到主机上。如下表所示,供应商具有不同的功能,每个 PV 的访问模式都将被设置为该卷支持的特定模式。例如,NFS 可以支持多个读/写客户端,但特定的 NFS PV 可能以只读方式导出到服务器上。每个 PV 都有一套自己的用来描述特定功能的访问模式。 + +- ReadWriteOnce——该卷可以被单个节点以读/写模式挂载 +- ReadOnlyMany——该卷可以被多个节点以只读模式挂载 +- ReadWriteMany——该卷可以被多个节点以读/写模式挂载 + +**在命令行中,访问模式缩写为:** + +- RWO - ReadWriteOnce +- ROX - ReadOnlyMany +- RWX - ReadWriteMany + +``` +# !注意 :一个卷一次只能使用一种访问模式进行挂载,即使它支持很多访问模式,GCEPersistentDisk 可以由单个节点做为 ReadWriteOnce 模式挂载,或者由多个节点以 ReadOnlyMany 模式挂载,但是不能同时挂载。 +``` + +| Volume 插件 | ReadWriteOnce | ReadOnlyMany | ReadWriteMany | +| :--------------------------------------: | :-----------: | :----------: | :---------------------: | +| AWSElasticBlockStoreAWSElasticBlockStore | ✓ | - | - | +| AzureFile | ✓ | ✓ | ✓ | +| AzureDisk | ✓ | - | - | +| CephFS | ✓ | ✓ | ✓ | +| Cinder | ✓ | - | - | +| FC | ✓ | ✓ | - | +| FlexVolume | ✓ | ✓ | - | +| Flocker | ✓ | - | - | +| GCEPersistentDisk | ✓ | ✓ | - | +| Glusterfs | ✓ | ✓ | ✓ | +| HostPath | ✓ | - | - | +| iSCSI | ✓ | ✓ | - | +| PhotonPersistentDisk | ✓ | - | - | +| Quobyte | ✓ | ✓ | ✓ | +| NFS | ✓ | ✓ | ✓ | +| RBD | ✓ | ✓ | - | +| VsphereVolume | ✓ | - | - (当 pod 并列时有效) | +| PortworxVolume | ✓ | - | ✓ | +| ScaleIO | ✓ | ✓ | - | +| ScaleIO | ✓ | - | - | + +## 四、回收策略 + +**Retain(保留)——手动回收** + +**Recycle(回收)——基本擦除( rm -rf /thevolume/\* )【已被废弃】** + +**Delete(删除)——关联的存储资产(例如 AWS EBS、GCE PD、Azure Disk 和 OpenStack Cinder 卷)将被删除** + + + +## 五、状态 + +**卷可以处于以下的某种状态:** + +**Available(可用)——一块空闲资源还没有被任何声明绑定** + +**Bound(已绑定)——卷已经被声明绑定** + +**Released(已释放)——声明被删除,但是资源还未被集群重新声明** + +**Failed(失败)——该卷的自动回收失败** + +**命令行会显示绑定到 PV 的 PVC 的名称** \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \344\273\213\347\273\215.md" new file mode 100644 index 0000000..01f0855 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \344\273\213\347\273\215.md" @@ -0,0 +1,163 @@ +## 一、什么是 Pod + +Pod 是 kubernetes 集群中最小的部署和管理的基本单元,协同寻址,协同调度。 + +Pod 是一个或多个容器的集合,是一个或一组服务(进程)的抽象集合。 + +Pod 中可以共享网络和存储(可以简单理解为一个逻辑上的虚拟机,但并不是虚拟机)。 + +Docker 是目前 Pod 最常用的容器环境,但仍支持其他容器环境。 + +![27.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602327208631.png) + +**我们可以看到,当我们启动一个 Pod 以后,每个 Pod 内都会有一个 Pause 的容器** + +每个 Pod 里运行着一个特殊的被称之为 Pause 的容器,其他容器则为业务容器,这些业务容器共享 Pause 容器的网络栈和 Volume 挂载卷,因此他们之间通信和数据交换更为高效,在设计时我们可以充分利用这一特性将一组密切相关的服务进程放入同一个 Pod 中。同一个 Pod 里的容器之间仅需通过 localhost 就能互相通信。 + +## 二、Pod 的网络 + +- 每个Pod被分配了唯一的IP地址,该Pod内的所有容器共享一个网络空间,包括IP和端口。 +- 同个Pod不同容器之间通过localhost通信,Pod内端口不能冲突。 +- 不同Pod之间的通信则通过IP+端口的形式来访问到Pod内的具体服务(容器)。 + +![28.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602326898782.png) + +## 三、Pod 的用法 + +Pod 实际上是容器的集合,在 kubernetes 中对运行容器的要求为 “容器的主程序需要一直在前台运行,而不是后台运行“ 当多个应用之间是紧耦合的关系时,可以将多个应用一起放在一个Pod中,同个Pod中的多个容器之间互相访问可以通过localhost来通信。 + + 相关命令: + +| 操作 | 命令 | +| :----------: | :----------------------------------------------------------- | +| 创建 | kubectl create -f 文件名.yaml | +| 查询运行状态 | kubectl get pods -n 空间名称,如果不指定则默认显示default空间内的 pod | +| 查询详情 | kebectl describe pod Pod名称 -n 空间名称,如果不指定则默认显示default空间内的 pod | +| 删除 | kubectl delete pod Pod名称 / kubectl delete pod --all | +| 更新 | kubectl replace 文件名.yaml | + +## 四、Pod 定义文件 + +在 kubernetes 中,一般使用 **yaml** 格式的文件来创建符合我们预期期望的 pod + +基本语法为: + +- 缩进时不允许使用Tab键,只允许使用空格 +- 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可 +- \#标识注释,从这个字符一直到行尾,都会被解释器忽略 + +这样的 yaml 文件我们一般称为资源清单,如下表所示: + +``` +必选字段: + +apiVersion: v1 #必选,版本号,例如v1 +kind: Pod #必选,资源类别 +metadata: #必选,元数据 + name: string #必选,Pod名称 + namespace: string #创建资源所属于的命名空间,不写的话默认创建在default空间 + labels: #自定义标签 + - name: string #自定义标签名称 +spec: #必选,Pod中容器的详细定义 + containers: #必选,Pod中容器列表 + - name: string #必选,容器名称 + image: string #必选,容器的镜像名称 +``` + +**示例文件:** + +``` +apiVersion: v1 +kind: Pod +metadata: + name: nginx + labels: + app: web +spec: + containers: + - name: nginx + image: docker.io/nginx + ports: + - containerPort: 80 +``` + +**完整资源清单详情示例:** + +``` +apiVersion: v1 #必选,版本号,例如v1 +kind: Pod #必选,Pod +metadata: #必选,元数据 + name: string #必选,Pod名称 + namespace: string #创建资源所属于的命名空间,不写的话默认创建在default空间 + labels: #自定义标签 + - name: string #自定义标签名字 + annotations: #自定义注释列表 + - name: string +spec: #必选,Pod中容器的详细定义 + containers: #必选,Pod中容器列表 + - name: string #必选,容器名称 + image: string #必选,容器的镜像名称 + imagePullPolicy: [Always | Never | IfNotPresent] #获取镜像的策略 Alawys表示下载镜像 IfnotPresent表示优先使用本地镜像,否则下载镜像,Nerver表示仅使用本地镜像 + command: [string] #容器的启动命令列表,如不指定,使用打包时使用的启动命令 + args: [string] #容器的启动命令参数列表 + workingDir: string #容器的工作目录 + volumeMounts: #挂载到容器内部的存储卷配置 + - name: string #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名 + mountPath: string #存储卷在容器内mount的绝对路径,应少于512字符 + readOnly: boolean #是否为只读模式 + ports: #需要暴露的端口库号列表 + - name: string #端口号名称 + containerPort: int #容器需要监听的端口号 + hostPort: int #容器所在主机需要监听的端口号,默认与Container相同 + protocol: string #端口协议,支持TCP和UDP,默认TCP + env: #容器运行前需设置的环境变量列表 + - name: string #环境变量名称 + value: string #环境变量的值 + resources: #资源限制和请求的设置 + limits: #资源限制的设置 + cpu: string #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数 + memory: string #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数 + requests: #资源请求的设置 + cpu: string #Cpu请求,容器启动的初始可用数量 + memory: string #内存清楚,容器启动的初始可用数量 + livenessProbe: #对Pod内个容器健康检查的设置,当探测无响应几次后将自动重启该容器,检查方法有exec、httpGet和tcpSocket,对一个容器只需设置其中一种方法即可 + exec: #对Pod容器内检查方式设置为exec方式 + command: [string] #exec方式需要制定的命令或脚本 + httpGet: #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port + path: string + port: number + host: string + scheme: string + HttpHeaders: + - name: string + value: string + tcpSocket: #对Pod内个容器健康检查方式设置为tcpSocket方式 + port: number + initialDelaySeconds: 0 #容器启动完成后首次探测的时间,单位为秒 + timeoutSeconds: 0 #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒 + periodSeconds: 0 #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次 + successThreshold: 0 + failureThreshold: 0 + securityContext: + privileged:false + restartPolicy: [Always | Never | OnFailure] #Pod的重启策略,Always表示一旦不管以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示不再重启该Pod + nodeSelector: obeject #设置NodeSelector表示将该Pod调度到包含这个label的node上,以key:value的格式指定 + imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定 + - name: string + hostNetwork:false #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络 + volumes: #在该pod上定义共享存储卷列表 + - name: string #共享存储卷名称 (volumes类型有很多种) + emptyDir: {} #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值 + hostPath: string #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录 + path: string #Pod所在宿主机的目录,将被用于同期中mount的目录 + secret: #类型为secret的存储卷,挂载集群与定义的secre对象到容器内部 + scretname: string + items: + - key: string + path: string + configMap: #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部 + name: string + items: + - key: string + path: string +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204 NameSpace.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204 NameSpace.md" new file mode 100644 index 0000000..3a42661 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204 NameSpace.md" @@ -0,0 +1,58 @@ +## 一、Pod 的 NameSpace + +使用 kubectl 管理命名空间及其包含的资源相当简单。在这一节中,我们将演示一些最常见的命名空间操作,便于你开始有效地分割资源。 + +在我们进行创建命名空间之前,先说一下 Kubernetes 是如何自动设置它的,在默认情况下,新的集群上有三个命名空间: + +**default:** 向集群中添加对象而不提供命名空间,这样它会被放入默认的命名空间中。在创建替代的命名空间之前,该命名空间会充当用户新添加资源的主要目的地,无法删除。 + +**kube-public:** 此命名空间是自动创建的,并且所有用户(包括未经过身份验证的用户)都可以读取。此命名空间主要用于群集使用,以防某些资源在整个群集中可见且可公开读取。此命名空间的公共方面只是一个约定,而不是一个要求。 + +**kube-system:** kube-system 命名空间用于 Kubernetes 管理的 Kubernetes 组件,一般规则是,避免向该命名空间添加普通的工作负载。它一般由系统直接管理,因此具有相对宽松的策略。 + +**要显示集群中可用的所有命名空间,使用 kubectl get namespaces 命令:** + +![40.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602327687759.png) + +**使用 kubectl get namespaces kube-system 指定namespaces 查看:** + +![41.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602327697548.png) + +**使用 kubectl describe namespaces kube-system 指定namespaces查看详情:** + +![42.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602327705291.png) + +**namespaces status 有两个状态:** + +- Active : 命名空间正在使用中 +- Terminating : 正在删除命名空间,不能用于新对象 + +**使用 kubectl create namespace test 创建 namespaces :** + +![43.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602327714091.png) + +**使用 kubectl delete namespaces test 删除 namespaces :** + +![44.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602327720750.png) + +**正常使用 namespaces ,只需要在我们创建的资源清单内指定即可:** + +``` +apiVersion: v1 +kind: Pod +metadata: + name: nginx + namespaces: test # 指定所属 namespaces + labels: + app: web +spec: + containers: + - name: nginx + image: docker.io/nginx + ports: + - containerPort: 80 +``` + +![45.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602327731423.png) + +可以看到,如果我们不指定查看具体是那个命名空间的 Pod ,那么会默认显示为 default 空间内的 Pod 信息。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204 Service \344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204 Service \344\273\213\347\273\215.md" new file mode 100644 index 0000000..fb58a85 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204 Service \344\273\213\347\273\215.md" @@ -0,0 +1,65 @@ +## 一、Service 介绍 + +**Kubernetes Service 定义了这样一种抽象:** + +一个 Pod 的逻辑分组,一种可以访问它们的策略,通常称为微服务。 这一组 Pod 能够被 Service 访问到,通常是通过 Label Selector 。 + +![69.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328903734.png) + +**Service能够提供负载均衡的能力,但是在使用上有以下限制:** + +只提供4层负载均衡能力,而没有7层功能,但有时我们可能需要更多的匹配规则来转发请求,这点上 4 层负载均衡是不支持的 + +**Service的网络类型** + +**ClusterIp:** 默认类型,自动分配一个仅 Cluster 内部可以访问的虚拟 IP + +![70.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328914937.png) + +**NodePort:** 在 ClusterIP 基础上为 Service 在每台机器上绑定一个端口,这样就可以通过 : NodePort 来访问该服务 + +![71.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328923772.png) + +**LoadBalancer:** 在 NodePort 的基础上,借助 cloud provider 创建一个外部负载均衡器,并将请求转发到: NodePort + +**ExternalName:** 把集群外部的服务引入到集群内部来,在集群内部直接使用。没有任何类型代理被创建,这只有 kubernetes 1.7 或更高版本的 kube-dns 才支持 + +## 二、Service 的代理模式分类 + +**VIP 和 Service 代理** + +在 Kubernetes 集群中,每个 Node 运行一个 kube-proxy 进程。 kube-proxy 负责为 Service 实现了一种VIP(虚拟 IP)的形式,而不是 ExternalName 的形式。 在 Kubernetes v1.0 版本,代理完全在 userspace。在Kubernetes v1.1 版本,新增了 iptables 代理,但并不是默认的运行模式。 从 Kubernetes v1.2 起,默认就是iptables 代理。 + +**在 Kubernetes v1.8.0-beta.0 中,添加了 ipvs 代理** + +**在 Kubernetes 1.14 版本开始默认使用 ipvs 代理** + +**在 Kubernetes v1.0 版本, Service 是 “4层”(TCP/UDP over IP)概念** + +**在 Kubernetes v1.1 版本,新增了 Ingress API(beta 版),用来表示 “7层”(HTTP)服务** + +**userspace 代理模式** + +![72.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328942567.png) + +**iptables 代理模式** + +![73.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328949839.png) + +**ipvs 代理模式** + +这种模式,kube-proxy 会监视 Kubernetes Service 对象和 Endpoints ,调用 netlink 接口以相应地创建ipvs 规则并定期与 Kubernetes Service 对象和 Endpoints 对象同步 ipvs 规则,以确保 ipvs 状态与期望一致。访问服务时,流量将被重定向到其中一个后端 Pod + +与 iptables 类似,ipvs 于 netfilter 的 hook 功能,但使用哈希表作为底层数据结构并在内核空间中工作。这意味着 ipvs 可以更快地重定向流量,并且在同步代理规则时具有更好的性能。此外,ipvs 为负载均衡算法提供了更多选项,例如: + +**rr :轮询调度** + +**lc :最小连接数** + +**dh :目标哈希** + +**sh :源哈希** + +**sed :最短期望延迟** + +**nq : 不排队调度** \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204 init Containers.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204 init Containers.md" new file mode 100644 index 0000000..190a55a --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204 init Containers.md" @@ -0,0 +1,109 @@ +Pod 我们可以分为两类,一种属于自主式 Pod ,还有一种属于控制器管理的 Pod 。 + +## 一、Pod 的 initContainers + +**基本概念:** + +Pod能够具有多个容器,应用运行在容器里面,但是它也可能有一个或多个先于应用容器启动的Init容器,Init容器与普通的容器非常像,除了如下两点: + +- Init容器总是运行到成功完成为止 +- 每个Init容器都必须在下一个Init容器启动之前成功完成 + +如果Pod的Init容器失败, Kubernetes 会不断地重启该Pod,直到Init容器成功为止。然而,如果Pod对应的restartPolicy为Never,它不会重新启动。 + +**它的优势:** + +因为Init容器具有与应用程序容器分离的单独镜像,所以它们的启动相关代码具有如下优势: + +1、它们可以包含并运行实用工具, 但是出于安全考虑,是不建议在应用程序容器镜像中包含这些实用工具的 + +2、它们可以包含使用工具和定制化代码来安装,但是不能出现在应用程序镜像中。例如,创建 镜像没必要FROM另一个镜像,只需要在安装过程中使用类似sed、 awk、python或dig这样的工具。 + +3、应用程序镜像可 以分离出创建和部署的角色,而没有 必要联合它们构建一个单独的镜像。 + +4、Init容器使用Linux Namespace, 所以相对应用程序容器来说具有不同的文件系统视图。因此,它们能够具有访问Secret 的权限,而应用程序容器则不能。 + +5、它们必须在应用程序 容器启动之前运行完成, 而应用程序容器是并行运行的, 所以Init容器能够提供了-种简单的阻塞或延迟应用容器的启动的方法,直到满足了一组先决条件。 + +**initContainers示例:** + +``` +apiVersion: v1 +kind: Pod +metadata: + name: initc-demo + labels: + app: myapp +spec: + containers: + - name: myapp-container + image: docker.io/busybox + command: ['sh', '-c', 'echo The app is running! && sleep 3600'] + initContainers: + - name: init-myservice + image: docker.io/busybox + command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;'] + - name: init-mydb + image: busybox + command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;'] +``` + +**我们创建模版资源后查看结果为:** + +![29.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602327495326.png) + +**我们查看一下日志:** + +![30.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602327507111.png) + +这个时候我们可以看到因为解析不成功,所以初始化程序卡住了,那么先创建满足第一个解析的service资源: + +``` +kind: Service +apiVersion: v1 +metadata: + name: myservice +spec: + ports: + - protocol: TCP + port: 80 + targetPort: 9376 +``` + +创建完成后我们在查看一下 Pod 的状态: + +![31.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602327523513.png) + +第一个 init 初始化程序已经成功,这是因为,我们创建名为“myservice”的 SVC 的数据会写到我们内部的DNS(coreDNS) 上,因为可以正常的解析了,所以第一个 init 初始化程序完成,同理我们加入第二个 init 初始化程序的 SVC 后查看 Pod 状态: + +``` +kind: Service +apiVersion: v1 +metadata: + name: mydb +spec: + ports: + - protocol: TCP + port: 80 + targetPort: 9377 +``` + +![32.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602327544223.png) + + 这个时候我们可以看到,第二个 init 初始化程序已经完成,我们的主容器 Pod 开始初始化,最后成功开始运行。 + +**initContainers特殊说明(重要点)** + +1、在 Pod 启动过程中,Init 容器会按顺序在网络和数据卷初始化之后启动。每个容器必须在下一个容器启动之前成功退出。 + +2、如果由于运行时或失败退出,将导致容器启动失败,它会根据 Pod 的 restartPolicy 指定的策略进行重试。然而,如果 Pod 的 restartPolicy 设置为 Always , Init 容器失败时会使用 RestartPolicy 策略。 + +3、在所有的Init容器没有成功之前,Pod 将不会变成 Ready 状态。Init 容器的端口将不会在 Service 中进行聚集。正在初始化中的 Pod 处于 Pending 状态,但会将 Initializing 状态设置为 true。 + +4、如果 Pod 重启,所有 Init 容器必须重新执行。 + +5、对 Init 容器 spec 的修改被限制在容器 image 字段, 修改其他字段都不会生效。 更改 Init 容器的 image字段,等价于重启该 Pod。 + +6、Init 容器具有应用容器的所有字段。除了 readinessProbe , 因为Init容器无法定义不同于完成 (completion) 的就绪 (readiness) 之外的其他状态。这会在验证过程中强制执行。 + +7、在 Pod 中的每个 app 和 Init 容器的名称必须唯一,与任何其它容器共享同个名称,会在验证时抛出错误。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\345\201\245\345\272\267\346\243\200\346\237\245-\346\216\242\351\222\210.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\345\201\245\345\272\267\346\243\200\346\237\245-\346\216\242\351\222\210.md" new file mode 100644 index 0000000..d340340 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\345\201\245\345\272\267\346\243\200\346\237\245-\346\216\242\351\222\210.md" @@ -0,0 +1,153 @@ +## 一、Pod 的健康检查-探针 + +### 1.1、探针基本概念 + +探针是由 kubelet 对容器执行的定期诊断。要执行诊断,kubelet 调用由容器实现的 Handler 有三种类型的处理程序: + +1、**ExecAction**: 在容器内执行指定命令。如果命令退出时返回码为0则认为诊断成功。 + +2、**TCPSocketAction**: 对指定端口上的容器的IP地址进行 TCP 检查,如果端口打开则诊断被认为是成功的。 + +3、**HTTPGetAction**: 对指定的端口和路径上的容器的IP地址执行 HTTP Get 请求。如果响应的状态码大于等于 200 且小于 400,则诊断被认为是成功的。 + +每次探测都将获得以下三种结果之: + +- 成功:容器通过了诊断。 +- 失败:容器未通过诊断。 +- 未知:诊断失败,因此不会采取任何行动。 + +**探测方式** + +1、**livenessProbe**: 指示容器是否正在运行。如果存活探测失败,则 kubelet 会杀死容器,并且容器将受到其重启策略的影响。如果容器不提供存活探针,则默认状态为 Success 。 + +2、**readinessProbe**: 指示容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与 Pod 匹配的所有 Service 的端点中删除该 Pod 的 IP 地址。初始延迟之前的就绪状态默认为 Failure 如果容器不提供就绪探针,则默认状态为 Success 。 + +### 1.2、探针实现 + +**就绪检测:** + +``` +vim readinessProbe-httpget.yaml + +apiVersion: v1 +kind: Pod +metadata: + name: readiness-httpget-pod +spec: + containers: + - name: readiness-httpget-container + image: docker.io/nginx + imagePullPolicy: IfNotPresent + readinessProbe: + httpGet: + port: 80 + path: /index.html + initialDelaySeconds: 1 + periodSeconds: 3 +``` + +**我们先运行该 Pod 然后查看其状态:** + +![33.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602327611392.png) + +**已经成功开始运行,这个时候我们进入到该 Pod 然后将其 index.html 文件删除后,在看其状态:** + +![34.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602327618520.png) + +**这个时候我们可以看到,虽然容器处于 Running 状态,但是却处于 No Ready 的状态,这个时候我们通过kubectl describe pod readiness-httpget-pod 命令,查看一下具体的信息:** + +![35.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602327625620.png) + +**我们看到,显示 “Readiness probe failed: HTTP probe failed with statuscode: 404” 就绪探测失败,错误代码 404 表明页面不存在。** + +### 1.3、存活检测: + +- EXEC + +``` +vim livenessProbe-exec.yaml + +apiVersion: v1 +kind: Pod +metadata: + name: liveness-exec-pod +spec: + containers: + - name: liveness-exec-container + image: docker.io/busybox + imagePullPolicy: IfNotPresent + command: ["/bin/sh","-c","touch /tmp/live ; sleep 60; rm -rf /tmp/live; sleep 3600"] + livenessProbe: + exec: + command: ["test","-e","/tmp/live"] + initialDelaySeconds: 1 + periodSeconds: 3 +``` + +**然后查看下我们 Pod 的实时状态:** + +![36.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602327643605.png) + +经过一段时间等待,我们发现 liveness-exec-pod 出现了重启的现象,这是因为,在我们创建这个 Pod 的时候,我们会在 /tmp 下创建一个 live 的文件,60 秒以后会将其删除,当进行存活检测的时候发现该文件没有了,那么 Pod 认为里面的容器死亡了,就会重启,那么就会重新执行一遍 yaml 文件内的配置,这个时候 live 文件又存在了,但是 60 秒以后,又会被删除,就会在重启一遍,以此类推。 + +- HTTPGET + +``` +vim livenessProbe-httpget.yaml + +apiVersion: v1 +kind: Pod +metadata: + name: liveness-httpget-pod +spec: + containers: + - name: liveness-httpget-container + image: docker.io/nginx + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: 80 + livenessProbe: + httpGet: + port: http + path: /index.html + initialDelaySeconds: 1 + periodSeconds: 3 + timeoutSeconds: 10 +``` + +**然后我们查看一下 Pod 的状态:** + +![37.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602327654983.png) + +**这个时候我们通过 “kubectl exec liveness-httpget-pod -it – rm -rf /usr/share/nginx/html/index.html” 命令将 index.html 文件删除掉,我们在进行查看 Pod 的状态:** + +![38.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602327663027.png) + +经过一段时间等待,我们发现 liveness-httpget-pod 出现了重启的现象,这是因为,当我们手动删除了 index.html 文件后,当进行存活检测的时候发现该文件没有了,那么 Pod 认为里面的容器死亡了,就会重启,那么就会重新执行一遍 yaml 文件内的配置,这个时候 index.html 文件又存在了,如果我们再次删除该文件,就会在重启一遍,以此类推。 + +- TCPSocket + +``` +vim livenessProbe-tcp.yaml + +apiVersion: v1 +kind: Pod +metadata: + name: probe-tcp +spec: + containers: + - name: nginx + image: docker.io/nginx + livenessProbe: + initialDelaySeconds: 5 + timeoutSeconds: 1 + tcpSocket: + port: 808 +``` + +**然后我们查看一下 Pod 的状态:** + +![39.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602327672456.png) + +我们可以看到,开始的时候,Pod 创建成功,但是 30 秒以后,重启了第一次,在经过 30 秒以后,又重启了一次,这是因为, nginx 默认开启的端口为 80 ,而当我们开始存活检测的时候,端口为 808 ,因为没有这个端口,所以认定 Pod 死亡,所以重启,当又开始存活检测的时候,依然没有端口,所以继续重启,以此类推。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\345\255\230\345\202\250\344\271\213Configmap.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\345\255\230\345\202\250\344\271\213Configmap.md" new file mode 100644 index 0000000..a61d219 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\345\255\230\345\202\250\344\271\213Configmap.md" @@ -0,0 +1,213 @@ +## 一、Configmap介绍 + +ConfigMap 功能在 Kubernetes1.2 版本中引入,许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。ConfigMap API 给我们提供了向容器中注入配置信息的机制,ConfigMap 可以被用来保存单个属性,也可以用来保存整个配置文件或者 JSON 二进制大对象。 + +**1、使用目录创建** + +``` +在我们的 configmap-map 文件夹下有两个文件分别为: test-1 与 test-2 里面的内容分别为: + +cat test-1 : + +enemies=aliens +lives=3 +enemies.cheat=true +enemies.cheat.level=noGoodRotten +secret.code.passphrase=UUDDLRLRBABAS +secret.code.allowed=true +secret.code.lives=30 + +cat test-2 : + +color.good=purple +color.bad=yellow +allow.textmode=true +how.nice.to.look=fairlyNice + +创建:kubectl create configmap zutuanxue --from-file=configmap-test +# —from-file 指定在目录下的所有文件都会被用在 ConfigMap 里面创建一个键值对,键的名字就是文件名,值就是文件的内容 +``` + +**创建完成后我们来看一下信息:** + +![101.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602332491199.png) + +**通过命令 kubectl get configmaps zutuanxue -o yaml 查看一下完整的信息:** + +![102.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602332496649.png) + +**2、使用文件创建** + +``` +我们依然使用 test-1 与 test-2 这两个文件 + +kubectl create configmap zutuanxue-1 --from-file=configmap-test/test-2 + +# —from-file 这个参数可以使用多次,你可以使用两次分别指定上个实例中的那两个配置文件,效果就跟指定整个目录是一样的 +``` + +**我们来看一下效果:** + +![103.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602332506906.png) + +**3、使用字面值创建** + +``` +使用文字值创建,利用 —from-literal 参数传递配置信息,该参数可以使用多次,格式如下: + +kubectl create configmap zutuanxue --from-literal=test.how=hello-word --from-literal=test.type=hi-word +``` + +**我们来看一下效果:** + +![104.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602332516673.png) + +## 二、Pod 中使用 ConfigMap + +**1、使用 ConfigMap 来替代环境变量** + +``` +vim test.yaml + +apiVersion: v1 +kind: ConfigMap +metadata: + name: special-config + namespace: default +data: + special.how: hello-word + special.type: hi-word + +#-----------------------------# 分割线 #--------------------------------------# + +vim test-env.yaml + +apiVersion: v1 +kind: ConfigMap +metadata: + name: env-config + namespace: default +data: + log_level: INFO + +#-----------------------------# 分割线 #--------------------------------------# + +vim test-pod.yaml + +apiVersion: v1 +kind: Pod +metadata: + name: dapi-test-pod +spec: + containers: + - name: test-container + image: docker.io/busybox + command: [ "/bin/sh", "-c", "env" ] + env: + - name: SPECIAL_LEVEL_KEY + valueFrom: + configMapKeyRef: + name: special-config + key: special.how + - name: SPECIAL_TYPE_KEY + valueFrom: + configMapKeyRef: + name: special-config + key: special.type + envFrom: + - configMapRef: + name: env-config + restartPolicy: Never +``` + +**运行以后我们来看一下结果:** + +![105.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602332527266.png) + +**2、用 ConfigMap 设置命令行参数** + +``` +这里我们依然使用 test.yaml 文件内的参数: + +apiVersion: v1 +kind: ConfigMap +metadata: + name: special-config + namespace: default +data: + special.how: hello-word + special.type: hi-word + +#-----------------------------# 分割线 #--------------------------------------# + +vim test-pod-1.yaml + +apiVersion: v1 +kind: Pod +metadata: + name: dapi-test-pod-1 +spec: + containers: + - name: test-container + image: docker.io/busybox + command: [ "/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ] + env: + - name: SPECIAL_LEVEL_KEY + valueFrom: + configMapKeyRef: + name: special-config + key: special.how + - name: SPECIAL_TYPE_KEY + valueFrom: + configMapKeyRef: + name: special-config + key: special.type + restartPolicy: Never +``` + +**运行以后我们来看一下结果:** + +![106.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602332536288.png) + +**3、通过数据卷插件使用ConfigMap** + +``` +这里我们依然使用 test.yaml 文件内的参数: + +apiVersion: v1 +kind: ConfigMap +metadata: + name: special-config + namespace: default +data: + special.how: hello-word + special.type: hi-word + +#-----------------------------# 分割线 #--------------------------------------# +在数据卷里面使用这个 ConfigMap,有不同的选项。最基本的就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容。 +#-----------------------------# 分割线 #--------------------------------------# + +vim test-pod-2.yaml + +apiVersion: v1 +kind: Pod +metadata: + name: dapi-test-pod-2 +spec: + containers: + - name: test-container + image: docker.io/busybox + command: [ "/bin/sh", "-c", "sleep 600s" ] + volumeMounts: + - name: config-volume + mountPath: /etc/config + volumes: + - name: config-volume + configMap: + name: special-config + restartPolicy: Never +``` + +**运行以后我们来看一下结果:** + +![107.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602332544646.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\345\255\230\345\202\250\344\271\213Secret.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\345\255\230\345\202\250\344\271\213Secret.md" new file mode 100644 index 0000000..ac0d47d --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\345\255\230\345\202\250\344\271\213Secret.md" @@ -0,0 +1,130 @@ +## 一、Secret 存在意义 + +Secret 解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者 Pod Spec中。Secret 可以以 Volume 或者环境变量的方式使用。 + +**Secret 有三种类型:** + +**Service Account :** 用来访问 Kubernetes API,由 Kubernetes 自动创建,并且会自动挂载到 Pod 的/run/secrets/kubernetes.io/serviceaccount 目录中。 + +**Opaque:base64** 编码格式的Secret,用来存储密码、密钥等 + +**kubernetes.io/dockerconfigjson:** 用来存储私有 docker registry 的认证信息 + +### 1.1、Service Account + +Service Account 用来访问 Kubernetes API,由 Kubernetes 自动创建,并且会自动挂载到 Pod的/run/secrets/kubernetes.io/serviceaccount 目录中。 + +``` +kubectl exec kube-proxy-hz44s -n kube-system -it -- /bin/sh + +cd /run/secrets/kubernetes.io/serviceaccount +``` + +来看一下查看到的结果: + +![111.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602332669830.png) + +**ca.crt** + +![112.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602332679776.png) + +**token** + +![113.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602332688822.png) + +### 1.2、Opaque Secret + +**1.2.1、创建说明:** + +Opaque 类型的数据是一个 map 类型,要求 value 是 base64 编码格式: + +``` +echo -n "admin" | base64 +YWRtaW4= + +echo -n "123456789" | base64 +MTIzNDU2Nzg5 + +#-----------------------------# 分割线 #--------------------------------------# + +vim secrets.yaml + +apiVersion: v1 +kind: Secret +metadata: + name: mysecret +type: Opaque +data: + password: MTIzNDU2Nzg5 + username: YWRtaW4= +``` + +**1.2.2、使用方式** + +**a、将 Secret 挂载到 Volume 中:** + +``` +apiVersion: v1 +kind: Pod +metadata: + name: seret-test + labels: + name: seret-test +spec: + volumes: + - name: secrets + secret: + secretName: mysecret + containers: + - name: db + image: docker.io/nginx + volumeMounts: + - name: secrets + mountPath: "/etc/secret" + readOnly: true +``` + +我们来看一下结果: + +![114.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602332700206.png) + +**b、将 Secret 导出到环境变量中**: + +``` +vim secret-pod-1.yaml + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: pod-deployment +spec: + selector: + matchLabels: + app: pod-deployment + replicas: 2 + template: + metadata: + labels: + app: pod-deployment + spec: + containers: + - name: pod-1 + image: docker.io/nginx + ports: + - containerPort: 80 + env: + - name: TEST_USER + valueFrom: + secretKeyRef: + name: mysecret + key: username + - name: TEST_PASSWORD + valueFrom: + secretKeyRef: + name: mysecret + key: password +``` + +**我们来看一下结果:** + +![115.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602332707405.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\345\255\230\345\202\250\344\271\213volume.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\345\255\230\345\202\250\344\271\213volume.md" new file mode 100644 index 0000000..e737079 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\345\255\230\345\202\250\344\271\213volume.md" @@ -0,0 +1,113 @@ +容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题。首先,当容器崩溃时,kubelet 会重启它,但是容器中的文件将丢失——容器以干净的状态(镜像最初的状态)重新启动。其次,在Pod 中同时运行多个容器时,这些容器之间通常需要共享文件。Kubernetes 中的 Volume 抽象就很好的解决了这些问题。 + +**背景** + +Kubernetes 中的卷有明确的寿命,与封装它的 Pod 相同。所以,卷的生命比 Pod 中的所有容器都长,当这个容器重启时数据仍然得以保存。当然,当 Pod 不再存在时,卷也将不复存在。也许更重要的是,Kubernetes支持多种类型的卷,Pod 可以同时使用任意数量的卷。 + +**卷的类型** + +- Kubernetes 支持以下类型的卷: + +awsElasticBlockStore、azureDisk、azureFile、cephfs、csi、downwardAPI、emptyDir、fc、flocker、gcePersistentDisk、gitRepo glusterfs、hostPath、iscsi、local、nfs、persistentVolumeClaim、projected、portworxVolume、quobyte、rbd、scaleIO、secret、storageos、vsphereVolume + +- emptyDir + +当 Pod 被分配给节点时,首先创建 emptyDir 卷,并且只要该 Pod 在该节点上运行,该卷就会存在。正如卷的名字所述,它最初是空的。Pod 中的容器可以读取和写入 emptyDir 卷中的相同文件,尽管该卷可以挂载到每个容器中的相同或不同路径上。当出于任何原因从节点中删除 Pod 时, emptyDir 中的数据将被永久删除。 + +**emptyDir 的用法有:** + +1、暂存空间,例如用于基于磁盘的合并排序 + +2、用作长时间计算崩溃恢复时的检查点 + +3、Web服务器容器提供数据时,保存内容管理器容器提取的文件 + +``` +vim vomule-pod.yaml + +apiVersion: v1 +kind: Pod +metadata: + name: test-vomule +spec: + containers: + - image: docker.io/nginx + imagePullPolicy: IfNotPresent + name: vomule-pod-1 + volumeMounts: + - mountPath: /test-1 + name: volume + - image: docker.io/busybox + name: vomule-pod-2 + command: ["/bin/sh","-c","sleep 6000s"] + imagePullPolicy: IfNotPresent + volumeMounts: + - mountPath: /test-2 + name: volume + volumes: + - name: volume + emptyDir: {} +``` + +我们来看一下效果: + +![117.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602332783199.png) + +**hostPath** + +hostPath 卷将主机节点的文件系统中的文件或目录挂载到集群中。 + +**hostPath 的用途如下:** + +运行需要访问 Docker 内部的容器;使用 /var/lib/docker 的 hostPath。 + +在容器中运行 cAdvisor;使用 /dev/cgroups 的 hostPath。 + +允许 pod 指定给定的 hostPath 是否应该在 pod 运行之前存在,是否应该创建,以及它应该以什么形式存在。 + +**除了所需的 path 属性之外,用户还可以为 hostPath 卷指定 type** + +| 值 | 行为 | +| ----------------- | ------------------------------------------------------------ | +| | 空字符串(默认)用于向后兼容,这意味着在挂载 hostPath 卷之前不会执行任何检查。 | +| DirectoryOrCreate | 如果在给定的路径上没有任何东西存在,那么将根据需要在那里创建一个空目录,权限设置为 0755,与 Kubelet 具有相同的组和所有权。 | +| Directory | 给定的路径下必须存在目录 | +| FileOrCreate | 如果在给定的路径上没有任何东西存在,那么会根据需要创建一个空文件,权限设置为 0644,与 Kubelet 具有相同的组和所有权。 | +| File | 给定的路径下必须存在文件 | +| Socket | 给定的路径下必须存在 UNIX 套接字 | +| CharDevice | 给定的路径下必须存在字符设备 | +| BlockDevice | 给定的路径下必须存在块设备 | + +**使用这种卷类型是请注意,因为:** + +由于每个节点上的文件都不同,具有相同配置(例如从 podTemplate 创建的)的 pod 在不同节点上的行为可能会有所不同。 + +当 Kubernetes 按照计划添加资源感知调度时,将无法考虑 hostPath 使用的资源。 + +在底层主机上创建的文件或目录只能由 root 写入。您需要在特权容器中以 root 身份运行进程,或修改主机上的文件权限以便写入hostPath 卷。 + +``` +vim vomule-pod-1.yaml + +apiVersion: v1 +kind: Pod +metadata: + name: test-vomule-1 +spec: + containers: + - image: docker.io/nginx + imagePullPolicy: IfNotPresent + name: vomule-pod-3 + volumeMounts: + - mountPath: /test + name: test-volume + volumes: + - name: test-volume + hostPath: + path: /date + type: Directory +``` + +我们来查看一下结果: + +![118.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602332807783.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250\347\261\273\345\236\213.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250\347\261\273\345\236\213.md" new file mode 100644 index 0000000..30fd9bd --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Pod \347\232\204\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250\347\261\273\345\236\213.md" @@ -0,0 +1,32 @@ +## 一、Pod 的资源控制器类型 + +什么是控制器呢?简单来说,控制器就好比是影视剧里面的剧本,演员会根据剧本所写的内容来针对不同的角色进行演绎,而我们的控制器就好比是剧本,Kubernetes 会根据我们所定义的规则,或者是按照我们写好的 “剧本” 来完成创建我们的 Pod 。 + +**控制器类型** + +1. **ReplicationController 与 ReplicaSet** + + Replicationcontroller (RC) 用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的 Pod 来替代,而如果异常多出来的容器也会自动回收。 + + 在新版本的 Kubernetes 中建议使用 Replicaset 来取代 ReplicationController . Replicaset 跟ReplicationController 没有本质的不同,只是名字不一样,并且 Replicaset 支持集合式的 selector。 + +2. **Deployment** + + Deployment 为 Pod 和 Replicaset 提供了一个声明式定义 declarative 方法,用来替代以前的ReplicationController 来方便的管理应用。 + +3. **DaemonSet** + + DoernonSet 确保全部(或者一些) Node 上运行一个 Pod 的副本,当有 Node 加入集群时,也会为他们新增一个 Pod,当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有Pod。 + +4. **StateFulSet(适用于有状态服务)** + + StatefulSet 作为 Controller 为 Pod 提供唯-的标识。 它可以保证部署和 scale 的顺序 + StatefulSet 是为了解决有状态服务的问题(对应 Deployments 和 ReplicaSets 是为无状态服务而设计)。 + +5. **Job 与 cronJob** + + Job 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束, Cron Job 管理基于时间的 Job ,其作用与计划任务类似。 + +6. **Horizontal Pod Autoscaling** + + 应用的资源使用率通常都有高峰和低谷的时候,如何削峰填谷,提高集群的整体资源利用率,让 service 中的 Pod 个数自动调整呢?这就有赖于 Horizontal Pod Autoscaling 了,顾名思义,使 Pod 水平自动缩放 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Service Ingress.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Service Ingress.md" new file mode 100644 index 0000000..c46a148 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Service Ingress.md" @@ -0,0 +1,363 @@ +![87.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602329577997.png) + +![88.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602329586972.png) + +Ingress-Nginx github 地址:https://github.com/kubernetes/ingress-nginx + +Ingress-Nginx 官方网站:https://kubernetes.github.io/ingress-nginx + +**部署 Ingress-Nginx** + +``` +https://kubernetes.github.io/ingress-nginx/deploy/ + +kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.27.0/deploy/static/mandatory.yaml + +kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.27.0/deploy/static/provider/baremetal/service-nodeport.yaml +``` + +**Ingress HTTP 代理访问** + +``` +vim ingress-nginx.yaml + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx +spec: + selector: + matchLabels: + name: nginx + replicas: 2 + template: + metadata: + labels: + name: nginx + spec: + containers: + - name: nginx + image: docker.io/nginx + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: Service +metadata: + name: nginx-svc +spec: + ports: + - port: 80 + targetPort: 80 + protocol: TCP + selector: + name: nginx + +#-----------------------------# 分割线 #--------------------------------------# + +vim ingress-nginx-svc.yaml + +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: nginx-test +spec: + rules: + - host: aaa.zutuanxue.com + http: + paths: + - path: / + backend: + serviceName: nginx-svc + servicePort: 80 +``` + +**我们可以通过命令 kubectl get svc -n ingress-nginx 查看对外宣告的端口:** + +![89.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602329870836.png) + +**然后使用浏览器通过域名:http://aaa.zutuanxue.com:31363/ 进行访问,因为需要进行域名解析,记得现在 hosts 文件内添加我们使用的域名的解析:** + +![90.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602331552519.png) + +**通过 Ingress 实现虚拟主机:** + +``` +vim ingress-nginx-1.yaml + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-1 +spec: + selector: + matchLabels: + name: nginx-1 + replicas: 2 + template: + metadata: + labels: + name: nginx-1 + spec: + containers: + - name: nginx-1 + image: docker.io/nginx + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: Service +metadata: + name: nginx-svc-1 +spec: + ports: + - port: 80 + targetPort: 80 + protocol: TCP + selector: + name: nginx-1 + + #-----------------------------# 分割线 #--------------------------------------# + +vim ingress-nginx-2.yaml + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-2 +spec: + selector: + matchLabels: + name: nginx-2 + replicas: 2 + template: + metadata: + labels: + name: nginx-2 + spec: + containers: + - name: nginx-2 + image: docker.io/nginx + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: Service +metadata: + name: nginx-svc-2 +spec: + ports: + - port: 80 + targetPort: 80 + protocol: TCP + selector: + name: nginx-2 + +#-----------------------------# 分割线 #--------------------------------------# + +vim ingress-nginx-svc-1.yaml + +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: ingress-1 +spec: + rules: + - host: bbb.zutuanxue.com + http: + paths: + - path: / + backend: + serviceName: nginx-svc-1 + servicePort: 80 +--- +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: ingress-2 +spec: + rules: + - host: ccc.zutuanxue.com + http: + paths: + - path: / + backend: + serviceName: nginx-svc-2 + servicePort: 80 +``` + +**创建完成后,我们来查看下一下相关的信息:** + +![91.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602331570318.png) + +**为了区分,我们对 Pod 内的 index.html 文件进行了对应的修改,然后我们通过不同的域名进行访问:** + +![92.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602331579254.png) + +**Ingress HTTPS 代理访问** + +``` +创建证书,以及 cert 存储方式: + +openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc" + +kubectl create secret tls tls-secret --key tls.key --cert tls.crt +``` + +![93.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602330583290.png) + +``` +创建deployment、Service、Ingress Yaml 文件: + +vim ingress-nginx-3.yaml + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-3 +spec: + selector: + matchLabels: + name: nginx-3 + replicas: 2 + template: + metadata: + labels: + name: nginx-3 + spec: + containers: + - name: nginx-3 + image: docker.io/nginx + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: Service +metadata: + name: nginx-svc-3 +spec: + ports: + - port: 80 + targetPort: 80 + protocol: TCP + selector: + name: nginx-3 + +#-----------------------------# 分割线 #--------------------------------------# + +vim ingress-nginx-svc-2.yaml + +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: ingress-3 +spec: + tls: + - hosts: + - ddd.zutuanxue.com + secretName: tls-secret + rules: + - host: ddd.zutuanxue.com + http: + paths: + - path: / + backend: + serviceName: nginx-svc-3 + servicePort: 80 +``` + +**创建完成后我们来查看一下效果:** + +![94.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602331601964.png) + +![95.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602331609166.png) + +**Nginx 进行 BasicAuth** + +``` +安装 httpd ,因为我们要使用相关的功能模块: + +yum -y install httpd + +htpasswd -c auth 用户名 + +kubectl create secret generic basic-auth --from-file=auth +``` + +![96.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602331621504.png) + +``` +创建 Ingress Yaml 文件: + +vim ingress-nginx-svc-3.yaml + +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: ingress-with-auth + annotations: + nginx.ingress.kubernetes.io/auth-type: basic + nginx.ingress.kubernetes.io/auth-secret: basic-auth + nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - tyschool' +spec: + rules: + - host: eee.zutuanxue.com + http: + paths: + - path: / + backend: + serviceName: nginx-svc + servicePort: 80 + +官方参考文档:https://kubernetes.github.io/ingress-nginx/examples/auth/basic/ +``` + +**创建完成后,我们来看一下相关的信息:** + +![97.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602331637455.png) + +**因为是重复使用的 aaa.zutuanxue.com 的信息,所以可以看到,域名是 “eee” 的,但是内容是 “aaa” 的。** + +![98.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602331678070.png) + +**Nginx 重定向:** + +| 名称 | 描述 | 值 | +| :--------------------------------------------: | :----------------------------------------------------------: | :--: | +| nginx.ingress.kubernetes.io/rewrite-target | 必须重定向流量的目标URI | 串 | +| nginx.ingress.kubernetes.io/ssl-redirect | 指示位置部分是否仅可访问SSL(当Ingress包含证书时默认为True) | 布尔 | +| nginx.ingress.kubernetes.io/force-ssl-redirect | 即使Ingress未启用TLS,也强制重定向到HTTPS | 布尔 | +| nginx.ingress.kubernetes.io/app-root | 定义Controller必须重定向的应用程序根,如果它在’/'上下文中 | 串 | +| nginx.ingress.kubernetes.io/use-regex | 指示Ingress上定义的路径是否使用正则表达式 | 布尔 | + +``` +vim rewrite-ingress-nginx-svc.yaml + +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: nginx-rewrite + annotations: + nginx.ingress.kubernetes.io/rewrite-target: https://eee.zutuanxue.com:31434 +spec: + rules: + - host: fff.zutuanxue.com + http: + paths: + - path: / + backend: + serviceName: nginx-svc + servicePort: 80 +``` + +我们来看一下效果: + +![99.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602331694901.png) + +跳转到了: + +![100.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602331701071.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Service \347\232\204\345\272\224\347\224\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Service \347\232\204\345\272\224\347\224\250.md" new file mode 100644 index 0000000..0cf89b8 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/Service \347\232\204\345\272\224\347\224\250.md" @@ -0,0 +1,161 @@ +**ClusterIP** + +clusterIP 主要在每个 node 节点使用 ipvs,将发向 clusterIP 对应端口的数据,转发到 kube-proxy 中。然后 kube-proxy 自己内部实现有负载均衡的方法,并可以查询到这个 service 下对应 pod 的地址和端口,进而把数据转发给对应的 pod 的地址和端口。 + +![74.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602329041269.png) + +**为了实现图上的功能,主要需要以下几个组件的协同工作:** + +- apiserver 用户通过kubectl命令向apiserver发送创建service的命令,apiserver接收到请求后将数据存储到etcd中。 +- kube-proxy kubernetes的每个节点中都有一个叫做kube-porxy的进程,这个进程负责感知service,pod的变化,并将变化的信息写入本地的iptables规则中。 +- ipvs 使用NAT等技术将virtualIP的流量转至endpoint中 + +示例: + +``` +vim nginx.yaml + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + selector: + matchLabels: + app: web-nginx + replicas: 3 + template: + metadata: + labels: + app: web-nginx + spec: + containers: + - name: web-nginx + image: docker.io/nginx + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + +#-----------------------------# 分割线 #--------------------------------------# + +vim nginx-svc.yaml + +apiVersion: v1 +kind: Service +metadata: + name: myapp +spec: + type: ClusterIP + selector: + app: web-nginx + ports: + - name: http + port: 80 + targetPort: 80 +``` + +我们先运行我们的资源清单,然后查看下是否可以正常访问: + +![75.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602329052731.png) + +为了方便分别当前是哪个 Pod 给我们提供的服务,我们依次将三个 Pod 内 index.html 的文件内容修改为 “1”、“2”、“3”,然后从新看一下: + +![76.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602329061534.png) + +我们在来看一下我们的 Pod 的 IP 地址 与 ipvs 的转发关系: + +![77.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602329067298.png) + +![78.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602329073337.png) + +**Headless Service** + +有时不需要或不想要负载均衡,以及单独的 Service IP 。遇到这种情况,可以通过指定 Cluster IP(spec.clusterIP) 的值为 “None” 来创建 Headless Service 。这类 Service 并不会分配 Cluster IP, kube-proxy 不会处理它们,而且平台也不会为它们进行负载均衡和路由 + +``` +vim headless.yaml + +apiVersion: v1 +kind: Service +metadata: + name: myapp +spec: + selector: + app: web-nginx + clusterIP: "None" + ports: + - name: http + port: 80 + targetPort: 80 + +dig -t A myapp.default.svc.cluster.local. @10.244.0.3 +``` + +![79.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602329083379.png) + +通过 dig 命令,我们可以看到,即使没有 SVC 的 IP 我们也可以通过域名的方式访问到我们的 Pod + +![80.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602329090527.png) + +**NodePort** + +nodePort 的原理在于在 node 上开了一个端口,将向该端口的流量导入到 kube-proxy,然后由 kube-proxy 进一步到给对应的 pod + +``` +vim nodeport.yaml + +apiVersion: v1 +kind: Service +metadata: + name: myapp +spec: + type: NodePort + selector: + app: web-nginx + ports: + - name: http + port: 80 + targetPort: 80 + nodePort: 31000 # 可以通过宿主机的的31000端口访问nginx服务 + # 有效端口范围为30000-32767 +``` + +我们来查看一下相关的信息: + +![81.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602329099291.png) + +验证一下: + +![82.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602329104915.png) + +![83.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602329110866.png) + +![84.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602329117343.png) + +**LoadBalancer** + +loadBalancer 和 nodePort 其实是同一种方式。区别在于 loadBalancer 比 nodePort 多了一步,就是可以调用cloud provider 去创建 LB 来向节点导流 + +**ExternalName** + +这种类型的 Service 通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容( 例如:www.zutuanxue.com )。ExternalName Service 是 Service 的特例,它没有 selector,也没有定义任何的端口和Endpoint。相反的,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务。 + +``` +vim external.yaml + +kind: Service +apiVersion: v1 +metadata: + name: my-service +spec: + type: ExternalName + externalName: www.zutuanxue.com +``` + +我们来查看一下: + +![85.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602329424397.png) + +![86.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602329437386.png) + +当查询主机 my-service.defalut.svc.cluster.local ( SVC_NAME.NAMESPACE.svc.cluster.local )时,集群的DNS 服务将返回一个值 my.database.example.com 的 CNAME 记录。访问这个服务的工作方式和其他的相同,唯一不同的是重定向发生在 DNS 层,而且不会进行代理或转发。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/StatefulSet\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/StatefulSet\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250.md" new file mode 100644 index 0000000..f51f924 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/StatefulSet\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250.md" @@ -0,0 +1,34 @@ +## 一、statefulset介绍 + +StatefulSet 是为了解决有状态服务的问题而设计的资源控制器。 + +- 匹配 Pod name ( 网络标识 ) 的模式为:(statefulset名称)-(序号),比如上面的示例:web-0,web-1,web-2 +- StatefulSet 为每个 Pod 副本创建了一个 DNS 域名,这个域名的格式为: $(podname).(headless server name),也就意味着服务间是通过Pod域名来通信而非 Pod IP,因为当Pod所在Node发生故障时, Pod 会被飘移到其它 Node 上,Pod IP 会发生变化,但是 Pod 域名不会有变化 + +![141.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602333569719.png) + +**删除 web-0 后查看:** + +![142.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602333577229.png) + + + +- StatefulSet 使用 Headless 服务来控制 Pod 的域名,这个域名的 FQDN 为:(service name).(namespace).svc.cluster.local,其中,“cluster.local” 指的是集群的域名 + +![143.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602333583439.png) + +- 根据 volumeClaimTemplates,为每个 Pod 创建一个 pvc,pvc 的命名规则匹配模式:(volumeClaimTemplates.name)-(pod_name),比如上面的 volumeMounts.name=www, Podname=web-[0-2],因此创建出来的 PVC 是 www-web-0、www-web-1、www-web-2 +- 删除 Pod 不会删除其 pvc,手动删除 pvc 将自动释放 pv + +## 二、Statefulset的启停顺序 + +- 有序部署:部署StatefulSet时,如果有多个Pod副本,它们会被顺序地创建(从0到N-1)并且,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态。 +- 有序删除:当Pod被删除时,它们被终止的顺序是从N-1到0。 +- 有序扩展:当对Pod执行扩展操作时,与部署一样,它前面的Pod必须都处于Running和Ready状态。 + +## 三、StatefulSet使用场景 + +- 稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于 PVC 来实现。 +- 稳定的网络标识符,即 Pod 重新调度后其 PodName 和 HostName 不变。 +- 有序部署,有序扩展,基于 init containers 来实现。 +- 有序收缩。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/istio \346\265\201\351\207\217\347\256\241\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/istio \346\265\201\351\207\217\347\256\241\347\220\206.md" new file mode 100644 index 0000000..21ba6a0 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/istio \346\265\201\351\207\217\347\256\241\347\220\206.md" @@ -0,0 +1,203 @@ +## 一、istio 流量管理 + +### 1、配置请求路由 + + Istio Bookinfo 示例包含四个独立的微服务,每个微服务都有多个版本。 其中一个微服务 reviews 的三个不同版本已经部署并同时运行。 为了说明这导致的问题,在浏览器中访问 Bookinfo 应用程序的 /productpage 并刷新几次。 您会注意到,有时书评的输出包含星级评分,有时则不包含。 这是因为没有明确的默认服务版本路由,Istio 将以循环方式请求路由到所有可用版本,此任务的最初目标是应用将所有流量路由到微服务的 v1 (版本 1)的规则。 + +``` +运行以下命令以应用 virtual services + +kubectl apply -f virtual-service-all-v1.yaml + +在浏览器中打开 Bookinfo 站点,请注意,无论您刷新多少次,页面的评论部分都不会显示评级星标。这是因为您将 Istio 配置为 将评论服务的所有流量路由到版本 reviews:v1,而此版本的服务不访问星级评分服务,您已成功完成此任务的第一部分:将流量路由到服务的某一个版本。 +cat virtual-service-all-v1.yaml + +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: productpage +spec: + hosts: + - productpage + http: + - route: + - destination: + host: productpage + subset: v1 +--- +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: reviews +spec: + hosts: + - reviews + http: + - route: + - destination: + host: reviews + subset: v1 +--- +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: ratings +spec: + hosts: + - ratings + http: + - route: + - destination: + host: ratings + subset: v1 +--- +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: details +spec: + hosts: + - details + http: + - route: + - destination: + host: details + subset: v1 +``` + +**基于用户身份的路由** + + 接下来,我们将更改路由配置,以便将来自特定用户的所有流量路由到特定服务版本。在这,来自名为 Jason 的用户的所有流量将被路由到服务 reviews:v2,请注意,Istio 对用户身份没有任何特殊的内置机制。事实上,productpage 服务在所有到 reviews 服务的 HTTP 请求中都增加了一个自定义的 end-user 请求头,从而达到了本例子的效果,请记住,reviews:v2 是包含星级评分功能的版本。 + +``` +运行以下命令以启用基于用户的路由 + +kubectl apply -f virtual-service-reviews-test-v2.yaml + +在 Bookinfo 应用程序的 /productpage 上,以用户 jason 身份登录,刷新浏览器。你看到了什么?星级评分显示在每个评论旁边,以其他用户身份登录(选择您想要的任何名称),刷新浏览器。现在星星消失了。这是因为除了 Jason 之外,所有用户的流量都被路由到 reviews:v1,您已成功配置 Istio 以根据用户身份路由流量 +cat virtual-service-reviews-test-v2.yaml + +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: reviews +spec: + hosts: + - reviews + http: + - match: + - headers: + end-user: + exact: jason + route: + - destination: + host: reviews + subset: v2 + - route: + - destination: + host: reviews + subset: v1 +``` + +### 2、故障注入 + + 为了测试微服务应用程序 Bookinfo 的弹性,我们将为用户 jason 在 reviews:v2 和 ratings 服务之间注入一个 7 秒的延迟。 这个测试将会发现一个故意引入 Bookinfo 应用程序中的 bug,注意 reviews:v2 服务对 ratings 服务的调用具有 10 秒的硬编码连接超时。 因此,尽管引入了 7 秒的延迟,我们仍然期望端到端的流程是没有任何错误的。 + +``` +创建故障注入规则以延迟来自测试用户 jason 的流量 + +kubectl apply -f virtual-service-ratings-test-delay.yaml + +打开浏览器的 开发工具 菜单,打开 网络 标签,重新加载 productpage 页面。你会看到页面加载实际上用了大约 6s +cat virtual-service-ratings-test-delay.yaml + +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: ratings +spec: + hosts: + - ratings + http: + - match: + - headers: + end-user: + exact: jason + fault: + delay: + percentage: + value: 100.0 + fixedDelay: 7s + route: + - destination: + host: ratings + subset: v1 + - route: + - destination: + host: ratings + subset: v1 +``` + +![11.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602491506327.png) + +![12.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602491517600.png) + +### 3、流量转移 + + 一个常见的用例是将流量从一个版本的微服务逐渐迁移到另一个版本。在 Istio 中,您可以通过配置一系列规则来实现此目标, 这些规则将一定百分比的流量路由到一个或另一个服务。在本任务中,您将会把 50% 的流量发送到 reviews:v1,另外 50% 的流量发送到 reviews:v3。然后,再把 100% 的流量发送到 reviews:v3 来完成迁移。 + +``` +开始之前 + 按照安装指南中的说明安装 Istio。 + 部署 Bookinfo 示例应用程序。 + +首先,运行此命令将所有流量路由到各个微服务的 v1 版本。 + +kubectl apply virtual-service-all-v1.yaml + +在浏览器中打开 Bookinfo 站点,请注意,不管刷新多少次,页面的评论部分都不会显示评级星号。 这是因为 Istio 被配置为将 reviews 服务的的所有流量都路由到了 reviews:v1 版本, 而该版本的服务不会访问带星级的 ratings 服务。 + +使用下面的命令把 50% 的流量从 reviews:v1 转移到 reviews:v3 + +kubectl apply -f virtual-service-reviews-50-v3.yaml + +等待几秒钟以让新的规则传播到代理中生效,刷新浏览器中的 /productpage 页面,大约有 50% 的几率会看到页面中出带 红色 星级的评价内容。这是因为 v3 版本的 reviews 访问了带星级评级的 ratings 服务,但 v1 版本却没有。 +cat networking/virtual-service-reviews-50-v3.yaml + +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: reviews +spec: + hosts: + - reviews + http: + - route: + - destination: + host: reviews + subset: v1 + weight: 50 + - destination: + host: reviews + subset: v3 + weight: 50 +如果您认为 reviews:v3 微服务已经稳定,你可以通过应用此 virtual service 规则将 100% 的流量路由到 reviews:v3 + +kubectl apply -f virtual-service-reviews-v3.yaml + +现在,当您刷新 /productpage 时,您将始终看到带有 红色 星级评分的书评 +cat virtual-service-reviews-v3.yaml + +apiVersion: networking.istio.io/v1alpha3 +kind: VirtualService +metadata: + name: reviews +spec: + hosts: + - reviews + http: + - route: + - destination: + host: reviews + subset: v3 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/istio \351\203\250\347\275\262.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/istio \351\203\250\347\275\262.md" new file mode 100644 index 0000000..1d101e2 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/istio \351\203\250\347\275\262.md" @@ -0,0 +1,157 @@ +## 一、istio 部署 + +下载地址:https://github.com/istio/istio/releases + +网盘链接:https://pan.baidu.com/s/1L4CK2icK6teT5Ef4eiJwKw 密码:i16u + +**资源配置:** + +**master 2U2G** + +**node 2U8G** + +``` +curl -L https://git.io/getLatestIstio | ISTIO_VERSION=1.5.4 sh - + +kubectl create namespace istio-system + +cd istio-1.5.4 + +使用 helm template 生成配置文件进行安装: + +初始化: + +helm template install/kubernetes/helm/istio-init --name istio-init --namespace istio-system > init.yaml + +kubectl apply -f init.yaml +等初始化 pod 完成后,就可以执行 istio 安装了 + +安装: + +vim install/kubernetes/helm/istio/values.yaml +编辑 valuse.yaml 文件,确认需要安装启动的组件 + +helm template install/kubernetes/helm/istio --name istio --namespace istio-system > istio.yaml + +kubectl apply -f istio.yaml + +或 + +使用 helm install 由 helm 服务来进行安装: + +初始化: + +helm install install/kubernetes/helm/istio-init --name istio-init --namespace istio-system + +vim install/kubernetes/helm/istio/values.yaml +编辑 valuse.yaml 文件,确认需要安装启动的组件 + +安装: + +helm install install/kubernetes/helm/istio --name istio --namespace istio-system + +查看 istio 的状态 + +kubectl get pod -n istio-system +kubectl get svc -n istio-system + +这里需要注意,因为是实验环境,如果集群运行在一个不支持外部负载均衡器的环境中,istio-ingressgateway 的 EXTERNAL-IP 将显示为 状态。我们需要使用服务的 NodePort 或 端口转发来访问网关,我们这里使用 NodePort 来进行访问,所以需要进行如下修改: + +kubectl edit svc istio-ingressgateway -n istio-system +在文件末尾将 LoadBalancer 修改为 NodePort 后保存退出即可。 +``` + +![4.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602491354708.png) + +![5.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602491367469.png) + +**Istio 对 Pod 和服务的要求** + +**要成为服务网格的一部分,Kubernetes 集群中的 Pod 和服务必须满足以下几个要求:** + +**需要给端口正确命名:**服务端口必须进行命名。端口名称只允许是<协议>[-<后缀>-]模式,其中<协议>部分可选择范围包括 grpc、http、http2、https、mongo、redis、tcp、tls 以及 udp,Istio 可以通过对这些协议的支持来提供路由能力。例如 name: http2-foo 和 name: http 都是有效的端口名,但 name: http2foo 就是无效的。如果没有给端口进行命名,或者命名没有使用指定前缀,那么这一端口的流量就会被视为普通 TCP 流量(除非显式的用 Protocol: UDP 声明该端口是 UDP 端口)。 + +**Pod 端口:**Pod 必须包含每个容器将监听的明确端口列表。在每个端口的容器规范中使用 containerPort。任何未列出的端口都将绕过 Istio Proxy。 + +**关联服务:**Pod 不论是否公开端口,都必须关联到至少一个 Kubernetes 服务上,如果一个 Pod 属于多个服务,这些服务不能在同一端口上使用不同协议,例如 HTTP 和 TCP。 + +**Deployment 应带有 app 以及 version 标签:**在使用 Kubernetes Deployment 进行 Pod 部署的时候,建议显式的为 Deployment 加上 app 以及 version 标签。每个 Deployment 都应该有一个有意义的 app 标签和一个用于标识 Deployment 版本的 version 标签。app 标签在分布式追踪的过程中会被用来加入上下文信息。Istio 还会用 app 和 version 标签来给遥测指标数据加入上下文信息。 + +**Application UID:**不要使用 ID(UID)值为 1337 的用户来运行应用。 + +**NET_ADMIN 功能:**如果您的集群中实施了 Pod 安全策略,除非您使用 Istio CNI 插件,您的 pod 必须具有NET_ADMIN功能。 + +## 二、部署 Bookinfo 示例 + +这个示例部署了一个用于演示多种 Istio 特性的应用,该应用由四个单独的微服务构成。 这个应用模仿在线书店的一个分类,显示一本书的信息。 页面上会显示一本书的描述,书籍的细节(ISBN、页数等),以及关于这本书的一些评论。 + +Bookinfo 应用分为四个单独的微服务: + +- `productpage`. 这个微服务会调用 `details` 和 `reviews` 两个微服务,用来生成页面。 +- `details`. 这个微服务中包含了书籍的信息。 +- `reviews`. 这个微服务中包含了书籍相关的评论。它还会调用 `ratings` 微服务。 +- `ratings`. 这个微服务中包含了由书籍评价组成的评级信息。 + +`reviews` 微服务有 3 个版本: + +- v1 版本不会调用 `ratings` 服务。 +- v2 版本会调用 `ratings` 服务,并使用 1 到 5 个黑色星形图标来显示评分信息。 +- v3 版本会调用 `ratings` 服务,并使用 1 到 5 个红色星形图标来显示评分信息。 + +下图展示了这个应用的端到端架构。 + +![6.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602491397770.png) + +Bookinfo 应用中的几个微服务是由不同的语言编写的。 这些服务对 Istio 并无依赖,但是构成了一个有代表性的服务网格的例子:它由多个服务、多个语言构成,并且 `reviews` 服务具有多个版本。 + +``` +部署前准备: + 1、kubernetes 集群部署完成 + 2、helm 部署完成 + +# Istio 默认自动注入 Sidecar. 请为 default 命名空间打上标签 istio-injection=enabled +kubectl label namespace default istio-injection=enabled + +# 使用 kubectl 部署应用 +kubectl apply -f bookinfo.yaml + +# 确认 Bookinfo 应用是否正在运行,请在某个 Pod 中用 curl 命令对应用发送请求,例如 ratings +kubectl exec -it $(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}') -c ratings -- curl productpage:9080/productpage | grep -o ".*" + +现在 Bookinfo 服务启动并运行中,我们需要使应用程序可以从外部访问 Kubernetes 集群,例如使用浏览器。可以用 Istio Gateway 来实现这个目标。 + +# 为应用程序定义 Ingress 网关 +kubectl apply -f bookinfo-gateway.yaml + +# 在 Kubernetes 环境中,使用 Kubernetes Ingress 资源来指定需要暴露到集群外的服务。 在 Istio 服务网格中,更好的选择(同样适用于 Kubernetes 及其他环境)是使用一种新的配置模型,名为 Istio Gateway。 Gateway 允许应用一些诸如监控和路由规则的 Istio 特性来管理进入集群的流量 + +启动 httpbin 样例程序 + +kubectl apply -f httpbin.yaml + +执行如下指令,明确自身 Kubernetes 集群环境支持外部负载均衡 + +kubectl get svc istio-ingressgateway -n istio-system + +若自身环境未使用外部负载均衡器,需要通过 NodePort 访问,执行如下命令,设置 ingress 端口: + +export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}') + +export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}') + +在使用 Istio 控制 Bookinfo 版本路由之前,我们需要在目标规则中定义好可用的应用默认目标规则,命名为 subsets + +kubectl apply -f destination-rule-all.yaml + +浏览器访问测试: + +http://IP:port/productpage +``` + +![10.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602491409437.png) + +![7.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602491423328.png) + +![8.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602491430887.png) + +![9.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602491438284.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/istio\345\210\206\345\270\203\345\274\217\350\277\275\350\270\252\344\270\216\345\217\257\350\247\206\345\214\226.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/istio\345\210\206\345\270\203\345\274\217\350\277\275\350\270\252\344\270\216\345\217\257\350\247\206\345\214\226.md" new file mode 100644 index 0000000..c0f6b29 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/istio\345\210\206\345\270\203\345\274\217\350\277\275\350\270\252\344\270\216\345\217\257\350\247\206\345\214\226.md" @@ -0,0 +1,69 @@ +## 一、istio分布式追踪 + +**官方网站:https://www.jaegertracing.io/** + +``` +修改 tracing 的 svc 模式由 ClusterIP 为 NodePort + +kubectl edit svc tracing -n istio-system + +查看 tracing 的端口 + +kubectl get svc -n istio-system + +通过浏览器进行访问 + +http://IP:PORT/jaeger +``` + +![23.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602491765466.png) + +![24.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602491771037.png) + +![25.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602491777987.png) + +![26.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602491787087.png) + +![27.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602491795646.png) + +## 二、 网络可视化 + +``` +首先,定义要用作 Kiali 用户名和密码的凭据。 + +KIALI_USERNAME=$(read -p 'Kiali Username: ' uval && echo -n $uval | base64) +当提示出现时输入 Kiali 用户名: + +KIALI_PASSPHRASE=$(read -sp 'Kiali Passphrase: ' pval && echo -n $pval | base64) +当提示出现时输入 Kiali 密码: + +运行以下命令创建 secret: + +NAMESPACE=istio-system + +cat < myout.file 2>&1 & + +打开浏览器进入链接 http://IP:8080 + +根据浏览器提示完成后续安装 + +cat /root/.jenkins/secrets/initialAdminPassword + +e8ec34c745064620a3f88ced0b522692 +``` + +![12.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602490364054.png) + +![13.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602490661759.png) + +![14.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602490383882.png) + +![15.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602490393305.png) + +![16.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602490695223.png) + +![17.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602490407199.png) + +![18.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602490413548.png) + +![19.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602490706017.png) + +## 三、流水线示例 + +``` +jenkins 流水线代码: + +node { + env.BUILD_DIR = "/opt/build-work/" + env.HOST = "aaa.zutuanxue.com" + stage('Preparation') { // for display purposes + // Get some code from a GitHub repository + git 'http://192.168.1.168/root/spring-web.git' + } + stage('Maven Build') { + // Run the maven build + sh "mvn package" + } + stage('Build Image') { + sh "/opt/jenkins/script/build-image-web.sh" + } + stage('Deploy') { + sh "/opt/jenkins/script/deploy.sh" + } +} + +------------------------------------------------------------------- +说明: + +node { + env.BUILD_DIR = "/opt/build-work/" 定义build的工作目录 + env.HOST = "aaa.zutuanxue.com" 定义 ingress 的域名 + + 下载我们需要的代码: + + stage('Preparation') { // for display purposes + // Get some code from a GitHub repository + git 'http://192.168.1.168/root/spring-web.git' + } + + 通过 maven 工具进行构建: + + stage('Maven Build') { + // Run the maven build + sh "mvn package" + } + + 通过脚本构建我们需要的镜像: + + stage('Build Image') { + sh "/opt/jenkins/script/build-image-web.sh" + } + + 通过脚本在k8s集群内部署我们的业务: + + stage('Deploy') { + sh "/opt/jenkins/script/deploy.sh" + } +} +build 脚本: + +#!/bin/bash + +#先判断一下我们 build 的工作目录是否存在,如果不存的话,那么就去创建对应的目录 +if [ "${BUILD_DIR}" == "" ];then + echo "env 'BUILD_DIR' There is no such directory" + exit 1 +fi + +DOCKER_DIR=${BUILD_DIR}/${JOB_NAME} + +if [ ! -d ${DOCKER_DIR} ];then + mkdir -p ${DOCKER_DIR} +fi + +# jenkins 的工作空间下的哪一个项目目录 +JENKINS_DIR=${WORKSPACE}/ + +#进入我们 build 的工作目录,清除不需要的文件,将我们要用到的文件移动过来 +cd ${DOCKER_DIR} +rm -rf * +mv ${JENKINS_DIR}/target ${DOCKER_DIR} +mv ${JENKINS_DIR}/dockerfile ${DOCKER_DIR} + +#以当前的时间当做我们镜像的版本号 +VERSION=$(date +%Y%m%d%H%M%S) +#定义我们镜像的名称:harbor地址/仓库项目名称/镜像项目名称:版本号 +IMAGE_NAME=www.zutuanxue.com.cn/library/${JOB_NAME}:${VERSION} +#将构建的镜像名称输入到文件,方便部署的时候进行调用 +echo "${IMAGE_NAME}" > ${WORKSPACE}/IMAGE +#构建镜像 +docker build -t ${IMAGE_NAME} . +#上传镜像到 harbor +docker push ${IMAGE_NAME} +k8s 部署脚本: + +#!/bin/bash + +name=${JOB_NAME} +image=$(cat ${WORKSPACE}/IMAGE) +host=${HOST} + +cd /opt/jenkins/script/template/ + +echo "deploying ... name: ${name}, image: ${image}, host: ${host}" + +sed -i "s,{{name}},${name},g" web.yaml +sed -i "s,{{image}},${image},g" web.yaml +sed -i "s,{{host}},${host},g" web.yaml +echo "ready to apply" +kubectl apply -f web.yaml +# yaml 模板文件: + +apiVersion: v1 +kind: Service +metadata: + name: {{name}} +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 8080 + selector: + app: {{name}} + type: ClusterIP +--- +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{name}} +spec: + rules: + - host: {{host}} + http: + paths: + - path: / + backend: + serviceName: {{name}} + servicePort: 80 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{name}} +spec: + selector: + matchLabels: + app: {{name}} + replicas: 1 + template: + metadata: + labels: + app: {{name}} + spec: + containers: + - name: {{name}} + image: {{image}} + ports: + - containerPort: 8080 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\214\201\344\271\205\345\214\226\344\271\213NFS.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\214\201\344\271\205\345\214\226\344\271\213NFS.md" new file mode 100644 index 0000000..7c2c0a4 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\214\201\344\271\205\345\214\226\344\271\213NFS.md" @@ -0,0 +1,226 @@ +## 一、安装 NFS 服务器 + +``` +服务端节点: +yum -y install nfs-utils + +mkdir /nfs-{1..6} + +cat /etc/exports +/nfs-1 *(rw,no_root_squash,no_all_squash,sync) +/nfs-2 *(rw,no_root_squash,no_all_squash,sync) +/nfs-3 *(rw,no_root_squash,no_all_squash,sync) +/nfs-4 *(rw,no_root_squash,no_all_squash,sync) +/nfs-5 *(rw,no_root_squash,no_all_squash,sync) +/nfs-6 *(rw,no_root_squash,no_all_squash,sync) + +systemctl enable nfs-server + +systemctl restart nfs-server + +客户端节点: +yum -y install nfs-utils + +systemctl enable nfs-server + +systemctl restart nfs-server + +showmount -e nfs-server-IP + Export list for 192.168.1.169: + /nfs-6 * + /nfs-5 * + /nfs-4 * + /nfs-3 * + /nfs-2 * + /nfs-1 * +``` + +## 二、部署 PV + +``` +vim pv.yaml + +apiVersion: v1 +kind: PersistentVolume +metadata: + name: nfs-pv001 +spec: + capacity: + storage: 2Gi + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Retain + storageClassName: nfs + nfs: + path: /nfs-1 + server: 192.168.1.169 +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: nfs-pv002 +spec: + capacity: + storage: 2Gi + accessModes: + - ReadOnlyMany + persistentVolumeReclaimPolicy: Retain + storageClassName: nfs + nfs: + path: /nfs-2 + server: 192.168.1.169 +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: nfs-pv003 +spec: + capacity: + storage: 2Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + storageClassName: nfs + nfs: + path: /nfs-3 + server: 192.168.1.169 +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: nfs-pv004 +spec: + capacity: + storage: 4Gi + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Retain + storageClassName: nfs + nfs: + path: /nfs-4 + server: 192.168.1.169 +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: nfs-pv005 +spec: + capacity: + storage: 4Gi + accessModes: + - ReadOnlyMany + persistentVolumeReclaimPolicy: Retain + storageClassName: nfs + nfs: + path: /nfs-5 + server: 192.168.1.169 +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: nfs-pv006 +spec: + capacity: + storage: 4Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + storageClassName: nfs + nfs: + path: /nfs-6 + server: 192.168.1.169 +``` + +![133.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602333388771.png) + +## 三、创建服务并使用 PVC + +``` +vim statefuset.yaml + +apiVersion: v1 +kind: Service +metadata: + name: nginx + labels: + app: nginx +spec: + ports: + - port: 80 + name: web + clusterIP: None + selector: + app: nginx +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: web +spec: + selector: + matchLabels: + app: nginx + serviceName: "nginx" + replicas: 3 + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: docker.io/nginx + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + name: web + volumeMounts: + - name: www + mountPath: /usr/share/nginx/html + volumeClaimTemplates: + - metadata: + name: www + spec: + accessModes: [ "ReadWriteOnce" ] + storageClassName: "nfs" + resources: + requests: + storage: 1Gi +``` + +**创建后我们来看一下效果,首先看一下 Pod 的创建过程:** + +![134.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602333411919.png) + +**然后我们来看一下 PV 的状态:** + +![135.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602333425856.png) + +**通过上述实验截图,我们发现,我们定义了三个副本,但是只有两个副本处于 “running” 的状态,还有一个处于 “pending” 的状态,这是因为,我们定的 PV 的访问模式为 “ReadWriteOnce” , 以单个节点以读/写模式挂载,我们在创建PV 的时候只创建两个模式为 “ReadWriteOnce” 的 PV ,所以第三个 Pod 没有可用的 PV 进行挂载,所以创建不成功。** + +**还有,我们要注意一下 StatefulSet 控制器,在创建的时候它是一个一个按照顺序的进行创建,在删除的时候,也是有序进行的删除。** + +![136.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602333435093.png) + +## 四、PV 资源回收 + + +**我们将由 StatefulSet 控制器创建的 Pod 进行删除操作,然后我们在查看一下我们的 PV 的状态:** + +![137.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602333469163.png) + +**这里,我们可以看到,由 StatefulSet 控制器创建的 Pod 已经全部删除了,但是我们的 PV 资源还没有释放,这是因为我们回收策略的原因所导致的,那么我们来手动回收一下:** + +**通过命令 kubectl edit pv nfs-pv001 来将 “claimRef” 字段进行删除,然后查看下 PV 状态。** + +**删除 “claimRef” 前:** + +![138.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602333475486.png) + +**删除 “claimRef” 后:** + +![139.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602333481556.png) + +**然后查看下 PV 的状态:** + +![140.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602333488156.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\214\207\345\256\232pod\350\277\220\350\241\214\345\234\250\345\233\272\345\256\232\350\212\202\347\202\271.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\214\207\345\256\232pod\350\277\220\350\241\214\345\234\250\345\233\272\345\256\232\350\212\202\347\202\271.md" new file mode 100644 index 0000000..379df3c --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\214\207\345\256\232pod\350\277\220\350\241\214\345\234\250\345\233\272\345\256\232\350\212\202\347\202\271.md" @@ -0,0 +1,70 @@ +## 一、指定固定节点:Pod.spec.nodeName + +**Pod.spec.nodeName 将 Pod 直接调度到指定的 Node 节点上,会跳过 Scheduler 的调度策略,该匹配规则是强制匹配:** + +``` +vim node-1.yaml + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: myweb +spec: + selector: + matchLabels: + app: myweb + replicas: 6 + template: + metadata: + labels: + app: myweb + spec: + nodeName: zutuanxue-node-1 + containers: + - name: myweb + image: docker.io/nginx + ports: + - containerPort: 80 +``` + +![130.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602326019117.png) + +正常情况下,创建 6 个副本,应该是两个节点进行平分,因为我们指定了具体的运行节点,所以全部在 node-1 上进行了创建。 + +## 二、指定固定节点标签:Pod.spec.nodeSelector + +**Pod.spec.nodeSelector:通过 kubernetes 的 label-selector 机制选择节点,由调度器调度策略匹配 label,而后调度 Pod 到目标节点,该匹配规则属于强制约束:** + +``` +vim node-2.yaml + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: myweb +spec: + selector: + matchLabels: + app: myweb + replicas: 4 + template: + metadata: + labels: + app: myweb + spec: + nodeSelector: + cname: zutuanxue + containers: + - name: myweb + image: docker.io/nginx + ports: + - containerPort: 80 +``` + +这个时候我们来看一下创建的情况: + +![131.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602326100231.png) + +因为没有对应标签的节点,所以创建卡主了,那么我们给 node-2 创建一个 “ cname:zutuanxue ” 这样的一个标签后,看下结果: + +![132.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602326186231.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\216\210\346\235\203\343\200\201\351\211\264\346\235\203\344\270\216\345\207\206\345\205\245\346\216\247\345\210\266.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\216\210\346\235\203\343\200\201\351\211\264\346\235\203\344\270\216\345\207\206\345\205\245\346\216\247\345\210\266.md" new file mode 100644 index 0000000..4d9bdbd --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\216\210\346\235\203\343\200\201\351\211\264\346\235\203\344\270\216\345\207\206\345\205\245\346\216\247\345\210\266.md" @@ -0,0 +1,283 @@ +认证过程,只是确认通信的双方都确认了对方是可信的,可以相互通信。而鉴权是确定请求方有哪些资源的权限。API Server 目前支持以下几种授权策略 (通过 API Server 的启动参数 “–authorization-mode” 设置) + +1、AlwaysDeny:表示拒绝所有的请求,一般用于测试 + +2、AlwaysAllow:允许接收所有请求,如果集群不需要授权流程,则可以采用该策略 + +3、ABAC(Attribute-Based Access Control):基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制(已经淘汰) + +4、Webbook:通过调用外部 REST 服务对用户进行授权 + +5、RBAC(Role-Based Access Control):基于角色的访问控制,现行默认规则 + +**RBAC 授权模式:** + +RBAC(Role-Based Access Control)基于角色的访问控制,在 Kubernetes 1.5 中引入,现行版本成为默认标准。相对其它访问控制方式,拥有以下优势: + +**① 对集群中的资源和非资源均拥有完整的覆盖** + +**② 整个 RBAC 完全由几个 API 对象完成,同其它 API 对象一样,可以用 kubectl 或 API 进行操作** + +**③ 可以在运行时进行调整,无需重启 API Server** + +官方说明文档:https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/ + +**1、RBAC 的 API 资源对象说明** + +**RBAC 引入了 4 个新的顶级资源对象:Role(角色)、ClusterRole(集群角色)、RoleBinding(角色绑定)、ClusterRoleBinding(集群角色绑定),4 种对象类型均可以通过 kubectl 与 API 操作** + +![148.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602333868350.png) + +**需要注意的是 Kubenetes 并不会提供用户管理,那么 User、Group、ServiceAccount 指定的用户又是从哪里来的呢? Kubenetes 组件(kubectl、kube-proxy)或是其他自定义的用户在向 CA 申请证书时,需要提供一个证书请求文件** + +``` +{ + "CN": "zutuanxue", + "hosts": [], + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "C": "CN", + "ST": "HangZhou", + "L": "XS", + "O": "k8s", + "OU": "System" + } + ] + } + +#-----------------------------# 分割线 #--------------------------------------# + +# API Server会把客户端证书的 CN 字段作为User,把 names.O 字段作为Group + +#kubelet 使用 TLS Bootstaping 认证时,API Server 可以使用 Bootstrap Tokens 或者 Token authenticationfile 验证 =token,无论哪一种,Kubenetes 都会为 token 绑定一个默认的 User 和 Group + +#Pod使用 ServiceAccount 认证时,service-account-token 中的 JWT 会保存 User 信息 + +#有了用户信息,再创建一对角色/角色绑定(集群角色/集群角色绑定)资源对象,就可以完成权限绑定了 +``` + +**Role and ClusterRole** + +在 RBAC API 中,Role 表示一组规则权限,权限只会增加(累加权限),不存在一个资源一开始就有很多权限而通过RBAC 对其进行减少的操作;Role 可以定义在一个 namespace 中,如果想要跨 namespace 则可以创建ClusterRole + +``` +kind: Role +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + namespace: default + name: pod-reader +rules: +- apiGroups: [""] # "" indicates the core API group + resources: ["pods"] + verbs: ["get", "watch", "list"] +``` + +ClusterRole 具有与 Role 相同的权限角色控制能力,不同的是 ClusterRole 是集群级别的,ClusterRole 可以用于: + +- 集群级别的资源控制( 例如 node 访问权限 ) +- 非资源型 endpoints( 例如 /healthz 访问 ) +- 所有命名空间资源控制(例如 pods ) + +``` +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + # "namespace" omitted since ClusterRoles are not namespaced + name: secret-reader +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "watch", "list"] +``` + +**RoleBinding and ClusterRoleBinding** + +RoloBinding 可以将角色中定义的权限授予用户或用户组,RoleBinding 包含一组权限列表(subjects),权限列表中包含有不同形式的待授予权限资源类型(users, groups, or service accounts);RoloBinding 同样包含对被Bind 的 Role 引用;RoleBinding 适用于某个命名空间内授权,而 ClusterRoleBinding 适用于集群范围内的授权。 + +将 default 命名空间的 pod-reader Role 授予 jane 用户,此后 jane 用户在 default 命名空间中将具有 pod-reader 的权限: + +``` +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: read-pods + namespace: default +subjects: +- kind: User + name: jane + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: Role + name: pod-reader + apiGroup: rbac.authorization.k8s.io +``` + +RoleBinding 同样可以引用 ClusterRole 来对当前 namespace 内用户、用户组或 ServiceAccount 进行授权,这种操作允许集群管理员在整个集群内定义一些通用的 ClusterRole,然后在不同的 namespace 中使用RoleBinding 来引用。 +​ 例如,以下 RoleBinding 引用了一个 ClusterRole,这个 ClusterRole 具有整个集群内对 secrets 的访问权限;但是其授权用户 dave 只能访问 development 空间中的 secrets(因为 RoleBinding 定义在 development 命名空间): + +``` +# This role binding allows "dave" to read secrets in the "development" namespace. +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: read-secrets + namespace: development # This only grants permissions within the "development" namespace. +subjects: +- kind: User + name: dave + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: secret-reader + apiGroup: rbac.authorization.k8s.io +``` + +使用 ClusterRoleBinding 可以对整个集群中的所有命名空间资源权限进行授权;以下 ClusterRoleBinding 样例展示了授权 manager 组内所有用户在全部命名空间中对 secrets 进行访问 + +``` +# This cluster role binding allows anyone in the "manager" group to read secrets in anynamespace. +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + name: read-secrets-global +subjects: +- kind: Group + name: manager + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: secret-reader + apiGroup: rbac.authorization.k8s.io +``` + +**Resources** + +Kubernetes 集群内一些资源一般以其名称字符串来表示,这些字符串一般会在 API 的 URL 地址中出现;同时某些资源也会包含子资源,例如 logs 资源就属于 pods 的子资源,API 中 URL 样例如下: + +``` +GET /api/v1/namespaces/{namespace}/pods/{name}/log +``` + +如果要在 RBAC 授权模型中控制这些子资源的访问权限,可以通过 / 分隔符来实现,以下是一个定义 pods 资资源logs 访问权限的 Role 定义样例 + +``` +kind: Role +apiVersion: rbac.authorization.k8s.io/v1beta1 +metadata: + namespace: default + name: pod-and-pod-logs-reader +rules: +- apiGroups: [""] + resources: ["pods/log"] + verbs: ["get", "list"] +``` + +**to Subjects** + +RoleBinding 和 ClusterRoleBinding 可以将 Role 绑定到 Subjects;Subjects 可以是 groups、users 或者service accounts + +Subjects 中 Users 使用字符串表示,它可以是一个普通的名字字符串,如 “alice”;也可以是 email 格式的邮箱地址,如 “tyschool@163.com”;甚至是一组字符串形式的数字 ID 。但是 Users 的前缀 system: 是系统保留的,集群管理员应该确保普通用户不会使用这个前缀格式 + +Groups 书写格式与 Users 相同,都为一个字符串,并且没有特定的格式要求;同样 system: 前缀为系统保留 + +**创建一个用户,只能管理zutuanxue空间:** + +``` +#创建对应的用户: + +useradd zutuanxue +passwd zutuanxue + +#准备证书相关信息: + +vim zutuanxue-csr.json + +{ + "CN": "zutuanxue", # 用户名 + "hosts": [], # 为空表示任何主机都可以使用,添加了IP地址表示特定主机来使用 + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "C": "CN", + "ST": "BeiJing", + "L": "BeiJing", + "O": "k8s", # 组名 + "OU": "System" + } + ] +} + +# 下载证书生成工具 +wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 +wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 +wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 + +chmod a+x * + +cp cfssl_linux-amd64 /usr/local/bin/cfssl +cp cfssljson_linux-amd64 /usr/local/bin/cfssljson +cp cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo + +#创建相关证书: + +cd /etc/kubernetes/pki/ + +cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes /opt/pod/rbac/zutuanxue-csr.json | cfssljson -bare zutuanxue + +#设置集群参数 +export KUBE_APISERVER="https://192.168.1.160:6443" + +kubectl config set-cluster kubernetes \ +--certificate-authority=/etc/kubernetes/pki/ca.crt \ +--embed-certs=true \ +--server=${KUBE_APISERVER} \ +--kubeconfig=zutuanxue.kubeconfig + +#设置客户端认证参数 + +kubectl config set-credentials zutuanxue \ +--client-certificate=/etc/kubernetes/pki/zutuanxue.pem \ +--client-key=/etc/kubernetes/pki/zutuanxue-key.pem \ +--embed-certs=true \ +--kubeconfig=zutuanxue.kubeconfig + +#设置上下文参数 + +kubectl create namespace zutuanxue + +kubectl config set-context kubernetes \ +--cluster=kubernetes \ +--user=zutuanxue \ +--namespace=zutuanxue \ +--kubeconfig=zutuanxue.kubeconfig + +#切换默认上下文 + +kubectl create rolebinding zutuanxue-admin-binding --clusterrole=admin --user=zutuanxue --namespace=zutuanxue + +mkdir /home/zutuanxue/.kube + +cp zutuanxue.kubeconfig /home/zutuanxue/.kube/config + +chown -R zutuanxue.zutuanxue /home/zutuanxue/.kube/config + +使用 zutuanxue 用户登录系统 + +kubectl config use-context kubernetes --kubeconfig=.kube/config +``` + +## 准入控制 + +准入控制是API Server的插件集合,通过添加不同的插件,实现额外的准入控制规则。甚至于API Server的一些主要的功能都需要通过 Admission Controllers 实现,这里我们列举几个插件的功能: + +- NamespaceLifecycle:防止在不存在的 namespace 上创建对象,防止删除系统预置 namespace,删除namespace 时,连带删除它的所有资源对象 +- LimitRanger:确保请求的资源不会超过资源所在 Namespace 的 LimitRange 的限制。 +- ResourceQuota:确保请求的资源不会超过资源的 ResourceQuota 限制。 +- ServiceAccount:为Pod中的进程和外部用户提供身份信息。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\220\255\345\273\272 Dashboard.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\220\255\345\273\272 Dashboard.md" new file mode 100644 index 0000000..8b4eb24 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\220\255\345\273\272 Dashboard.md" @@ -0,0 +1,504 @@ +Kubernetes Dashboard 是 Kubernetes 集群的基于 Web 的通用 UI。它允许用户管理在群集中运行的应用程序并对其进行故障排除,以及管理群集本身。 + +``` +mkdir /opt/dashboard + +cd /opt/dashboard + +创建 kubernetes-dashboard.yaml + +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + k8s-app: kubernetes-dashboard + name: kubernetes-dashboard + namespace: kube-system + +--- + +kind: Service +apiVersion: v1 +metadata: + labels: + k8s-app: kubernetes-dashboard + name: kubernetes-dashboard + namespace: kube-system +spec: + type: NodePort + ports: + - port: 443 + targetPort: 8443 + nodePort: 31000 + selector: + k8s-app: kubernetes-dashboard + +--- + +apiVersion: v1 +kind: Secret +metadata: + labels: + k8s-app: kubernetes-dashboard + name: kubernetes-dashboard-certs + namespace: kube-system +type: Opaque + +--- + +apiVersion: v1 +kind: Secret +metadata: + labels: + k8s-app: kubernetes-dashboard + name: kubernetes-dashboard-csrf + namespace: kube-system +type: Opaque +data: + csrf: "" + +--- + +apiVersion: v1 +kind: Secret +metadata: + labels: + k8s-app: kubernetes-dashboard + name: kubernetes-dashboard-key-holder + namespace: kube-system +type: Opaque + +--- + +kind: ConfigMap +apiVersion: v1 +metadata: + labels: + k8s-app: kubernetes-dashboard + name: kubernetes-dashboard-settings + namespace: kube-system + +--- + +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + labels: + k8s-app: kubernetes-dashboard + name: kubernetes-dashboard + namespace: kube-system +rules: + # Allow Dashboard to get, update and delete Dashboard exclusive secrets. + - apiGroups: [""] + resources: ["secrets"] + resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"] + verbs: ["get", "update", "delete"] + # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map. + - apiGroups: [""] + resources: ["configmaps"] + resourceNames: ["kubernetes-dashboard-settings"] + verbs: ["get", "update"] + # Allow Dashboard to get metrics. + - apiGroups: [""] + resources: ["services"] + resourceNames: ["heapster", "dashboard-metrics-scraper"] + verbs: ["proxy"] + - apiGroups: [""] + resources: ["services/proxy"] + resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"] + verbs: ["get"] + +--- + +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + labels: + k8s-app: kubernetes-dashboard + name: kubernetes-dashboard +rules: + # Allow Metrics Scraper to get metrics from the Metrics server + - apiGroups: ["metrics.k8s.io"] + resources: ["pods", "nodes"] + verbs: ["get", "list", "watch"] + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + k8s-app: kubernetes-dashboard + name: kubernetes-dashboard + namespace: kube-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: kubernetes-dashboard +subjects: + - kind: ServiceAccount + name: kubernetes-dashboard + namespace: kube-system + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: kubernetes-dashboard +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: + - kind: ServiceAccount + name: kubernetes-dashboard + namespace: kube-system + +--- + +kind: Deployment +apiVersion: apps/v1 +metadata: + labels: + k8s-app: kubernetes-dashboard + name: kubernetes-dashboard + namespace: kube-system +spec: + replicas: 1 + revisionHistoryLimit: 10 + selector: + matchLabels: + k8s-app: kubernetes-dashboard + template: + metadata: + labels: + k8s-app: kubernetes-dashboard + spec: + containers: + - name: kubernetes-dashboard + image: kubernetesui/dashboard:v2.0.0 + imagePullPolicy: Always + ports: + - containerPort: 8443 + protocol: TCP + args: + - --auto-generate-certificates + - --namespace=kube-system + # Uncomment the following line to manually specify Kubernetes API server Host + # If not specified, Dashboard will attempt to auto discover the API server and connect + # to it. Uncomment only if the default does not work. + # - --apiserver-host=http://my-address:port + volumeMounts: + - name: kubernetes-dashboard-certs + mountPath: /certs + # Create on-disk volume to store exec logs + - mountPath: /tmp + name: tmp-volume + livenessProbe: + httpGet: + scheme: HTTPS + path: / + port: 8443 + initialDelaySeconds: 30 + timeoutSeconds: 30 + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsUser: 1001 + runAsGroup: 2001 + volumes: + - name: kubernetes-dashboard-certs + secret: + secretName: kubernetes-dashboard-certs + - name: tmp-volume + emptyDir: {} + serviceAccountName: kubernetes-dashboard + nodeSelector: + "kubernetes.io/os": linux + # Comment the following tolerations if Dashboard must not be deployed on master + tolerations: + - key: node-role.kubernetes.io/master + effect: NoSchedule + +--- + +kind: Service +apiVersion: v1 +metadata: + labels: + k8s-app: dashboard-metrics-scraper + name: dashboard-metrics-scraper + namespace: kube-system +spec: + ports: + - port: 8000 + targetPort: 8000 + selector: + k8s-app: dashboard-metrics-scraper + +--- + +kind: Deployment +apiVersion: apps/v1 +metadata: + labels: + k8s-app: dashboard-metrics-scraper + name: dashboard-metrics-scraper + namespace: kube-system +spec: + replicas: 1 + revisionHistoryLimit: 10 + selector: + matchLabels: + k8s-app: dashboard-metrics-scraper + template: + metadata: + labels: + k8s-app: dashboard-metrics-scraper + annotations: + seccomp.security.alpha.kubernetes.io/pod: 'runtime/default' + spec: + containers: + - name: dashboard-metrics-scraper + image: kubernetesui/metrics-scraper:v1.0.4 + ports: + - containerPort: 8000 + protocol: TCP + livenessProbe: + httpGet: + scheme: HTTP + path: / + port: 8000 + initialDelaySeconds: 30 + timeoutSeconds: 30 + volumeMounts: + - mountPath: /tmp + name: tmp-volume + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsUser: 1001 + runAsGroup: 2001 + serviceAccountName: kubernetes-dashboard + nodeSelector: + "kubernetes.io/os": linux + # Comment the following tolerations if Dashboard must not be deployed on master + tolerations: + - key: node-role.kubernetes.io/master + effect: NoSchedule + volumes: + - name: tmp-volume + emptyDir: {} + +kubectl apply -f kubernetes-dashboard.yaml + +kubectl get pod -n kube-system + +kubectl edit svc kubernetes-dashboard -n kube-system +``` + +查看资源状态: + +![155.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486355457.png) + +![156.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486361159.png) + +我们可以看到默认的 SVC 类型是 ClusterIP , 用命令 kubectl edit svc kubernetes-dashboard -n kube-system 将其修改为 NodePort ,看到了暴露的端口号,这个时候我们使用 https://master IP :端口号 进行访问,因为浏览器的问题可能会被拦截,可以使用火狐浏览器进行访问: + +![157.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486370197.png) + +![158.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486376669.png) + +``` +通过如下命令就能得到我们的令牌: + +kubectl -n kube-system get secret | grep kubernetes-dashboard-token +# kubernetes-dashboard-token-rnjmx kubernetes.io/service-account-token 3 32m + +kubectl describe secret kubernetes-dashboard-token-rnjmx -n kube-system +``` + +![159.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486395634.png) + +![160.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486401384.png) + +**Metrics Server 部署** + +介绍 Metrics Server 前首先介绍下 Heapster,该工具是用于 Kubernetes 集群监控和性能分析工具,可以收集节点上的指标数据,例如,节点的 CPU、Memory、Network 和 Disk 的 Metric 数据。不过在 Kubernetes V1.11 版本后将被逐渐废弃。而 Metrics Server 正是 Heapster 的代替者。 + + Metrics Server 是 Kubernetes 集群核心监控数据的聚合器,可以通过 Metrics API 的形式获取 Metrics 数据,不过仅仅是获取指标的最新值,不对旧值进行存储,且不负责将指标转发到第三方目标。Metrics Server 还可以与 Kubectl 工具结合使用,提供 kubectl top 命令来展示集群中的指标数据,接下来我们开始部署 Metrics Server + +``` +cat metrics-server.yaml + +## ServiceAccount +apiVersion: v1 +kind: ServiceAccount +metadata: + name: metrics-server + namespace: kube-system +--- +## ClusterRole aggregated-metrics-reader +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: system:aggregated-metrics-reader + labels: + rbac.authorization.k8s.io/aggregate-to-view: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-admin: "true" +rules: +- apiGroups: ["metrics.k8s.io"] + resources: ["pods","nodes"] + verbs: ["get","list","watch"] +--- +## ClusterRole metrics-server +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: system:metrics-server +rules: +- apiGroups: [""] + resources: ["pods","nodes","nodes/stats","namespaces","configmaps"] + verbs: ["get","list","watch"] +--- +## ClusterRoleBinding auth-delegator +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: metrics-server:system:auth-delegator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:auth-delegator +subjects: +- kind: ServiceAccount + name: metrics-server + namespace: kube-system +--- +## RoleBinding metrics-server-auth-reader +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: metrics-server-auth-reader + namespace: kube-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: +- kind: ServiceAccount + name: metrics-server + namespace: kube-system +--- +## ClusterRoleBinding system:metrics-server +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: system:metrics-server +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:metrics-server +subjects: +- kind: ServiceAccount + name: metrics-server + namespace: kube-system +--- +## APIService +apiVersion: apiregistration.k8s.io/v1beta1 +kind: APIService +metadata: + name: v1beta1.metrics.k8s.io +spec: + service: + name: metrics-server + namespace: kube-system + group: metrics.k8s.io + version: v1beta1 + insecureSkipTLSVerify: true + groupPriorityMinimum: 100 + versionPriority: 100 +--- +## Service +apiVersion: v1 +kind: Service +metadata: + name: metrics-server + namespace: kube-system + labels: + kubernetes.io/name: "Metrics-server" + kubernetes.io/cluster-service: "true" +spec: + selector: + k8s-app: metrics-server + ports: + - port: 443 + targetPort: 4443 +--- +## Deployment +apiVersion: apps/v1 +kind: Deployment +metadata: + name: metrics-server + namespace: kube-system + labels: + k8s-app: metrics-server +spec: + selector: + matchLabels: + k8s-app: metrics-server + template: + metadata: + name: metrics-server + labels: + k8s-app: metrics-server + spec: + hostNetwork: true + serviceAccountName: metrics-server + containers: + - name: metrics-server + image: registry.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6 + imagePullPolicy: IfNotPresent + args: + - --cert-dir=/tmp + - --secure-port=4443 + - --kubelet-insecure-tls + - --kubelet-preferred-address-types=InternalDNS,InternalIP,ExternalDNS,ExternalIP,Hostname + ports: + - name: main-port + containerPort: 4443 + protocol: TCP + securityContext: + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + resources: + limits: + memory: 1Gi + cpu: 1000m + requests: + memory: 1Gi + cpu: 1000m + volumeMounts: + - name: tmp-dir + mountPath: /tmp + - name: localtime + readOnly: true + mountPath: /etc/localtime + volumes: + - name: tmp-dir + emptyDir: {} + - name: localtime + hostPath: + type: File + path: /etc/localtime + nodeSelector: + kubernetes.io/os: linux + kubernetes.io/arch: "amd64" +``` + +![196.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486455548.png) + +![197.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486464440.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\220\255\345\273\272 Prometheus.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\220\255\345\273\272 Prometheus.md" new file mode 100644 index 0000000..85c99e2 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\220\255\345\273\272 Prometheus.md" @@ -0,0 +1,232 @@ +## 一、Prometheus介绍 + +Prometheus(普罗米修斯)是一套开源的监控、报警、时间序列数据库的组合,起始是由SoundCloud公司开发的。随着发展,越来越多公司和组织接受采用Prometheus,社会也十分活跃,他们便将它独立成开源项目,并且有公司来运作。Google SRE的书内也曾提到跟他们BorgMon监控系统相似的实现是Prometheus。现在最常见的Kubernetes容器管理系统中,通常会搭配Prometheus进行监控。 +​Prometheus基本原理是通过HTTP协议周期性抓取被监控组件的状态,这样做的好处是任意组件只要提供HTTP接口就可以接入监控系统,不需要任何SDK或者其他的集成过程,这样做非常适合虚拟化环境。 + +**组件说明** + +1.MetricServer:是kubernetes集群资源使用情况的聚合器,收集数据给kubernetes集群内使用,如 +kubectl,hpa,scheduler等。 + +2.PrometheusOperator:是一个系统监测和警报工具箱,用来存储监控数据。 + +3.NodeExporter:用于各node的关键度量指标状态数据。 + +4.KubeStateMetrics:收集kubernetes集群内资源对象数据,制定告警规则。 + +5.Prometheus:采用pull方式收集apiserver,scheduler,controller-manager,kubelet组件数据,通过http协议传输。 + +6.Grafana:是可视化数据统计和监控平台。 + +## 二、grafana介绍 + +Grafana是一个跨平台的开源的度量分析和可视化工具,可以通过将采集的数据查询然后可视化的展示,并及时通知。它主要有以下六大特点: + +``` +1、展示方式:快速灵活的客户端图表,面板插件有许多不同方式的可视化指标和日志,官方库中具有丰富的仪表盘插件,比如热图、折线图、图表等多种展示方式 + +2、数据源:Graphite,InfluxDB,OpenTSDB,Prometheus,Elasticsearch,CloudWatch和KairosDB等 + +3、通知提醒:以可视方式定义最重要指标的警报规则,Grafana将不断计算并发送通知,在数据达到阈值时通过Slack、PagerDuty等获得通知 + +4、混合展示:在同一图表中混合使用不同的数据源,可以基于每个查询指定数据源,甚至自定义数据源 + +5、注释:使用来自不同数据源的丰富事件注释图表,将鼠标悬停在事件上会显示完整的事件元数据和标记 + +6、过滤器:Ad-hoc过滤器允许动态创建新的键/值过滤器,这些过滤器会自动应用于使用该数据源的所有查询。 + +展示模版下载: +https://grafana.com/grafana/dashboards +``` + +## 三、prometheus部署 + +``` +git网站:https://github.com/coreos/kube-prometheus + +mkdir prometheus + +cd prometheus + +git clone https://github.com/coreos/kube-prometheus.git + +cd kube-prometheus + +修改 grafana-service.yaml 文件,使用 nodepode 方式访问 grafana: + +vim manifests/grafana-service.yaml + +apiVersion: v1 +kind: Service +metadata: + labels: + app: grafana + name: grafana + namespace: monitoring +spec: + type: NodePort # 添加内容 + ports: + - name: http + port: 3000 + targetPort: http + nodePort: 30100 # 添加内容 + selector: + app: grafana + + +修改 prometheus-service.yaml,改为 nodepode + +vim manifests/prometheus-service.yaml + +apiVersion: v1 +kind: Service +metadata: + labels: + prometheus: k8s + name: prometheus-k8s + namespace: monitoring +spec: + type: NodePort # 添加内容 + ports: + - name: web + port: 9090 + targetPort: web + nodePort: 30200 # 添加内容 + selector: + app: prometheus + prometheus: k8s + sessionAffinity: ClientIP + + +修改 alertmanager-service.yaml,改为 nodepode + +vim manifests/alertmanager-service.yaml + +apiVersion: v1 +kind: Service +metadata: + labels: + alertmanager: main + name: alertmanager-main + namespace: monitoring +spec: + type: NodePort # 添加内容 + ports: + - name: web + port: 9093 + targetPort: web + nodePort: 30300 # 添加内容 + selector: + alertmanager: main + app: alertmanager + sessionAffinity: ClientIP + + +kubectl apply -f manifests/setup + +kubectl apply -f manifests/ + +kubectl get pod -n monitoring + +kubectl get svc -n monitoring + +稍等两分钟执行: + +kubectl top node + +kubectl top pod +``` + +**执行完成后查看一下状态,首先是 Pod:** + +![161.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486637948.png) + +**在看下SVC:** +![162.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486645070.png) + +**看下收集的 Node 的数据:** + +![163.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486652295.png) + +**访问 prometheus** + +**通过浏览器输入 Master IP : 30200** + +![164.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486659070.png) + +**我们可以在 status 下 Targets 里看到我们的节点状态:** + +![165.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486664504.png) + +**显示 UP 状态 说明我们部署成功:** + +![166.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486670615.png) + +**prometheus 的 WEB 界面上提供了基本的查询,查询条件如下:** + +``` +1.POD内存使用率 + +sum(container_memory_rss{container!="POD",container!="alermanager",image!="",pod!=""})by(pod) / sum(container_spec_memory_limit_bytes{container!="",container!="POD"})by(pod) * 100 != +inf + +2.POD的CPU使用率 + +sum(rate(container_cpu_usage_seconds_total{image!="",container!="POD",container!=""}[1m])) by (pod,namespace) / (sum(container_spec_cpu_quota{image!="",container!="POD",container!=""}/100000) by (pod,namespace)) * 100 + +3.POD的文件系统使用量 + +sum(container_fs_usage_bytes{image!="",container!="POD",container!=""}) by(pod, namespace) / 1024 / 1024 / 1024 +``` + +![167.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486679359.png) + +![168.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486685401.png) + +![169.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486692503.png) + +![170.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486698480.png) + +**上述的查询有出现数据,说明 node-exporter 往 prometheus 中写入数据正常,接下来我们就可以部署grafana 组件,实现更友好的 webui 展示数据了** + +**访问 grafana** + +**查看 grafana 服务暴露的端口号:** + + + +``` + kubectl get service -n monitoring | grep grafana + grafana NodePort 10.109.190.229 3000:30100/TCP 28m +``` + +**如上可以看到 grafana 的端口号是 30100,浏览器访问 http://MasterIP:30100 用户名密码默认 admin/admin** + +![171.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486707287.png) + +**修改密码后登陆:** + +![172.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486714106.png) + +**添加数据源** + +![173.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486719537.png) + +**选择模版:** + +![174.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486724776.png) + +**数据信息已经自动填好** + +![175.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486730245.png) + +**测试完好** + +![176.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486739204.png) + +**添加插件** + +![177.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486746518.png) + +**这样我们的数据可以正常显示** + +![178.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602486754155.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\234\215\345\212\241\351\203\250\347\275\262\344\270\216\350\277\201\347\247\273\347\232\204\346\255\245\351\252\244.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\234\215\345\212\241\351\203\250\347\275\262\344\270\216\350\277\201\347\247\273\347\232\204\346\255\245\351\252\244.md" new file mode 100644 index 0000000..4b7f19c --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\234\215\345\212\241\351\203\250\347\275\262\344\270\216\350\277\201\347\247\273\347\232\204\346\255\245\351\252\244.md" @@ -0,0 +1,47 @@ +## 一、服务部署与迁移的步骤 + +### 1.1、将应用封装进容器 + +应用容器化是部署与迁移的第一步,需要设计并规划好镜像的构建方案,由于Docker镜像分层的特性,通常建议使用分层方式进行Docker镜像构建。 + +操作系统层:制作公司常用的系统版本如CentOS、Ubuntu,可以在官方镜像的基础上添加自己需要的软件包。 + +运行环境层:在已经构建的操作系统层的基础上,把业务常用的运行环境都打包好,如JDK7、JDK8、JDK8+Tomcat8、Python2、Python3等通用模板。 + +应用层:在已经构建好了通用运行环境的基础上,根据应用再进行调整,然后将代码放进去即可。 + +### 1.2、将容器放入Pod中 + +应用容器化后,就需要考虑如何在Pod中运行,因为Pod是Kubernetes管理的最小单元,Kubernetes不直接管理容器,而是管理Pod,Pod里面包含容器。需要考虑是一个Pod中放置多个容器,还是一个Pod中放置一个容器,同时需要考虑Pod的资源限制,健康检查,数据持久化等。 + +### 1、3、使用Controllers管理Pod + +单一Pod如果出现故障,就会影响业务连续性,所以需要多副本,就像我们给一个Web应用做集群是一样的。Kubernetes提供了不同的Controller,需要根据应用的实际情况选择使用Deployment、DaemonSet、StatefulSet、Job、CronJob等,只需要在Pod的YAML模板上封装上对应的配置即可。 + + **Deployment:封装了Pod的副本管理、部署更新、回滚、扩容、缩容等。** + + **DaemonSet:保证所有的Node上有且只有一个Pod在运行。** + + **StatefulSet:有状态的应用,为Pod提供唯一的标识,它可以保证部署和scale的顺序。** + + **Job:使用Kubernetes运行单一任务。** + + **CronJob:使用Kubernetes运行定时任务。** + +### 1.4、使用Service管理Pod访问 + +使用Deployment通过多副本的方式保证了Pod的高可用和横向扩展,那么就需要考虑负载均衡,Kubernetes Service就是实现此功能,为应用创建对应的Service。目前Service的负载均衡支持两种实现方式:iptable 和 ipvs。 + +### 1.5、使用Ingress提供外部访问 + +集群内部可以直接使用Service Name进行通信,因为在集群中定义的每个 Service,都会被指派一个 DNS 名称,外部要访问到Kubernetes集群,由于网络路由不通(也可以使用其它手段打通),可以通过Node Port、LoadBlancer、外部IP等对外暴露访问。不过这些都可以理解为4层的负载均衡,如果要实现7层的负载均衡,Kubernetes提供了Ingress。 + +在Kubernetes中由Ingress Controller来实现Ingress的功能,这个控制器比较特殊,因为其它的控制器基本上都是kube-controller-manager这个服务的一部分,而Ingress Controller确是独立的。 + +### 1.6、使用PV/PVC管理持久化数据 + +容器中的存储都是临时的,因此Pod重启的时候,内部的数据会发生丢失。实际应用中,我们有些应用是无状态,有些应用则需要保持状态数据,确保Pod重启之后能够读取到之前的状态数据,有些应用则作为集群提供服务。这三种服务归纳为无状态服务、有状态服务以及有状态的集群服务,其中后面两个存在数据保存与共享的需求,因此就要采用容器外的存储方案。 + +### 1.7、使用ConfigMap管理应用配置文件 + +在DevOps的部署流水线中,我们强调代码和配置的分离,这样更容易实现流水线的编排。在Kubernetes中提供了ConfigMap资源对象,其实ConfigMap和Secret都是一种卷类型,可以从文件、文件夹等途径创建ConfigMap。然后再Pod中挂载使用。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\234\215\345\212\241\351\203\250\347\275\262\344\270\216\350\277\201\347\247\273\347\244\272\344\276\213.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\234\215\345\212\241\351\203\250\347\275\262\344\270\216\350\277\201\347\247\273\347\244\272\344\276\213.md" new file mode 100644 index 0000000..b2bb82c --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\346\234\215\345\212\241\351\203\250\347\275\262\344\270\216\350\277\201\347\247\273\347\244\272\344\276\213.md" @@ -0,0 +1,595 @@ +## 一、服务部署与迁移示例 + +### 1、简单的部署 wordpress + +通过 mysql 与 wordpress 镜像包部署持久化的 wordpress 博客网站 + +#### 1.1、创建 PV + +``` +cat lnmp-pv.yaml + +apiVersion: v1 +kind: PersistentVolume +metadata: + name: nfs-pv001 +spec: + capacity: + storage: 2Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + storageClassName: nfs + nfs: + path: /nfs-1 + server: 192.168.1.169 +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: nfs-pv002 +spec: + capacity: + storage: 2Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + storageClassName: nfs + nfs: + path: /nfs-2 + server: 192.168.1.169 +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: nfs-pv003 +spec: + capacity: + storage: 2Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + storageClassName: nfs + nfs: + path: /nfs-3 + server: 192.168.1.169 +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: nfs-pv004 +spec: + capacity: + storage: 2Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + storageClassName: nfs + nfs: + path: /nfs-4 + server: 192.168.1.169 +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: nfs-pv005 +spec: + capacity: + storage: 2Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + storageClassName: nfs + nfs: + path: /nfs-5 + server: 192.168.1.169 +``` + +#### 1.2、部署 mysql + +``` +cat wp-mysql.yaml + +apiVersion: v1 +kind: Service +metadata: + name: mysql-svc +spec: + type: ClusterIP + ports: + - port: 3306 + targetPort: 3306 + selector: + app: wp-mysql +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: mysql-pvc + labels: + app: wp-mysql +spec: + accessModes: + - ReadWriteMany + storageClassName: "nfs" + resources: + requests: + storage: 2Gi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: wp-mysql +spec: + selector: + matchLabels: + app: wp-mysql + replicas: 1 + template: + metadata: + labels: + app: wp-mysql + spec: + containers: + - name: wp-mysql + image: docker.io/mysql:5.7 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 3306 + env: + - name: MYSQL_ROOT_PASSWORD + value: "123456" + - name: MYSQL_DATABASE + value: "wordpress" + - name: MYSQL_USER + value: "wordpress" + - name: MYSQL_PASSWORD + value: "wordpress" + volumeMounts: + - name: mysql + mountPath: /var/lib/mysql + volumes: + - name: mysql + persistentVolumeClaim: + claimName: mysql-pvc +``` + +#### 1.3、部署 wordpress + +``` +cat wp-wordpress + +apiVersion: v1 +kind: Service +metadata: + name: wordpress +spec: + type: NodePort + ports: + - port: 80 + nodePort: 30001 + selector: + app: wordpress +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: wordpress-pvc + labels: + app: wordpress +spec: + accessModes: + - ReadWriteMany + storageClassName: "nfs" + resources: + requests: + storage: 2Gi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: wp-wordpress +spec: + selector: + matchLabels: + app: wordpress + replicas: 1 + template: + metadata: + labels: + app: wordpress + spec: + containers: + - name: wp-wordpress + image: docker.io/wordpress + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + env: + - name: WORDPRESS_DB_HOST + value: "mysql-svc" + - name: WORDPRESS_DB_USER + value: "wordpress" + - name: WORDPRESS_DB_PASSWORD + value: "wordpress" + volumeMounts: + - name: wordpress + mountPath: /var/www/html + volumes: + - name: wordpress + persistentVolumeClaim: + claimName: wordpress-pvc +``` + +### 2、部署 LNMP 环境 + +通过部署 LNMP 环境 部署持久化的 wordpress + +#### 2.1、部署 PV + +``` +cat lnmp-pv.yaml + +apiVersion: v1 +kind: PersistentVolume +metadata: + name: nfs-pv001 +spec: + capacity: + storage: 2Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + storageClassName: nfs + nfs: + path: /nfs-1 + server: 192.168.1.169 +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: nfs-pv002 +spec: + capacity: + storage: 2Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + storageClassName: nfs + nfs: + path: /nfs-2 + server: 192.168.1.169 +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: nfs-pv003 +spec: + capacity: + storage: 2Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + storageClassName: nfs + nfs: + path: /nfs-3 + server: 192.168.1.169 +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: nfs-pv004 +spec: + capacity: + storage: 2Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + storageClassName: nfs + nfs: + path: /nfs-4 + server: 192.168.1.169 +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: nfs-pv005 +spec: + capacity: + storage: 2Gi + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + storageClassName: nfs + nfs: + path: /nfs-5 + server: 192.168.1.169 +``` + +#### 2.2、部署 nginx + php + +``` +cat lnmp-nginx-php.yaml + +apiVersion: v1 +kind: Service +metadata: + name: nginx-php-svc + labels: + app: lnmp-nginx-php +spec: + type: NodePort + ports: + - port: 80 + nodePort: 30001 + selector: + app: lnmp-nginx-php +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: lnmp-web-pvc + labels: + app: wordpress +spec: + accessModes: + - ReadWriteMany + storageClassName: "nfs" + resources: + requests: + storage: 2Gi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: lnmp-nginx-php +spec: + selector: + matchLabels: + app: lnmp-nginx-php + replicas: 1 + template: + metadata: + labels: + app: lnmp-nginx-php + spec: + containers: + - name: lnmp-nginx + image: richarvey/nginx-php-fpm + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + - containerPort: 9000 + volumeMounts: + - name: nginx-data + mountPath: /var/www/html/ + volumes: + - name: nginx-data + persistentVolumeClaim: + claimName: lnmp-web-pvc +``` + +#### 2.3、部署 MYSQL + +``` +cat lnmp-mysql.yaml + +apiVersion: v1 +kind: Service +metadata: + name: lnmp-mysql-svc +spec: + type: ClusterIP + ports: + - port: 3306 + targetPort: 3306 + selector: + app: lnmp-mysql +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: lnmp-mysql-pvc + labels: + app: lnmp-mysql +spec: + accessModes: + - ReadWriteMany + storageClassName: "nfs" + resources: + requests: + storage: 2Gi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: lnmp-mysql +spec: + selector: + matchLabels: + app: lnmp-mysql + replicas: 1 + template: + metadata: + labels: + app: lnmp-mysql + spec: + containers: + - name: lnmp-mysql + image: docker.io/mysql:5.7 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 3306 + env: + - name: MYSQL_ROOT_PASSWORD + value: "123456" + - name: MYSQL_DATABASE + value: "wordpress" + - name: MYSQL_USER + value: "wordpress" + - name: MYSQL_PASSWORD + value: "wordpress" + volumeMounts: + - name: mysql + mountPath: /var/lib/mysql + volumes: + - name: mysql + persistentVolumeClaim: + claimName: lnmp-mysql-pvc +``` + +#### 2.4、部署 wordpress + +``` +下载 wordpress 的安装包 + +wordpress官网:https://cn.wordpress.org + +将解压后的 wordpress 目录内的所有的内容 上传/复制/移动 到 /nfs-x 目录内 + +打开浏览器,输入 IP+端口 回车后即可看到如下 wordpress 的安装界面 +``` + +**点击 “现在就开始”** + +![1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602489341115.png) + +**输入我们在 lnmp-mysql.yaml 文件内定义的 用户名、密码、数据库名、以及我们的 mysql 的 svc 的名称** + +![2.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602489359694.png) + +**如果数据库信息填写正确,点击 “提交” 后可以看到如下提示,我们点击 “现在安装”** + +![3.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602489375812.png) + +**设置我们站点的相关信息** + +![4.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602490022952.png) + +![5.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602489406449.png) + +![6.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602489413332.png) + +![7.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602489421863.png) + +### 3、springboot-web + + 当前,Spring毫无疑问已经成为java后台对象管理标准框架,除了通过IOC能够管理我们的自定义对象的生命周期之外还提供了众多功能繁复的可配置功能模块。但同时带来了复杂的配置项,这对初学者而言简直是一种灾难。于是SpringBoot应运而生,Springboot的出现大大简化了配置,主要表现在消除了web.xml和依赖注入配置的整合,处处遵循规约大于配置的思想,将初学者在繁杂的配置项中解放出来,专注于业务的实现,而不需要去关注太底层的实现。 + +``` +cat dockerfile + +FROM openjdk:8-jdk + +COPY target/springboot-web-demo-1.0-SNAPSHOT.jar /springboot-web.jar + +ENTRYPOINT ["java", "-jar", "/springboot-web.jar"] + +docker build -t spring-web:v1 . + +docker tag www.zutuanxue.com/library/spring-web:v1 + +docker tag spring-web:v1 www.zutuanxue.com/library/spring-web:v1 + +cat spring-web.yaml + +apiVersion: v1 +kind: Service +metadata: + name: spring-web-svc +spec: + type: NodePort + ports: + - port: 8181 + targetPort: 8080 + nodePort: 30600 + selector: + app: spring-web +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: spring-web +spec: + selector: + matchLabels: + app: spring-web + replicas: 3 + template: + metadata: + labels: + app: spring-web + spec: + containers: + - name: spring-web + image: www.zutuanxue.com/library/spring-web:v1 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8080 + +kubectl apply -f spring-web.yaml + +kubectl get pod + +kubectl get svc + +打开浏览器输入 IP:30600/hello?name=zutuanxue +``` + +![8.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602490040564.png) + +![9.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602490046413.png) + +### 4、JAVA + +``` +cat dockerfile + +FROM tomcat + +COPY jspdemo_war.war /usr/local/tomcat/webapps/jspdemo_war.war + +ENTRYPOINT ["catalina.sh","run"] + +cat tomcat-java.yaml + +apiVersion: v1 +kind: Service +metadata: + name: tomcat-java-svc +spec: + type: NodePort + ports: + - port: 8282 + targetPort: 8080 + nodePort: 30700 + selector: + app: tomcat-java +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tomcat-java +spec: + selector: + matchLabels: + app: tomcat-java + replicas: 3 + template: + metadata: + labels: + app: tomcat-java + spec: + containers: + - name: tomcat-java + image: www.zutuanxue.com/library/tomcat-java:v1 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8080 + +打开浏览器进入链接 http://IP:30700/jspdemo_war (项目名) 用户名与密码为:lisi +``` + +![10.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602489458274.png) + +![11.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602489484136.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250\344\271\213DaemonSet.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250\344\271\213DaemonSet.md" new file mode 100644 index 0000000..4e4b385 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250\344\271\213DaemonSet.md" @@ -0,0 +1,32 @@ +DaemonSet 确保全部(或者一些) Node上运行一个 Pod 的副本,当有 Node 加入集群时,也会为他们新增一个 Pod,当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod 。 + +![61.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328744399.png) + +**DaemonSet 应用示例:** + +``` +vim daemonset.yaml + +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: deamonset + labels: + app: daemonset +spec: + selector: + matchLabels: + name: deamonset + template: + metadata: + labels: + name: deamonset + spec: + containers: + - name: daemonset + image: docker.io/nginx +``` + +创建完成后,查看pod状态: + +![62.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328751642.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250\344\271\213Deployment.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250\344\271\213Deployment.md" new file mode 100644 index 0000000..5135a0e --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250\344\271\213Deployment.md" @@ -0,0 +1,85 @@ +Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义(declarative)方法,用来替代以前的ReplicationController 来方便的管理应用。典型的应用场景包括: + +- 定义 Deployment 来创建 Pod 和 ReplicaSet + +- 滚动升级和回滚应用 + +- 扩容和缩容 + +![49.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328553716.png) + +**Deployment 应用示例:** + +``` +vim deploy.yaml + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + selector: + matchLabels: + app: web-nginx + replicas: 3 + template: + metadata: + labels: + app: web-nginx + spec: + containers: + - name: web-nginx + image: docker.io/nginx + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 + + +kubectl create -f deploy.yaml --record + ## --record参数可以记录命令,我们可以很方便的查看每次 revision 的变化 +``` + +**创建完成后,我们可以查看下我们的 Pod 状态:** + +![50.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328566876.png) + + +**我们可以通过命令 kubectl scale deployment my-nginx --replicas=5 将副本数量扩容到 5 个:** + +![53.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328576964.png) + +**也可以通过该命令 kubectl scale deployment my-nginx --replicas=2 缩容到 2 个:** + +![54.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328582504.png) + +**这个时候我们注意一下,在缩容的时候,优先删除的是创建时间短的 Pod 。下面我们在来看一下 deployment 的升级与回滚:** + +**查看当前的 Pod 当中的 nginx 的版本: kubectl exec Pod-name -it – nginx -v** + +**升级 images 版本: kubectl set image deployment/my-nginx web-nginx=nginx:1.9.1** + +![55.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328593851.png) + +**使用命令 kubectl get rs 命令查看 Pod 的更新过程:** + +![56.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328600900.png) + +**当升级完成后,查看一下当前 Pod 的 nginx 的版本:** + +![57.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328607639.png) + +**通过命令查看 deployment 的历史记录: kubectl rollout history deployment my-nginx** + +![58.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328614191.png) + +**回滚到之前的版本: kubectl rollout undo deployment --to-revision=1** + +![59.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328621007.png) + +**回滚完成后,查看一下当前 Pod 的 nginx 的版本:** + +![60.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328627324.png) + +**清理 Policy :** + +可以通过设置 spec.revisonHistoryLimit 项来指定 deployment 最多保留多少 revision 历史记录。默认的会保留所有的 revision,如果将该项设置为 0,Deployment 就不允许回退了。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250\344\271\213RS.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250\344\271\213RS.md" new file mode 100644 index 0000000..58ae8d0 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\350\265\204\346\272\220\346\216\247\345\210\266\345\231\250\344\271\213RS.md" @@ -0,0 +1,57 @@ +RC (ReplicationController )主要的作用就是用来确保容器应用的副本数始终保持在用户定义的副本数 。即如果有容器异常退出,会自动创建新的 Pod 来替代;而如果异常多出来的容器也会自动回收(已经成为过去时)。 + +**Kubernetes 官方建议使用 RS(ReplicaSet ) 替代 RC (ReplicationController ) 进行部署,RS 跟 RC 没有本质的不同,只是名字不一样,并且 RS 支持集合式的 selector。** + +![48.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328407339.png) + + +**RS 用示例:** + +``` +vim rs.yaml + +apiVersion: apps/v1 +kind: ReplicaSet +metadata: + name: myweb +spec: + replicas: 3 + selector: + matchLabels: + tier: myweb + template: + metadata: + labels: + tier: myweb + spec: + containers: + - name: nginx + image: docker.io/nginx + imagePullPolicy: IfNotPresent + ports: + - containerPort: 80 +``` + +**我们来查看下我们的 Pod 信息:** + +![46.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328432263.png) + +**这个时候我们来随便删除一个其中的 Pod 后在查看下我们的 Pod 信息:** + +![47.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328445225.png) + +通过上述操作,我们可以看到,当我们定义了一个 RS 控制器的副本数目为 3 以后,那么,系统会始终保持我们的副本数为,不管是多了还是少了,系统始终会保持我们的副本数量与我们定义的数量一致(多删少建)。这个时候我们可以通过 kubectl get pod --show-labels 来查看我们 Pod 的标签: + +![51.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328453093.png) + +这个时候可以看到我们在 **rs.yanl** 文件内所定义的标签,这个时候,我们来通过命令 kubectl label pod myweb-rkqjz tier=my-nginx --overwrite=True 修改我们 myweb-rkqjz 这个Pod 的标签然后看下效果: + +![52.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602328460412.png) + +这个时候我们需要注意一下 + +``` +“error: 'tier' already has a value (myweb), and --overwrite is false“ +``` + +因为标签已经存在,所以后面需要接上 --overwrite=True 才能修改,我们的标签,但是修改玩以后,因为 RS 是通过 Pod 的标签来确定哪些 Pod 是我管理的, 哪些 Pod 不是我管理的,当我们修改了其中一个 Pod 的标签以后,RS 发现我所管理的 Pod 数量与副本定义数量不符,所以会创建一个新的 Pod 来补足,这也就是为什么,当使用删除 RS 的命令 kubectl delete rs --all 以后,会有一个 Pod 没有被删除,因为该 Pod 标签与 rs.yaml 内定义的标签不符,所以不归该 RS 管理器管辖。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\351\203\250\347\275\262EFK pod\346\227\245\345\277\227\345\210\206\346\236\220\347\263\273\347\273\237.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\351\203\250\347\275\262EFK pod\346\227\245\345\277\227\345\210\206\346\236\220\347\263\273\347\273\237.md" new file mode 100644 index 0000000..e6563d6 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\351\203\250\347\275\262EFK pod\346\227\245\345\277\227\345\210\206\346\236\220\347\263\273\347\273\237.md" @@ -0,0 +1,225 @@ +EFK不是一个软件,而是一套解决方案,并且都是开源软件,之间互相配合使用,完美衔接,高效的满足了很多场合的应用,是目前主流的一种日志系统。EFK是三个开源软件的缩写,分别表示:Elasticsearch , Fluentd, Kibana + +**组件说明:** + +EFK由ElasticSearch、Fluentd和Kiabana三个开源工具组成。 + +1、其中Elasticsearch是一款分布式搜索引擎,能够用于日志的检索 + +2、Fluentd是一个实时开源的数据收集器, + +3、Kibana 是一款能够为Elasticsearch 提供分析和可视化的 Web 平台。 + +这三款开源工具的组合为日志数据提供了分布式的实时搜集与分析的监控系统。 + +## 一、环境准备 + +``` +# 资源配置: + +Master: 4U4G +Node-1: 4U4G +Node-2: 4U4G + +mkdir efk + +cd efk + +kubectl create namespace efk + +添加 Google incubator 仓库: + +helm repo add bitnami https://charts.bitnami.com/bitnami +``` + +## 二、部署 Elasticsearch + +``` +helm fetch bitnami/elasticsearch + +tar zxvf elasticsearch-12.3.1.tgz + +cd elasticsearch/ + +vim values.yaml + +# 因为是实验环境,需要修改一下配置文件,否则可能会因为资源问题而导致实验失败 + +volumePermissions: + enabled: false # 修改为 “false” + image: + registry: docker.io + repository: bitnami/minideb + tag: buster + pullPolicy: Always + +master: + name: master + replicas: 1 # 修改为 “1” + persistence: + enabled: false # 修改为 “false” + +coordinating: + replicas: 1 # 修改为 “1” + updateStrategy: + type: RollingUpdate + +data: + name: data + replicas: 1 # 修改为 “1” + persistence: + enabled: false # 修改为 “false” + +# 保存退出 + +helm install . --name ela --namespace=efk -f values.yaml + +# 测试一下: +kubectl run cirror-$RANDOM --rm -it --image=cirros -- /bin/sh + +curl Elasticsearch:Port/_cat/nodes +``` + +**完成后我们查看一下:** + +![185.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602487270082.png) + +## 三、部署 Fluentd + +``` +helm fetch stable/fluentd + +tar zxvf fluentd-2.4.1.tgz + +cd fluentd + +vim values.yaml + +# 更改其中 Elasticsearch 访问地址 + +elasticsearch: + host: 'es-elasticsearch-coordinating-only' # 修改地址 + port: 9200 + scheme: 'http' + ssl_version: TLSv1_2 + buffer_chunk_limit: 2M + buffer_queue_limit: 8 + logstash_prefix: 'logstash' + +在 system.conf 上方添加下列代码: + + containers.input.conf: |- + + @id fluentd-containers.log + @type tail + path /var/log/containers/*.log + pos_file /var/log/es-containers.log.pos + tag raw.kubernetes.* + read_from_head true + + @type multi_format + + format json + time_key time + time_format %Y-%m-%dT%H:%M:%S.%NZ + + + format /^(? + + + + @id raw.kubernetes + @type detect_exceptions + remove_tag_prefix raw + message log + stream stream + multiline_flush_interval 5 + max_bytes 500000 + max_lines 1000 + + +vim templates/deployment.yaml 在 volumeMounts 与 volumes 下方进行挂载: + +volumeMounts: + - name: varlog + mountPath: /var/log + - name: dockercontainers + mountPath: /var/lib/docker/containers + readOnly: true + +volumes: + - name: varlog + hostPath: + path: /var/log + - name: dockercontainers + hostPath: + path: /var/lib/docker/containers + +helm install . --name flu --namespace=efk -f values.yaml +``` + +**完成后查看:** + +![186.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602487280980.png) + +## 四、部署 kibana + +``` +helm fetch bitnami/kibana + +# 这里要特别注意一下,Kibana 的版本要与Elasticsearch 的版本一直,否则会出错,需要特别、特别注意 + +tar zxvf kibana-5.1.2.tgz + +cd kibana/ + +vim values.yaml + +# 更改其中 Elasticsearch 访问地址 +# 更改 Service 中的 ClusterIP 为 NodePort + +elasticsearch: + hosts: + - es-elasticsearch-coordinating-only + port: 9200 + +service: + port: 80 + type: NodePort + +volumePermissions: + enabled: false + + +helm install . --name kia --namespace=efk -f values.yaml +``` + +完成后查看效果: + +![187.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602487293380.png) + +**通过暴露的端口号,进行 WEB 访问:** + +![188.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602487299380.png) + +**创建一下索引序列:** + +![189.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602487304443.png) + +**我们来以时间为例,创建索引:** + +![190.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602487309733.png) + +**通过时间序列分片:** + +![191.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602487315415.png) + +**分片成功:** + +![192.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602487322082.png) + +**查看我们收集的日志信息:** + +![193.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/12/1602487329159.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\351\233\206\347\276\244\345\256\211\345\205\250\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\351\233\206\347\276\244\345\256\211\345\205\250\344\273\213\347\273\215.md" new file mode 100644 index 0000000..8e6917e --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Kubernetes\344\272\221\350\256\241\347\256\227\345\256\236\346\210\230/\351\233\206\347\276\244\345\256\211\345\205\250\344\273\213\347\273\215.md" @@ -0,0 +1,69 @@ +## 一、机制说明 + + Kubernetes 作为一个分布式集群的管理工具,保证集群的安全性是其一个重要的任务。API Server 是集群内部各个组件通信的中介,也是外部控制的入口。所以 Kubernetes 的安全机制基本就是围绕保护 API Server 来设计的,Kubernetes 使用了认证(Authentication)、鉴权(Authorization)、准入控制(AdmissionControl)三步来保证API Server的安全 。 + +![144.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602333731707.png) + +## 二、认证 Authentication + +**HTTP Token 认证:** + +通过一个 Token 来识别合法用户,HTTP Token 的认证是用一个很长的特殊编码方式的并且难以被模仿的字符串 - Token 来表达客户的一种方式。Token 是一个很长的很复杂的字符串,每一个 Token 对应一个用户名存储在 API Server 能访问的文件中,当客户端发起 API 调用请求时,需要在 HTTP Header 里放入 Token。 + +**HTTP Base 认证:** + +通过用户名+密码的方式进行认证,用户名+密码用 BASE64 算法进行编码后的字符串放在 HTTP Request 中的 Heather Authorization 域里发送给服务端,服务端收到后进行编码,获取用户名及密码。 + +**HTTPS 证书认证:** + +HTTPS 证书认证是最严格的认证,基于 CA 根证书签名的客户端身份认证方式。 + +**1、HTTPS 证书认证:** + +![145.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602333745001.png) + +**2、需要认证的节点** + +![146.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602333752242.png) + +**两种类型** + +- Kubenetes 组件对 API Server 的访问:kubectl、Controller Manager、Scheduler、kubelet、kube-proxy +- Kubernetes 管理的 Pod 对容器的访问:Pod(dashborad 也是以 Pod 形式运行) + +**安全性说明** + +Controller Manager、Scheduler 与 API Server 在同一台机器,所以直接使用 API Server 的非安全端口访问, --insecure-bind-address=127.0.0.1 + +kubectl、kubelet、kube-proxy 访问 API Server 就都需要证书进行 HTTPS 双向认证 + +**证书颁发** + +- 手动签发:通过 k8s 集群的跟 ca 进行签发 HTTPS 证书 +- 自动签发:kubelet 首次访问 API Server 时,使用 token 做认证,通过后,Controller Manager 会为kubelet 生成一个证书,以后的访问都是用证书做认证了 + +**3、kubeconfig** + +kubeconfig 文件包含集群参数(CA证书、API Server地址),客户端参数(上面生成的证书和私钥),集群context 信息(集群名称、用户名)。Kubenetes 组件通过启动时指定不同的 kubeconfig 文件可以切换到不同的集群。 + +**4、ServiceAccount** + +Pod中的容器访问API Server。因为Pod的创建、销毁是动态的,所以要为它手动生成证书就不可行了。Kubenetes使用了Service Account解决Pod 访问API Server的认证问题。 + +**5、Secret 与 SA 的关系** + +Kubernetes 设计了一种资源对象叫做 Secret,分为两类,一种是用于 ServiceAccount 的 service-account-token,另一种是用于保存用户自定义保密信息的 Opaque。ServiceAccount 中用到包含三个部分:Token、ca.crt、namespace。 + +1、token是使用 API Server 私钥签名的 JWT。用于访问API Server时,Server端认证 + +2、ca.crt,根证书。用于Client端验证API Server发送的证书 + +3、namespace, 标识这个service-account-token的作用域名空间 + +``` +# Json web token(JWT),是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准(RFC 7519),该 token 被设计为紧凑且安全的,特别适合用于分布式站点的单点登陆(SSO)场景,JWT 的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其他业务逻辑所必需声明的信息,该 token 也可以直接用于认证,也可以被加密。 +``` + +默认情况下,每个 namespace 都会有一个 ServiceAccount,如果 Pod 在创建时没有指定 ServiceAccount,就会使用 Pod 所属的 namespace 的 ServiceAccount + +![147.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/10/1602333792724.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/DHCP\346\234\215\345\212\241.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/DHCP\346\234\215\345\212\241.md" new file mode 100644 index 0000000..c87f542 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/DHCP\346\234\215\345\212\241.md" @@ -0,0 +1,704 @@ +## 一、DHCP介绍 + +在LAN(局域网)中我们常会遇到以下的情况: + +``` +1)不知道如何配置IP地址及相关信息的员工,无法上网; + +2)IP地址配置冲突,无法上网; + +3)来访用户因不熟悉公司网络情况无法上网; +``` + +以上这些情况都是日常最常见也是最无脑的工作,公司网络管理员需要不停的去帮忙去解决这些问题,以此来保障公司网络的正常使用及员工的正常用网需求。而这些工作对于网络管理员来说实在是太低级、太无脑、太繁琐了,会消耗网络管理员的大量工作时间,也会影响公司员工的工作效能。那么如何通过其他的方法让计算机就能直接解决了上述问题,从而解放网络管理员呢?DHCP就是一个不二的选择。 + +DHCP(Dynamic Host Configuration Protocol,动态主机配置协议),通常被应用在局域网络环境中,主要作用是集中的管理、分配IP地址,使网络环境中的主机动态的获得IP地址、Gateway地址、DNS服务器地址等信息,并能够提升地址的使用率。由于DHCP是一个UDP协议,所以运行起来更加高效。 + +DHCP协议采用客户端/服务器模型(C/S模型),服务端可以为客户端提供IP、掩码、网关、主机名、DNS等信息。客户端只需将IP获得方式设置为自动获取即可。 + +目前可以提供DHCP服务的设备有很多,比如: + +- DHCP服务器(windows server、linux) +- 硬件路由器 +- 家用宽带路由 + +## 二、DHCP应用场景 + +1)公司局域网环境 + +2)家庭局域网环境 + +3)公共场合的wifi环境 + +4)宽带环境网络 + +``` +使用DHCP的优点: + +1)傻瓜式接入:用户只需懂得插网线到电脑,或者输入WiFi密码接入网络即可实现联网 + +2)IP高效利用:及时回收IP机制,保证IP的高利用性,特别是对IP不足的网络 + +3)避免IP冲突:避免IP冲突,保证网络的高效利用,保证公司员工及临时人员高效工作 + +4)降低了公司网络管理员的工作量,提升了工作效率 +``` + +## 三、DHCP工作原理 + +![image20200113193556339.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602997688363.png) + +### 3.1)工作方式 + +IP获得需要通过发广播来实现客户端和服务器的通信,所以DHCP只能工作在局域网。 + +### 3.2)工作原理解析 + +1、Client:向网络中发送广播,通过自己的UDP协议的68号端口向网络中发送DHCP Discover包,用来寻找网络中的DHCP Server.类似于你在你的公司大喊一声:"谁是公司老板"一样的道理。 + +2、Server:局域网中的所有DHCP服务器都能收到该Client发送的广播包,然后DHCP Server会检查自己的IP池中(也叫做作用域)是否还有可用IP可以分发。如果有的话,会直接将这个IP地址从池中拿出来,避免在发给别的客户端,并且通过自己的UDP协议的67号端口给Client发一个响应包DHCP Offer,同样通信是采用广播的方式,明确告诉其可以提供哪个IP给Client使用。类似于公司的几个老板都在公司喊了一声:“我是X老板,我有时间在哪个办公室接待你”。 + +3、Client:Client会收到局域网中的所有DHCP服务器发给自己的DHCP Offer包,默认选一个最优的DHCP Server进行IP获取(在这里就是第一个发送给他DHCP Offer的服务器算作最优)。然后继续向网络中通过UDP的68号端口发广播DHCP Resquest,明确指定DHCP Server IP地址和需要租用的IP地址,告诉它要从他这里获得IP信息。自然其他DHCP Server也能收到广播,确认不从自己这里拿IP信息后,会将上步从IP池中拿出来的IP在释放到池中,以便别人使用。类似于你在公司大喊一声:“李老板,我找你接待”,那么其他老板刚才计划接待你的时间就会被释放出来,用于接待别的客户。 + +4、Server:被确认的DHCP Server就会通过其UDP协议的67号端口发送DHCP ACK确认包,采用广播将IP、掩码、网关、DNS等信息还有IP租约一起发送给DHCP Client,Client确认IP可用后,根据IP租约开始计算使用时间。类似于李老板把你请进他的办公室,开始和你聊天,并计算聊天时间为30分钟,开始倒计时。 + +### 3.3)计算机获得IP的时间点 + +a、计算机开机 + +b、网卡接通网络 + +c、重启网卡服务 + +### 3.4)租约更新阶段 + +a、租约完成1/2 + +b、租约完成7/8 + +c、租约到期 + +## 四、DHCP服务器部署 + +**约定:本实验中使用过的机器为centos8.0_x86_64系统,计算机名称:localhost.localdomain,IP地址192.168.11.16/24.请关闭防火墙和SELINUX。** + +### 4.1)DHCP安装 + +``` +[root@zutuanxue ~]# dnf -y install dhcp-server +``` + +### 4.2)DHCP配置文件详解 + +默认情况下,dhcp服务并没有提供配置文件,只是给提供了一个demo,存放在/usr/share/doc/dhcp-server/目录下.我们将demo文件拷贝到/etc/dhcp目录下,并且命名为dhcpd.conf。 + +``` +[root@zutuanxue ~]# cp /usr/share/doc/dhcp-server/dhcpd.conf.example /etc/dhcp/dhcpd.conf +cp:是否覆盖"/etc/dhcp/dhcpd.conf" y +``` + +配置文件详解 + +``` +[root@zutuanxue ~]# cat /etc/dhcp/dhcpd.conf +# #号代表注释 +# DHCP服务配置文件分为全局配置和作用域配置,很好区分:subnet的就是作用域 不在subnet里面的就是全局设置。 +# dhcpd.conf +# +# Sample configuration file for ISC dhcpd +# + +#DNS全局选项,指定DNS服务器的地址,可以是IP,也可以是域名。 +# option definitions common to all supported networks... +# DNS的域名 +option domain-name "example.org"; + +#具体的DNS服务器 +option domain-name-servers ns1.example.org, ns2.example.org; + +#默认租约为600s +default-lease-time 600; +#最大租约为7200s,客户机会在default-lease-time快到期时向服务器续租,如果此时客户机死机/重启,而默认租约时间到期了,服务器并不会立即回收IP地址,而是等到最大租约时间到期,客户机还没有过来续约,才会回收IP地址。 +max-lease-time 7200; + +#动态DNS更新方式(none:不支持;interim:互动更新模式;ad-hoc:特殊更新模式) +# Use this to enble / disable dynamic dns updates globally. +#ddns-update-style none; + +#如果该DHCP服务器是本地官方DHCP就将此选项打开,避免其他DHCP服务器的干扰。 +#当一个客户端试图获得一个不是该DHCP服务器分配的IP信息,DHCP将发送一个拒绝消息,而不会等待请求超时。当请求被拒绝,客户端会重新向当前DHCP发送IP请求获得新地址。保证IP是自己发出去的 +# +# If this DHCP server is the official DHCP server for the local +# network, the authoritative directive should be uncommented. +#authoritative; + +# Use this to send dhcp log messages to a different log file (you also +# have to hack syslog.conf to complete the redirection). +# 日志级别 +log-facility local7; + +# No service will be given on this subnet, but declaring it helps the +# DHCP server to understand the network topology. + +#作用域相关设置指令 +#subnet 定义一个作用域 +#netmask 定义作用域的掩码 +#range 允许发放的IP范围 +#option routers 指定网关地址 +#option domain-name-servers 指定DNS服务器地址 +#option broadcast-address 广播地址 +# +# +#案例:定义一个作用域 网段为10.152.187.0 掩码为255.255.255.0 +#此作用域不提供任何服务 +subnet 10.152.187.0 netmask 255.255.255.0 { +} + +# This is a very basic subnet declaration. + +#案例:定义一个基本的作用域 +#网段10.254.239.0 掩码255.255.255.224 +#分发范围10.254.239.10-20 +#网关为rtr-239-0-1.example.org, rtr-239-0-2.example.org +subnet 10.254.239.0 netmask 255.255.255.224 { + range 10.254.239.10 10.254.239.20; + option routers rtr-239-0-1.example.org, rtr-239-0-2.example.org; +} + +# This declaration allows BOOTP clients to get dynamic addresses, +# which we don't really recommend. +#案例:允许采用bootp协议的客户端动态获得地址 +#bootp DHCP的前身 +#BOOTP用于无盘工作站的局域网中,可以让无盘工作站从一个中心服务器上获得IP地址。通过BOOTP协议可以为局域网中的无盘工作站分配动态IP地址, +#这样就不需要管理员去为每个用户去设置静态IP地址。 +subnet 10.254.239.32 netmask 255.255.255.224 { + range dynamic-bootp 10.254.239.40 10.254.239.60; + option broadcast-address 10.254.239.31; + option routers rtr-239-32-1.example.org; +} + + +#案例:一个简单的作用域案例 +# A slightly different configuration for an internal subnet. +subnet 10.5.5.0 netmask 255.255.255.224 { + range 10.5.5.26 10.5.5.30; + option domain-name-servers ns1.internal.example.org; + option domain-name "internal.example.org"; + option routers 10.5.5.1; + option broadcast-address 10.5.5.31; + default-lease-time 600; + max-lease-time 7200; +} + +# Hosts which require special configuration options can be listed in +# host statements. If no address is specified, the address will be +# allocated dynamically (if possible), but the host-specific information +# will still come from the host declaration. +# +#保留地址:可以将指定的IP分发给指定的机器,根据网卡的MAC地址来做触发 +#host: 启用保留。 +#hardware:指定客户端的mac地址 +#filename:指定文件名 +#server-name:指定下一跳服务器地址 +#fixed-address: 指定保留IP地址 +# +# +#案例:这个案例中分发给客户端的不是IP地址信息,而是告诉客户端去找toccata.fugue.com服务器,并且下载vmunix.passacaglia文件 +host passacaglia { + hardware ethernet 0:0:c0:5d:bd:95; + filename "vmunix.passacaglia"; + server-name "toccata.fugue.com"; +} + +# Fixed IP addresses can also be specified for hosts. These addresses +# should not also be listed as being available for dynamic assignment. +# Hosts for which fixed IP addresses have been specified can boot using +# BOOTP or DHCP. Hosts for which no fixed address is specified can only +# be booted with DHCP, unless there is an address range on the subnet +# to which a BOOTP client is connected which has the dynamic-bootp flag +# set. +# 案例:保留地址,将指定IP(fantasia.fugue.com对应的IP)分给指定客户端网卡(MAC:08:00:07:26:c0:a5) +host fantasia { + hardware ethernet 08:00:07:26:c0:a5; + fixed-address fantasia.fugue.com; +} + +#超级作用域 +#超级作用域是DHCP服务中的一种管理功能,使用超级作用域,可以将多个作用域组合为单个管理实体。 +# You can declare a class of clients and then do address allocation +# based on that. The example below shows a case where all clients +# in a certain class get addresses on the 10.17.224/24 subnet, and all +# other clients get addresses on the 10.0.29/24 subnet. + + +#在局域网中,可以配置策略根据各个机器的具体信息分配IP地址和其他的网络参数,客户机的具体信息:客户机能够给dhcp服务提供的信息由有两个, +#第一个就是网卡的dhcp-client-identifier(mac地址), +#第二个就是设备的vendor-class-identifier。 +#管理员可以根据这两个信息给不同的机器分组。 + +#案例: +#按client某种类型分组DHCP,而不是按物理接口网段 +#例子: SUNW 分配地址段10.17.224.0/24 +# 非SUNW的主机,分配地址段10.0.29.0/24 +#定义一个dhcp类:foo +#request广播中vendor-class-identifier字段对应的值前四个字节如果是"SUNW",则视合法客户端. +class "foo" { + match if substring (option vendor-class-identifier, 0, 4) = "SUNW"; +} + +#定义一个超级作用域: 224-29 +shared-network 224-29 { +#定义第一个作用域 + subnet 10.17.224.0 netmask 255.255.255.0 { + option routers rtr-224.example.org; + } +#定义第二个作用域 + subnet 10.0.29.0 netmask 255.255.255.0 { + option routers rtr-29.example.org; + } + +#关连池,如果客户端匹配foo类,将获得该池地址 + pool { + allow members of "foo"; + range 10.17.224.10 10.17.224.250; + } +#关连池,如果客户端配置foo类,则拒绝获得该段地址 + pool { + deny members of "foo"; + range 10.0.29.10 10.0.29.230; + } +} +``` + +### 4.3)DHCP启动 + +``` +[root@zutuanxue ~]# systemctl enable dhcpd +Created symlink from /etc/systemd/system/multi-user.target.wants/dhcpd.service to /usr/lib/systemd/system/dhcpd.service. +[root@zutuanxue ~]# systemctl start dhcpd + +注意:可能发现无法启动DHCP服务,原因是DHCP在启动的时候检查配置文件,发现并没有有效作用域(和服务器同网段的作用域)。 +``` + +## 五、DHCP作用域 + +**教学案例一、配置一个作用域,用于为本地局域网中的计算机发放IP信息。要求:** + +本地网段:192.168.11.0/24 + +发放IP地址:192.168.11.153–252 + +网关:192.168.11.254 + +DNS1:202.106.0.20 + +DNS2:114.114.114.114 + +默认租约为两个小时 + +最大租约为3个小时 + +**本DHCP服务器为本地权威DHCP,要求可以本地所有计算机获得IP都是由本DHCP发放** + +### 5.1)DHCP服务配置 + +``` +[root@zutuanxue dhcp]# cat /etc/dhcp/dhcpd.conf +option domain-name-servers 202.106.0.20, 114.114.114.114; +#声明DNS服务器 +default-lease-time 7200; #定义默认租约时间 +max-lease-time 10800; #定义最大租约时间 +authoritative; #拒绝不正确的IP地址的要求 +log-facility local7; #定义日志 + +subnet 192.168.11.0 netmask 255.255.255.0 { + range 192.168.11.153 192.168.11.252; + option routers 192.168.11.254; + option broadcast-address 192.168.11.255; + default-lease-time 7200; + max-lease-time 10800; +} + +请根据4.2中的讲解理解配置文件内容。 +``` + +### 5.2)重启DHCP服务,生效配置 + +``` +#重启dhcpd服务 +[root@zutuanxue dhcp]# systemctl restart dhcpd + +#查看启动情况,同时也验证了客户端使用的是68端口,服务端使用的是67端口 +[root@zutuanxue dhcp]# lsof -i :68 +COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME +dhclient 55234 root 6u IPv4 110700 0t0 UDP *:bootpc +[root@zutuanxue dhcp]# lsof -i :67 +COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME +dnsmasq 1507 nobody 3u IPv4 27149 0t0 UDP *:bootps +dhcpd 56570 dhcpd 7u IPv4 129157 0t0 UDP *:bootps +``` + +### 5.3)测试IP分发 + +打开一个客户端机器,IP获得方式为自动获取,测试是否获得到了自己这个DHCP服务器发放的IP地址。本例子中测试机使用了centos 8系统。来看下测试结果吧! + +``` +1) 查看一下当前eth0的IP地址、MAC地址,并保证其IP获得方式为:DHCP +[root@test 桌面]# ifconfig eth0 +eth0 Link encap:Ethernet HWaddr 00:0C:29:1A:F8:BD + inet addr:172.16.44.132 Bcast:172.16.44.255 Mask:255.255.255.0 + inet6 addr: fe80::20c:29ff:fe1a:f8bd/64 Scope:Link + UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 + RX packets:86 errors:0 dropped:0 overruns:0 frame:0 + TX packets:63 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:15294 (14.9 KiB) TX bytes:6769 (6.6 KiB) + + +2)使用dhclient命令来获得IP,看一下重要输出 +[root@test 桌面]# dhclient -d eth0 +Internet Systems Consortium DHCP Client 4.1.1-P1 +Copyright 2004-2010 Internet Systems Consortium. +All rights reserved. +For info, please visit https://www.isc.org/software/dhcp/ + +Listening on LPF/eth0/00:0c:29:1a:f8:bd +Sending on LPF/eth0/00:0c:29:1a:f8:bd +Sending on Socket/fallback +DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 6 (xid=0x316768c3) 发广播寻找DHCP服务器 +DHCPOFFER from 192.168.11.16 192.168.11.16DHCP服务器应答 +DHCPREQUEST on eth0 to 255.255.255.255 port 67 (xid=0x316768c3) client向服务器请求IP地址 +DHCPACK from 192.168.11.16 (xid=0x316768c3) 确认租赁关系 +bound to 192.168.11.156 -- renewal in 2983 seconds. client分得IP:192.168.11.156 + +注意:看到这些信息后,按CTRL+C退出。 +dhclient是一个DHCP协议客户端,它使用DHCP协议或者BOOTP协议或在这两个协议都不可用时使用静态地址来配置一个或多个网络接口 +dhclient -r 释放IP地址 +dhclient -d 强制dhclient作为前台进程运行。 通常情况下,DHCP客户端将在前台运行,直到配置了一个接口,此时它将恢复为在后 + 台运行。 + + + + +3) 服务器日志查看验证获取信息 +[root@zutuanxue ~]# tailf /var/log/messages +Feb 21 13:40:44 baism dhcpd: DHCPDISCOVER from 00:0c:29:1a:f8:bd via ens33 +Feb 21 13:40:45 baism dhcpd: DHCPOFFER on 192.168.11.156 to 00:0c:29:1a:f8:bd via ens33 +Feb 21 13:40:45 baism dhcpd: DHCPREQUEST for 192.168.11.156 (192.168.11.16) from 00:0c:29:1a:f8:bd via ens33 +Feb 21 13:40:45 baism dhcpd: DHCPACK on 192.168.11.156 to 00:0c:29:1a:f8:bd via ens33 + +4) 在client上通过ifconfig命令再次查看eth0 IP地址,验证是否为192.168.11.156 +[root@test 桌面]# ifconfig eth0 +eth0 Link encap:Ethernet HWaddr 00:0C:29:1A:F8:BD + inet addr:192.168.11.156 Bcast:192.168.11.255 Mask:255.255.255.0 + inet6 addr: fe80::20c:29ff:fe1a:f8bd/64 Scope:Link + UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 + RX packets:97 errors:0 dropped:0 overruns:0 frame:0 + TX packets:67 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:17364 (16.9 KiB) TX bytes:7537 (7.3 KiB) + + +5)查看网关,确定网关为192.168.11.254 +[root@test 桌面]# route -n +Kernel IP routing table +Destination Gateway Genmask Flags Metric Ref Use Iface +192.168.11.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1 +192.168.11.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 +169.254.0.0 0.0.0.0 255.255.0.0 U 1003 0 0 eth1 +0.0.0.0 192.168.11.254 0.0.0.0 UG 0 0 0 eth0 + + +6)查看DNS配置文件,看DNS是否为DHCP服务器发放的DNS服务器IP +[root@test 桌面]# cat /etc/resolv.conf +; generated by /sbin/dhclient-script +nameserver 202.106.0.20 +nameserver 114.114.114.114 +``` + +### 5.4)通过DHCP服务器租约文件查看具体租约 + +租约文件的路径: /var/lib/dhcpd/dhcpd.leases + +``` +[root@zutuanxue ~]# cat /var/lib/dhcpd/dhcpd.leases +# The format of this file is documented in the dhcpd.leases(5) manual page. +# This lease file was written by isc-dhcp-4.3.6 + +# authoring-byte-order entry is generated, DO NOT DELETE +authoring-byte-order little-endian; + +server-duid "\000\001\000\001%\257\376\022\000\014)c.\345"; + +lease 192.168.11.153 { + starts 2 2020/01/14 04:21:04; #开始时间 + ends 2 2020/01/14 06:21:04; #结束时间 + cltt 2 2020/01/14 04:21:04; + binding state active; + next binding state free; + rewind binding state free; + hardware ethernet 00:0c:29:6d:1c:b3; + uid "\001\000\014)m\034\263"; +} + + + +注意:当你发现这里的时间和你的服务器时间不一致的时候,建议你修改时区解决问题,一般是差8个小时,大家明白就好。 +``` + +### 5.5)保留IP + +在IP租约到期后,如果无法续订租约,client只能乖乖交出IP地址,重新获得一个其他IP使用。但是在公司有些服务器的IP地址是不能变化的,因为变了用户就无法连接到服务器了,比如公司文件服务器、打印服务器等等。那么在这种环境中我们既想使用DHCP管理公司IP,又想实现部分机器的IP永久不变,那么怎么实现呢。 + +DHCP的作者在写DHCP的时候也想到了这个问题,提出了保留IP的概念,就是将某些IP保留,然后服务器来获得IP的时候,根据其MAC地址做匹配,将对应的IP分给它即可。 + +**教学案例:希望这个MAC地址为00:0C:29:1A:F8:C7的网卡能永久获得IP 192.168.11.252,实现方式如下:** + +``` + a、在配置文件/etc/dhcp/dhcpd.conf末尾添加以下内容 + host print { + hardware ethernet 00:0C:29:1A:F8:C7; + fixed-address 192.168.11.252; +} + +host print host为指令,print是个名字,随便起,但是最好有意义,要不过一段你也记不住了。 +hardware ethernet 指定以太网网卡MAC地址 +fixed-address 指定要绑定的IP + +b、重启DHCP服务 +[root@zutuanxue ~]# systemctl restart dhcpd + +c、测试,登陆测试机,释放挡墙IP,重新获得新的IP,查看IP地址是否正确分发 +[root@test 桌面]# ifconfig eth1 +eth1 Link encap:Ethernet HWaddr 00:0C:29:1A:F8:C7 + inet addr:192.168.11.155 Bcast:192.168.11.255 Mask:255.255.255.0 + inet6 addr: fe80::20c:29ff:fe1a:f8c7/64 Scope:Link + UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 + RX packets:4071 errors:0 dropped:0 overruns:0 frame:0 + TX packets:187 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:433880 (423.7 KiB) TX bytes:16888 (16.4 KiB) + +[root@test 桌面]# dhclient -r eth1 + +[root@test 桌面]# dhclient -d eth1 +Internet Systems Consortium DHCP Client 4.1.1-P1 +Copyright 2004-2010 Internet Systems Consortium. +All rights reserved. +For info, please visit https://www.isc.org/software/dhcp/ + +Listening on LPF/eth1/00:0c:29:1a:f8:c7 +Sending on LPF/eth1/00:0c:29:1a:f8:c7 +Sending on Socket/fallback +DHCPDISCOVER on eth1 to 255.255.255.255 port 67 interval 4 (xid=0x45c162c2) +DHCPOFFER from 192.168.11.16 +DHCPREQUEST on eth1 to 255.255.255.255 port 67 (xid=0x45c162c2) +DHCPACK from 192.168.11.16 (xid=0x45c162c2) +bound to 192.168.11.252 -- renewal in 2881 seconds. +^C + +[root@test 桌面]# ifconfig eth1 +eth1 Link encap:Ethernet HWaddr 00:0C:29:1A:F8:C7 + inet addr:192.168.11.252 Bcast:192.168.11.255 Mask:255.255.255.0 + inet6 addr: fe80::20c:29ff:fe1a:f8c7/64 Scope:Link + UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 + RX packets:4081 errors:0 dropped:0 overruns:0 frame:0 + TX packets:191 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:436337 (426.1 KiB) TX bytes:17656 (17.2 KiB) + + +完美! +``` + +## 六、DHCP超级作用域 + +体验了DHCP服务器给大家带来的方便后,我们工作轻松了很多,但是随着时间的推移,突然有这么一个问题急需你解决,由于公司的发展壮大,公司人员数量越来越多,公司一个网段的IP无法满足日常使用,所以又加了一个网段。但是默认情况下,DHCP服务器只能发放和自己网卡在同一网段的IP地址,目前我们DHCP的网卡IP地址为192.168.11.0段,我们新加的网段为192.168.12.0,那么怎么能让DHCP服务器既能发11网段,又能发放12网段呢?学会超级作用域就可以解决这个问题。 + +超级作用域:将两个或以上的不同网段的作用域合成一个作用域既是超级作用域。 + +**案例:部署一个超级作用域,作用域是192.168.11.0/24网段,192.168.12.0/24网段。** + +``` +a、编辑配置文件 +[root@zutuanxue ~]# cat /etc/dhcp/dhcpd.conf +option domain-name-servers 4.2.2.2, 4.2.2.1; + +default-lease-time 28800; +max-lease-time 43200; +#authoritative; +log-facility local7; + +#share-network 部署一个超级作用域 +#supper 超级作用域名称,随便起,但是建议有意义。 +shared-network supper { +#192.168.11.0作用域 +subnet 192.168.11.0 netmask 255.255.255.0 { +range 192.168.11.150 192.168.11.150; +option domain-name-servers 202.106.0.20, 114.114.114.114; +option routers 192.168.11.254; +default-lease-time 7200; +max-lease-time 10800; +} + +#192.168.12.0作用域 +subnet 192.168.12.0 netmask 255.255.255.0 { +range 192.168.12.150 192.168.12.150; +option domain-name-servers 202.106.0.20, 114.114.114.114; +option routers 192.168.12.254; +default-lease-time 7200; +max-lease-time 10800; +} + +} + + +注意:案例中为了方便验证,我每个作用域只发布一个IP,否者测试无法保证能100%分到两个网段。 + +b、重启DHCP服务,生效配置文件 +[root@zutuanxue dhcp]# systemctl restart dhcpd + +c、验证 +#释放两网卡IP +[root@test 桌面]# dhclient -r eth0 +[root@test 桌面]# dhclient -r eth1 + +#释放成功 +[root@test 桌面]# ifconfig +eth0 Link encap:Ethernet HWaddr 00:0C:29:1A:F8:BD + inet6 addr: fe80::20c:29ff:fe1a:f8bd/64 Scope:Link + UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 + RX packets:1591 errors:0 dropped:0 overruns:0 frame:0 + TX packets:162 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:282324 (275.7 KiB) TX bytes:30619 (29.9 KiB) + +eth1 Link encap:Ethernet HWaddr 00:0C:29:1A:F8:C7 + inet6 addr: fe80::20c:29ff:fe1a:f8c7/64 Scope:Link + UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 + RX packets:4719 errors:0 dropped:0 overruns:0 frame:0 + TX packets:216 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:559954 (546.8 KiB) TX bytes:19582 (19.1 KiB) + +lo Link encap:Local Loopback + inet addr:127.0.0.1 Mask:255.0.0.0 + inet6 addr: ::1/128 Scope:Host + UP LOOPBACK RUNNING MTU:16436 Metric:1 + RX packets:12 errors:0 dropped:0 overruns:0 frame:0 + TX packets:12 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 + RX bytes:720 (720.0 b) TX bytes:720 (720.0 b) + +#分别获取IP地址 +[root@test 桌面]# dhclient -d eth0 +Internet Systems Consortium DHCP Client 4.1.1-P1 +Copyright 2004-2010 Internet Systems Consortium. +All rights reserved. +For info, please visit https://www.isc.org/software/dhcp/ + +Listening on LPF/eth0/00:0c:29:1a:f8:bd +Sending on LPF/eth0/00:0c:29:1a:f8:bd +Sending on Socket/fallback +DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 6 (xid=0x2574199a) +DHCPOFFER from 192.168.11.16 +DHCPREQUEST on eth0 to 255.255.255.255 port 67 (xid=0x2574199a) +DHCPACK from 192.168.11.16 (xid=0x2574199a) +bound to 192.168.11.150 -- renewal in 3026 seconds. +^C +#确保都是来自我们实验中的DHCP服务器 +[root@test 桌面]# dhclient -d eth1 +Internet Systems Consortium DHCP Client 4.1.1-P1 +Copyright 2004-2010 Internet Systems Consortium. +All rights reserved. +For info, please visit https://www.isc.org/software/dhcp/ + +Listening on LPF/eth1/00:0c:29:1a:f8:c7 +Sending on LPF/eth1/00:0c:29:1a:f8:c7 +Sending on Socket/fallback +DHCPDISCOVER on eth1 to 255.255.255.255 port 67 interval 7 (xid=0x2cebde11) +DHCPOFFER from 192.168.11.16 +DHCPREQUEST on eth1 to 255.255.255.255 port 67 (xid=0x2cebde11) +DHCPACK from 192.168.11.16 (xid=0x2cebde11) +bound to 192.168.12.150 -- renewal in 3102 seconds. + +#确保都是来自我们实验中的DHCP服务器 + + +#查看IP情况,发现实验成功了,分别获得到了不同网段IP +[root@test 桌面]# ifconfig +eth0 Link encap:Ethernet HWaddr 00:0C:29:1A:F8:BD + inet addr:192.168.11.150 Bcast:192.168.11.255 Mask:255.255.255.0 + inet6 addr: fe80::20c:29ff:fe1a:f8bd/64 Scope:Link + UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 + RX packets:1613 errors:0 dropped:0 overruns:0 frame:0 + TX packets:166 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:287076 (280.3 KiB) TX bytes:31387 (30.6 KiB) + +eth1 Link encap:Ethernet HWaddr 00:0C:29:1A:F8:C7 + inet addr:192.168.12.150 Bcast:192.168.12.255 Mask:255.255.255.0 + inet6 addr: fe80::20c:29ff:fe1a:f8c7/64 Scope:Link + UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 + RX packets:4741 errors:0 dropped:0 overruns:0 frame:0 + TX packets:220 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:564706 (551.4 KiB) TX bytes:20350 (19.8 KiB) + +lo Link encap:Local Loopback + inet addr:127.0.0.1 Mask:255.0.0.0 + inet6 addr: ::1/128 Scope:Host + UP LOOPBACK RUNNING MTU:16436 Metric:1 + RX packets:12 errors:0 dropped:0 overruns:0 frame:0 + TX packets:12 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 + RX bytes:720 (720.0 b) TX bytes:720 (720.0 b) +``` + +## 七、补充 + +### 7.1) 如果客户端获得不到 IP会怎么办 + +当客户端获得不到IP地址,会得到一个169.254开头的临时IP,此IP不能和其他网段通信,但是Client会继续向网络中发DHCP广播,继续坚持不懈申请IP。 + +### 7.2)DHCP会面临单机故障,如何解决 + +两台设备互相分发对方网段一段IP,将作用域采用8/2原则,彼此互相冗余,当一台服务器出现问题,不至于整个网段故障。 + +### 7.3)抓包验证方法 + +``` +[root@zutuanxue dhcp]# tcpdump -nn -vvv -s 1500 -i ens33 host 192.168.11.16 and udp port 67 or udp port 68 +``` + +### 7.4)如何发放计算机名称 + +发放计算机名称只能在保留中完成,要求Client的计算机名配置文件中将对应字段删除。 + +``` +option domain-name-servers 4.2.2.2, 4.2.2.1; + +default-lease-time 28800; +max-lease-time 43200; +authoritative; +log-facility local7; + +subnet 192.168.11.0 netmask 255.255.255.0 { + range 192.168.11.153 192.168.11.252; + option domain-name-servers 202.106.0.20, 114.114.114.114; + option routers 192.168.11.254; + option broadcast-address 192.168.11.255; + default-lease-time 7200; + max-lease-time 10800; +} + +host print { + #指定计算机名称 + option host-name "test.hello.com"; + hardware ethernet 00:0c:29:af:f1:84; + fixed-address 192.168.11.252; +} + +注意:请把/etc/hostname 中的计算机名称清除 + /etc/sysconfig/network中的hostname字段清除 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/DNS\346\234\215\345\212\241.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/DNS\346\234\215\345\212\241.md" new file mode 100644 index 0000000..c8f3c28 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/DNS\346\234\215\345\212\241.md" @@ -0,0 +1,702 @@ +DNS:域名系统(英文:Domain Name System)是一个域名系统,是万维网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。类似于生活中的114服务,可以通过人名找到电话号码,也可以通过电话号码找到人名(生活中没有那么准确的原因是人名有重名,而域名是全世界唯一的)。 + +DNS协议运行在UDP协议之上,使用端口号53 + +``` +域名: +域名是一个网站的逻辑地址,比如www.zutuanxue.com,相比IP地址更加方便人类记忆,所以被广泛使用。 +``` + +## 一、DNS介绍 + +计算机的发展起源于上世纪60年代,最初只有美国的几所高校在使用,计算机之间通信需要知道对方的地址(IP地址),但是人们对IP地址的记忆又是不敏感的(就像生活中你能记住多少个好友的手机号码一样)。为了方便人类记忆,大学的科学家们把计算机的名字和对应的IP地址写入到计算机中的hosts文件,以此文件来做解析。 + +但是随着计算机和网络的发展出现了局域网,计算机的数量随之增加;后来为了解决方便通信问题,我们使用了wins服务器来进行计算机名和IP的注册服务,通过一个名称服务器来自动管理局域网中的计算机,并提供解析服务。人们在局域网中通过计算机名就能连接到了对应的计算机。该技术中要求计算机名称必须唯一,正是由于这个原因使得局域网中的计算机又不能太多。 + +微型计算机的出现和局域网的发展推动了广域网的发展,hosts文件只能针对极少的计算机网络,wins可以管理局域网的解析。到了广域网,人们就迫切需要一个新的服务做解析服务器,使解析方便、快速、高效的应对广域网环境。为了解决广域网解析问题,美国人研发出了DNS服务,以及成立了管理DNS相关的机构,并提出了域名命名规则。 + +``` +域名管理机构 +Internet 域名与地址管理机构(ICANN)是为承担域名系统管理,IP地址分配,协议参数配置,以及主服务器系统管理等职能而设立的非盈利机构. +现由IANA和其他实体与美国政府约定进行管理。 + +域名分国际域名和国内域名两种,对于国际域名而言,其命名规则是: +域名可以由(a-z、A-Z大小写等价)26个英文字母、数字(0-9)以及连接符“-”组成,但是域名的首位必须是字母或数字。对于域名的长度也有一定 +的限制:国际通用顶级域名长度不得超过26个字符,中国国家顶级域名长度不得超过20个字符 +``` + +## 二、DNS的解析原理 + +目前,因特网的命名方法是层次树状结构的方法。采用这种命名方法,任何一个连接在因特网上的主机或设备,都有一个某一的层次结构的名字,即域名(domain name)。域是名字空间中一个可被管理的划分。域可以继续按层次划分为子域,如二级域、三级域等等。 + +![image20200114172132398.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602998062358.png) + +## 三、DNS查询 + +递归查询:一般客户机和服务器之间属递归查询,即当客户机向DNS服务器发出请求后,若DNS服务器本身不能解析,则会向另外的DNS服务器发出查询请求,得到结果后转交给客户机;如果主机所询问的本地域名服务器不知道被查询的域名的IP地址,那本地 DNS就会扮演DNS客户的角色,去代理原客户去帮忙找根域名服务器发出请求,递归即递给服务器,所有操作都有服务器来完成。 + +迭代查询:一般DNS服务器之间属迭代查询,如:DNS1问DNS2,DNS2不知道会告诉DNS1一个DNS3的IP地址,让DNS1去问问DNS3知不知道,以此类推,就是迭代查询。 + +关于递归和迭代举个生活例子帮助大家理解:比如你问张老师一个问题,张老师告诉他答案这之间的叫递归查询。这期间也许张老师也不会,这时张老师问李老师,张老师去问崔老师,这之间的查询叫迭代查询! + +![image20200114180942259.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602998078641.png) + +正向查找:将域名解析为IP + +``` + www.zutuanxue.com ---> 118.190.209.153 +``` + +反向查找:将IP解析为域名 + +``` + 118.290.209.153 ---> www.zutuanxue.com +``` + +## 四、DNS服务器部署 + +**约定:本实验中使用过的机器为centos8.0_x86_64系统,IP地址192.168.11.16/24.请关闭防火墙和SELINUX。** + +### 4.1)DNS安装 + +DNS服务是由bind程序提供的,所以要实现DNS服务就需要安装bind程序包。 + +``` +[root@zutuanxue ~]# dnf -y install bind bind-chroot +bind DNS主程序包 +bind-chroot DNS安全包,改变默认DNS根目录,将DNS运行在监牢模式 + +说明:chroot监牢模式 +监牢是一个软件机制,其功能是使得某个程序无法访问规定区域之外的资源,同样也为了增强安全性(LCTT 译注:chroot “监牢”,所谓“监牢”就是指通过chroot机制来更改某个进程所能看到的根目录,即将某进程限制在指定目录中,保证该进程只能对该目录及其子目录的文件进行操作,从而保证整个服务器的安全)。Bind Chroot DNS 服务器的默认“监牢”为 /var/named/chroot。 +``` + +### 4.2)DNS启动 + +DNS的守护进程叫做named,DNS是以named用户身份来运行,named用户在安装包的时候会在系统中自动创建。 + +``` +CentOS8下安装了bind-chroot之后,若要使用named-chroot.service,则需要关闭named.service。两者只能运行一个 + +方法一: 不使用chroot模式启动DNS +开启开机启动 +[root@zutuanxue ~]# systemctl enable named +Created symlink from /etc/systemd/system/multi-user.target.wants/named.service to /usr/lib/systemd/system/named.service. + +启动DNS服务 +[root@zutuanxue ~]# systemctl start named + +验证启动 +[root@zutuanxue ~]# lsof -i :53 +COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME +dnsmasq 1520 nobody 5u IPv4 27001 0t0 UDP bogon:domain +dnsmasq 1520 nobody 6u IPv4 27002 0t0 TCP bogon:domain (LISTEN) +named 2553 named 21u IPv4 38662 0t0 TCP localhost:domain (LISTEN) +named 2553 named 22u IPv6 38664 0t0 TCP localhost:domain (LISTEN) +named 2553 named 512u IPv4 38660 0t0 UDP localhost:domain +named 2553 named 513u IPv4 38660 0t0 UDP localhost:domain +named 2553 named 514u IPv4 38660 0t0 UDP localhost:domain +named 2553 named 515u IPv4 38660 0t0 UDP localhost:domain +named 2553 named 516u IPv6 38663 0t0 UDP localhost:domain +named 2553 named 517u IPv6 38663 0t0 UDP localhost:domain +named 2553 named 518u IPv6 38663 0t0 UDP localhost:domain +named 2553 named 519u IPv6 38663 0t0 UDP localhost:domain + +方法二: 使用chroot模式DNS +将对应的文件移动到chroot根目录 +主配文件 +[root@zutuanxue ~]# cp /etc/named.conf /var/named/chroot/etc/ +[root@zutuanxue ~]# chgrp named /var/named/chroot/etc/named.conf +[root@zutuanxue ~]# named-checkconf /var/named/chroot/etc/named.conf + +区域数据库文件 +[root@zutuanxue named]# cd /var/named/ +[root@zutuanxue named]# cp -r data /var/named/chroot/var/named/ +[root@zutuanxue named]# cp -r dynamic /var/named/chroot/var/named/ +[root@zutuanxue named]# cp named.* /var/named/chroot/var/named/ +[root@zutuanxue named]# cd /var/named/chroot/var/named/ +[root@zutuanxue named]# chown -R named.named * + + +启动DNS服务 +开机启动 +[root@zutuanxue ~]# systemctl enable named-chroot.service +Created symlink from /etc/systemd/system/multi-user.target.wants/named-chroot.service to /usr/lib/systemd/system/named-chroot.service. +启动服务 +[root@zutuanxue ~]# mv /etc/named.conf /root/ +[root@zutuanxue ~]# systemctl start named-chroot + +验证启动 +[root@zutuanxue ~]# lsof -i :53 +COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME +dnsmasq 1525 nobody 5u IPv4 27359 0t0 UDP bogon:domain +named 2877 named 21u IPv4 44717 0t0 TCP localhost:domain (LISTEN) +named 2877 named 22u IPv4 44719 0t0 TCP bogon:domain (LISTEN) +named 2877 named 23u IPv4 44721 0t0 TCP bogon:domain (LISTEN) +named 2877 named 512u IPv4 44715 0t0 UDP localhost:domain +named 2877 named 513u IPv4 44715 0t0 UDP localhost:domain +named 2877 named 514u IPv4 44715 0t0 UDP localhost:domain +named 2877 named 515u IPv4 44715 0t0 UDP localhost:domain +named 2877 named 516u IPv4 44718 0t0 UDP bogon:domain +named 2877 named 517u IPv4 44718 0t0 UDP bogon:domain +named 2877 named 518u IPv4 44718 0t0 UDP bogon:domain +named 2877 named 519u IPv4 44718 0t0 UDP bogon:domain +named 2877 named 520u IPv4 44720 0t0 UDP bogon:domain +named 2877 named 521u IPv4 44720 0t0 UDP bogon:domain +named 2877 named 522u IPv4 44720 0t0 UDP bogon:domain +named 2877 named 523u IPv4 44720 0t0 UDP bogon:domain +``` + +### 4.3)DNS配置文件 + +默认情况下,如果不安装bind-chroot这个包,配置文件的路径如下: + +配置文件:/etc/named.conf + +区域数据库文件:/var/named/ + +由于我们安装了bind-chroot这个用于改变默认DNS配置文件的路径的包,所以相对应的配置文件的路径也发生了变化。 + +变化如下: + +配置文件:/var/named/chroot/etc/named.conf + +区域数据库文件:/var/named/chroot/var/named/ + +a、主配文件详解 + +``` +// +// named.conf +// +// Provided by Red Hat bind package to configure the ISC BIND named(8) DNS +// server as a caching only nameserver (as a localhost DNS resolver only). +// +// See /usr/share/doc/bind*/sample/ for example named configuration files. +// + + +options +{ + + #IPv4监听端口为53,只允许本机连接 + listen-on port 53 { 127.0.0.1; }; + #IPv6监听端口为53,只允许本机连接 + listen-on-v6 port 53 { ::1; }; + #定义工作目录 + directory "/var/named"; + #CACHE文件路径,指定服务器在收到rndc dump命令时,转储数据到文件的路径。默认cache_dump.db + dump-file "data/cache_dump.db"; + #静态文件路径,指定服务器在收到rndc stats命令时,追加统计数据的文件路径。默认named.stats + statistics-file "data/named_stats.txt"; + #内存静态文件路径,服务器在退出时,将内存统计写到文件的路径。默认named.mem_stats + memstatistics-file "data/named_mem_stats.txt"; + #在收到rndc secroots指令后,服务器转储安全根的目的文件的路径名。默认named.secroots + secroots-file "data/named.secroots"; + # 指定服务器在通过rndc recursing命令指定转储当前递归请求到的文件路径。默认named.recursing + recursing-file "data/named.recursing"; + + #指定允许哪些主机可以进行普通的DNS查询,可以是关键字:any/localhost/none,也可以是IPV4,IPV6地址 + allow-query { localhost; }; + #指定允许哪些主机可以对缓存的访问 + allow-query-cache { localhost; }; + + /* + - If you are building an AUTHORITATIVE DNS server, do NOT enable recursion. + 假如你建立的是一个权威DNS你不需要开启递归 + - If you are building a RECURSIVE (caching) DNS server, you need to enable recursion. + 假如你建立的是一个递归DNS,你需要开启递归服务 + - If your recursive DNS server has a public IP address, you MUST enable access control to limit queries to your legitimate users. Failing to do so will + 如果你的递归DNS是具有公网IP,你必须要设置访问控制来限制对合法用户的查询. + cause your server to become part of large scale DNS amplification + 否则你的DNS会被大规模的攻击 + attacks. Implementing BCP38 within your network would greatly + 在您的网络中实现BCP38将非常重要减少此类攻击面 + reduce such attack surface + */ + #开启递归 + recursion yes; + + #开启DNSSEC在权威或者递归服务器之间信任服务 + dnssec-enable yes; + + #开启DNSSEC验证在递归服务器 + dnssec-validation yes; + + #指定目录,其中保存着跟踪被管理DNSSEC密钥文件。默认为工作目录。 + managed-keys-directory "/var/named/dynamic"; + + #PID文件路径 + pid-file "/run/named/named.pid"; + #session-keyfile文件路径 + session-keyfile "/run/named/session.key"; +}; + +logging +{ +#开启DNS日志记录 + channel default_debug { + file "data/named.run"; + severity dynamic; + }; +}; + + + + #定义一个根域 +zone "." IN { + #域类型为hint,还有master slave forward等类型 + type hint; + #区域数据库文件路径 + file "/var/named/named.ca"; + }; +}; + #包含两个子配置文件 + include "/etc/named.rfc1912.zones"; + include "/etc/named.root.key"; +``` + +b、区域数据库文件详解 + +``` +正向解析 +[root@zutuanxue ~]# cat /var/named/named.localhost +;缓存时间 +$TTL 1D +;@表示相应的域名 + @ IN SOA @ rname.invalid. ( +;解析的域名 类型 授权域 授权域名服务器 管理员邮箱 + 0 ; serial + 序列号,每次更新该文件系列号都应该变大 + 1D ; refresh +刷新时间,即规定从域名服务器多长时间查询一个主服务器,以保证从服务器的数据是最新的 + 1H ; retry +重试时间,即当从服务试图在主服务器上查询更时,而连接失败了,则这个值规定了从服务多长时间后再试 + 1W ; expire + 过期时间,从服务器在向主服务更新失败后多长时间后清除对应的记录 + 3H ) ; minimum + 这个数据用来规定缓存服务器不能与主服务联系上后多长时间清除相应的记录 + NS @ + ;NS 名称服务器,表示这个主机为域名服务器 + A 127.0.0.1 +;主机头 A记录 IP + AAAA ::1 +; AAAA 解析为IPV6地址 + +#反向解析 +[root@zutuanxue ~]# cat named.loopback +$TTL 1D +@ IN SOA @ rname.invalid. ( + 0 ; serial + 1D ; refresh + 1H ; retry + 1W ; expire + 3H ) ; minimum + NS @ + PTR localhost +;IP 反向指针 主机名 +;PTR 反向指针 反解 +``` + +## 五、部署一个正向解析 + +### 5.1)教学案例 + +**对zutuanxue.com域名做解析,解析要求如下:** + +**www 解析为A记录 IP地址为 192.168.11.88** + +**news 做别名解析CNAME 解析为 www** + +``` +1)主配置文件 +[root@zutuanxue ~]# cat /var/named/chroot/etc/named.conf +options { + listen-on port 53 { any; }; + directory "/var/named"; +}; + +//定义根域 +//用于DNS向根递归查询 +zone "." IN { + type hint; + //保存了DNS根级服务器的地址 + file "named.ca"; +}; + +//定义一个主域 +//注意每行都要;结尾 +zone "zutuanxue.com" IN { +//类型为master + type master; +//区域数据库文件名称 + file "zutuanxue.com.zone"; +}; + + +2)区域数据库文件 +[root@zutuanxue named]# cat zutuanxue.com.zone +$TTL 1D +zutuanxue.com. IN SOA ns1.zutuanxue.com. rname.invalid. ( + 0 ; serial + 1D ; refresh + 1H ; retry + 1W ; expire + 3H ) ; minimum +;zutuanxue.com. 需要做解析的域名 +;ns1.zutuanxue.com. 为zutuanxue.com.做解析的DNS 这里我们既是DNS也同时为自己域名做了解析 + + NS ns1.zutuanxue.com. + + +;A 域名机械为IP +;PTR IP解析为域名 +;MX 邮件标记 +;CNAME 别名 + + +ns1 A 192.168.11.16 +www A 192.168.11.88 +news CNAME www +``` + +### 5.2)测试方法 + +域名解析linux系统为大家提供了三个命令,看大家喜欢用哪个都可以。 + +a、host采用非交互式解析, + +b、nslookup可以采用交互或非交互式解析 + +c、dig显示详细的解析流程 + +``` +测试注意:请将你的测试客户端机器的DNS指向你自己的DNS服务器的IP地址。本例中我使用DNS服务器给自己当测试端,我修改了自己的DNS服务器地址 +[root@zutuanxue ~]# cat /etc/resolv.conf +# Generated by NetworkManager +nameserver 192.168.11.16 + +#host命令 +[root@zutuanxue ~]# host news.zutuanxue.com +news.zutuanxue.com is an alias for www.zutuanxue.com. +www.zutuanxue.com has address 192.168.11.88 + + +#nslookup 命令---交互式解析 +[root@zutuanxue ~]# nslookup +> news.zutuanxue.com +Server: 192.168.11.16 +Address: 192.168.11.16#53 + +news.zutuanxue.com canonical name = www.zutuanxue.com. +Name: www.zutuanxue.com +Address: 192.168.11.88 +> exit + +#nslookup 命令---非交互式解析 +[root@zutuanxue ~]# nslookup news.zutuanxue.com +Server: 192.168.11.16 +Address: 192.168.11.16#53 + +news.zutuanxue.com canonical name = www.zutuanxue.com. +Name: www.zutuanxue.com +Address: 192.168.11.88 + + +#dig命令 +[root@zutuanxue ~]# dig news.zutuanxue.com + +; <<>> DiG 9.9.4-RedHat-9.9.4-73.el7_6 <<>> news.zutuanxue.com +;; global options: +cmd +;; Got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28487 +;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 1, ADDITIONAL: 1 + +;; OPT PSEUDOSECTION: +; EDNS: version: 0, flags:; udp: 4096 +;; QUESTION SECTION: +;news.zutuanxue.com. IN A + +;; ANSWER SECTION: +news.zutuanxue.com. 86400 IN CNAME www.zutuanxue.com. +www.zutuanxue.com. 86400 IN A 192.168.11.88 + +;; AUTHORITY SECTION: +zutuanxue.com. 86400 IN NS www.zutuanxue.com. + +;; Query time: 0 msec +;; SERVER: 192.168.11.16#53(192.168.11.16) +;; WHEN: 一 2月 25 10:52:19 CST 2019 +;; MSG SIZE rcvd: 93 + + +技巧: +在dig解析中,后面跟上+trace来显示详细解析流程 +[root@zutuanxue ~]# dig www.zutuanxue.com +trace +``` + +## 六、部署一个反向解析 + +**案例:对www.zutuanxue.com做反向解析,其对应的IP地址为192.168.11.88** + +``` +1)主配置文件添加反向解析zone +[root@zutuanxue ~]# cat /var/named/chroot/etc/named.conf +options { + listen-on port 53 { any; }; + directory "/var/named"; +}; + +//定义根域 +//用于DNS向根递归查询 +zone "." IN { + type hint; + //保存了DNS根级服务器的地址 + file "named.ca"; +}; + +//定义一个主域 +//注意每行都要;结尾 +zone "zutuanxue.com" IN { +//类型为master + type master; +//区域数据库文件名称 + file "zutuanxue.com.zone"; +}; + +//定义一个反向解析 +//此处需要倒写网段 +zone "11.168.192.in-addr.arpa" IN { + type master; + file "192.168.11.arpa"; +}; + + + +2)区域数据库文件设置 +[root@zutuanxue named]# cat 192.168.11.arpa +$TTL 1D +11.168.192.in-addr.arpa. IN SOA ns1.zutuanxue.com. rname.invalid. ( + 0 ; serial + 1D ; refresh + 1H ; retry + 1W ; expire + 3H ) ; minimum + NS ns1.zutuanxue.com. +88 PTR www.zutuanxue.com. + +注意:文件的所有者和所有者组都是named +3)使用nslookup测试 +[root@zutuanxue ~]# nslookup 192.168.11.88 +Server: 192.168.11.16 +Address: 192.168.11.16#53 + +88.11.168.192.in-addr.arpa name = www.zutuanxue.com. +``` + +## 七、DNS服务器冗余 + +![image20200114172337009.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602998138816.png) + +DNS服务器在网络中为全世界的服务器提供了域名解析服务,扮演着至关重要的角色。网络中的某台DNS一旦宕机,就会造成部分域名无法解析,用户无法顺利访问到对应的服务器。但是我们学习的过程中也发现了,我们的DNS部署在单台服务器上,如果出现单点故障,我们应该如何应对呢?我们可以通过部署多台相同解析的DNS来解决单点故障,就算一台DNS服务器出现问题,也不会影响解析服务。怎么部署呢?如何保障多台之间的解析一致?这就是我们要讨论的问题了。我们来学习辅助DNS吧! + +辅助DNS是从主DNS拉取区域数据库文件的的,当主DNS解析的域名对应的区域数据库文件发生变化,辅助就会去找主DNS拉取新的区域数据库文件,保证和主的解析一致,而且是自动的不需要人为干预的,确保了主从DNS的区域数据库文件的一致性。 + +**教学案例:按照图例,为主DNS(192.168.11.16)部署一台辅助DNS(192.168.11.116),实现数据同步。** + +``` +辅助DNS设置 +a、软件包安装 +[root@slave ~]# dnf -y install bind bind-chroot + +b、设置主配文件 +[root@slave etc]# cat /var/named/chroot/etc/named.conf +options { + listen-on port 53 { any; }; + directory "/var/named"; +}; + +//定义根域 +//用于DNS向根递归查询 +zone "." IN { + type hint; + //保存了DNS根级服务器的地址 + file "named.ca"; +}; + +//定义一个主域 +//注意每行都要;结尾 +zone "zutuanxue.com" IN { +//类型为slave 代表辅助 + type slave; +//区域数据库文件名称 + file "zutuanxue.com.zone"; +//设置主DNS IP,向该IP去同步数据 + masters { 192.168.11.16; }; +}; + +//定义一个反向解析 +//此处需要倒写网段 +zone "11.168.192.in-addr.arpa" IN { +//类型写slave 代表辅助 + type slave; + file "192.168.11.arpa"; +//设置主DNS IP,向该IP去同步数据 + masters { 192.168.11.16; }; +}; + + +修改权限 +[root@slave etc]# chgrp named named.conf + + +c、启动服务 +[root@slave chroot]# systemctl enable named-chroot.service +Created symlink from /etc/systemd/system/multi-user.target.wants/named-chroot.service to + /usr/lib/systemd/system/named-chroot.service. +[root@slave chroot]# systemctl start named-chroot + + +d、验证 +[root@slave ~]# ls /var/named/chroot/var/named/ +192.168.11.arpa zutuanxue.com.zone chroot data dynamic named.ca named.empty named.localhost named.loopback slaves + + +发现192.168.11.arpa zutuanxue.com.zone 这两个数据库文件已经同步过来了,解析一下看看吧! + + +设置客户端的DNS IP为192.168.11.116,我的测试机就是这台slave机器,所以设置为192.168.11.116即可 +[root@slave ~]# cat /etc/resolv.conf +nameserver 192.168.11.116 + +使用nslookup验证一下 +[root@slave ~]# nslookup news.zutuanxue.com +Server: 192.168.11.116 +Address: 192.168.11.116#53 + +news.zutuanxue.com canonical name = www.zutuanxue.com. +Name: www.zutuanxue.com +Address: 192.168.11.88 + +[root@slave ~]# nslookup 192.168.11.88 +Server: 192.168.11.116 +Address: 192.168.11.116#53 + +88.11.168.192.in-addr.arpa name = www.11.168.192.in-addr.arpa. + +看到结果了,完美!! +``` + +## 八、智能DNS + +在我们访问WEB的时候,发现有的网站打开的速度非常快,有的网站打开的非常慢,这是为什么呢?原因就是很多公司为了提升用户的体验,自己的网站使用了CDN内容加速服务,让你直接在你本地城市的服务器上拿数据并展示给你看。什么是CDN我们暂且理解为本地缓存服务器就好,那么你是怎么准确知道你本地的缓存服务器的呢!因为很多CDN公司的DNS使用了智能解析服务,根据你的源IP判断你属于哪个城市,让后再把本地的缓存服务器解析给你,你就会直接去找该服务器拿数据了。 + +智能解析原理 + +在DNS中植入全世界的IP库以及IP对应的地域,当用户来请求解析时,DNS会根据其源IP来定位他属于哪个区域,然后去找这个区域的view视图查询对应的域名的区域数据库文件做解析。从而使得不同地域的用户解析不同。 + +**教学案例:部署一台DNS智能解析服务器,对zutuanxue.com域名做智能解析:** + +**上海的用户解析IP为 1.1.1.1** + +**北京的用户解析IP为 2.2.2.2** + +**其他用户解析为 3.3.3.3** + +``` +智能解析 +a、设置主配文件 +定义IP库,DNS根据IP库判断源IP属于哪个区域 +根据地域定义视图,将该区域的客户端的解析请求都由该视图中的zone来解析 + +[root@master named]# cat /var/named/chroot/etc/named.conf +options { + directory "/var/named"; +}; + +//定义IP库 + +acl shanghai { 192.168.11.50; }; +acl beijing { 192.168.11.100; }; + +//定义视图,通过IP匹配后,通过不同的区域数据库文件进行解析 +view sh { + match-clients { shanghai; }; + zone "zutuanxue.com" IN { + type master; + file "zutuanxue.com.zone.sh"; +}; +}; + +view bj { + match-clients { beijing; }; + zone "zutuanxue.com" IN { + type master; + file "zutuanxue.com.zone.bj"; +}; +}; + + +view other { + match-clients { any; }; + zone "zutuanxue.com" IN { + type master; + file "zutuanxue.com.zone.any"; +}; +}; + + + +b、根据主配文件设置不同的区域数据库文件 +[root@master named]# cd /var/named/chroot/var/named +[root@master named]# cp zutuanxue.com.zone zutuanxue.com.zone.bj +[root@master named]# cp zutuanxue.com.zone zutuanxue.com.zone.sh +[root@master named]# cp zutuanxue.com.zone zutuanxue.com.zone.any +[root@master named]# chgrp named zutuanxue.com.zone.* + + + +[root@master named]# cat /var/named/chroot/var/named/zutuanxue.com.zone.sh +$TTL 1D +@ IN SOA zutuanxue.com. rname.invalid. ( + 0 ; serial + 1D ; refresh + 1H ; retry + 1W ; expire + 3H ) ; minimum + NS www.zutuanxue.com. +www A 1.1.1.1 + +[root@master named]# cat /var/named/chroot/var/named/zutuanxue.com.zone.bj +$TTL 1D +@ IN SOA zutuanxue.com. rname.invalid. ( + 0 ; serial + 1D ; refresh + 1H ; retry + 1W ; expire + 3H ) ; minimum + NS www.zutuanxue.com. +www A 2.2.2.2 + +[root@master named]# cat /var/named/chroot/var/named/zutuanxue.com.zone.any +$TTL 1D +@ IN SOA zutuanxue.com. rname.invalid. ( + 0 ; serial + 1D ; refresh + 1H ; retry + 1W ; expire + 3H ) ; minimum + NS www.zutuanxue.com. +www A 3.3.3.3 + + + +c、测试 +依次修改主配的IP库中的IP为本机,观看解析情况 + +[root@master named]# nslookup www.zutuanxue.com +Server: 192.168.11.16 +Address: 192.168.11.16#53 + +Name: www.zutuanxue.com +Address: 1.1.1.1 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/FTP\346\226\207\344\273\266\346\234\215\345\212\241\345\231\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/FTP\346\226\207\344\273\266\346\234\215\345\212\241\345\231\250.md" new file mode 100644 index 0000000..ae958c0 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/FTP\346\226\207\344\273\266\346\234\215\345\212\241\345\231\250.md" @@ -0,0 +1,538 @@ +## 一、FTP介绍 + +FTP (File transfer protocol) 是TCP/IP 协议组中的协议之一。他最主要的功能是在服务器与客户端之间进行文件的传输。FTP就是实现两台计算机之间的拷贝,从远程计算机拷贝文件至自己的计算机上,称之为“下载 (download)”文件。将文件从自己计算机中拷贝至远程计算机上,则称之为“上传(upload)”文件。这个古老的协议使用的是明码传输方式,且过去有相当多的安全危机历史。为了更安全的使用 FTP 协议,我们主要介绍较为安全但功能较少的 vsftpd(very secure File transfer protocol ) 这个软件。FTP是一个C/S类型的软件,FTP监听TCP端口号为21,数据端口为20。 + +## 二、应用场景 + +下载服务器:提供对外的下载服务 + +文件服务器:提供上传和下载服务 + +## 三、FTP的权限 + +FTP 服务器的功能除了单纯的进行文件的传输与管理之外,依据服务器软件的设定架构,它还可以提供几个主要的功能。: +不同等级的用户身份:user, guest, anonymous +FTP 服务器在默认的情况下,依据使用者登录的情况而分为三种不同的身份,分别是: + +(1)本地用户:系统中真实存在的用户 + +(2)来宾, guest; + +(3)匿名登录者, anonymous + +这三种身份的用户在系统上面的权限差异很大!例如实体用户取得系统的权限比较完整, 所以可以进行比较多的动作;至于匿名登录者,大概我们就仅提供他下载资源的能力而已,并不许匿名者使用太多主机的资源! 当然,这三种人物因为权限的不同能够使用的【在线命令】自然也就不相同! + +## 四、FTP的工作模式 + +FTP支持两种模式,一种方式叫做Standard (也就是 PORT方式,主动方式),一种是 Passive (也就是PASV,被动方式)。 Standard模式 FTP的客户端发送 PORT 命令到FTP服务器。Passive模式FTP的客户端发送 PASV命令到 FTP Server。 + +下面介绍一个这两种方式的工作原理: + +Port模式FTP 客户端首先和FTP服务器的TCP 21端口建立连接,通过这个通道发送命令,客户端需要接收数据的时候在这个通道上发送PORT命令。 PORT命令包含了客户端用什么端口接收数据。在传送数据的时候,服务器端通过自己的TCP 20端口连接至客户端的指定端口发送数据。 FTP server必须和客户端建立一个新的连接用来传送数据。 + +Passive模式在建立控制通道的时候和Standard模式类似,但建立连接后发送的不是Port命令,而是Pasv命令。FTP服务器收到Pasv命令后,随机打开一个高端端口(端口号大于1024)并且通知客户端在这个端口上传送数据的请求,客户端连接FTP服务器此端口,然后FTP服务器将通过这个端口进行数据的传送,这个时候FTP server不再需要建立一个新的和客户端之间的连接。 + +很多防火墙在设置的时候都是不允许接受外部发起的连接的,所以许多位于防火墙后或内网的FTP服务器不支持PASV模式,因为客户端无法穿过防火墙打开FTP服务器的高端端口;而许多内网的客户端不能用PORT模式登陆FTP服务器,因为从服务器的TCP 20无法和内部网络的客户端建立一个新的连接,造成无法工作。 + +## 五、FTP安装部署 + +**约定:本实验中使用过的机器为centos8.0_x86_64系统,IP地址192.168.11.16/24.请关闭防火墙和SELINUX。** + +``` +vsftp安装 +[root@localhost ~]# dnf -y install vsftpd ftp + +vsftp开机启动 +[root@localhost ~]# systemctl enable vsftpd +Created symlink from /etc/systemd/system/multi-user.target.wants/vsftpd.service to +/usr/lib/systemd/system/vsftpd.service. + +启动vsftp服务 +[root@localhost ~]# systemctl start vsftpd + +验证启动 +[root@localhost ~]# lsof -i :21 +COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME +vsftpd 1951 root 4u IPv6 32837 0t0 TCP *:ftp (LISTEN) +``` + +## 六、FTP配置文件 + +### 6.1)相关文件 + +主配文件:/etc/vsftpd/vsftpd.conf + +下载目录:/var/ftp/ + +FTP日志:/var/log/xferlog + +### 6.2)主配文件详解 + +``` +# Example config file /etc/vsftpd/vsftpd.conf +# +# The default compiled in settings are fairly paranoid. This sample file +# loosens things up a bit, to make the ftp daemon more usable. +# Please see vsftpd.conf.5 for all compiled in defaults. +# +# READ THIS: This example file is NOT an exhaustive list of vsftpd options. +# Please read the vsftpd.conf.5 manual page to get a full idea of vsftpd's +# capabilities. +# +#匿名用户访问,YES是允许,NO是拒绝 +# Allow anonymous FTP? (Beware - allowed by default if you comment this out). +anonymous_enable=NO +# +# Uncomment this to allow local users to log in. +# 本地用户登录,YES是允许,NO是拒绝.默认访问的是本地用户家目录,如果你开启了selinux +# 请设置开启布尔值ftp_home_dir为ON +# When SELinux is enforcing check for SE bool ftp_home_dir +local_enable=YES +# +#允许本地用户上传 +# Uncomment this to enable any form of FTP write command. +write_enable=YES +# +# Default umask for local users is 077. You may wish to change this to 022, +# 上传的权限是022,使用的是umask权限。对应的目录是755,文件是644 +# if your users expect that (022 is used by most other ftpd's) +local_umask=022 + +# +# Uncomment this to allow the anonymous FTP user to upload files. This only +# has an effect if the above global write enable is activated. Also, you will +# obviously need to create a directory writable by the FTP user. +# When SELinux is enforcing check for SE bool allow_ftpd_anon_write, allow_ftpd_full_access +# 开启匿名用户上传功能,默认是拒绝的 +#anon_upload_enable=YES +# +# Uncomment this if you want the anonymous FTP user to be able to create +# new directories. +# 开启匿名用户创建文件或文件夹权限 +#anon_mkdir_write_enable=YES +# +# Activate directory messages - messages given to remote users when they +# go into a certain directory. +# 开启目录欢迎消息,一般对命令行登陆有效 +dirmessage_enable=YES +# +# Activate logging of uploads/downloads. +# 开启上传和下载日志记录功能 +xferlog_enable=YES +# +#使用标准模式 +# Make sure PORT transfer connections originate from port 20 (ftp-data). +connect_from_port_20=YES +# +# If you want, you can arrange for uploaded anonymous files to be owned by +# a different user. Note! Using "root" for uploaded files is not +# recommended! +# 声明匿名用户上传文件的所有者 +# 允许更改匿名用户上传文件的所有者 +#chown_uploads=YES +#所有者为whoever +#chown_username=whoever +# +# You may override where the log file goes if you like. The default is shown +# below. +# 日志文件路径 +#xferlog_file=/var/log/xferlog +# +# If you want, you can have your log file in standard ftpd xferlog format. +# Note that the default log file location is /var/log/xferlog in this case. +# 日志文件采用标准格斯 +xferlog_std_format=YES +# +# You may change the default value for timing out an idle session. +# 会话超时时间 +#idle_session_timeout=600 +# +# You may change the default value for timing out a data connection. +# 数据传输超时时间 +#data_connection_timeout=120 +# +# It is recommended that you define on your system a unique user which the +# ftp server can use as a totally isolated and unprivileged user. +# FTP子进程管理用户 +#nopriv_user=ftpsecure +# +# Enable this and the server will recognise asynchronous ABOR requests. Not +# recommended for security (the code is non-trivial). Not enabling it, +# however, may confuse older FTP clients. +# 是否允许客户端发起“async ABOR”请求,该操作是不安全的默认禁止。 +#async_abor_enable=YES +# +# By default the server will pretend to allow ASCII mode but in fact ignore +# the request. Turn on the below options to have the server actually do ASCII +# mangling on files when in ASCII mode. The vsftpd.conf(5) man page explains +# the behaviour when these options are disabled. +# Beware that on some FTP servers, ASCII support allows a denial of service +# attack (DoS) via the command "SIZE /big/file" in ASCII mode. vsftpd +# predicted this attack and has always been safe, reporting the size of the +# raw file. +# ASCII mangling is a horrible feature of the protocol. +# 该选项用于指定是否允许上传时以ASCII模式传输数据 +#ascii_upload_enable=YES +#该选项用于指定是否允许下载时以ASCII模式传输数据 +#ascii_download_enable=YES +# +# You may fully customise the login banner string: +# FTP文本界面登陆欢迎词 +#ftpd_banner=Welcome to blah FTP service. +# +# You may specify a file of disallowed anonymous e-mail addresses. Apparently +# useful for combatting certain DoS attacks. +# 是否开启拒绝的Email功能 +#deny_email_enable=YES +# (default follows) +# 指定保存被拒接的Email地址的文件 +#banned_email_file=/etc/vsftpd/banned_emails +# +# You may specify an explicit list of local users to chroot() to their home +# directory. If chroot_local_user is YES, then this list becomes a list of +# users to NOT chroot(). +# (Warning! chroot'ing can be very dangerous. If using chroot, make sure that +# the user does not have write access to the top level directory within the +# chroot) +# 是否开启对本地用户chroot的限制,YES为默认所有用户都不能切出家目录,NO代表默认用户都可以切出家目录 +# 设置方法类似于:YES拒绝所有,允许个别 NO 允许所有拒绝个别 +#chroot_local_user=YES +#开启特例列表 +#chroot_list_enable=YES +# (default follows) +# 如果chroot_local_user的值是YES则该文件中的用户是可以切出家目录,如果是NO,该文件中的用户则不能切出家目录 +# 一行一个用户。 +#chroot_list_file=/etc/vsftpd/chroot_list +# +# You may activate the "-R" option to the builtin ls. This is disabled by +# default to avoid remote users being able to cause excessive I/O on large +# sites. However, some broken FTP clients such as "ncftp" and "mirror" assume +# the presence of the "-R" option, so there is a strong case for enabling it. +# 是否开启ls 递归查询功能 ls -R +#ls_recurse_enable=YES +# +# When "listen" directive is enabled, vsftpd runs in standalone mode and +# listens on IPv4 sockets. This directive cannot be used in conjunction +# with the listen_ipv6 directive. +# 是否开启ftp独立模式在IPV4 +listen=NO +# +# This directive enables listening on IPv6 sockets. By default, listening +# on the IPv6 "any" address (::) will accept connections from both IPv6 +# and IPv4 clients. It is not necessary to listen on *both* IPv4 and IPv6 +# sockets. If you want that (perhaps because you want to listen on specific +# addresses) then you must run two copies of vsftpd with two configuration +# files. +# Make sure, that one of the listen options is commented !! +# 是否开启ftp独立模式在ipv6 +listen_ipv6=YES + + +#启用pam模块验证 +pam_service_name=vsftpd +#是否开启userlist功能. + +#是否启用用户列表功能 +userlist_enable=YES +``` + +通过配置文件的分析,VSFTP不允许匿名访问,本地用户可以下载和上传。如果允许匿名用户登录的话需要将anonymous_enable=YES,然后重新启动服务 + +我们可以通过修改配置文件的内容即可配置FTP的相关登陆情况。 + +## 七、FTP客户端访问 + +FTP是一个C/S类型的软件,连接服务端需要FTP客户端才能完成,常见的FTP客户端有以下几种: + +浏览器:可以通过浏览器中输入 ftp://ip或者ftp://域名的方式来访问FTP + +自带客户端:命令行下可以使用ftp命令去连接 + +三方客户端:FileZilla 8uftp 图形软件或者文本界面的lftp等 + +三种方式中,文本界面是比较麻烦的,无法鼠标流。所以我重点给大家讲解一下 + +### 7.1)文本界面登陆 + +``` +文本界面匿名登陆 +[root@localhost ~]# ftp 192.168.11.16 +Connected to 192.168.11.16 (192.168.11.16). +220 (vsFTPd 3.0.3) +Name (192.168.11.16:root): ftp #用户名可以是ftp也可以是anonymous +331 Please specify the password. +Password: #密码为空 +230 Login successful. #显示登陆成功 +Remote system type is UNIX. +Using binary mode to transfer files. +ftp> ls +227 Entering Passive Mode (192,168,11,16,90,35). +150 Here comes the directory listing. +drwxr-xr-x 2 0 0 6 May 14 2019 pub +226 Directory send OK. +通过ls可以列出当前目录下有哪些内容 看到有一个目录叫pub +ftp> pwd +257 "/" +通过pwd命令查看当前路径 注意这里显示的是FTP的根目录 + +ftp> bye +221 Goodbye. +退出使用bye命令 + +文本界面本地用户登录 +[root@localhost ~]# ftp 192.168.11.16 +Connected to 192.168.11.16 (192.168.11.16). +220 (vsFTPd 3.0.3) +Name (192.168.11.16:root): hello +331 Please specify the password. +Password: +230 Login successful. +Remote system type is UNIX. +Using binary mode to transfer files. +ftp> ls +227 Entering Passive Mode (192,168,11,16,130,240). +150 Here comes the directory listing. +drwxr-xr-x 2 1001 1001 6 Jan 15 08:56 下载 +drwxr-xr-x 2 1001 1001 6 Jan 15 08:56 公共 +drwxr-xr-x 2 1001 1001 6 Jan 15 08:56 图片 +drwxr-xr-x 2 1001 1001 6 Jan 15 08:56 文档 +drwxr-xr-x 2 1001 1001 6 Jan 15 08:56 桌面 +drwxr-xr-x 2 1001 1001 6 Jan 15 08:56 模板 +drwxr-xr-x 2 1001 1001 6 Jan 15 08:56 视频 +drwxr-xr-x 2 1001 1001 6 Jan 15 08:56 音乐 +226 Directory send OK. +ftp> pwd +257 "/home/hello" is the current directory +``` + +### 7.2)FTP客户端常用命令 + +``` +键入help命令可以查看所有可使用的命令 +ftp> help +Commands may be abbreviated. Commands are: + +! debug mdir sendport site +$ dir mget put size +account disconnect mkdir pwd status +append exit mls quit struct +ascii form mode quote system +bell get modtime recv sunique +binary glob mput reget tenex +bye hash newer rstatus tick +case help nmap rhelp trace +cd idle nlist rename type +cdup image ntrans reset user +chmod lcd open restart umask +close ls prompt rmdir verbose +cr macdef passive runique ? +delete mdelete proxy send + + +!+linux命令 执行系统命令 +!ls /opt 显示linux系统中/opt目录下的内容 +ftp> !ls /opt +dhcp dns rh + + +lcd linux系统中的当前目录 +lcd /root 将linux系统中的当前目录切换到/root下 +ftp> lcd /root +Local directory now /root + + +put 上传命令,mput批量上传命令 +上传initial-setup-ks.cfg文件到hello家目录下 +ftp> put initial-setup-ks.cfg +local: initial-setup-ks.cfg remote: initial-setup-ks.cfg +227 Entering Passive Mode (192,168,11,16,96,132). +150 Ok to send data. +226 Transfer complete. +1803 bytes sent in 0.00135 secs (1333.58 Kbytes/sec) +可以看到上传成功了 + +验证一下上传结果 +ftp> ls +227 Entering Passive Mode (192,168,11,16,173,142). +150 Here comes the directory listing. +-rw-r--r-- 1 1000 1000 1803 Feb 26 07:01 initial-setup-ks.cfg +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 下载 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 公共 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 图片 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 文档 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 桌面 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 模板 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 视频 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 音乐 +226 Directory send OK. +看见了吧 + +切换linux当前目录到/tmp +ftp> lcd /tmp +Local directory now /tmp + + + +get下载命令,mget批量下载 +下载initial-setup-ks.cfg到linux系统当前目录/tmp +ftp> get initial-setup-ks.cfg +local: initial-setup-ks.cfg remote: initial-setup-ks.cfg +227 Entering Passive Mode (192,168,11,16,229,134). +150 Opening BINARY mode data connection for initial-setup-ks.cfg (1803 bytes). +226 Transfer complete. +1803 bytes received in 2.9e-05 secs (62172.41 Kbytes/sec) + +列出linux目录/tmp的内容,看到了下载的文件initial-setup-ks.cfg +ftp> !ls /tmp/ +dhcp tracker-extract-files.0 +initial-setup-ks.cfg VMwareDnD +systemd-private-8e7a99ea89c14ab396d66116970fe04d-chronyd.service-sghHHs vmware-root +systemd-private-8e7a99ea89c14ab396d66116970fe04d-colord.service-wK7h08 yum_save_tx.2019-02-20.16-10.Z6uXqR.yumtx +systemd-private-8e7a99ea89c14ab396d66116970fe04d-cups.service-cokBro yum_save_tx.2019-02-21.09-03.08zIbU.yumtx +systemd-private-8e7a99ea89c14ab396d66116970fe04d-rtkit-daemon.service-6wt1S0 yum_save_tx.2019-02-22.11-10.prawAT.yumtx + +ftp> close +221 Goodbye. +ftp> ls +Not connected. +可以使用close断开连接,当连接断开希望再次连接直接使用open命令即可 +ftp> open 192.168.11.16 +Connected to 192.168.11.16 (192.168.11.16). +220 (vsFTPd 3.0.2) +Name (192.168.11.16:root): hello +331 Please specify the password. +Password: +230 Login successful. +Remote system type is UNIX. +Using binary mode to transfer files. +ftp> ls +227 Entering Passive Mode (192,168,11,16,192,88). +150 Here comes the directory listing. +-rw-r--r-- 1 1000 1000 1803 Feb 26 07:01 initial-setup-ks.cfg +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 下载 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 公共 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 图片 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 文档 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 桌面 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 模板 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 视频 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 音乐 +226 Directory send OK. + + + +delete命令可以删除属于自己的文件 +删除initial-setup-ks.cfg文件 +ftp> delete initial-setup-ks.cfg +250 Delete operation successful. +ftp> ls +227 Entering Passive Mode (192,168,11,16,168,142). +150 Here comes the directory listing. +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 下载 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 公共 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 图片 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 文档 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 桌面 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 模板 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 视频 +drwxr-xr-x 2 1000 1000 6 Jan 11 01:37 音乐 +226 Directory send OK. +``` + +## 八、基于虚拟用户配置安全的ftp + +在ftp中不论是匿名用户还是实名用户都是系统中真实存在的用户,或多或少都会有一些安全方面的风险,为了避免这个风险,开发者在ftp中加入了一个虚拟用户的概念,所有虚拟用户都会被统一映射为一个系统账号,免去了管理过多账户的麻烦,那么这个虚拟用户如何实现呢? + +``` +a、修改配置文件 +[root@zutuanxue pam.d]# egrep -v "^#" /etc/vsftpd/vsftpd.conf +anonymous_enable=YES +local_enable=YES +write_enable=YES +local_umask=022 +dirmessage_enable=YES +xferlog_enable=YES +connect_from_port_20=YES +xferlog_std_format=YES +chroot_local_user=YES +listen=NO +listen_ipv6=YES + + +#虚拟用户配置选项 +#pam登陆验证 +pam_service_name=vftp +#允许虚拟用户功能 +guest_enable=YES +#虚拟用户映射到本地用户hello +guest_username=hello +#这里我通过指令改变了默认设置,允许虚拟用户写 +allow_writeable_chroot=YES + +#本地用户的根目录 +#这里是定义虚拟用户主目录,用户和组必须指定为宿主用户hello +local_root=/home/hello + + +#允许虚拟用户和本地用户权限一致 +virtual_use_local_privs=YES + +#如果虚拟用户和本地用户权限不同,可以通过以下的指令来设置指令,配置文件和登陆名同步即可。 +#user_config_dir=/etc/vsftpd/vconf.d/ + + + + +b、生成虚拟用户账号密码文件 +奇数行数账户,偶数行是密码 +[root@zutuanxue ~]# cat /etc/vsftpd/vuser +vuser01 +123456 +vuser02 +123456 + +使用db_load转成db格式 +[root@zutuanxue ~]# db_load -T -t hash -f /etc/vsftpd/vuser /etc/vsftpd/vuser.db +要求权限是600 +[root@zutuanxue ~]# chmod 600 /etc/vsftpd/vuser.db + +c、配置pam认证,注意先后顺序 +[root@zutuanxue ~]# cat /etc/pam.d/vftp +#虚拟用户登录 +auth sufficient /lib64/security/pam_userdb.so db=/etc/vsftpd/vuser +account sufficient /lib64/security/pam_userdb.so db=/etc/vsftpd/vuser +#本地登陆 +session optional pam_keyinit.so force revoke +auth required pam_listfile.so item=user sense=deny file=/etc/vsftpd/ftpusers onerr=succeed +auth required pam_shells.so +auth include password-auth +account include password-auth +session required pam_loginuid.so +session include password-auth + + + +d、重启服务生效 +[root@zutuanxue ~]# systemctl restart vsftpd +[root@zutuanxue ~]# cat /etc/vsftpd/chroot_list +vuser01 +vuser02 + +e、验证登陆 +[root@zutuanxue ~]# ftp 192.168.11.16 +Connected to 192.168.11.16 (192.168.11.16). +220 Welcome to ayitula FTP service. +Name (192.168.11.16:root): vuser01 +331 Please specify the password. +Password: +230 Login successful. +Remote system type is UNIX. +Using binary mode to transfer files. +ftp> ls +227 Entering Passive Mode (192,168,11,16,82,91). +150 Here comes the directory listing. +226 Transfer done (but failed to open directory). + + +登陆成功了. +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/Linux \345\217\214\346\234\272\347\203\255\345\244\207.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/Linux \345\217\214\346\234\272\347\203\255\345\244\207.md" new file mode 100644 index 0000000..ecd35b8 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/Linux \345\217\214\346\234\272\347\203\255\345\244\207.md" @@ -0,0 +1,211 @@ +## 一 Rsync概述 + +### 1.1、什么是Rsync + +rsync是一款开源,快速,多功能的可实现增量的本地或远程的数据镜像同步备份的优秀工具。适用于多个平台。从软件名称可以看出来是远程同步的意思(remote sync)可实现全量备份与增量备份,因此非常适合用于架构集中式备份或异地备份等应用。 + +**官网:** http://rsync.samba.org/ + +**端口:** 873 + +**运行模式:** C/S B/S + +### 1.2、rsync特性 + +1、支持拷贝特殊文件如链接文件、设备等 + +2、可以有排除指定文件或目录同步的功能,相当于tar的排除功能 + +3、可以做到保持原文件或目录的权限、时间、软硬链接、属主、组等所有属性均不改变 + +4、可以实现增量同步,即只同步发生变化的数据,因此数据传输效率很高 + +5、可以使用rcp,rsh,ssh等方式来配合传输文件(rsync本身不对数据加密) + +6、可以通过socket(进程方式)传输文件和数据(服务端和客户端)。 + +7、支持匿名的或认证(无须系统用户)的进程模式传输,可实现方便安全的进行数据备份及镜像 + +### 1.3、传输方式 + +**拉复制(下载):** rsync备份服务器定期去所有主机上拉取数据 + +![image20200116202338681.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603525992068.png) + +**推复制(上传):** 所有主服务器将本地数据推送至从服务器 + +![image20200116202157436.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603526014361.png) + +在日常使用中,这两种形式都是混合使用的如: + +**大量数据备份** + +![image20200116202528449.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603526031950.png) + +**异地备份** + +![image20200116202556118.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603526050140.png) + +## 二 rsync拉复制实战 + +**环境:** + +- 两台主机,IP地址为192.168.11.16,192.168.11.100 +- 操作系统为CentOS8 +- 关闭selinux和防火墙 + +**需求:** 希望192.168.11.100这台主机/cache目录的数据与192.168.11.16这台主机/cache目录中的数据保持一致 + +``` +step1 在192.168.11.16这台主机上制作rsync服务 +[root@zutuanxue ~]# rpm -qa | grep rsync +rsync-3.1.3-4.el8.x86_64 +#检查是或否安装的相关软件包 +[root@zutuanxue ~]# mkdir /etc/rsyncd +[root@zutuanxue ~]# vim rsyncd.conf +uid=root #定义以哪个用户的身份启动进程 +gid=root #定义以哪个组的身份启动进程 +port=873 #此服务默认端口873 +max connections=0 #最大连接数(正整数),0代表不限制。 +log file=/var/log/rsyncd.log #定义日志文件位置 +pid file=/var/run/rsyncd.pid #定义pid文件位置 +lock file=/var/run/rsyncd.lock #定义锁定文件位置,避免多开 +motd file=/etc/rsyncd/rsyncd.motd #定义欢迎信息 +read only=yes #权限为只读 +hosts allow=192.168.11.0/24 #允许的网段 +hosts deny=* #拒绝所有,允许个别 +[www] #定义共享名称为www +path=/cache #路径 +list=yes #允许别人看到 +ignore errors #忽略错误 +auth users=hello #授权的账号 +secrets file=/etc/rsyncd/rsyncd.secrets #密码文件 + +setp2 建立欢迎信息文件,内容随意 +[root@zutuanxue ~]# vim /etc/rsyncd/rsyncd.motd + + +step3 建立密码文件 +[root@zutuanxue ~]# vim /etc/rsyncd/rsyncd.secrets +hello:123456 +[root@zutuanxue ~]# chmod 600 rsyncd.secrets + +step4 建立cache目录和文件 +[root@zutuanxue ~]# mkdir /cache +[root@zutuanxue ~]# touch /cache/file{1..10} + +step5启动服务 +[root@zutuanxue ~]# rsync --daemon --config=/etc/rsyncd/rsyncd.conf +[root@zutuanxue ~]# lsof -i :873 + +step6 在192.168.11.100上建立密码文件并修改权限 +[root@slave ~]# vim /etc/rsync.pw +123456 +[root@slave ~]# chmod 600 /etc/rsync.pw +[root@slave ~]# mkdir /cache +step7 同步测试 +[root@slave ~]# rsync -avzP --delete --password-file=/etc/rsync.pw hello@192.168.11.16::www /cache + +rsync参数 +-a 归档模式传输,相当于-rlptgoD一起使用 +-v 详细模式输出 +-z 传输时进行压缩以提高效率 +-r 递归传输目录及子目录,即目录下得所有目录都同样传输 +-t 保持文件时间信息 +-o 保持文件属主信息 +-p 保持文件权限 +-g 保持文件属组信息 +-l 保留软连接 +-P 显示同步的过程及传输时的进度等信息 +-D 保持设备文件信息 +-L 保留软连接指向的目标文件 +--exclude=PATTERN 指定排除不需要传输的文件模式 +--bwlimit=1m 限速传输 +--delete 让目标目录和源目录数据保持一致 +--password-file 指定密码文件位置 + +step8 定义计划任务 +[root@slave ~]# crontab -e +* * * * * rsync -avzP --delete --password-file=/etc/rsync.pw hello@192.168.11.16::www /cache + +step9 将11.16主机上文件进行调整,观察是否改变 +``` + +## 三 Rsync推复制 + +**环境:** + +- 两台主机,IP地址为192.168.11.16,192.168.11.100 +- 操作系统为CentOS8 +- 关闭selinux和防火墙 + +**需求:** 希望192.168.11.100这台主机/cache目录的数据与192.168.11.16这台主机/cache目录中的数据保持一致 + +``` +注:停止192.168.11.16主机上的rsync服务 +step1 在192.168.11.100这台主机上制作rsync服务 +[root@slave ~]# rpm -qa | grep rsync +rsync-3.1.3-4.el8.x86_64 +#检查是或否安装的相关软件包 +[root@slave ~]# mkdir /etc/rsyncd +[root@slave ~]# vim rsyncd.conf +uid=root #定义以哪个用户的身份启动进程 +gid=root #定义以哪个组的身份启动进程 +port=873 #此服务默认端口873 +max connections=0 #最大连接数(正整数),0代表不限制。 +log file=/var/log/rsyncd.log #定义日志文件位置 +pid file=/var/run/rsyncd.pid #定义pid文件位置 +lock file=/var/run/rsyncd.lock #定义锁定文件位置,避免多开 +motd file=/etc/rsyncd/rsyncd.motd #定义欢迎信息 +read only=no #权限为不只读(可写) +hosts allow=192.168.11.0/24 #允许的网段 +hosts deny=* #拒绝所有,允许个别 +[www] #定义共享名称为www +path=/cache #路径 +list=yes #允许别人看到 +ignore errors #忽略错误 +auth users=hello #授权的账号 +secrets file=/etc/rsyncd/rsyncd.secrets #密码文件 + +setp2 建立欢迎信息文件,内容随意 +[root@slave ~]# vim /etc/rsyncd/rsyncd.motd + + +step3 建立密码文件 +[root@slave ~]# vim /etc/rsyncd/rsyncd.secrets +hello:123456 +[root@slave ~]# chmod 600 rsyncd.secrets + +step4 建立cache目录 +[root@slave ~]# mkdir /cache + + +step5启动服务 +[root@slave ~]# rsync --daemon --config=/etc/rsyncd/rsyncd.conf +[root@slave ~]# lsof -i :873 + +step6 在192.168.11.16上安装监控软件 +[root@zutuanxue ~]# tar fx sersync2.5_32bit_binary_stable_final.tar.gz -C /usr/src/ +[root@zutuanxue ~]# cd /usr/src/GNU-Linux-x86/ + +step7 配置监控软件 +[root@zutuanxue ~]# vim confxml.xml + + + + . + . + . + + + + +[root@zutuanxue ~]# vim /etc/rsync.pw +123456 +[root@zutuanxue ~]# chmod 600 rsync.pw + +step8 启动监控软件 +[root@zutuanxue ~]# ./sersync2 -r #第一次启动加-r 可以查看到工作流程 + +step9 重新打开一个终端,在192.168.11.16上建立、删除文件,去192.168.11.100上查看是否同步成功 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/Linux \346\227\266\351\227\264\346\234\215\345\212\241\345\231\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/Linux \346\227\266\351\227\264\346\234\215\345\212\241\345\231\250.md" new file mode 100644 index 0000000..c724c36 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/Linux \346\227\266\351\227\264\346\234\215\345\212\241\345\231\250.md" @@ -0,0 +1,178 @@ +## 概述 + +**什么是时间服务器** + +NTP:Network Time Protocol 网络时间协议,用来同步网络中各主机的时间,在linux系统中早期使用ntp来实现,后来使用chrony来实现,Chrony 应用本身已经有几年了,其是是网络时间协议的 (NTP) 的另一种实现。 + +**Chrony可以同时做为ntp服务的客户端和服务端** + +一直以来众多发行版里标配的都是ntpd对时服务,自rhel7/centos7 起,Chrony做为了发行版里的标配服务,不过老的ntpd服务依旧在rhel7/centos7里可以找到 。 + +**核心组件:** + +chronyd:是守护进程,主要用于调整内核中运行的系统时间和时间服务器同步。它确定计算机增减时间的比率,并对此进行调整补偿。 + +chronyc:提供一个用户界面,用于监控性能并进行多样化的配置。它可以在chronyd实例控制的计算机上工作,也可以在一台不同的远程计算机上工作。 + +**优势** + +chrony用来同步时间,来代替ntp服务,优点是很精巧的时间同步工具,更快响应时钟变化,在应对延时提供更好的稳定性能,不会出现时间空白,跨越互联网同步时间只需要几毫秒。 + +它的优势主要包括 + +``` +#更快的同步:能在最大程度的减少时间和频率误差,这对于非全天运行的台式计算机或系统而言非常有用 + +#更快的响应速度:能够更好的响应时间频率的快速变化,这对于具备不稳定时钟的虚拟机或导致时钟频率发生变化的节能技术而言更有帮助 + +#稳定:在初始同步后,它并不会停止时钟,以防对需要系统时间的程序造成影响,以及可以更好的应对延迟 +``` + +**相关文件说明** + +/etc/chrony.conf 主配置文件 + +/usr/bin/chronyc 客户端程序工具 + +/usr/sbin/chronyd 服务端程序 + +**配置文件说明** + +``` +[root@zutuanxue ~]# vim /etc/chrony.conf +# Use public servers from the pool.ntp.org project. +# Please consider joining the pool (http://www.pool.ntp.org/join.html). +pool 2.centos.pool.ntp.org iburst +###指定时间服务器的地址,可以使用pool开始也可以使用server开始,iburst可以加速初始同步,perfer表示优先 +# Record the rate at which the system clock gains/losses time. +driftfile /var/lib/chrony/drift +#用来记录时间差异,由于chrony是通过BIOS判断时间的,他会用这个时间与上层时间服务器进行对比,将差异记录下来 +# Allow the system clock to be stepped in the first three updates +# if its offset is larger than 1 second. +makestep 1.0 3 +#让chrony可以根据需求逐步进行时间的调整,避免在某些情况下时间差异较大,导致调整时间耗时过长,以上的设置表示在误差时间大于1.0秒的话,前三次使用update更新时间是使用step(分阶段)而不是slew(微调),如果最后一个值是负数的话,如-1则表示随时步进 +# Enable kernel synchronization of the real-time clock (RTC). +rtcsync +#启用内核模式,在内核模式中,系统时间每11分钟会同步到实时时钟(RTC) +# Enable hardware timestamping on all interfaces that support it. +#hwtimestamp * +# 通过使用hwtimestamp指令启用硬件时间戳 +# Increase the minimum number of selectable sources required to adjust +# the system clock. +#minsources 2 + +# Allow NTP client access from local network. +#allow 192.168.0.0/16 +#允许同步的网段 +# Serve time even if not synchronized to a time source. +#local stratum 10 +#即时自己未能通过网络时间服务器同步时间,也允许将本地时间作为标准时间同步给其他客户端 +# Specify file containing keys for NTP authentication. +keyfile /etc/chrony.keys +#验证的秘钥文件 +# Get TAI-UTC offset and leap seconds from the system tz database. +leapsectz right/UTC +#从system tz数据库中获取TAI(国际原子时)和UTC(协调世界时)之间的时间偏移及闰秒 +# Specify directory for log files. +logdir /var/log/chrony +#日志文件的位置 +# Select which information is logged. +#log measurements statistics tracking +``` + +## 时间服务器实战 + +环境:两台主机,系统为CentOS8,IP地址为192.168.2.100,192.168.2.200,selinux和防火墙关闭 + +要求: 192.168.2.100为内网时间服务器,192.168.2.200为客户端,200的客户端的时间要与100的时间同步 + +``` +在192.168.2.100主机上 +step1 检查时间服务器上是否有相关软件包 +[root@zutuanxue ~]# rpm -qa | grep chrony +chrony-3.3-3.el8.x86_64 + +step2 检查本机的时区 +[root@zutuanxue ~]# timedatectl + Local time: 五 2020-01-17 17:36:14 CST + Universal time: 五 2020-01-17 09:36:14 UTC + RTC time: 五 2020-01-17 09:36:56 + Time zone: Asia/Shanghai (CST, +0800) +System clock synchronized: yes + NTP service: active + RTC in local TZ: no +注:如果不是本地时区请设置时区 +[root@zutuanxue ~]# timedatectl list-timezones | grep Shanghai +Asia/Shanghai +[root@zutuanxue ~]# timedatectl set-timezone Asia/Shanghai + +step3 修改配置文件 +[root@zutuanxue ~]# vim /etc/chrony.conf +server 192.168.2.100 iburst #定义时间服务器的地址 +driftfile /var/lib/chrony/drift +makestep 1.0 3 +rtcsync +allow 192.168.2.0/24 #定义允许谁来同步 +local stratum 10 #允许将本地时间作为标准 +leapsectz right/UTC +logdir /var/log/chrony +bindaddress 192.168.2.100 #监听的网络接口 + +step4 启动服务&查看端口 +[root@zutuanxue ~]# systemctl start chronyd +[root@zutuanxue ~]# lsof -i :123 + +在192.168.2.200主机上 +step5 检查软件包 +[root@slave ~]# rpm -qa | grep chrony +chrony-3.3-3.el8.x86_64 + +step6 检查并设置本机时区 +[root@slave ~]# timedatectl + Local time: 五 2020-01-17 04:19:38 EST + Universal time: 五 2020-01-17 09:19:38 UTC + RTC time: 五 2020-01-17 16:04:57 + Time zone: America/New_York (EST, -0500) +System clock synchronized: yes + NTP service: active + RTC in local TZ: no +[root@slave ~]# timedatectl list-timezones |grep Shanghai +Asia/Shanghai +[root@slave ~]# timedatectl set-time Asia/Shanghai + +step7 修改配置文件 +[root@zutuanxue ~]# vim /etc/chrony.conf +server 192.168.2.100 iburst +driftfile /var/lib/chrony/drift +makestep 1.0 3 +rtcsync +keyfile /etc/chrony.keys +leapsectz right/UTC +logdir /var/log/chrony + +step8 启动服务&检查能否连接时间服务器 +[root@slave ~]# systemctl start chronyd +[root@slave ~]# chronyc sources -v +210 Number of sources = 1 + + .-- Source mode '^' = server, '=' = peer, '#' = local clock. + / .- Source state '*' = current synced, '+' = combined , '-' = not combined, +| / '?' = unreachable, 'x' = time may be in error, '~' = time too variable. +|| .- xxxx [ yyyy ] +/- zzzz +|| Reachability register (octal) -. | xxxx = adjusted offset, +|| Log2(Polling interval) --. | | yyyy = measured offset, +|| \ | | zzzz = estimated error. +|| | | \ +MS Name/IP address Stratum Poll Reach LastRx Last sample +=============================================================================== +^* 192.168.2.100 11 6 377 57 +13ms[ +278us] +/- 3718us + +#可以在2.100上使用date -s命令修改时间,在2.200上重启服务,看到时间同步 +chronyc命令 + +chronyc sources -v 查看时间同步源 +chronyc sourcestats -v 查看时间同步源状态 +timedatectl set-local-rtc 1 设置硬件时间硬件时间默认为UTC +timedatectl set-ntp yes 启用NTP时间同步: +chronyc tracking 校准时间服务器: +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/\351\203\250\347\275\262linux\347\275\221\347\273\234\345\256\211\350\243\205\346\234\215\345\212\241\345\231\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/\351\203\250\347\275\262linux\347\275\221\347\273\234\345\256\211\350\243\205\346\234\215\345\212\241\345\231\250.md" new file mode 100644 index 0000000..8bfe565 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\345\270\270\347\224\250\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262\345\256\236\346\210\230/\351\203\250\347\275\262linux\347\275\221\347\273\234\345\256\211\350\243\205\346\234\215\345\212\241\345\231\250.md" @@ -0,0 +1,354 @@ +## 一、批量部署概述 + +**什么是PXE** +预启动执行环境(PXE)是由Intel公司开发的最新技术,工作于Client/Server的网络模式,支持工作站通过网络从远端服务器下载映像,并由此支持通过网络启动操作系统,在启动过程中,终端要求服务器分配IP地址,再用TFTP(trivial file transfer protocol)或MTFTP(multicast trivial file transfer protocol)协议下载一个启动软件包到本机内存中执行,由这个启动软件包完成终端(客户端)基本软件设置,从而引导预先安装在服务器中的终端操作系统。PXE可以引导多种操作系统,如:Windows95/98/2000/windows2003/windows2008/winXP/win7/win8,linux系列系统等。 + +**PXE原理** +PXE是在没有软驱、硬盘、CD-ROM的情况下引导计算机的一种方式,也就是BIOS将使用PXE协议从网络引导。整个安装的过程是这样的: + +PXE网卡启动 => DHCP获得IP地址 => 从TFTP上下载 pxelinux.0、vmlinuz、initr.img 等 => 引导系统进入安装步骤 => 通过PEX linux 下载ks.cfg文件并跟据ks.cfg自动化安装系统 => 完成。 + +![image20200403143123698.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603526488594.png) + +**TFTP服务** +TFTP是用来下载远程文件的最简单网络协议,它其于UDP协议而实现。 + +**什么是kickstart** +KickStart是一种无人职守安装方式。KickStart的工作原理是通过记录典型的安装过程中所需人工干预填写的各种参数,并生成一个名为ks.cfg的文件;在其后的安装过程中(不只局限于生成KickStart安装文件的机器)当出现要求填写参数的情况时,安装程序会首先去查找KickStart生成的文件,当找到合适的参数时,就采用找到的参数,当没有找到合适的参数时,才需要安装者手工干预。这样,如果KickStart文件涵盖了安装过程中出现的所有需要填写的参数时,安装者完全可以只告诉安装程序从何处取ks.cfg文件,然后去忙自己的事情。等安装完毕,安装程序会根据ks.cfg中设置的重启选项来重启系统,并结束安装。 + +## 二、批量部署原理 + +![image20200403144115628.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603526515184.png) + +**1、PXE Client向DHCP发送请求:** +  PXE Client从自己的PXE网卡启动,通过PXE BootROM(自启动芯片)会以UDP(简单用户数据报协议)发送一个广播请求,向本网络中的DHCP服务器索取IP。 + +**2、DHCP服务器提供信息:** +  DHCP服务器收到客户端的请求,验证是否来至合法的PXE Client的请求,验证通过它将给客户端一个“提供”响应,这个“提供”响应中包含了为客户端分配的IP地址、pxelinux启动程序(TFTP)位置,以及配置文件所在位置。 + +**3、PXE客户端请求下载启动文件:** +  客户端收到服务器的“回应”后,会回应一个帧,以请求传送启动所需文件。这些启动文件包括:pxelinux.0、pxelinux.cfg/default、vmlinuz、initrd.img等文件。 + +**4、Boot Server响应客户端请求并传送文件:** +  当服务器收到客户端的请求后,他们之间之后将有更多的信息在客户端与服务器之间作应答, 用以决定启动参数。BootROM由TFTP通讯协议从Boot Server下载启动安装程序所必须的文件(pxelinux.0、pxelinux.cfg/default)。default文件下载完成后,会根据该文件中定义的引导顺序,启动Linux安装程序的引导内核。 + +**5、请求下载自动应答文件:** +  客户端通过pxelinux.cfg/default文件成功的引导Linux安装内核后,安装程序首先必须确定你通过什么安装介质来安装linux,如果是通过网络安装(NFS, FTP, HTTP),则会在这个时候初始化网络,并定位安装源位置。接着会读取default文件中指定的自动应答文件ks.cfg所在位置,根据该位置请求下载该文件。 +  这里有个问题,在第2步和第5步初始化2次网络了,这是由于PXE获取的是安装用的内核以及安装程序等,而安装程序要获取的是安装系统所需的二进制包以及配置文件。因此PXE模块和安装程序是相对独立的,PXE的网络配置并不能传递给安装程序,从而进行两次获取IP地址过程,但IP地址在DHCP的租期内是一样的。 + +**6、客户端安装操作系统:** +  将ks.cfg文件下载回来后,通过该文件找到OS Server,并按照该文件的配置请求下载安装过程需要的软件包。 +  OS Server和客户端建立连接后,将开始传输软件包,客户端将开始安装操作系统。安装完成后,将提示重新引导计算机。 + +## 三、kickstart批量部署实战 + +环境: + +- selinux关闭,防火墙关闭 +- Server:192.168.2.100 + +**Step 1 配置dnf源** + +``` +[root@zutuanxue ~]# cat server.repo +[serverApp] +name=app +enabled=1 +gpgcheck=0 +baseurl=file:///mnt/AppStream +[serverOS] +name=os +enabled=1 +gpgcheck=0 +baseurl=file:///mnt/BaseOS +``` + +**Step 2 安装软件包** + +``` +[root@zutuanxue ~]# dnf install dhcp-server tftp-server httpd syslinux -y +``` + +**Step 3 搭建并启动DHCP** + +``` +[root@zutuanxue ~]# vim /etc/dhcp/dhcpd.conf +subnet 192.168.2.0 netmask 255.255.255.0 { + option routers 192.168.2.100; + range 192.168.2.10 192.168.2.20; + next-server 192.168.2.100; + filename "pxelinux.0"; +} + +[root@zutuanxue ~]# systemctl start dhcpd +[root@zutuanxue ~]# systemctl status dhcpd +[root@zutuanxue ~]# netstat -antlup | grep :67 +udp 0 0 0.0.0.0:67 0.0.0.0:* 31465/dhcpd +udp 0 0 0.0.0.0:67 0.0.0.0:* 1345/dnsmasq +``` + +**Step 4 生成需要的文件并启动tftp服务** + +``` +[root@zutuanxue ~]# cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot/ +[root@zutuanxue ~]# cp /mnt/isolinux/{vmlinuz,ldlinux.c32,initrd.img} /var/lib/tftpboot/ +[root@zutuanxue ~]# mkdir /var/lib/tftpboot/pxelinux.cfg +[root@zutuanxue ~]# vim /var/lib/tftpboot/pxelinux.cfg/default #生成default文件 +default linux +timeout 3 +label linux + kernel vmlinuz + append initrd=initrd.img ip=dhcp method=http://192.168.2.100/RHEL ks=http://192.168.2.100/ks.cfg +[root@zutuanxue mnt]# systemctl start tftp #启动tftp服务 +[root@zutuanxue mnt]# systemctl status tftp +[root@zutuanxue mnt]# netstat -antulp | grep :69 +udp6 0 0 :::69 :::* 1/systemd +``` + +**Step 5 搭建并启动http服务** + +``` +[root@zutuanxue ~]# mkdir /var/www/html/RHEL #建立软件包存放目录 +[root@zutuanxue ~]# mount /dev/cdrom /var/www/html/RHEL #将光盘挂载到对应目录中 +``` + +**Step 6 生成ks.cfg文件** + +由于CentOS8.0中没有system-config-kickstart包,所以无法通过工具生成ks文件,需要手动生成,例子中root用户和新建的hello用户的密码都为‘`123qwe’ + +如果需要自己额外指定密码,请使用其它工具进行转换,例如doveadm命令 + +``` +cp /root/anaconda-ks.cfg /var/www/html/ks.cfg #生成ks.cfg文件 +[root@zutuanxue ~]# vim /var/www/html/ks.cfg +#version=RHEL8 +ignoredisk --only-use=sda +autopart --type=lvm +# Partition clearing information +clearpart --all #删除所有分区 +# Use graphical install +graphical +url --url="http://192.168.2.100/RHEL/" #指定安装URL +# Keyboard layouts +keyboard --vckeymap=cn --xlayouts='cn' +# System language +lang zh_CN.UTF-8 +# Network information +network --bootproto=dhcp --device=ens33 --ipv6=auto --activate +network --hostname=localhost.localdomain +##root用户的密码"111111" +rootpw --iscrypted $6$kdHt1qIdgNPlHUD1$zibMjh/AQGZQjIJe8Q4HYiin.IKaV7MHWciueiwbLD/03giuSqzU5ynSu/giDAjMLpJFj/CpNgT7TKSm5XyxV1 +# X Window System configuration information +xconfig --startxonboot +# Run the Setup Agent on first boot +#firstboot disable #初次启动设置 +firstboot --disable +# System services +services --enabled="chronyd" +# System timezone +timezone America/New_York --isUtc +#Reboot after installation #安装完成后自动重启 +reboot +# License agreement #同意授权协议 +eula --agreed +#添加一个普通用户名字为zutuanxue密码"111111" 属组为 whell +user --groups=wheel --name=zutuanxue --password=$6$kdHt1qIdgNPlHUD1$zibMjh/AQGZQjIJe8Q4HYiin.IKaV7MHWciueiwbLD/03giuSqzU5ynSu/giDAjMLpJFj/CpNgT7TKSm5XyxV1 --iscrypted --gecos="zutuanxue" +%packages +@^graphical-server-environment +%end + +%addon com_redhat_kdump --disable --reserve-mb='auto' + +%end + +%anaconda +pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty +pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok +pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty +%end +``` + +**Step 7 修改文件权限,启动http服务** + +``` +[root@zutuanxue ~]# chmod a+r /var/www/html/ks.cfg +[root@zutuanxue ~]# systemctl start httpd +[root@zutuanxue ~]# systemctl start httpd +[root@zutuanxue ~]# systemctl status httpd +[root@zutuanxue ~]# netstat -antlp | grep :80 +tcp6 0 0 :::80 :::* LISTEN 33976/httpd +``` + +**Step 8 测试** + +选择网络启动 + +![image20191202110450898.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603526811897.png) + +获取IP和相关文件 + +![image20191202110525859.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603526828444.png) + +开启安装进程 + +![install6.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603526884300.png) + +安装完成后自动重启 + +![install7.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603526915193.png) + +## 四、kickstart+uefi批量部署 + +**环境:** + +- selinux关闭,防火墙关闭 +- Server:192.168.2.100 + +**Step 1 配置dnf源** + +``` +[root@zutuanxue ~]# cat server.repo +[serverApp] +name=app +enabled=1 +gpgcheck=0 +baseurl=file:///mnt/AppStream +[serverOS] +name=os +enabled=1 +gpgcheck=0 +baseurl=file:///mnt/BaseOS +``` + +**Step 2 安装软件包** + +``` +[root@zutuanxue ~]# dnf install dhcp-server tftp-server httpd -y +``` + +**Step 3 搭建并启动DHCP** + +``` +[root@zutuanxue ~]# vim /etc/dhcp/dhcpd.conf +subnet 192.168.2.0 netmask 255.255.255.0 { + option routers 192.168.2.100; + range 192.168.2.10 192.168.2.20; + next-server 192.168.2.100; + filename "BOOTX64.EFI";#注意差异,使用的不是pxelinux.0 +} + +[root@zutuanxue ~]# systemctl start dhcpd +[root@zutuanxue ~]# systemctl status dhcpd +[root@zutuanxue ~]# netstat -antlup | grep :67 +udp 0 0 0.0.0.0:67 0.0.0.0:* 31465/dhcpd +udp 0 0 0.0.0.0:67 0.0.0.0:* 1345/dnsmasq +``` + +**Step 4 生成需要的文件并启动tftp服务** + +``` +[root@zutuanxue ~]# cd /mnt/EFI/BOOT/ +[root@zutuanxue BOOT]# cp BOOTX64.EFI grub.cfg grubx64.efi /var/lib/tftpboot/ + +[root@zutuanxue ~]# cp /mnt/isolinux/{vmlinuz,initrd.img} /var/lib/tftpboot/ + +[root@zutuanxue ~]# vim /var/lib/tftpboot/grub.cfg +set default="0" +set timeout=3 +menuentry 'Install CentOS Linux 8.0.1905' { + linuxefi /vmlinuz ip=dhcp ks=http://192.168.2.100/ks.cfg + initrdefi /initrd.img +} +[root@zutuanxue mnt]# systemctl start tftp #启动tftp服务 +[root@zutuanxue mnt]# systemctl status tftp +[root@zutuanxue mnt]# netstat -antulp | grep :69 +udp6 0 0 :::69 :::* 1/systemd +``` + +**Step 5 搭建并启动http服务** + +``` +[root@zutuanxue ~]# mkdir /var/www/html/RHEL #建立软件包存放目录 +[root@zutuanxue ~]# mount /dev/cdrom /var/www/html/RHEL #将光盘挂载到对应目录中 +``` + +**Step 6 生成ks.cfg文件** + +由于CentOS8.0中没有system-config-kickstart包,所以无法通过工具生成ks文件,需要手动生成,例子中root用户和新建的hello用户的密码都为‘`123qwe’ + +https://access.redhat.com/labs/kickstartconfig/ + +如果需要自己额外指定密码,请使用其它工具进行转换,例如doveadm命令,但是系统没有这个工具,所以推荐使用python来实现 + +注意: + +``` +[root@zutuanxue ~]# python3 -c 'import crypt,getpass;pw="zutuanxue";print(crypt.crypt(pw))' +``` + +**生成ks.cfg文件** + +``` +cp /root/anaconda-ks.cfg /var/www/html/ks.cfg #生成ks.cfg文件 +[root@zutuanxue ~]# vim /var/www/html/ks.cfg +#version=RHEL8 +ignoredisk --only-use=nvme0n1 ###注意这是与BIOS方式差异的位置,注意设备类型,可在BIOS中查看到 +autopart --type=lvm +# Partition clearing information +clearpart --all #删除所有分区 +# Use graphical install +graphical +url --url="http://192.168.2.100/RHEL/" #指定安装URL +# Keyboard layouts +keyboard --vckeymap=cn --xlayouts='cn' +# System language +lang zh_CN.UTF-8 +# Network information +network --bootproto=dhcp --device=ens33 --ipv6=auto --activate +network --hostname=localhost.localdomain +# Root password “`123qwe” ##root用户的密码"111111" +rootpw --iscrypted $6$kdHt1qIdgNPlHUD1$zibMjh/AQGZQjIJe8Q4HYiin.IKaV7MHWciueiwbLD/03giuSqzU5ynSu/giDAjMLpJFj/CpNgT7TKSm5XyxV1 +# X Window System configuration information +xconfig --startxonboot +# Run the Setup Agent on first boot +#firstboot disable #初次启动设置 +firstboot --disable +# System services +services --enabled="chronyd" +# System timezone +timezone America/New_York --isUtc +#Reboot after installation #安装完成后自动重启 +reboot +# License agreement #同意授权协议 +eula --agreed +#添加一个普通用户名字为zutuanxue密码"111111" 属组为 whell +user --groups=wheel --name=zutuanxue --password=$6$kdHt1qIdgNPlHUD1$zibMjh/AQGZQjIJe8Q4HYiin.IKaV7MHWciueiwbLD/03giuSqzU5ynSu/giDAjMLpJFj/CpNgT7TKSm5XyxV1 --iscrypted --gecos="zutuanxue" +%packages +@^graphical-server-environment +%end + +%addon com_redhat_kdump --disable --reserve-mb='auto' + +%end + +%anaconda +pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty +pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok +pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty +%end +``` + +**Step 7 修改文件权限,启动http服务** + +``` +[root@zutuanxue ~]# chmod a+r /var/www/html/ks.cfg +[root@zutuanxue ~]# systemctl start httpd +[root@zutuanxue ~]# systemctl start httpd +[root@zutuanxue ~]# systemctl status httpd +[root@zutuanxue ~]# netstat -antlp | grep :80 +tcp6 0 0 :::80 :::* LISTEN 33976/httpd +``` + +**Step 8 测试** + +新建虚拟机的是要选择自定义使用UEFI \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/CentOS 8\345\220\257\345\212\250\346\265\201\347\250\213.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/CentOS 8\345\220\257\345\212\250\346\265\201\347\250\213.md" new file mode 100644 index 0000000..c2a89c0 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/CentOS 8\345\220\257\345\212\250\346\265\201\347\250\213.md" @@ -0,0 +1,302 @@ +## 一、BIOS与UEFI + +**BIOS** + +Basic Input Output System的缩写,翻译过来就是“基本输入输出系统”,是一种业界标准的固件接口,第一次出现在1975年,是计算机启动时加载的第一个程序,主要功能是检测和设置计算机硬件,引导系统启动。 + +**UEFI** +Unified Extensible Firmware interface的缩写,翻译过来为统一可扩展固件接口,是BIOS的替代方案,前身是Intel在1998年开始开发的Inter Bot Initiative,后来被命名为可扩展固件接口(Extensible Firmware Interface EFI),2005年交由统一可扩展固件接口论坛,并更名为UEFI + +**UEFI的优势** + +1、支持硬盘容量更大:相比于传统BIOS+MBR只能支持2048G的硬盘分区和4个主分区相比,UEFI+GPT不会受到硬盘容量大小、分区数量的限制,不过在Windows系统上由于系统的限制,支持最多128个GPT磁盘分区,最大分区18EB,并且GPT格式是没有主分区和逻辑分区这个概念的 + +2、容错特性:UEFI是模块化构建,比BIOS容错和纠错特性强。 + +3、鼠标操作:UEFI内置图形驱动,可以提供原生分辨率的图形环境,用户进入后可以使用鼠标调整。 + +4、扩展性强:UEFI包含一个可编程的开放接口,厂商利用这个接口可以对功能进行扩展,如:备份和诊断 + +5、支持联网:在不进入操作系统的前提下就可以通过网络进行远程故障诊断 + +## 二、CentOS8启动流程 + +现代计算机是软件与硬件的复杂组合,从接通电源开始,到可以登录到系统中,需要大量的软件和硬件的配合,我们一起来了解一下CentOS8的x86_64系统在启动过程中所涉及的任务,虚拟机的流程也是大致相同的,但是某些与硬件相关的步骤是由虚拟机的相关程序在软件中处理的。 + +**1、接通电源** + + 系统固件(UEFI或BIOS初始化)运行开机自检,并初始化部分硬件 + +**2、系统固件搜索可启动设备** + + 启动设备可能是UEFI启动固件中配置的,也可能是按照BIOS中配置的顺序搜索所有磁盘上的主启动记录(MBR) + +**3、读取启动加载器**(boot loader) + + 系统固件会从MBR中读取启动加载器,然后将控制权交给启动加载器,在CentOS8中启动加载器为GRUB2 + +**4、grub.cfg** + + GRUB2将从/boot/grub2/grub.cfg文件中加载配置并显示一个菜单,在这个菜单中可以选择要启动的内核,我们可以使用grub2-mkconfig命令配合/etc/grub.d/目录和/etc/default/grub文件生成grub.cfg文件。 + +``` +[root@zutuanxue ~]# cd /boot/grub2/ +[root@zutuanxue grub2]# ls +device.map fonts grub.cfg grubenv i386-pc +[root@zutuanxue grub2]# pwd +/boot/grub2 +``` + +**5、initramfs** + + 在选择内核或到达超时时间后,启动加载器会从磁盘加载内核(vmlinuz)和initramfs,并将它们放入内存中,initramfs中包含启动时所有必要硬件的内核模块(驱动)和初始化脚本等,使用lsinitrd和dracut命令配合/etc/dracut.conf.d/目录可以查看和配置initramfs文件 + +``` +[root@zutuanxue grub2]# lsinitrd | more +Image: /boot/initramfs-4.18.0-80.el8.x86_64.img: 27M +##可以在回显中看到系统的主要目录,包括/etc /usr /dev /lib /lib64等 +``` + +**6、启动加载器放权** + + 启动加载器将控制权交给内核 + +**7、内核初始化** + + 内核会在initramfs中寻找硬件的相关驱动并初始化相关硬件,然后启动/usr/sbin/init(PID=1),在CentOS8中/sbin/init是systemd的链接 + +``` +[root@zutuanxue grub2]# ll /sbin/init +lrwxrwxrwx. 1 root root 22 5月 23 2019 /sbin/init -> ../lib/systemd/systemd +[root@zutuanxue grub2]# find / -name systemd +/usr/lib/systemd/systemd +``` + +**8、启动initrd.target并挂载** + + systemd会执行initrd.target包含的所有单元,并将根文件系统挂载到/sysroot/目录,在initrd.target启动时的依赖单元,会按照/etc/fstab设置对硬盘进行挂载 + +**9、切换根文件系统** + + 内核将根文件系统从initramfs切换为/sysroot(硬盘上的根文件系统),systemd会找到磁盘上安装的systemd并自动重新执行 + +**10、启动相应目标** + + 硬盘上安装的systemd会查找从内核命令行传递的目标或是系统中配置的默认目标并启动对应单元后就可以进入到对应的登录界面。默认目标是/etc/systemd/system/default.target, + +**注意:** +字符界面: + + 如果默认目标为multi-user.target(字符界面),systemd会先执行sysinit.target初始化系统之后执行basic.target与getty.target准备基本系统环境和终端,再启动multi-user.target下的相关应用,同时执行/etc/rc.d/rc.local(需要执行权限)与与登录服务(systemd-logind.service),开启登录界面 + +``` +[root@zutuanxue ~]# systemctl list-dependencies multi-user.target | grep target +multi-user.target +● ├─basic.target +● │ ├─paths.target +● │ ├─slices.target +● │ ├─sockets.target +● │ ├─sysinit.target +● │ │ ├─cryptsetup.target +● │ │ ├─local-fs.target +● │ │ └─swap.target +● │ └─timers.target +● ├─getty.target +● ├─nfs-client.target +● │ └─remote-fs-pre.target +● └─remote-fs.target +● └─nfs-client.target +● └─remote-fs-pre.target +``` + +图形界面: + + 在multi-user.target的基础上执行graphical.target启动所需要的服务,开启图形界面 + +``` +[root@zutuanxue ~]# systemctl list-dependencies graphical.target | grep target +graphical.target +● └─multi-user.target +● ├─basic.target +● │ ├─paths.target +● │ ├─slices.target +● │ ├─sockets.target +● │ ├─sysinit.target +● │ │ ├─cryptsetup.target +● │ │ ├─local-fs.target +● │ │ └─swap.target +● │ └─timers.target +● ├─getty.target +● ├─nfs-client.target +● │ └─remote-fs-pre.target +● └─remote-fs.target +● └─nfs-client.target +● └─remote-fs-pre.target +``` + +## 三、运行级别切换与相关配置文件 + +**运行级别切换** + + 通过前面的课程我们了解到CentOS8在启动过程中需要判断对应的运行级别,在不同的运行级别中会启动不同的单元,那么运行级别如何切换呢? + + 在CentOS8中运行级别的设置涉及到下面几个命令 + +``` +systemctl isolate .../init [0-6] 切换运行级别 +systemctl get-default 查看当前的默认运行级别 +systemctl set-default ... 设置默认的运行级别 +runlevel 查看之前的运行级别和当前的运行级别 +``` + + +运行级别对照 + +``` +[root@localhost system]# cd /usr/lib/systemd/system +[root@localhost system]# ll runlevel*.target +runlevel0.target -> poweroff.target +runlevel1.target -> rescue.target +runlevel2.target -> multi-user.target +runlevel3.target -> multi-user.target +runlevel4.target -> multi-user.target +runlevel5.target -> graphical.target +runlevel6.target -> reboot.target +``` + +所以当我们使用init [0-6]切换运行级别的时候系统执行的是systemctl isolate runlevel[0-6].target + +``` +[root@zutuanxue ~]# runlevel #查看运行级别 +N 5 +[root@zutuanxue ~]# init 3 #切换到字符界面 +[root@zutuanxue ~]# runlevel #查看运行级别 +5 3 +[root@zutuanxue ~]# systemctl isolate graphical.target #切换到图形界面 +[root@zutuanxue ~]# runlevel +3 5 + +######### +emergency.target +[root@zutuanxue ~]# systemctl isolate emergency.target +``` + +![image20191224152253190.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996176505.png) + +注意:此为紧急模式,用于紧急处理系统的错误,无法使用rescue.target时,可以尝试使用此模式。 + +## 四、Boot Loader与GRUB2 + +前面的课程我们了解的CentOS8的启动流程,在这个流程中有一个叫启动加载器,也就是boot loader的工具,如果没有这个boot loader就无法加载内核。在CentOS8中使用的是启动加载器是Grub2,在了解Grub2之前,我们先聊一下boot loader + +### 4.1、Boot Loader的两个阶段 + +我们知道在BIOS或者UEFI加载完成之后,会到MBR中读取boot loader,这个boot loader可以让用户选择加载的内核并且移交系统的控制权限等,而加载内核只能通过boot loader,但是boot loader在MBR中,这个MBR是硬盘的第一个扇区,一个扇区的大小是512字节,boot loader的大小只有446字节,即便是GPT磁盘也没有足够的空间存储boot loader所包含的内容,所以为了避免空间的限制,导致无法引导系统正常启动的问题,Linux将boot loader的工作过程分为了两步。 + +stage1 执行boot loader的主程序 +主程序必须安装在MBR或者是启动扇区,由于空间限制,MBR或启动扇区仅存放最小化的boot loader,并不会存放相关的配置文件 + +stage2 通过主程序加载配置文件 +通过boot loader的主程序加载所有相关的配置文件,这些配置文件中包括定义文件系统类型的和CentOS8中的grub.cfg文件,而这些文件通常都存放在/boot当中 + +``` +[root@zutuanxue ~]# ll -F /boot/grub2/ +总用量 32 +-rw-r--r--. 1 root root 64 12月 13 21:50 device.map +drwxr-xr-x. 2 root root 4096 12月 13 21:50 fonts/ +-rw-r--r--. 1 root root 5032 12月 13 21:50 grub.cfg +-rw-r--r--. 1 root root 1024 12月 13 21:50 grubenv +drwxr-xr-x. 2 root root 12288 12月 13 21:50 i386-pc/ + +device.map 设备对应文件,用来帮助系统判断磁盘与设备文件的对应关系 +fonts 开机过程中用到的字体文件 +grub.cfg grub2的主配置文件 +grubenv grub环境区块文件大小为1K,用来记录GRUB环境变量 +i386-PC 针对x86架构的电脑所需要的相关模块,包括电源管理支持,文件系统支持等模块 +``` + +在这些文件中最重要的就是grub.cfg文件,以及文件系统支持的相关模块 + +### 4.2、GRUB2 + +**GRUB与LILO** +目前为止,linux下的启动加载器有两种,一种是LILO另外一种就是GRUB,由于GRUB的功能更强大,支持的文件系统较多,所以越来越多的操作系统使用GRUB做为boot loader,CentOS从7开始使用了功能更为强大的GRUB2 + +**GRUB2的优点** + +- 支持更多的文件系统 +- 开机时可以手动调整启动参数 +- 动态更新配置文件,修改完配置文件后不需要重新安装 + +**GRUB2与硬盘** + +由于grub2的主要任务是从硬盘当中加载内核,所以grub2必须要识别硬盘,但是grub2识别硬盘的方式与linux系统识别的方式还是有些区别的。在Linux系统中,硬盘一般会被识别为类似sda1这种形式,而在grub2中硬盘会统一被识别为hd的设备,排序方式全部是用数字进行排序,而不是用字母加数字的混合形式。这么做的目的是为了定义grub2的查找内核时的顺序。如: + +``` +hd0,1 搜索第一块硬盘的第一个分区 +hd0,msdos1 搜索第一块MBR硬盘的第一个分区 +hd0,gpt1 搜索第一块GPT磁盘的第一个分区 +简单来说,两个数字,第一个数字表示硬盘序号,第二个数字表示分区序号 +``` + +**grub2配置文件** + +了解了grub2中的硬盘识别方式,我们就可以了解一下grub2的配置文件了,这个文件建议各位不要随意更改 + +``` +# +# DO NOT EDIT THIS FILE +# +# It is automatically generated by grub2-mkconfig using templates +# from /etc/grub.d and settings from /etc/default/grub +# + +此部分内容提示我们不要编辑这个文件,此文件是有grub2-mkconfig命令自动建立的,相关模板与设置存放在/etc/grub.d/目录以及/etc/default/grub中,也就是说grub.cfg文件的内容会调用/etc/grub.d目录下的内容,如果需要修改的话需要调整/etc/default/grub文件 +``` + +基本上grub2不希望用户去修改grub.cfg这个文件,如果需要调整的话需要通过修改其它文件并配合grub2-mkconfig命令来生成新的grub.cfg文件,但是各位还是要了解一下这个文件的大致格式 + +### /etc/default/grub与/etc/grub.d/ + +在前面的课程中我们知道了grub2的配置文件是grub.cfg,但是此文件内容比较复杂,且官方不建议我们手动修改,如果需要修改的话需要通过/etc/default/grub文件以及/etc/grub.d/目录内的内容来实现,那我们一起来看一下 + +**/etc/default/grub** + +``` +[root@zutuanxue ~]# vim /etc/default/grub +GRUB_TIMEOUT=5 定义在启动菜单默认的等待时间,单位是秒 +GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)" 定义获取操作系统名称的方式 +GRUB_DEFAULT=saved 定义开机时默认启动的项目,可以是数字,也可以是标题名称,(这个标题就是开机时看到的那个标题),还可以是saved(表示默认启动上次启动成功的操作系统) +GRUB_DISABLE_SUBMENU=true 是否隐藏子菜单 +GRUB_TERMINAL_OUTPUT="console" 定义启动时的界面使用哪种终端输出,值包含console,serial,gfxterm,vga_text等 +GRUB_CMDLINE_LINUX="resume=/dev/mapper/cl-swap rd.lvm.lv=cl/root rd.lvm.lv=cl/swap rhgb quiet" 定义额外的启动参数 +GRUB_DISABLE_RECOVERY="true" 是否启用修复模式 +GRUB_ENABLE_BLSCFG=true 是否启用bootloader规范 + +修改完成之后需要使用 +grub2-mkconfig -o /boot/grub2/grub.cfg,重新生成配置文件 +``` + +**/etc/grub.d/** + +00_header 设置默认参数 + +00_tuned 额外调整的值 + +01_menu_auto_hide 与菜单隐藏相关的设置 + +01_users 与用户相关的设置 + +10_linux 与内核相关的设置 + +20_ppc_terminfo 与终端相关的设置 + +20_linux_xen 与虚拟化相关的设置 + +30_os-prober 与操作系统检测相关 + +30_uefi-firmware 与UEFI启动设置相关,需要硬件支持 + +40_custom&41_custom 自定义设置 + +注:这些文件会按照数字的顺序由小到大加载 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/GPT\347\243\201\347\233\230\347\256\241\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/GPT\347\243\201\347\233\230\347\256\241\347\220\206.md" new file mode 100644 index 0000000..a5c01c3 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/GPT\347\243\201\347\233\230\347\256\241\347\220\206.md" @@ -0,0 +1,151 @@ +GPT分区工具:gdisk gdisk + +**gdisk分区** + +``` +GPT 128个主分区 +[root@zutuanxue ~]# gdisk -l /dev/sdc +[root@zutuanxue ~]# gdisk -l /dev/sdc 查看sdc信息 +GPT fdisk (gdisk) version 1.0.3 + +Partition table scan: + MBR: MBR only + BSD: not present + APM: not present + GPT: not present ###GPT分区无法使用 + + +*************************************************************** +Found invalid GPT and valid MBR; converting MBR to GPT format +in memory. +*************************************************************** + +Disk /dev/sdc: 41943040 sectors, 20.0 GiB +Model: VMware Virtual S +Sector size (logical/physical): 512/512 bytes +Disk identifier (GUID): B228357D-34EC-4E47-BB81-A7312F3BCF8D +Partition table holds up to 128 entries +Main partition table begins at sector 2 and ends at sector 33 +First usable sector is 34, last usable sector is 41943006 +Partitions will be aligned on 2048-sector boundaries +Total free space is 37748669 sectors (18.0 GiB) + +Number Start (sector) End (sector) Size Code Name + 1 2048 2099199 1024.0 MiB 8300 Linux filesystem + 2 2099200 4196351 1024.0 MiB 8300 Linux filesystem + + + + +将MBR转换成GPT分区 +[root@zutuanxue ~]# gdisk /dev/sdc +GPT fdisk (gdisk) version 1.0.3 + +Partition table scan: + MBR: MBR only + BSD: not present + APM: not present + GPT: not present + + +*************************************************************** +Found invalid GPT and valid MBR; converting MBR to GPT format +in memory. THIS OPERATION IS POTENTIALLY DESTRUCTIVE! Exit by +typing 'q' if you don't want to convert your MBR partitions +to GPT format! +*************************************************************** + + +Command (? for help): o +This option deletes all partitions and creates a new protective MBR. +Proceed? (Y/N): y + +Command (? for help): w + +Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING +PARTITIONS!! + +Do you want to proceed? (Y/N): y +OK; writing new GUID partition table (GPT) to /dev/sdc. +The operation has completed successfully. + + + +[root@zutuanxue ~]# gdisk -l /dev/sdc +GPT fdisk (gdisk) version 1.0.3 + +Partition table scan: + MBR: protective + BSD: not present + APM: not present + GPT: present ###GPT可用了 + +Found valid GPT with protective MBR; using GPT. +Disk /dev/sdc: 41943040 sectors, 20.0 GiB +Model: VMware Virtual S +Sector size (logical/physical): 512/512 bytes +Disk identifier (GUID): 7CA4232A-4A9E-467D-AADD-BB84DB2126E3 +Partition table holds up to 128 entries +Main partition table begins at sector 2 and ends at sector 33 +First usable sector is 34, last usable sector is 41943006 +Partitions will be aligned on 2048-sector boundaries +Total free space is 41942973 sectors (20.0 GiB) + +Number Start (sector) End (sector) Size Code Name + + + +#再次分区 +[root@zutuanxue ~]# gdisk /dev/sdc +GPT fdisk (gdisk) version 1.0.3 + +Partition table scan: + MBR: protective + BSD: not present + APM: not present + GPT: present + +Found valid GPT with protective MBR; using GPT. + +Command (? for help): n +Partition number (1-128, default 1): 1 +First sector (34-41943006, default = 2048) or {+-}size{KMGTP}: +Last sector (2048-41943006, default = 41943006) or {+-}size{KMGTP}: +2G +Current type is 'Linux filesystem' +Hex code or GUID (L to show codes, Enter = 8300): +Changed type of partition to 'Linux filesystem' + +Command (? for help): p +Disk /dev/sdc: 41943040 sectors, 20.0 GiB +Model: VMware Virtual S +Sector size (logical/physical): 512/512 bytes +Disk identifier (GUID): 7CA4232A-4A9E-467D-AADD-BB84DB2126E3 +Partition table holds up to 128 entries +Main partition table begins at sector 2 and ends at sector 33 +First usable sector is 34, last usable sector is 41943006 +Partitions will be aligned on 2048-sector boundaries +Total free space is 37748669 sectors (18.0 GiB) + +Number Start (sector) End (sector) Size Code Name + 1 2048 4196351 2.0 GiB 8300 Linux filesystem +Command (? for help): w + +Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING +PARTITIONS!! + +Do you want to proceed? (Y/N): y +OK; writing new GUID partition table (GPT) to /dev/sdc. +The operation has completed successfully. + + +[root@zutuanxue ~]# partprobe /dev/sdc + +2.创建文件系统(格式化)CentOS8默认使用xfs +[root@zutuanxue ~]# mkfs.xfs -f /dev/sdc1 + + +3.挂载 +[root@zutuanxue ~]# mkdir /disk1 +[root@zutuanxue ~]# mount -t xfs -o ro /dev/sdc1 /disk1 //手动挂载 +[root@zutuanxue ~]# umount /disk1 ##卸载 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/LVM\351\200\273\350\276\221\345\215\267\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/LVM\351\200\273\350\276\221\345\215\267\344\273\213\347\273\215.md" new file mode 100644 index 0000000..cee7060 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/LVM\351\200\273\350\276\221\345\215\267\344\273\213\347\273\215.md" @@ -0,0 +1,35 @@ +在分区的时候,每个分区应该分多大是令人头疼的,而且随着长时间的运行,分区不管你分多大,都会被数据给占满。当遇到某个分区不够用时管理员可能甚至要备份整个系统、清除硬盘、重新对硬盘分区,然后恢复数据到新分区。 + +虽然现在有很多动态调整磁盘的工具可以使用,但是它并不能完全解决问题,因为某个分区可能会再次被耗尽;另外一个方面这需要重新引导系统才能实现,对于很多关键的服务器,停机是不可接受的,而且对于添加新硬盘,希望一个能跨越多个硬盘驱动器的文件系统时,分区调整程序就不能解决问题。 + +因此完美的解决方法应该是在零停机前提下可以自如对文件系统的大小进行调整,可以方便实现文件系统跨越不同磁盘和分区。那么我们可以通过逻辑盘卷管理(LVM,Logical Volume Manager)的方式来非常完美的实现这一功能。 + +解决思路:将所有可用存储汇集成池,当池中某个分区空间不够时就会从池中继续划分空间给分区,池中空间不够就可以通过加硬盘的方式来解决。 + +## 一、逻辑卷介绍 + +逻辑卷(LVM):它是Linux环境下对磁盘分区进行管理的一种机制,它是建立在**物理存储设备**之上的一个抽象层,优点在于**灵活**管理。 +**特点:** +1、动态在线扩容 +2、离线裁剪 +3、数据条带化 +4、数据镜像 + +## 二、名词解释: + +![lvm.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602992183885.png) + +- 物理卷 + 物理卷就是指硬盘分区或从逻辑上与磁盘分区具有同样功能的设备(如RAID),是LVM的基本存储逻辑块,但和基本的物理存储介质(如分区、磁盘等)比较,却包含有与LVM相关的管理参数 +- 卷组 + LVM卷组类似于非LVM系统中的物理硬盘,其由物理卷组成。可以在卷组上创建一个或多个“LVM分区”(逻辑卷),LVM卷组由一个或多个物理卷组成。 +- 逻辑卷 + LVM的逻辑卷类似于非LVM系统中的硬盘分区,在逻辑卷之上可以建立文件系统(比如/home或者/usr等)。 +- PE + 每一个物理卷被划分为称为PE(Physical Extents)的基本单元,具有唯一编号的PE是可以被LVM寻址的最小单元。PE的大小是可配置的,默认为4MB。 +- LE + 逻辑卷也被划分为被称为LE(Logical Extents) 的可被寻址的基本单位。在同一个卷组中,LE的大小和PE是相同的,并且一一对应。 + +## 三、逻辑卷使用流程 + +真实的物理设备---->物理卷(pv)---->卷组(vg)---->逻辑卷(lv)------>逻辑卷格式化---->挂载使用 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\345\221\275\344\273\244\350\241\214\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\345\221\275\344\273\244\350\241\214\344\273\213\347\273\215.md" new file mode 100644 index 0000000..c75ca70 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\345\221\275\344\273\244\350\241\214\344\273\213\347\273\215.md" @@ -0,0 +1,75 @@ +# Linux命令行介绍 + + 阅读 (246299) + + 分享 + +## 一、命令行的介绍 + +命令行界面(英语:command-line interface,缩写:CLI)是在图形用户界面得到普及之前使用最为广泛的用户界面,它通常不支持鼠标,用户通过键盘输入指令,计算机接收到指令后,予以执行。也有人称之为字符用户界面CUI。通常认为,命令行界面(CLI)没有图形用户界面GUI那么方便用户操作。因为,命令行界面的软件通常需要用户记忆操作的命令,但是,由于其本身的特点,命令行界面要较图形用户界面节约计算机系统的资源。在熟记命令的前提下,使用命令行界面往往要较使用图形用户界面的操作速度要快。所以,图形用户界面的操作系统中,都保留着可选的命令行界面。另外Linux 系统的优势基因还是快速、批量、自动化、智能化管理系统及处理业务。和Windows系统使用鼠标点击的可视化管理大不相同 ,Linux通过键盘输入指令就可以完成管理系统的相关操作。说完命令行,我们来看下命令提示符 + +## 二、命令提示符的介绍 + +当我们打开终端时,不论是在图形界面还是在字符界面,我们看到的格式都是类似于[root@localhost ~]#这种格式的一串字符,这串字符就是命令提示符 + +![1570783019496.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602388003591.png) + +提示符组成详解: + +``` +root:当前用户的名称 + +@:分隔符 + +localhost:当前主机的主机名 + +~:用户当前所在的目录名称 “~”表示为用户家目录(发音tilde[ˈtɪldə]) + +#: 用户身份提示符,#表示超级用户,也就是管理员;$表示普通用户 (发音pound[paʊnd]) +``` + +## 三、命令的语法格式 + +命令+选项+操作对象这三部分是组成了一个标准的linux命令,其中命令部分需要输入命令的名称;选项部分定义命令的执行特性,可以有长短两种选项,长选项用“ --” (发音dash[dæʃ])引导,后面跟完整的单词,如 --help;短选项用 ‘- ’引导,后面跟单个的字符, 如 -a 。多个短选项可以组合使用,例如:-h -l -a == -hla,但是长选项不能组合使用,如 --help后面就不能再跟另外一个单词了。 + +![1570784712025.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602388105934.png) + +但是大家需要注意,命令与选项,选项与选项,选项与操作对象,操作对象与操作对象他们之间是必须用空格分隔!至于操作对象就是图片中的/boot,操作对象是可以有多个的 + +![1570784853770.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602388129124.png) + +语法格式我们就介绍完了,咱们接着往下看 + +## 四、如何高效的输入命令 + +想提高命令的输入效率除了要提升命令的熟练度之外,还要掌握我们上节课所学的快捷键,这样能让你在输入命令是更得心应手。 +那如何提升命令熟练度呢? + +- 就要会查看命令的说明,只有看懂了才能记住,记住了才能熟练 +- 使用tab键查询或补全 + +### 4.1、如何快速获取命令的帮助说明 + +在linux中获取命令的帮助说明的途径很多,这里面给大家简单介绍几个 + +a、help命令可以帮助我们获取到内建命令的使用帮助 + +![1570785422297.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602388151270.png) + +b、–help参数 + +![1570785480088.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602388165544.png) + +c、man手册 + +![1570785620561.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602388192478.png) + +以上这是三种获取帮助的方式,另外还有info、whatis等也可以获取帮助,各位还可以通过一些在线查询工具获取到相关命令的帮助! + +### 4.2、Tab键模糊查询命令 + +a、命令模糊查找:如果你命令记不住了,大概能记得个开头,你可以使用: 命令开头字符+两次tab键找到所有以该命令开头字符的命令,然后就能找到了! + +![命令模糊查找.gif](https://www.zutuanxue.com:8000/static/media/images/2020/11/25/1606275307362.gif) + +b、命令补全: 当你打命令的时候,一般情况下你打出命令的前3-5个字符按一下tab就可以完成命令补全,补全的前提是你打的这些字符可以直接匹配到这个命令。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\345\237\272\346\234\254\344\274\230\345\214\226.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\345\237\272\346\234\254\344\274\230\345\214\226.md" new file mode 100644 index 0000000..5d549c0 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\345\237\272\346\234\254\344\274\230\345\214\226.md" @@ -0,0 +1,123 @@ +## 一、selinux和防火墙优化 + +### 1、SElinux + +selinux 安全增强型 Linux(Security-Enhanced Linux)简称 SELinux,它是一个 Linux 内核模块,也是 Linux 的一个安全子系统。SELinux 主要由美国国家安全局开发。它的主要 作用就是最大限度地减小系统中服务进程可访问的资源(最小权限原则)。也由于它的这个原则,导致我们很多操作无法正确的执行,所以对于初学者而言在会用selinux之前我们要把这个子系统关闭 + +**SELinux 的工作模式** + +SELinux 有三种工作模式,分别是: + +``` +- enforcing:强制模式。违反 SELinux 规则的行为将被阻止并记录到日志中。 + +- permissive:宽容模式。违反 SELinux 规则的行为只会记录到日志中。一般为调试用。 + +- disabled:关闭 SELinux。 +``` + +**SElinux工作模式设置方法** + +- 临时设置 + enforcing 和 permissive 模式可以通过 setenforce 1|0 命令快速切换,重启系统后失效。 +- 永久生效 + SELinux 工作模式可以在 /etc/selinux/config 中设定。 + +``` +如果想从 disabled 切换到 enforcing 或者 permissive 的话,需要重启系统。反过来也一样。 +``` + +需要注意的是,如果系统已经在关闭 SELinux 的状态下运行了一段时间,在打开 SELinux 之后的第一次重启速度可能会比较慢。因为系统必须为磁盘中的文件创建安全上下文,我们现在来看一下如何关闭selinux,首先用root的身份登录系统,打开一个终端输入gedit /etc/selinux/config命令,回车之后会打开一个文件,将所标记出来部分的enforcing改为disabled,保存之后重启linux系统 + +``` +[root@zutuanxue ~]# gedit /etc/selinux/config + +##/etc/selinux/config 内容 +# This file controls the state of SELinux on the system. +# SELINUX= can take one of these three values: +# enforcing - SELinux security policy is enforced. +# permissive - SELinux prints warnings instead of enforcing. +# disabled - No SELinux policy is loaded. +SELINUX=enforcing #这里定义selinux是否为开启状态 + +# SELINUXTYPE= can take one of these three values: +# targeted - Targeted processes are protected, +# minimum - Modification of targeted policy. Only selected processes are protected. +# mls - Multi Level Security protection. +SELINUXTYPE=targeted #这里定义的是selinux保护级别 +``` + +重启登录之后可以使用sestatus -v命令去查看是否成功,如果看到的状态不是disabled则需要重新操作 + +``` +[root@zutuanxue ~]# sestatus -v +SELinux status: disabled +``` + +### 2、防火墙 + +防火墙技术是通过有机结合各类用于安全管理与筛选的软件和硬件设备,帮助计算机网络于其内、外网之间构建一道相对隔绝的保护屏障,以保护用户资料与信息安全性的一种技术。 在CentOS8中使用firewalld作为防火墙,基于iptables的防火墙被默认不启动,但仍然可以继续使用。CentOS8中有几种防火墙共存:firewalld、iptables、ebtables等,默认使用firewalld作为防火墙,通过firewall-cmd工具来管理netfilter,不过底层调用的命令仍然是iptables,虽然防火墙是安全软件,但是它的一些默认设置会对初学者造成困扰,所以我们要先关闭firewalld。通过systemctl stop firewalld.service停止防火墙,systemctl disable firewalld.service禁止防火墙服务开机启动,接下来我们看一下如何设置中文 + +![1571044294838.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602389727708.png) + +## 二、中文设置优化 + +我们在安装系统选择的是中文,但是我们系统当中并没有中文输入法,所以如果要想输入中文的话需要添加中文输入法,以root用户身份登录系统之后我们使用gedit /etc/yum.repos.d/server.repo,输入如下内容保存退出,确保虚拟机的光驱中加载的是CentOS8的光盘镜像,并且已连接 +![1571048414719.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602389773586.png) +![1571047694890.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602389785159.png) + +设置完成之后执行mkdir命令建立目录,然后挂载光盘 + +![1571047821170.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602389813049.png) + +光盘挂载完成之后执行输入法安装命令,如果只要拼音则安装的是: ibus-libpinyin.x86_64 + +``` +# 安装所有支持的输入法 +[root@zutuanxue ~]# dnf install ibus* -y + +# 或者 精准安装拼音输入法 +[root@zutuanxue ~]# dnf install ibus-libpinyin.x86_64 -y +``` + +等待软件包安装完成之后重启系统然后重新登录 + +``` +如果不想重启系统可以使用 + +[root@zutuanxue ~]# ibus restart + +命令重启ibus-daemon进程来实现 +``` + +![1571048752409.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602389829983.png) + +安装完成之后点击右上角的按钮然后点击设置 + +![1571048826875.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602389850869.png) + +在新打开的窗口中找到语言,选择添加,选择汉语,然后选择一个适合自己的中文输入法点击添加之后就可以使用中文输入法了 + +![1571048904227.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602389866470.png) + +![1571049215146.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602389893147.png) + +![1571049244944.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602389909572.png) + +输入法设置完成之后,我们来看下时间相关的设置 + +## 三、网络时间服务器优化 + +如果系统的时间不准,自己手动设置起来比较麻烦,我们可以看下怎么来优化一下 + +同样还是找到设置,在里面找到详细信息,展开之后可以看到日期和时间的设置,两个自动设置的选项打开,如果你的虚拟机可以联网的话,过一会就会看到时间正常了 + +![1571049564017.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602389925235.png) + +![1571049605979.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602389936841.png) +![1571049727212.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602389949009.png) + +## 四、自启动服务优化 + +自启动服务优化的方式类似我们之前提到的停止firewalld,但是首先我们要确认一下有哪些服务是开机启动的,然后利用之前用过的systemctl stop servername和systemctl disabled servername这两条命令停止相应的服务,比如说蓝牙服务和防火墙服务,但是各位需要注意的是,这里面所涉及的服务在你不了解的前提下不要乱停止,否则可能会导致系统功能失灵,甚至是崩溃 +![1571050099841.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602389969693.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\345\237\272\346\234\254\345\221\275\344\273\244\344\270\216\345\270\270\347\224\250\347\254\246\345\217\267.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\345\237\272\346\234\254\345\221\275\344\273\244\344\270\216\345\270\270\347\224\250\347\254\246\345\217\267.md" new file mode 100644 index 0000000..9aaa703 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\345\237\272\346\234\254\345\221\275\344\273\244\344\270\216\345\270\270\347\224\250\347\254\246\345\217\267.md" @@ -0,0 +1,337 @@ +## 一、常用命令介绍 + +在linux系统中存在很多命令,这些命令可以帮助我们完成不同的工作,在这里面我们先介绍一些常用的基础命令,这些命令可以帮助我们完成对应的基本操作,随着以后的学习,我们还会接触到更多可以帮助我们完成不同工作的linux命令,我们来一起看一下这些基础命令都有哪些 + +**1、关机、重启命令** + +**关机命令** + +- init 0 #管理员可以使用 +- halt +- shutdown -h +- poweroff + +**重启命令** + +- shutdown -r +- reboot +- shutdown -r + +强烈推荐:关机或重启命令及步骤 + +``` +1) sync:将缓冲区的数据同步到磁盘中(关机,重启前都需要执行,避免数据丢失),在Linux系统中,当数据需要存入磁盘时,通常会先放到缓冲区内,等到适当的时刻再写入磁盘,如此可提高系统的执行效率 + +2) shutdown: 以一种安全的方式关闭或重启系统。所有登陆用户都可以看到关机信息提示,并且禁止登陆 + + -k 并非真正关机,只向所有人显示警告信息。 + 如:shutdown -k +5 + -r 重启。默认延迟一分钟 + 如:shutdown -r +3 "shutdown in 3 minutes" + -h 关机。默认延迟一分钟 + 如:shutdown -h 12:00/shutdown -h now + -f 重启时跳过磁盘检测。 + -F 重启时强制磁盘检测。 + -c 取消shutdown + +推荐理由: +1、将内存中的数据刷入硬盘,避免因为重启或关机数据没有及时保存而丢失 +2、避免多用户使用突然某个用户强行关机,影响其他用户,使用shutdown关机和重启可以通知其他用户,给予缓冲时间 +``` + +**2、系统信息** + +- uname + +``` +-s 输出内核名称 +-n 输出网络节点上的主机名 +-r 输出内核发行号 +-v 输出内核版本 +-m 输出主机的硬件架构名称 +-p 输出处理器类型或"unknown" +-i 输出硬件平台或"unknown" +-o 输出操作系统名称 +-a 以如下次序输出所有信息。其中若-p和-i的结果不可知则省略 +``` + +- hostname 查看主机名 + +``` +# hostnamectl set-hostname hello +``` + +- date 查看和设置时间 + +``` +时间方面: +%n : 下一行 +%t : 跳格 tab +%H : 小时(00..23) +%I : 小时(01..12) +%k : 小时(0..23) +%l : 小时(1..12) +%M : 分钟(00..59) +%p : 显示本地 AM 或 PM +%r : 直接显示时间 (12 小时制,格式为 hh:mm:ss [AP]M) +%s : 从 1970 年 1 月 1 日 00:00:00 UTC 到目前为止的秒数 +%S : 秒(00..60) +%T : 直接显示时间 (24 小时制) +%X : 相当于 %H:%M:%S +%Z : 显示时区 + + +日期方面: +%a : 星期几 (Sun..Sat) +%A : 星期几 (Sunday..Saturday) +%b : 月份 (Jan..Dec) +%B : 月份 (January..December) +%c : 直接显示日期与时间 +%d : 日 (01..31) +%D : 直接显示日期 (mm/dd/yy) +%h : 同 %b +%j : 一年中的第几天 (001..366) +%m : 月份 (01..12) +%U : 一年中的第几周 (00..53) (以 Sunday 为一周的第一天的情形) +%w : 一周中的第几天 (0..6) +%W : 一年中的第几周 (00..53) (以 Monday 为一周的第一天的情形) +%x : 直接显示日期 (yyyy-mm-dd) +%y : 年份的最后两位数字 (00.99) +%Y : 完整年份 (0000..9999) + + + +[root@zutuanxue ~]# date '+%I%M%S' +025929 +[root@zutuanxue ~]# date '+%r' +上午 02时59分49秒 +[root@zutuanxue ~]# date '+%s' +1584428402 +[root@zutuanxue ~]# date '+%Z' +EDT +[root@zutuanxue ~]# date '+%a' +二 +[root@zutuanxue ~]# date '+%A' +星期二 +[root@zutuanxue ~]# date '+%b' +3月 +[root@zutuanxue ~]# date '+%B' +三月 +[root@zutuanxue ~]# date '+%c' +2020年03月17日 星期二 03时01分36秒 +[root@zutuanxue ~]# date '+%T%n%D' +03:03:35 +03/17/20 +[root@zutuanxue ~]# date '+%T%t%D' +03:03:58 03/17/20 +[root@zutuanxue ~]# date -s 2021-10-25 +2021年 10月 25日 星期一 00:00:00 EDT +[root@zutuanxue ~]# date -s 18:00 +2021年 10月 25日 星期一 18:00:00 EDT +[root@zutuanxue ~]# date -s 18:30:21 +2021年 10月 25日 星期一 18:30:21 EDT +[root@zutuanxue ~]# date -s "2021-04-28 15:30:20" +2021年 04月 28日 星期三 15:30:20 EDT +``` + +**3、文件和目录** + +- cd 目录 进入目录 +- pwd: 查看当前的工作路径 + +``` +-P 显示实际位置 +-L 显示所在位置 + +[root@zutuanxue ~]# cd /etc #进入到/etc这个目录 +[root@zutuanxue ~]# cd / +[root@zutuanxue /]# ls +bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var +[root@zutuanxue /]# cd bin/ +[root@zutuanxue bin]# pwd +/bin +[root@zutuanxue bin]# pwd -P +/usr/bin +[root@zutuanxue bin]# pwd -L +/bin +``` + +- ls: 查看当前目录下有哪些文件 + +``` +-a 列出目录下的所有文件,包括以 . 开头的隐含文件。 +-A 显示除 “.”和“..”外的所有文件。 +-B 不输出以 “~”结尾的备份文件。 +-c 与lt一起使用,显示并按照修改时间(ctime)排序,与l一起使用,显示修改时间,按名称排序。 +-d 将目录象文件一样显示,而不是显示其下的文件。 +-f 对输出的文件不排序,使用此选项后aU选项生效,lst选项失效 +-F 在每个文件名后附上一个字符以说明该文件的类型,“*”表示可执行的普通文件;“/”表示目录;“@”表示符号链接;“|”表示FIFOs;“=”表示套接字(sockets)。 +-g 类似l但是不显示所有者 +-h 与l一起,以易于阅读的格式输出文件大小(例如 1K 234M 2G) +-i 输出文件的i节点的索引信息。 +-k 以k字节的形式表示文件的大小。--si类似k但是以1000为进制而非1024 +-l 列出文件的详细信息。 +-L 遇到链接文件是,显示原文件的信息,而非链接信息 +-m 横向输出文件名,并以“,”作分格符。 +-n 类似l,但是用数字的 UID,GID 代替名称。 +-o 显示文件的除组信息外的详细信息。 +-p 目录后面加上/标识 +-q 用?代替不可输出的字符。 +-r 对目录反向排序。 +-s 在每个文件名后输出该文件的大小。 +-t 以修改时间排序。 +-u 与lt一起使用,以访问时间(atime)排序;与l一起使用显示访问时间,按照名称排序 +-x 按列输出,横向排序。 +-Q 把输出的文件名用双引号括起来。 +-R 列出所有子目录下的文件。 +-S 以文件大小排序。 +-X 以文件的扩展名(最后一个 . 后的字符)排序。 +-1 一行只输出一个文件。 +--color=no 不显示彩色文件名 +--help 在标准输出上显示帮助信息。 +--version 在标准输出上输出版本信息并退出。 +``` + +- mkdir 建立目录 + +``` +-m 设置权限模式(类似chmod) +-p 需要时创建目标目录的上层目录,但即使这些目录已存在也不当作错误处理 +-v 每次创建新目录都显示信息 +-Z 将每个创建的目录的SELinux 安全环境设置为CTX +``` + +- rmdir 删除空文件夹 + +``` +-p 递归删除空目录,从最后一个目录倒删 +``` + +- touch 建立文件 + +``` +-a 只更改访问时间 +-c 不创建任何文件 +-m 只更改修改时间 +-r 使用指定文件的时间属性替代当前时间 +-t 使用[[CC]YY]MMDDhhmm[.ss] 格式的时间替代当前时间 + +[root@zutuanxue ~]# stat hello + 文件:hello + 大小:0 块:0 IO 块:4096 普通空文件 +设备:fd00h/64768d Inode:34502264 硬链接:1 +权限:(0644/-rw-r--r--) Uid:( 0/ root) Gid:( 0/ root) +最近访问:2020-03-17 16:51:35.502961371 -0400 +最近更改:2020-03-17 16:51:35.502961371 -0400 +最近改动:2020-03-17 16:51:35.502961371 -0400 +创建时间:- +[root@zutuanxue ~]# touch -a -t 202002010101.30 hello +[root@zutuanxue ~]# stat hello + 文件:hello + 大小:0 块:0 IO 块:4096 普通空文件 +设备:fd00h/64768d Inode:34502264 硬链接:1 +权限:(0644/-rw-r--r--) Uid:( 0/ root) Gid:( 0/ root) +最近访问:2020-02-01 01:01:30.000000000 -0500 +最近更改:2020-03-17 16:51:35.502961371 -0400 +最近改动:2020-03-17 16:51:53.143475189 -0400 +创建时间:- +[root@zutuanxue ~]# touch -m -t 202002050101.30 hello +[root@zutuanxue ~]# stat hello + 文件:hello + 大小:0 块:0 IO 块:4096 普通空文件 +设备:fd00h/64768d Inode:34502264 硬链接:1 +权限:(0644/-rw-r--r--) Uid:( 0/ root) Gid:( 0/ root) +最近访问:2020-02-01 01:01:30.000000000 -0500 +最近更改:2020-02-05 01:01:30.000000000 -0500 +最近改动:2020-03-17 16:52:07.837453512 -0400 +创建时间:- + + +#将hello-linux.txt的属性改成与anaconda-ks.cfg一样 +[root@zutuanxue ~]# stat hello-linux.txt + 文件:hello-linux.txt + 大小:12 块:8 IO 块:4096 普通文件 +设备:fd00h/64768d Inode:34513350 硬链接:1 +权限:(0644/-rw-r--r--) Uid:( 0/ root) Gid:( 0/ root) +最近访问:2020-03-17 22:50:51.319377144 -0400 +最近更改:2020-03-17 22:50:45.909483733 -0400 +最近改动:2020-03-17 22:50:45.912483674 -0400 +创建时间:- +[root@zutuanxue ~]# stat anaconda-ks.cfg + 文件:anaconda-ks.cfg + 大小:1378 块:8 IO 块:4096 普通文件 +设备:fd00h/64768d Inode:34973658 硬链接:1 +权限:(0600/-rw-------) Uid:( 0/ root) Gid:( 0/ root) +最近访问:2020-03-16 23:08:34.121427663 -0400 +最近更改:2020-02-04 15:01:33.273959663 -0500 +最近改动:2020-03-18 16:33:48.873881970 -0400 +创建时间:- +[root@zutuanxue ~]# touch -r anaconda-ks.cfg hello-linux.txt +[root@zutuanxue ~]# stat hello-linux.txt + 文件:hello-linux.txt + 大小:12 块:8 IO 块:4096 普通文件 +设备:fd00h/64768d Inode:34513350 硬链接:1 +权限:(0644/-rw-r--r--) Uid:( 0/ root) Gid:( 0/ root) +最近访问:2020-03-16 23:08:34.121427663 -0400 +最近更改:2020-02-04 15:01:33.273959663 -0500 +最近改动:2020-03-18 18:22:48.694597233 -0400 +创建时间:- +``` + +- cat 查看文件内容 + +``` +-A 等价于-vET +-b 对非空输出行编号 +-e 等价于-vE +-E 在每行结束处显示$ +-n 对输出的所有行编号 +-s 不输出多行空行 +-t 与-vT等价 +-T 将跳格字符(tab)显示为 ^I +-v 使用^和M +``` + +- rm 删除文件或目录 + +``` +-f 强制删除。忽略不存在的文件,不提示确认 +-i 在删除前需要确认 +-I 超过三个文件或者递归删除前要求确认。比-i提示内容更少 +-d 删除空目录 +-r 递归删除目录及其内容 +``` + +这些命令都是初学者可能会经常用到的,大家可以在自己的虚拟机上练习一下 + +- cp 拷贝 + +``` +-i 覆盖前询问(使前面的 -n 选项失效) +-n 不要覆盖已存在的文件(使前面的 -i 选项失效) +-R, -r, --recursive 递归复制目录及其子目录内的所有内容 +-s 只创建符号链接而不复制文件 +-f 强制,将目标文件无法打开则将其移除并重试 +``` + +- mv 移动/改名 + +``` +-f 覆盖前不询问 +-i 覆盖前询问 +-n 不覆盖已存在文件 +#如果您指定了-i、-f、-n 中的多个,仅最后一个生效。 +``` + +## 二、常用符号 + +``` + +* 任意字符串 + +? 任意字符 + +/ 路径间隔符 + +~ 当前用户的家目录 管理员家目录为/root,其它用户的家目录在/home/用户名 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\346\234\215\345\212\241\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\346\234\215\345\212\241\344\273\213\347\273\215.md" new file mode 100644 index 0000000..d4f7641 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\346\234\215\345\212\241\344\273\213\347\273\215.md" @@ -0,0 +1,94 @@ +什么是服务?在linux系统中,有一些特殊程序,启动后就会持续在后台执行,等待用户或者其他软件调用使用,这种程序我们称为服务。 + +linux系统中服务的管理工具 + +- systemV +- systemd + +## 一、systemV与init + +systemV,systemV当中有一个叫init的程序,这个程序可以让系统中的service命令去调用/etc/init.d/目录下的服务脚本,我们可以通过service命令去控制服务的启动与关闭,或者找到服务相应的执行文件,然后执行,比如/usr/sbin/httpd,这样才能启动一个服务,如果想要停止一个服务则需要使用kill命令去停止 +该服务管理方式从RHEL7之前的系统中默认 + +### init的特点 + +- 启动/停止/查看 + /etc/init.d/servername start/stop/restart/status + ​ 或 + ​service servername start/stop/restart/status +- 开机启动管理与查看 + chkconfig --level 0-6 servername on/off 指定一个服务在哪个运行级别启动 + chkconfig --list servername 查看一个服务在哪些运行级别启动 + +#### 分类 + +按照功能分类 + +- 系统服务:这些服务的服务对象是linux系统本身,或者linux系统的用户 +- 网络服务:网络服务的服务对象是网络中的其他客户端 + +按照启动方法分类 + +- 独立系统服务:这类服务一经启动,除非系统关闭或者管理者手动结束,否则会一直在后台执行,不管是否用到。由于这类服务一直在后台执行,所以响应速度快,同时也会占用系统资源 +- 临时服务:跟独立的服务不同,临时服务是用到的时候启动,使用完毕后服务会停止,所以临时服务响应速度慢,但是节省系统资源 + +##### 手动解决服务的依赖关系 + + 服务之间是有依赖关系的,比如说,联网的服务如果想正常运行的话,就必须启动网络服务。而这些服务就需要用户手动去处理 + +#### 运行级别分类 + + init会根据用户指定的运行级别,来启动不同的服务,在linux系统中包含了0-6,一共7个运行级别 + +0 关机 + +1 单用户 + +2 无网络的多用户 + +3 字符模式 + +4 保留 + +5 图形模式 + +6 重启 + +## 二、systemd与unit + +从CentOS7开始SystemV,也就是init服务,被效率更高的systemd所替代,而这个systemd对应的管理命令就是systemctl,并且systemctl命令也兼容了service(service命令做为systemd的入口,是systemctl命令的封装)。 + +#### systemd的优势 + +- 并行处理所有服务,缩短开机时间 +- 响应速度快,通过systemctl命令就可以完成所有操作 +- 自动解决服务的依赖关系,类似yum +- 方便记忆,按照类型对服务进行分类 +- 兼容init + +#### 相关文件 + +/usr/lib/systemd/system/ 服务的启动脚本,包含所有安装完成的服务设置文件 + +/run/systemd/system/ 系统运行过程中的服务脚本优先级高于上一个文件 + +/etc/systemd/system/ 管理员手动建立的服务启动脚本,优先级最高 + +/etc/sysconfig/* 系统功能的默认设置 + +#### 服务分类 + +``` +[root@zutuanxue ~]# systemctl -t help +service 服务单元,用于控制服务 +socket 套接字单元,用于进程间通信 +target 目标单元,用于控制一组其它单元 +device 设备单元,用于控制动态的设备 +mount 挂载单元,用于管理文件系统挂载点 +automount 自动挂载单元,用于管理文件系统自动挂载点 +swap 交换分区单元,用于管理swap设备或swap文件 +timer 定时器单元,用于管理基于时间触发的动作 +path 路径单元,用于监视文件系统路径,以用于基于路径的启动 +slice 范围单元,用于管理与控制一组特定进程的资源占用 +scope 范围单元,与service类似,系统自动创建 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\347\211\271\346\256\212\346\235\203\351\231\220.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\347\211\271\346\256\212\346\235\203\351\231\220.md" new file mode 100644 index 0000000..8a4b350 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\347\211\271\346\256\212\346\235\203\351\231\220.md" @@ -0,0 +1,59 @@ +linux基本权限只是规定了所有者、属组、其他人三种用户的权限,如果希望对文件或文件夹做一些特殊的权限设置呢? +比如: + +- 设置属组继承权限 +- 为执行文件设置临时超管执行权限 +- 公共文件夹中的文件谁建立谁删除 + 这些任务基本权限就解决不聊了,需要解决这个问题得靠特殊权限。 + +## 一、特殊权限的介绍 + +之前我们提到了特殊权限有三个,这三个特殊权限是在可执行程序运行时影响操作权限的,它们分别是SUID,SGID,sticky-bit位 + +| 特殊权限 | 说明 | +| --------- | ------------------------------------------------------------ | +| SUID | 当一个设置了SUID 位的可执行文件被执行时,该文件将以所有者的身份运行,也就是说无论谁来执行这个文件,他都有文件所有者的特权。任意存取该文件拥有者能使用的全部系统资源。如果所有者是 root 的话,那么执行人就有超级用户的特权了。 | +| SGID | 当一个设置了SGID 位的可执行文件运行时,该文件将具有所属组的特权,任意存取整个组所能使用的系统资源;若一个目录设置了SGID,则所有被复制到这个目录下的文件,其所属的组都会被重设为和这个目录一样,除非在复制文件时保留文件属性,才能保留原来所属的群组设置。 | +| stickybit | 对一个文件设置了sticky-bit之后,尽管其他用户有写权限,也必须由属主执行删除、移动等操作;对一个目录设置了sticky-bit之后,存放在该目录的文件仅准许其属主执行删除、移动等操作。 | + +一个典型的例子就是passwd命令,这个命令允许用户修改自己的密码。我们可以看到本来是rwx的权限表示形式变成了rws,同样如果/usr/bin/passwd这个文件同时被设置了三个特殊权限,那么权限的格式就会变成rwsrwsrwt,需要注意的是特殊权限设置的前置要求是可执行,也就是如果没有x权限位,是不要设置的,即便你使用root用户设置上了特殊权限,也不会生效。 + +``` +[root@zutuanxue test]# ll /usr/bin/passwd +-rwsr-xr-x. 1 root root 34928 5月 11 11:14 /usr/bin/passwd +``` + +## 二、特殊权限的设置和查看 + +**特殊权限的设置也是使用chmod** + +``` +[root@zutuanxue test]# ll +总用量 0 +-rwxr-xr-x 1 oracle oracle 0 10月 18 01:26 file1 +[root@zutuanxue test]# chmod u+s file1 +[root@zutuanxue test]# ll +总用量 0 +-rwsr-xr-x 1 oracle oracle 0 10月 18 01:26 file1 +[root@zutuanxue test]# chmod g+s file1 +[root@zutuanxue test]# ll +总用量 0 +-rwsr-sr-x 1 oracle oracle 0 10月 18 01:26 file1 +[root@zutuanxue test]# chmod o+t file1 +[root@zutuanxue test]# ll +总用量 0 +-rwsr-sr-t 1 oracle oracle 0 10月 18 01:26 file1 +``` + +或者使用数字 + +``` +[root@zutuanxue test]# chmod u-s,g-s,o-t file1 +[root@zutuanxue test]# ll +总用量 0 +-rwxr-xr-x 1 oracle oracle 0 10月 18 01:26 file1 +[root@zutuanxue test]# chmod 7755 file1 +[root@zutuanxue test]# ll +总用量 0 +-rwsr-sr-t 1 oracle oracle 0 10月 18 01:26 file1 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\347\233\256\345\275\225\347\273\223\346\236\204\345\222\214\346\226\207\344\273\266\345\261\236\346\200\247\347\256\241\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\347\233\256\345\275\225\347\273\223\346\236\204\345\222\214\346\226\207\344\273\266\345\261\236\346\200\247\347\256\241\347\220\206.md" new file mode 100644 index 0000000..858420b --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\347\233\256\345\275\225\347\273\223\346\236\204\345\222\214\346\226\207\344\273\266\345\261\236\346\200\247\347\256\241\347\220\206.md" @@ -0,0 +1,92 @@ +## 一、FHS介绍 + +Filesystem Hierarchy Standard(文件系统层次化标准)的缩写,多数Linux版本采用这种文件组织形式,类似于Windows操作系统中c盘的文件目录,FHS采用树形结构组织文件。FHS定义了系统中每个区域的用途、所需要的最小构成的文件和目录,同时还给出了例外处理与矛盾处理。 + +FHS定义了两层规范,第一层是, / 下面的各个目录应该要放什么文件数据,例如/etc应该要放置设置文件,/bin与/sbin则应该要放置可执行文件等等。第二层则是针对/usr及/var这两个目录的子目录来定义。例如/var/log放置系统登录文件、/usr/share放置共享数据等等。 + +## 二、linux目录结构介绍 + +整个Linux系统最重要的地方就是在于目录树架构,所谓的目录树架构就是以根目录为主, 然后向下呈现分支状的目录结构的一种档案架构。下图给出了linux的目录结构,那这些目录都有什么作用呢? + +![1571118994639.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602390979455.png) + +## 三、linux目录的作用 + +- **根目录(/)** + +最高一级目录,所有目录都是根目录衍生出来,只有root用户具有写权限,一般根目录下只存放目录,不要存放件 + +- **/bin目录 – 用户二进制文件** + +包含二进制的可执行文件,你需要的常见的Linux命令都位于此目录下。 + +- **/sbin目录 – 系统二进制文件** + +这个目录下的命令通常由系统管理员使用, 对系统进行维护。 + +- **/etc– 配置文件** + +包含所有程序所需要的配置文件,也包含用于启动/停止单个程序的起动和关闭shell脚本。 + +- **/dev-设备文件** + +包含设备文件,包括终端设备、USB或连接到系统的任何设备,如网卡等。 + +- **/proc-进程信息文件** + +这是一个虚拟的文件系统,包含有关正在运行的进程信息。 + +- **/usr-用户程序** + +包含二进制文件、库文件、文档和二级程序的源代码。 + +``` +/usr/bin中包含用户程序的二进制文件。如果你在/bin中找不到用户二进制文件,到/usr/bin目录看看。 +/usr/sbin中包含系统管理员的二进制文件。如果你在/sbin中找不到系统二进制文件,到/usr/sbin目录看看。 +/usr/lib中包含了/usr/bin和/usr/sbin用到的库。 +/usr/local中包含了从源安装的用户程序。 +``` + +- **/home -HOME目录** + +包含所有用户的个人档案,Linux是多用户的系统,所以用该目录保存各用户的信息。 + +- **/boot -引导加载程序** + +包含引导加载程序相关的文件。 + +- **/lib -系统库** + +包含支持位于/lib和/sbin下的二进制文件的库文件。 + +- **/opt -可选的附加应用程序** + +给主机额外安装软件所摆放的目录,以前的 Linux 系统中,习惯放置在 /usr/local 目录下 + +- **/mnt /media -挂载目录** + +光盘默认挂载点,通常光盘挂载于 /mnt/cdrom 下,也不一定,可以选择任意位置进行挂载。 + +- **/root** 管理员家目录 + +在这里我们所介绍的目录是在linux系统中常见的目录,不同厂商的linux有所差异,有的版本中会出现有额外作用的目录,这个就需要具体问题具体对待了。 + +## 四、目录和设备节点 + +我们已经知道目录是用来存放文件的,不同的目录存放的文件作用不同,那么我们来看下设备节点是什么? 一个设备节点其实就是一个文件,Linux中称为设备文件。有一点必要说明的是,在Linux中,**所有的设备访问都是通过文件的方式,一般的数据文件程序普通文件,设备节点称为设备文件**,而这些设备节点,或者说是设备文件都统一存放在/dev目录下,简单来说,设备节点是一种特殊的文件,只不过这个文件存放的不是一般的数据,而是和你计算机中的设备相关联的。 + +## 五、.和… + +在linux系统中,使用ls -a命令时,你会发现每一个目录下都包含两个目录,这两个目录就是.和…,其中".“表示是的是当前目录,也就是你使用pwd所查看到的路径,而”…"表示的上一级目录,也就是父目录。 + +## 六、绝对路径和相对路径 + +linux的路径书写方式有两种: + +- 绝对路径:路径的写法一定是由根目录 / 写起的,以根目录为起点; +- 相对路径:路径的写法不是由根目录 / 写起的,不以根目录为起点。 + +例如,你知道你的朋友在四楼,而你在五楼,如果你的朋友询问你的位置,你就有两种回答方式: + +- 绝对路径的方式就是你告诉对方你在XX小区的xx号楼的五楼, +- 相对路径的方式就是你告诉对方你在对方五楼。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\347\263\273\347\273\237\347\233\221\346\216\247\345\267\245\345\205\267-glances.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\347\263\273\347\273\237\347\233\221\346\216\247\345\267\245\345\205\267-glances.md" new file mode 100644 index 0000000..1a799a8 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\347\263\273\347\273\237\347\233\221\346\216\247\345\267\245\345\205\267-glances.md" @@ -0,0 +1,256 @@ +## 一、glances介绍 + +glances是一个基于python语言开发,可以为linux或者UNIX性能提供监视和分析性能数据的功能。glances在用户的终端上显示重要的系统信息,并动态的进行更新,让管理员实时掌握系统资源的使用情况,而动态监控并不会消耗大量的系统资源,比如CPU资源,通常消耗小于2%,glances默认每两秒更新一次数据。同时glances还可以将相同的数据捕获到一个文件,便于以后对报告进行分析和图形绘制,支持的文件格式有.csv电子表格格式和和html格式。 + +glances可以分析系统的: + +- CPU使用率 +- 内存使用率 +- 内核统计信息和运行队列信息 +- 磁盘I/O速度、传输和读/写比率 +- 磁盘适配器 +- 网络I/O速度、传输和读/写比率 +- 页面监控 +- 进程监控-消耗资源最多的进程 +- 计算机信息和系统资源 + +## 二、glances安装方式 + +1. 源码安装 +2. 基于pip命令安装 +3. 基于epel公网yum源 + +由于源码安装需要解决大量的依赖包的问题,对于小白同学学习压力较大,所以本文将重点介绍基于yum的安装方法,让大家快速安装,并能及时体验到glances监控的强大和高效。 + +## 三、基于epel公网源安装glances + +由于glances运行需要python环境,所以我们需要首先安装好python环境,这里我给大家使用的是一个脚本安装python3.7.3,目前的最新版本。 + +#### 3.1、python3.7.3安装脚本 + +``` +#!/bin/bash +# +#Name: +#Author: zutuanxue_com +#Created Time: 2019/10/1 11:20 +#Release: +#Description:python 3.7.3安装脚本 + +#变量 +source_url="https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tgz" +source_pkg="Python-3.7.3.tgz" +source_doc="Python-3.7.3" + +cpu_count=`egrep "flags" /proc/cpuinfo |wc -l` + +#程序 +check () { + [ "$USER" != "root" ]&&echo "need be root so that"&&exit 1 + [ ! -x /usr/bin/wget ]&&echo "not found command: wget"&&exit 1 +} + + +install_python () { + +check + +#1、download python source package +if ! (wget $source_url &>/dev/null) ;then + echo "$source_pkg download fail" + exit 1 +fi +#2、Decompression source package +if [ -f $source_pkg ];then + tar xf $source_pkg +else + echo "not found package: $source_pkg" + exit 1 +fi + +#3、python install pre +if ! (yum -y install gcc-* openssl-* libffi-devel curses-devel lm_sensors sqlite-devel &>/dev/null);then + echo "yum install software package fail" + exit 1 +fi + + + +#4、configure python install env +if [ -d $source_doc ];then + + + #5、python configure + cd $source_doc + + sed -i.bak '212s/#//' Modules/Setup.dist + sed -i '213s/#//' Modules/Setup.dist + sed -i '214s/#//' Modules/Setup.dist + + echo "python configure...please waiting" + if ./configure --enable-optimizations --with-openssl=/usr/bin/openssl &>/dev/null ;then + + #6、python make + echo "python make...please waiting" + if make -j $cpu_count &>/dev/null ;then + + #7、python install + echo "python install...please waiting" + if make install & > /dev/null;then + echo "$source_doc install success" + else + echo "python make install fail" + exit 1 + fi + else + echo "python make fail" + exit 1 + fi + else + echo "python configure fail" + exit 1 + fi +else + echo "not found $source_doc" + exit 1 +fi + + +post_install + +} + + +#Post-installation settings +post_install () { +#update pip tool +pip3 install --upgrade pip + +} + + +#函数调用 + +install_python && rm -rf $source_doc +``` + +#### 3.2、glances 安装 + +``` +[root@manager01 ~]# pip install glances +Collecting glances + Downloading https://files.pythonhosted.org/packages/32/34/72f9202ad5b7ada314507a50b9ab1fb604d2f468b138679e0a4fedeb91fa/Glances-3.1.0.tar.gz (6.7MB) + |████████████████████████████████| 6.7MB 659kB/s +Collecting psutil>=5.3.0 (from glances) + Downloading https://files.pythonhosted.org/packages/1c/ca/5b8c1fe032a458c2c4bcbe509d1401dca9dda35c7fc46b36bb81c2834740/psutil-5.6.3.tar.gz (435kB) + |████████████████████████████████| 440kB 575kB/s +Installing collected packages: psutil, glances + Running setup.py install for psutil ... done + Running setup.py install for glances ... done +Successfully installed glances-3.1.0 psutil-5.6.3 +``` + +#### 3.3、温度监控工具安装 + +``` +[root@manager01 ~]# yum -y install lm_sensors +``` + +#### 3.4、epel公网源安装 + +``` +[root@manager01 ~]# yum install epel* -y +[root@manager01 ~]# yum -y install glances +``` + +## 四、glances监控 + +#### 4.1、开启glances监控 + +``` +[root@manager01 ~]# glances +``` + +![glances_1.png](https://www.zutuanxue.com:8000/static/media/images/2020/12/7/1607301391828.png) + +**glances 工作界面的说明 :** +在上图 的上部是 CPU 、Load(负载)、Mem(内存使用)、 Swap(交换分区)的使用情况。在上图的中上部是网络接口、Processes(进程)的使用情况。通常包括如下字段: + +``` + %CPU:该进程占用的 CPU 使用率 + %MEM:该进程占用的物理内存和总内存的百分比 + VIRT: 虚拟内存大小 + RES: 进程占用的物理内存值 + PID: 进程 ID 号 + USER: 进程所有者的用户名 + NI: 进程优先级 + S: 进程状态,其中 S 表示休眠,R 表示正在运行,Z 表示僵死状态。 + TIME+: 该进程启动后占用的总的 CPU 时间 + IO_R 和 IO_W: 进程的读写 I/O 速率 + Command: 进程名称 +``` + +在上图的左侧是网络、磁盘IO、磁盘分区使用情况。 另外 glances 可以使用交互式的方式运行该工具,用户可以使用如下快捷键: + +``` + h : 显示帮助信息 + q : 离开程序退出 + c :按照 CPU 实时负载对系统进程进行排序 + m :按照内存使用状况对系统进程排序 + i:按照 I/O 使用状况对系统进程排序 + p: 按照进程名称排序 + d : 显示磁盘读写状况 + w : 删除日志文件 + l :显示日志 + s: 显示传感器信息 + f : 显示系统信息 + 1 :轮流显示每个 CPU 内核的使用情况(次选项仅仅使用在多核 CPU 系统) +``` + +#### 4.2、glances 使用方法 + +``` + glances 是一个命令行工具包括如下命令选项: + -b:显示网络连接速度 Byte/ 秒 + -B @IP|host :绑定服务器端 IP 地址或者主机名称 + -c @IP|host:连接 glances 服务器端 + -C file:设置配置文件默认是 /etc/glances/glances.conf + -d:关闭磁盘 I/O 模块 + -e:显示传感器温度 + -f file:设置输出文件(格式是 HTML 或者 CSV) + -m:关闭挂载的磁盘模块 + -n:关闭网络模块 + -p PORT:设置运行端口默认是 61209 + -P password:设置客户端 / 服务器密码 + -s:设置 glances 运行模式为服务器 + -t sec:设置屏幕刷新的时间间隔,单位为秒,默认值为 2 秒,数值许可范围:1~32767 + -h : 显示帮助信息 + -v : 显示版本信息 +``` + +## 五、glances C/S模式 + +glances还支持C/S模式监控,被监控机运行服务端,监控端运行客户端既可以实现远程监控。 + +![glances_cs.png](https://www.zutuanxue.com:8000/static/media/images/2020/12/7/1607301423160.png) + +注意:C/S模式都必须安装glances才可以实现 + +#### 5.1、服务端启动 + +**服务端使用的端口默认是61209,如果使用服务端请注意开启防火墙。** +![glances_服务端.png](https://www.zutuanxue.com:8000/static/media/images/2020/12/7/1607301474604.png) + +#### 5.2、客户端访问 + +``` +[root@zutuanxue ~]# glances -c 192.168.10.100 +``` + +## 六、其他数据保存方式 + +#### 6.1、导出数据为CSV电子表格 + +``` +[root@manager01 ~]# glances --export-csv /tmp/1.csv +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\347\273\210\347\253\257\347\232\204\344\275\277\347\224\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\347\273\210\347\253\257\347\232\204\344\275\277\347\224\250.md" new file mode 100644 index 0000000..e833166 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/Linux\347\273\210\347\253\257\347\232\204\344\275\277\347\224\250.md" @@ -0,0 +1,65 @@ +## 一、终端的作用 + +要了解终端,就要了解一下计算机方面的历史,早期的计算机都属于大中型计算机,是个庞然大物,占用很大的空间,属于公用产品。不像现在的电脑,可以人手一部,直接操作。那如何对这些计算机进行控制与操作呢。那就搞个终端设备来操作。因此一台计算机上有很多种不同的终端设备也和正常。也就是说终端就是为主机提供了人机接口,每个人都通过终端使用主机的资源。 + +终端有字符终端和图形终端两种模式。在linux的图形环境下,我们可以通过鼠标点击来完成所有的管理任务,这是图形界面终端,另外一种就是文本界面的终端,在这个界面的终端下我们可以使用linux命令来控制系统完成响应的工作,而这个文本终端也是服务器常用的模式。 + +用一句话来说终端就是存在于用户和计算机之间沟通的桥梁,通过终端,用户可以控制计算机完成响应的工作,也可以获得到计算机的反馈 + +## 二、打开终端的几种方法 + +第一种,我们登录系统之后就已经打开了图形终端,在图形终端中也给我们提供了一个可以用linux命令控制系统的工具,我们点击屏幕左上角的“活动”就可以找到这个它 + +![1570773103451.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602387773855.png) + +打开之后我们会看到linux的命令行,在这里面我们可以输入linux命令来进行操作 + +![1570773158443.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602387794098.png) + +第二种 打开文本终端,这个需要键盘上的组合键[Ctrl] + [Alt] + [F1] - [F6] ,其中F1和F2是两个可供登录的图形终端,F3-F6为文本终端,现在我们使用[Ctrl] + [Alt] + [F3]打开文本终端,然后使用root用户登录 + +![1570773655859.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602387807896.png) + +这就是在linux中终端的打开方式,那我们接下来看一下有哪些快捷键 + +## 三、常用快捷键 + +1、图形界面下通过点击屏幕右上角的“活动”按钮打开的终端 + +``` +[Shift]+[Ctrl]+t 以标签的形式打开一个新的终端 + +[Shift]+[Ctrl]+n 以窗口的形式打开一个新的终端 + +[Shift]+[Ctrl]+w 关闭标签页 + +[Shift]+[Ctrl]+q 关闭窗口 +``` + +如果你想知道额外的快捷键,点击终端上方的文字按钮,会有对应快捷键的提示 + +![1570774251987.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602387826764.png) + +2、通用快捷键 + +```powersheall +Ctrl+r: 实现快速检索使用过的历史命令. +Ctrl+a: 光标回到命令行首。 +Ctrl+e: 光标回到命令行尾。 +ctrl+w: 移除光标前的一个单词 +Ctrl+k: 删除光标处到行尾的字符。 +Ctrl+u: 删除整个命令行文本字符。 +Ctrl+y: 粘贴Ctrl+u,Ctrl+k,Ctrl+w删除的文本。 +Ctrl+d: 删除提示符所在出的一个字符,在空命令行的情况下可以退出终端。 +esc+. : 上一个命令的后面的参数 +Ctrl+b: 光标向行首移动一个字符。 +Ctrl+f: 光标向行尾移动一个字符。 +Ctrl+h: 向行首删除一个字符。 +Ctrl+i: 相当于Tab键。 +Ctrl+L: 清屏 +Ctrl+s: 使终端发呆,静止,可以使快速输出的终端屏幕停下来。 +Ctrl+q: 退出Ctrl+s引起的发呆。 +Ctrl+z: 使正在运行在终端的任务,运行于后台。 (可用fg恢复) +Ctrl+c: 中断终端中正在执行的任务。 +Tab键: 命令、文件名等自动补全功能。 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/VIM\346\226\207\346\234\254\347\274\226\350\276\221\345\231\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/VIM\346\226\207\346\234\254\347\274\226\350\276\221\345\231\250.md" new file mode 100644 index 0000000..d4cf184 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/VIM\346\226\207\346\234\254\347\274\226\350\276\221\345\231\250.md" @@ -0,0 +1,260 @@ +## 一、vim使用介绍 + +**vim介绍** + +在linux系统中,大部分配置文件都是ASCII的纯文本形式存放的,所以我们在修改系统设置的时候使用简单的文本编辑软件就可以实现了,如果你使用过windows当中的word的话,那么你可能会感觉linux字符界面的文本编辑工具并不是太好用,毕竟没有图形窗口,看着不会太舒服。但是既然要学习linux,掌握并熟练使用文本编辑工具是必不可少的技能,在linux当中的文本编辑工具有很多,如emacs pico nano joe vi/vim 等等 + +既然有这么多文本编辑工具,为什么要学习vi/vim呢? + +**为什么要使用vim?** + +虽然在linux下的文本编辑器众多,这些工具都有各自的优点,但是有几点是其它编辑工具所不能比拟的 + +- 所有的类Unix系统都内建vi,其它的编辑工具则不一定,而vim相当于是vi的升级版 +- 很多软件的编辑界面都会调用vi,如后面提到的crontab、edquota等 +- vim具有程序编辑能力,可以主动以字体颜色标识语法的正确性,方便代码编写 +- 程序简单,编辑速度非常快 + +综上所述这是一个老式的文字处理工具,但是功能很齐全,不仅是文本处理工具,还是一个程序编辑工具,就连官方网站也说vim是一个程序开发工具而不是文字处理软件,因为它包含了很多额外的功能,如:多文件编辑,区块复制等,这些功能让我们在进行配置文件修改的时候会更方便。 + +介绍就到这里,我们来看一下基本使用 + +## 二、基本使用 + +由于vi/vim是一个全屏幕的文本编辑器,它工作在三种模式下:分别是命令模式、输入模式和末行模式。可以分别从命令模式切换到输入模式和末行模式,也可以从末行模式或输入模式切换到命令模式,但是输入模式与末行模式之间不能互相切换。 + +![1571203454643.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602392063340.png) + +第一种:命令模式,当我使用“vim myfile”命令打开myfile这个文件时就处于命令模式,屏幕左下角为文件名(myfile),1L 表示本文件有1 行,26C 表示此文件有26 个字符。1,25表示光标当前位置,在此模式下用户可以输入命令来进行文件存盘、移动光标、删除字符、撤消命令和重复命令等操作,还可以设置编辑环境。 + +``` +this is the command mode. +~ +~ 表示没有内容 +"myfile" 1L, 26C 1,25 全部 +``` + +第二种:编辑模式,又叫输入模式。在输入模式下,屏幕的左下方会出现INSERT (插入)字样。在输入状态下,用户可以输入文本的内容。 + +``` +this is the command mode. +~ +~ +~ +~ +-- 插入 -- 1,25 全部 +``` + +第三种:末行模式。只要在命令模式下输入命令“:”即可进入末行模式。在末行模式下,可以进行保存文件、退出vi、进行查找和替换等操作。 + +``` +this is the command mode. +~ +~ +~ +~ +:q! +``` + +三种模式介绍完了,我们看下vim的使用,这里面我们还是按照三种模式来对vim的使用进行说明 + +**命令模式可以使用的按键说明** + + **光标控制按键** + +| | | +| ------------------ | ------------------------------------------------------------ | +| h 或 向左箭头键(←) | 光标向左移动一个字符 | +| j 或 向下箭头键(↓) | 光标向下移动一个字符 | +| k 或 向上箭头键(↑) | 光标向上移动一个字符 | +| l 或 向右箭头键(→) | 光标向右移动一个字符 | +| 15j/15↓ | 向下移动15行 | +| [Ctrl] + [f] | 屏幕『向下』移动一页,相当于 [Page Down]按键 (常用) | +| [Ctrl] + [b] | 屏幕『向上』移动一页,相当于 [Page Up] 按键 (常用) | +| [Ctrl] + [d] | 屏幕『向下』移动半页 | +| [Ctrl] + [u] | 屏幕『向上』移动半页 | +| n | 那个 n 表示『数字』,例如 3 。按下数字后再按空格键,光标会向右移动3 个字符。 | +| 0 或功能键[Home] | 这是数字『 0 』:移动到这一行的最前面字符处 (常用) | +| $ 或功能键[End] | 移动到这一行的最后面字符处(常用) | +| H | 光标移动到这个屏幕的最上方那一行的第一个字符 | +| M | 光标移动到这个屏幕的中央那一行的第一个字符 | +| L | 光标移动到这个屏幕的最下方那一行的第一个字符 | +| G | 移动到这个文件的最后一行(常用) | +| nG | n 为数字。移动到这个文件的第 n 行。可配合 :set nu | +| gg | 移动到这个档案的第一行,相当于 1G (常用) | +| n | n 为数字。光标向下移动 n 行(常用) | + + **搜索与替换** + +| | | +| ------------------- | ------------------------------------------------------------ | +| /abc | 向光标之下查找一个名称为 abc 的字符串。 (常用) | +| ?abc | 向光标之上查找一个字符串名称为 abc 的字符串。 | +| n | 这个 n 是英文按键。代表『重复前一个查找的动作』。 | +| N | 这个 N 是英文按键。与 n 刚好相反 | +| :n1,n2s/abc1/abc2/g | n1 与 n2 为数字。在第 n1 与 n2 行之间查找 abc1 替换为 abc2 | +| :1,$s/abc1/abc2/g | 从第一行到最后一行查找 abc1 字符串,并将该字符串替换为 abc2 (常用) | +| :1,$s/abc1/abc2/gc | 从第一行到最后一行查找 abc1 字符串,并将该字符串替换为 abc2 ,且在替换前显示提示字符给用户确认 | + + **删除与复制粘贴** + +| | | +| -------- | ------------------------------------------------------------ | +| x, X | x 相当于 [del] , X 相当于 [backspace] (常用) | +| nx | n 为数字,连续向后删除 n 个字符。 | +| dd | 删除光标所在的那一整行(常用) | +| ndd | n 为数字。删除光标所在的向下 n 行(常用) | +| d1G | 删除光标所在行到第一行的所有数据 | +| dG | 删除光标所在行到最后一行的所有数据 | +| d$ | 删除光标所在处,到该行的最后一个字符 | +| d0 | 那个是数字的 0 ,删除光标所在处,到该行的最前面一个字符 | +| yy | 复制光标所在的那一行(常用) | +| nyy | n 为数字。(常用) | +| y1G | 复制光标所在行到第一行的所有数据 | +| yG | 复制光标所在行到最后一行的所有数据 | +| y0 | 复制光标所在的那个字符到该行行首的所有数据 | +| y$ | 复制光标所在的那个字符到该行行尾的所有数据 | +| p, P | p 为将已复制的数据在光标下一行贴上,P 则为贴在光标上一行 (常用) | +| J | 将光标所在行与下一行的数据结合成同一行 | +| c | 重复删除多个数据,例如向下删除 4 行,[ 4cj ],配合上下左右的按键使用 | +| u | 撤销操作。(常用) | +| [Ctrl]+r | 重做上一个动作。(常用) | + +**从命令模式进入输入模式** + +| | | +| ----- | ------------------------------------------------------------ | +| i, I | i=从当前光标所在处插入, I =在当前所在行的第一个非空处开始插入。 (常用) | +| a, A | a =从当前光标所在的下一个字符处开始插入, A =从光标所在行的最后一个字符处开始插入。(常用) | +| o, O | o =在当前光标所在的下一行处插入新的一行; O =在当前光标所在处的上一行插入新的一行。(常用) | +| r, R | r 只会取代光标所在的那一个字符一次;R会一直取代光标所在的文字,直到按下 ESC 为止;(常用) | +| [Esc] | 退出输入模式,回到命令模式中(常用) | + +**从命令模式进入到末行模式** + +| | | +| ------------------- | ------------------------------------------------------------ | +| :w | 保存(常用) | +| :w! | 若文件属性为『只读』时,强制保存,是否能保存与权限有关 | +| :q | 不保存退出(常用) | +| :q! | 强制退出不保存。 | +| :wq | 保存退出, :wq! 则为强制保存退出 (常用) | +| ZZ | 这是大写的 Z !若档案没有更动,则不储存离开,若档案已经被更动过,则储存后离开! | +| :w [filename] | 将编辑的数据储存成另一个档案(类似另存新档) | +| :r [filename] | 在编辑的数据中,从指定的文件读取数据并加到光标所在行后面 | +| :n1,n2 w [filename] | 将 n1 到 n2 的内容保存为 filename 这个档案。 | +| :! command | 在系统中执行指定的命令 如 :! ls /home | +| vim 环境的变更 | | +| :set nu | 显示行号 | +| :set nonu | 取消行号 | + +## 三、额外功能 + +**区块选择** + +| | | +| -------- | ---------------------------- | +| v | 字符选择,选中光标经过的地方 | +| V | 选中光标经过的行 | +| [Ctrl]+v | 区块选择 | +| y | 复制选中的部分 | +| d | 删除选中的部分 | + +**多文件编辑** + +| | | +| ------ | --------------------------------- | +| :n | 编辑下一个文件 | +| :N | 编辑上一个文件 | +| :files | 列出目前这个 vim 的开启的所有文件 | + +**多窗口编辑** + +| | | +| ---------------------- | ------------------------------------------------------------ | +| :sp/:vsp [filename] | 开启一个新窗口,如果加 filename, 表示在新窗口编辑指定的文件,否则表示两个窗口为同一个文件(同步显示)。 | +| [ctrl]+w+ j [ctrl]+w+↓ | 按键的按法是:先按下 [ctrl] 不放, 再按下 w 后放开所有的按键,然后再按下 j (或向下箭头键),则光标可移动到下方的窗口。 | +| [ctrl]+w+ k [ctrl]+w+↑ | 同上,不过光标移动到上面的窗口。 | +| [ctrl]+w+ q | 退出光标所在窗口,也可以 [ctrl]+w+j/k 切换窗口后,按下 :q 即可离开, 也可以按下 [ctrl]+w+q 。 | + +**环境变量与记录** + +.viminfo:记录用户的行为,之前编辑过的文件光标在什么位置,在这个文件中进行过什么操作等,自动建立 + +.vimrc:定义vim的默认设置,如是否显示行号等,需要手动生成 + +| | | +| --------------------------------- | ------------------------------------------------------------ | +| :set nu /:set nonu | 就是设定与取消行号! | +| :set hlsearch /:set nohlsearch | 搜索时是否高亮显示。默认值是 hlsearch | +| :set autoindent :set noautoindent | 是否自动缩排?autoindent 就是自动缩排。 | +| :set backup/:set nobackup | 是否自动备份,一般是 nobackup 的, 如果设定 backup 的话,那么当你更动任何一个档案时,则源文件会被另存成一个档名为 filename~ 的档案。 | +| :set ruler/:set noruler | 是否显示右下角的一些状态栏说明 | +| :set showmode/:set noshowmode | 是否显示左下角的状态栏。 | +| :set backspace=(012) | 一般来说, 如果我们按下 i 进入编辑模式后,可以利用backspace来删除任意字符的。 但是,某些版本则不许如此。这时就可以使用这个设置2 可以删除任意;0 或 1 仅可删除刚刚输入内容 | +| :set all | 显示目前所有的环境变量设定值。 | +| :set | 显示与系统默认值不同的设置, 用户修改过的 | +| :syntax on :syntax off | 是否显示颜色 | +| :set bg=dark :set bg=light | 可用以显示不同的颜色色调,预设是『 light 』。如果你常常发现批注的字体深蓝色实在很不容易看, 那么这里可以设定为 dark 喔!试看看,会有不同的样式呢! | + +**密码设置与取消** + +加密 + +``` +vim filename--->:X--->输入密码--->保存(否则不加密) +``` + +取消密码 + +``` +vim filename--->输入正确密码--->:X--->空密码--->保存 +vim filename--->:set key= --->保存 + +注意:不要对系统文件进行加密的操作 +``` + +**vim插件** + +``` +1、虚拟机网卡设置为NAT +2、释放IP并重新获取IP +dhclient -r ensxx +dhclient ensxx +3、安装EPELyum源 +dnf install epel-release -y +4、安装vim插件 +dnf install vim-airline -y +``` + +**vimdiff&vimtutor** + +vimdiff:编辑两个或者更多个文件并显示不同 + +vimtutor:一条神奇的命令 + +## 四、使用中的注意事项 + +由于个别版本的linux默认只安装vi,所以你需要额外安装vim的软件包,如何安装软件包我们会在后续的课程中讲解,另外vim在字符界面下不能输入中文,而在图形界面下能否输入中文则取决于系统中是否安装了中文输入法 + +字符差异 + +由于linux和windows的系统差异,它们针对于文件的中的一些特殊符号表示方式也是不同的,比如说用来表示换行的符号等,如 + +``` +[root@zutuanxue ~]# cat -A hello-linux.txt +hello$ +$ +[root@zutuanxue ~]# cat -A hello-windows.txt +hello^M$ +^M$ +``` + +如果这种文件是从windows拷贝到linux的一本小说的话,基本没什么问题,但是如果是一个我们需要执行指定工作的shell脚本就会出现问题,因为linux不认识这种符号的含义,就会导致shell脚本无法执行。所以此时我们就要对这种文件进行处理 + +``` +[root@zutuanxue ~]# unix2dos [-kn] file [newfile] +选项与参数: +-k :保留文件原本的 mtime 时间格式 +-n :保留旧文件,将转换后的内容输出到新文件,如: dos2unix -n old new +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux acl\346\235\203\351\231\220.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux acl\346\235\203\351\231\220.md" new file mode 100644 index 0000000..52a3292 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux acl\346\235\203\351\231\220.md" @@ -0,0 +1,139 @@ +linux的权限非常重要,我们之前所说的几种权限中,但是并不能只针对一个用户或者一个组进行单独设置,而ACL权限可以帮助我们实现这个功能,比如说有一个文件的所有者和所有者组都是a,这个文件的权限是660,我可以让b这个用户可以对文件进行读写的操作,而b这个用户并不属于a组的成员。那我们来看下如何使用 + +## ACL权限的设置和查看 + +如果要使用acl权限,首先要确定你的文件系统支持acl权限,如果再Default mount options字段出现acl字样就意味着你的文件系统支持acl,不过在CentOS8中默认是都支持的。 + +``` +[root@zutuanxue test]# tune2fs -l /dev/sda1 +tune2fs 1.44.3 (10-July-2018) +Filesystem volume name: +Last mounted on: /boot +Filesystem UUID: be03eaec-6474-42ea-8f79-06e7198f5155 +Filesystem magic number: 0xEF53 +Filesystem revision #: 1 (dynamic) +Filesystem features: has_journal ext_attr resize_inode dir_index filetype needs_recovery extent 64bit flex_bg sparse_super large_file huge_file dir_nlink extra_isize metadata_csum +Filesystem flags: signed_directory_hash +Default mount options: user_xattr acl +Filesystem state: clean +. +. +. +``` + +配置acl权限我们需要使用两个命令一个是setfacl用来设置acl权限,另一个是getfacl用来查看acl权限 + +- **setfacl命令:设置文件或文件夹的ACL权限** + +``` +命令选项: +-m :设置acl +-x :删除指定的acl +-b :删除所有的acl +``` + +- **getfacl命令:用来查看文件的acl权限** + 现在我们来看下如何设置 + +``` +[root@zutuanxue test]# ls +file file1 +[root@zutuanxue test]# ll file1 +-rw-r--r-- 1 root root 0 10月 18 02:48 file1 +[root@zutuanxue test]# setfacl -m u:oracle:rw file1 为指定的用户配置一个rw的权限 +[root@zutuanxue test]# setfacl -m u::rwx file1 如果没有指定用户则默认是为该文件的所有者设置 +[root@zutuanxue test]# ll file1 +-rwxrw-r--+ 1 root root 0 10月 18 02:48 file1 所有者权限变成的rwx而且后面多了一个+号 +``` + +你会发现使用ll(等同于ls -l)命令查看时会发现多了一个+号,这只是提醒我们此文件被设置了acl权限,但是具体是什么样的,我们还需要使用getfacl来查看 + +``` +[root@zutuanxue test]# getfacl file1 +# file: file1 文件名 +# owner: root 所有者 +# group: root 所有者组 +user::rwx user:后面是空的,代表的是所有者的权限 +user:oracle:rw- 我们之前给额外用户设置的权限 +group::r-- 所有者组的权限 +mask::rw- 默认的有效权限 +other::r-- 其他人的权限 +``` + +以上是我们针对一个额外的用户设置的权限,同理可以设置针对组和其他人的acl权限 + +**为不同用户或组设置不同权限** + +``` +[root@zutuanxue test]# setfacl -m g:oracle:rw file1 +[root@zutuanxue test]# setfacl -m o:rw file1 +[root@zutuanxue test]# getfacl file1 +# file: file1 +# owner: root +# group: root +user::rwx +user:oracle:rw- +group::r-- +group:oracle:rw- +mask::rw- +other::rw- +``` + +**删除指定的acl** + +``` +[root@zutuanxue test]# setfacl -x u:oracle file1 删除用户acl +[root@zutuanxue test]# getfacl file1 +# file: file1 +# owner: root +# group: root +user::rwx +group::r-- +group:oracle:rw- +mask::rw- +other::rw- +[root@zutuanxue test]# setfacl -x g:oracle file1 删除组acl +[root@zutuanxue test]# getfacl file1 +# file: file1 +# owner: root +# group: root +user::rwx +group::r-- +mask::r-- +other::rw- +[root@zutuanxue test]# chmod o=r file1 删除其他人直接使用chmod就可以 +[root@zutuanxue test]# ll file1 +-rw-r--r-- 1 root root 0 10月 18 04:21 file1 +[root@zutuanxue test]# getfacl file1 +# file: file1 +# owner: root +# group: root +user::rw- +group::r-- +other::r-- +``` + +**删除所有acl** + +``` +[root@zutuanxue test]# setfacl -m u:oracle:rw,g:oracle:rw,o:rwx file1 +[root@zutuanxue test]# getfacl file1 +# file: file1 +# owner: root +# group: root +user::rw- +user:oracle:rw- +group::r-- +group:oracle:rw- +mask::rw- +other::rwx + +[root@zutuanxue test]# setfacl -b file1 +[root@zutuanxue test]# getfacl file1 +# file: file1 +# owner: root +# group: root +user::rw- +group::r-- +other::rwx +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux nmcli\345\221\275\344\273\244\350\257\246\350\247\243.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux nmcli\345\221\275\344\273\244\350\257\246\350\247\243.md" new file mode 100644 index 0000000..269e5f6 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux nmcli\345\221\275\344\273\244\350\257\246\350\247\243.md" @@ -0,0 +1,148 @@ +## nmcli connection及常用选项 + +``` +[root@zutuanxue ~]# nmcli connection +add 添加 +delete 删除 +edit 编辑 +help 帮助 +load 加载 +monitor 监控 +show 查看 +clone 克隆 +down 停用 +modify 修改 +reload 重载 +up 启用 + +[root@zutuanxue ~]# nmcli connection modify ens37 ipv4.addresses 192.168.18.100/24 ipv4.gateway 192.168.18.1 ipv4.method manual autoconnect yes +[root@zutuanxue ~]# nmcli connection down ens37 +成功停用连接 "ens37"(D-Bus 活动路径:... +[root@zutuanxue ~]# nmcli connection up ens37 +连接已成功激活(D-Bus 活动路径:... +[root@zutuanxue ~]# nmcli +ens37: 已连接 to ens37 + "Intel 82545EM" + ethernet (e1000), 00:0C:29:11:47:A1, 硬件, mtu 1500 + ip4 默认 + inet4 192.168.18.100/24 + route4 192.168.18.0/24 + route4 0.0.0.0/0 + inet6 fe80::4283:ec57:8781:deff/64 + route6 fe80::/64 + route6 ff00::/8 + +[root@zutuanxue ~]# nmcli connection clone ens37 ens-test1 +ens37 (077945cb-1d12-4c06-bba3-562426336b67) 已克隆为 ens-test1 (ab1cc22a-21b5-4059-9b3e-b9d14b1084fe)。 +[root@zutuanxue ~]# nmcli connection +NAME UUID TYPE DEVICE +ens33 b5ecf... ethernet ens33 +ens37 07794... ethernet ens37 +ens-test1 ab1cc... ethernet -- + +!!!! 此命令在使用时,可以加设备名称,UUID,配置文件 +如 +[root@zutuanxue ~]# nmcli connection down ens37 +[root@zutuanxue ~]# nmcli connection up ens37 + +[root@zutuanxue ~]# nmcli connection down 077945cb-1d12-4c06-bba3-562426336b67 +[root@zutuanxue ~]# nmcli connection up 077945cb-1d12-4c06-bba3-562426336b67 + +[root@zutuanxue ~]# nmcli connection down /etc/sysconfig/network-scripts/ifcfg-ens37 +[root@zutuanxue ~]# nmcli connection up /etc/sysconfig/network-scripts/ifcfg-ens37 + +这三种方式都可以,其中最后一种是网卡配置文件存放的位置,都会以ifcfg-开头,后面加上设备名 +``` + +## nmcli device及常用选项 + +``` +[root@zutuanxue ~]# nmcli device +connect 连接 +disconnect 断开 +lldp 显示通过lldp协议学习到的相邻设备信息 +monitor 监控设备 +set 设置设备 +status 显示设备状态 +delete 删除设备 只能删除软件设备 +help 帮助 +modify 修改 +reapply 更新 +show 查看详细信息 +wifi 无线网络管理 + +例: +[root@zutuanxue ~]# nmcli device modify ens37 +ipv4.addresses 192.168.20.100/24 +成功重新应用连接到设备 "ens37"。 +[root@zutuanxue ~]# nmcli +ens37: 已连接 to ens37 + "Intel 82545EM" + ethernet (e1000), 00:0C:29:11:47:A1, 硬件, mtu 1500 + ip4 默认 + inet4 192.168.20.100/24 + inet4 192.168.17.131/24 + route4 0.0.0.0/0 + route4 192.168.17.0/24 + route4 192.168.20.0/24 + inet6 fe80::f91c:608a:8381:2cb4/64 + route6 fe80::/64 +``` + +## nmcli的其他常用设置 + +``` +[root@zutuanxue ~]# nmcli +-t 简洁输出 与-p冲突 +-p 人性化输出 与-t冲突 +-c 颜色开关 auto/on/off +-f 过滤字段 all查看所有字段 +connection 连接 +device 设备 +general 全局 +monitor 监控 +networking 网络 +radio 无线广播 + +例: +[root@zutuanxue ~]# nmcli -t connection +ens33:b5ecf570-543c-4da7-b082-bdc073b56acb:802-3-ethernet:ens33 +ens37:5b91e453-1130-48ce-a2a1-f6f728e072ed:802-3-ethernet:ens37 +ens37:077945cb-1d12-4c06-bba3-562426336b67:802-3-ethernet: + +[root@zutuanxue ~]# nmcli -p connection +======================== + 网络管理器连接配置集 +======================== +NAME UUID TYPE DEVICE +---------------------------------------------------- +ens33 b5ec... ethernet ens33 +ens37 5b91... ethernet ens37 +ens37 0779... ethernet -- + +[root@zutuanxue ~]# nmcli -f STATE connection +STATE +已激活 +已激活 +-- + +[root@zutuanxue ~]# nmcli general hostname +localhost.localdomain +[root@zutuanxue ~]# nmcli general hostname hello +[root@zutuanxue ~]# nmcli general hostname +hello +``` + +### nmcli的返回值 + +``` +0: 成功-指示操作已成功 +1: 位置或指定的错误 +2: 无效的用户输入,错误的nmcli调用 +3: 超时了(请参阅 --wait 选项) +4: 连接激活失败 +5: 连接停用失败 +6: 断开设备失败 +7: 连接删除失败 +8: 网络管理器没有运行 +10: 连接、设备或接入点不存在 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux shadow\346\226\207\344\273\266.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux shadow\346\226\207\344\273\266.md" new file mode 100644 index 0000000..0eaea65 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux shadow\346\226\207\344\273\266.md" @@ -0,0 +1,130 @@ +说到用户管理,就不得不提到shadow这个文件,shadow有三个功能: + +- 隐藏密码 +- 扩充密码的功能 +- 提供账号管理工具 + +**隐藏密码:** 因为/etc/passwd和/etc/group文件的权限必须是0644,这意味着所有的用户都能读取到内容,所以为了安全起见,我们通过shaodw把用户和组的密码分别隐藏在/etc/shadow,/etc/gshadow文件中,且这两个文件只有管理员,也就是root能调用 + +**提供账号管理工具** :我们之前所介绍的用户和组管理的相关命令,都是shadow所提供的工具 + +**扩充密码功能**: 这个扩充密码功能就是除了密码之外的额外功能,如,密码的有效期限,设置群组管理员(组长)等,这些都是记录在/etc/shadow,/etc/gshadow文件中 + +**/etc/shadow:** 存储用户密码及密码额外功能的文件 + +``` +文件内容: +root:$6$T52Xvk7zu84.tDXp$nfXcm6LTfUx.ZviEo7Eq1bPjDO...::0:99999:7::: +bin:*:18027:0:99999:7::: +``` + +/etc/shadow文件的格式与/etc/passwd类似,也是每一行代表一个账号的数据,使用:进行分隔. + +**内容详解** + +``` +USERNAME:PASSWORD:LAST_CHANGED:MIN_DAYS:MAX_DAYS:WARNNING:EXPIRES:INVALID:RESERVED + +1、USERNAME:用户账号名称。 + +2、PASSWORD:加密后的密码。 + +3、LAST_CHANGED:密码最后一次修改的日期。 + +4、MIN_DAYS:密码修改的最小间隔天数。 + +5、MAX_DAYS:密码修改的最大天数。 + +6、WARNNING:密码过期前警告的天数。 + +7、EXPIRES:密码过期的日期 + +8、INVALID: 账号失效日期 + +9、RESERVED:保留位,未定义功能 +``` + +这里面我们所提到的日期都是从1970年1月1日起经过的天数,所以我们看到的不是日期的格式,而是一组数字,我们接下来看下另一个文件 + +**/etc/gshadow:** 存储组密码及密码额外功能的文件 + +``` +文件内容: +root::: +bin::: +daemon::: +``` + +**内容详解** + +``` +GROUPNAME:PASSWORD:ADMINISTRATORS:MEMBERS + +GROUPNAME: 组名 + +PASSWORD: 组密码 + +ADMINISTRATORS: 组长 + +MEMBERS: 组成员 +``` + +除此之外用户管理还有一个简单的方法,那就是以root用户身份登录图形界面 + +![1571302990425.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602399129291.png) + +![1571303014802.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602399151313.png) + +**cockpit** + +``` +# systemctl start cockpit +http://localhost:9090 +``` + +![image20200331143440902.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602399169696.png) + +![image20200331143459395.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602399191502.png) + +**管理密码的有效期限** + +Shadow除了会把密码数据隐藏到其他文件、提供许多账号管理工具外,还允许你为账号或密码设置有效期限,以提高Linux 的安全性。目前的 Shadow 可以设置下列两种期限: + +密码过期 + +一旦超过密码过期日期,用户成功的登录Linux 时,会强迫用户设置一个新的密码。设置完毕后,才会开启用户的 Shell 程序。设置密码过期的目的,在于提高 Linux 的安全性。 + +账号过期 + +若超过账号过期日期,Linux 会禁止用户登录系统,即使输入正确的密码,也无法登录。当账号过期时,Linux 会提示用户联系管理员修改账号过期日期。 + +``` +Your account has expired; please contact your system administrator +``` + +我们可以使用chage命令来查看或调整这些相关的期限 + +- chage命令 + +``` +[root@zutuanxue ~]# chage -l hello +最近一次密码修改时间 :从不 +密码过期时间 :从不 +密码失效时间 :从不 +帐户过期时间 :从不 +两次改变密码之间相距的最小天数 :0 +两次改变密码之间相距的最大天数 :99999 +在密码过期之前警告的天数 :7 + +chage + -m 设置密码修改的最小天数 + -M 设置密码修改的最大天数 + -d 设置密码最后修改日期 + -I 设置密码过期后,锁定账号的天数 + -E 设置账号过期日期,0=立即过期,-1=永不过期 + -W 设置密码过期前的警告天数 + -l 查看指定用户的相关信息 + -h 帮助 +``` + +![image20200331164400723.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602399247448.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \345\257\206\347\240\201\347\256\241\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \345\257\206\347\240\201\347\256\241\347\220\206.md" new file mode 100644 index 0000000..dd7fa15 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \345\257\206\347\240\201\347\256\241\347\220\206.md" @@ -0,0 +1,80 @@ +账号犹如一张通行证,有了账号你才能顺利的使用Linux。不过 Linux 怎么确认使用某账号的人,是这个账号的真正拥有者呢?此时Linux 会根据用户的密码,来确认用户的身份。Linux 的用户账号与群组账号都可设置密码。用户账号的密码用来验证用户的身份;而群组账号的密码则是用来确认用户是否为该群组的成员,以及确认是否为该群组的管理者。 + +在 Linux 中,使用 useradd 新建一个用户账号时,useradd 会锁定用户的密码,如此一来,用户暂时不能使用 。你必须要修改其密码后,新建的用户才能用他的账号登录。要修改用户账号的密码需要使用passwd命令 + +- passwd命令 + +``` +命令介绍 + 修改用户密码 + +命令语法 + passwd [选项] 用户 + +命令选项 +-d 删除用户密码,亦即把文件中的密码字段清空。 + +-l 这个参数用来锁定账号,账号一经锁定,用户再怎样输入密码,都会被判断为错误。这个参数只能由 root 使用,普通用户无法用来锁定自己的账号。 + +-u 解锁用户 +``` + +除了可以修改用户账号的密码外,你也可以为每一个群组设置一个密码,这个密码称为群组密码(Group Password)。Linux 的用户,可以通过 newgrp 暂时修改其主要群组的身份。执行 newgrp 时,会以指定的群组身份,开启一个登录 Shell,这样就可以获得暂时修改主要群组之功效。此时,如果该群组没有指定密码,那么 Linux 只允许群组的成员可以使用 newgrp修改主要群组的身份;如果群组设置了密码,群组成员仍可以不用密码就可切换主要群组身份,但非群组的成员,则必须要提供正确的密码才行。 + +- gpasswd命令 + +``` +命令介绍 + 修改组密码,对群组管理 + +命令选项 +-r 用来删除群组的密码。 + +-R 锁定 GROUP 的群组密码。 + +-A 设置组管理员 + +-a 添加组成员到组 + +-d 从组中 删除组成员 + + +命令用法 +指派群组管理员,如果有多个管理员用“,”分隔,如果想删除群组管理员,保持位置为空 + + +组管理员用法案例 +创建组admin + +[root@zutuanxue ~]# groupadd admin + +创建用户 ztxa ztxb ztxc + +[root@zutuanxue ~]# useradd ztxa + +[root@zutuanxue ~]# useradd ztxb + +[root@zutuanxue ~]# useradd ztxc + +设置ztxa为admin组的组管理员 + +[root@zutuanxue ~]# gpasswd -A ztxa admin + + +切换到ztxa 将ztxb ztxc加入 admin组 + +[root@zutuanxue ~]# su - ztxa -c "gpasswd -a ztxb admin" + +正在将用户“ztxb”加入到“admin”组中 + +[root@zutuanxue ~]# su - ztxa -c "gpasswd -a ztxc admin" + +正在将用户“ztxc”加入到“admin”组中 + + +切换到ztxa 从admin组中删除ztxc + +[root@zutuanxue ~]# su - ztxa -c "gpasswd -d ztxc admin" + +正在将用户“ztxc”从“admin”组中删除 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \347\243\201\347\233\230\345\210\206\345\214\272\344\270\216\346\240\274\345\274\217\345\214\226.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \347\243\201\347\233\230\345\210\206\345\214\272\344\270\216\346\240\274\345\274\217\345\214\226.md" new file mode 100644 index 0000000..59bcfbf --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \347\243\201\347\233\230\345\210\206\345\214\272\344\270\216\346\240\274\345\274\217\345\214\226.md" @@ -0,0 +1,128 @@ +## 一、基本分区管理 + +### 1.1、linux磁盘表示方法介绍 + +##### 硬盘命名方式 + +| OS | IDE(并口) | SATA(串口) | SCSI | +| ------- | --------- | ---------- | -------- | +| CentOS6 | /dev/hda | /dev/sda | /dev/sda | +| CentOS7 | /dev/sda | /dev/sda | /dev/sda | +| CentOS8 | /dev/sda | /dev/sda | /dev/sda | + +##### 磁盘设备的命名 + +/dev/sda2 + +s=硬件接口类型(sata/scsi),d=disk(硬盘),a=第1块硬盘(b,第二块),2=第几个分区 +/dev/hd h=IDE硬盘 /dev/hdd3 +/dev/vd v=虚拟硬盘 /dev/vdf7 + +##### HP服务器硬盘 + +/dev/cciss/c0d0 +/dev/cciss/c0d0p1 c0第一个控制器, d0第一块磁盘, p1分区1 +/dev/cciss/c0d0p2 c0第一个控制器, d0第一块磁盘, p2分区2 + +### 1.2、磁盘分区 + +#### 1)、磁盘划分思路 + +- 进入分区表 新建分区 +- 更新分区表<刷新分区表> +- 格式化分区——>文件系统 + +#### 2)、磁盘分区 + +fdisk命令 + +``` +fdisk磁盘分区命令 +fidsk [命令选项] [参数] + +命令选项 +-l list 列出磁盘分区 +-u 与-l一起使用,显示分区的相关信息 + +fdisk /dev/sda 为/dev/sda分区 +m :显示菜单和帮助信息 +a :活动分区标记/引导分区 +d :删除分区 +l :显示分区类型 +n :新建分区 +p :显示分区信息 +q :退出不保存 +t :设置分区号 +v :进行分区检查 +w :保存修改 +x :扩展应用,高级功能 +``` + +分区前了解设备信息 + +``` +# lsblk 查看块设备 +# df -h 查看正在挂载的设备情况 +# blkid 打印某个已经格式化分区的UUID +# fdisk -l 查看当前系统的所有设备分区情况 +# fdisk /dev/sdb + + +[root@zutuanxue ~]# fdisk -l /dev/sdb +硬盘容量 = 柱面数 × 盘面数(磁头数) × 扇区数 × 扇区大小(一般为512字节) +Disk /dev/sdb: 20 GiB, 21474836480 bytes, 41943040 sectors 磁盘空间统计,大小和扇区数量 +几何属性:255 个磁头, 63 个扇区/磁道, 2610 个柱面 + ###此行内容只有在使用fdisk分区时,使用c命令加上与dos兼容的标记时才会出现,这里面所提到的磁头等数量与磁盘中的物理寻址和逻辑块寻址相关,而且它们都是逻辑地址,产生访问时,磁盘控制器会把这些确定的逻辑地址转换为实际的物理地址;对于我们来讲这几个数值可以帮助我们计算磁盘空间的大小以及一个磁柱的大小,比如说 + ##一个磁柱的容量=255x63x512=8225280(约8M空间) +单元:扇区 / 1 * 512 = 512 字节 +扇区大小(逻辑/物理):512 字节 / 512 字节 +I/O 大小(最小/最佳):512 字节 / 512 字节 +磁盘标签类型:dos +磁盘标识符:0x178c5f83 + + + 设备 启动 起点 末尾 扇区 大小 Id 类型 +/dev/sda1 * 2048 2099199 2097152 1G 83 Linux +/dev/sda2 2099200 41943039 39843840 19G 8e Linux LVM + +命令(输入 m 获取帮助): +``` + +**fdisk分区总结** +命令缺点:单个分区不能超过2T 超过的话需要用parted命令 +在linux 下大磁盘的分区不能再采用fdisk了,MBR分区表只支持2T磁盘,所以大于2T的磁盘必须使用GPT分区表。 + +##### 3)、磁盘格式化 + +格式化(format)是指对磁盘或磁盘中的分区(partition)进行初始化的一种操作,这种操作通常会导致现有的磁盘或分区中所有的文件被清除。格式化通常分为低级格式化和高级格式化。如果没有特别指明,对硬盘的格式化通常是指高级格式化,而对软盘的格式化则通常同时包括这两者。 + +``` +-L 标签名 +-V : 详细显示模式 +-t : 给定档案系统的型式,Linux 的预设值为 ext2 +-c : 在制做档案系统前,检查该partition 是否有坏轨 +-l bad_blocks_file : 将有坏轨的block资料加到 bad_blocks_file 里面 +-b : 给定 block 的大小 + +关于block and inode dentry +实验发现这句话不对 +block越大,inode越少,适合存储大文件的文件系统;block越小,inode越多,适合存储文件多而小的文件系统。 + + +磁盘分区格式化 +mkfs.ext4 /dev/sda3 +``` + +**注意**: + +MBR分区表最多允许4个主分区,或者3个主分区+1个扩展分区 + +扩展分区不能直接存储数据 + +扩展分区的大小决定了所有逻辑分区的大小,逻辑分区的编号从5开始 + +删除扩展分区后下面的逻辑分区都被删除 + +分完区后需要手动刷新分区表,如果刷新不成功需要重启操作系统 + +创建分区的时候尽可能注意分区序号的连续性 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \347\273\204\347\256\241\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \347\273\204\347\256\241\347\220\206.md" new file mode 100644 index 0000000..46314fc --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \347\273\204\347\256\241\347\220\206.md" @@ -0,0 +1,85 @@ +## 组账号管理 + +本机的群组账号数据被储存在 /etc/group 文件中,权限也必须为0644,与 /etc/passwd 一样,这也是一个文本文件。 + +``` +root:x:0: +bin:x:1: +daemon:x:2: +``` + +这与/etc/passwd文件的格式类似 + +``` +GROUPNAME:PASSWORD:GID:MEMBERS + +- GROUPNAME:组名 + +- PASSWORD:组密码,这里也和passwd文件一样是个x + +- GID:群组识别号 + +- MEMBERS:组成员 +``` + +一起来看下组管理的相关命令 + +- **groupadd** 建立组 + +``` +命令介绍 + groupadd - 创建一个新组 + +命令语法 + groupadd [选项] group + +命令选项 +-g GID 指定群组账号的标识符 + +-r 指定添加的群组成为系统群组 + +-f 强制执行。 在一般的情况下,groupadd 不允许建立一个与使用过的 GID 相同的群组账号,而使用这个参数时,groupadd 将会建立相同 GID 的 群组账号。 + +-o 此选项允许添加一个使用非唯一 GID 的组。 + + + +#组相关文件 + /etc/group + 组账户信息。 + + /etc/gshadow + 安全组账户信息。 + + /etc/login.defs + Shadow 密码套件配置。 +``` + +- **groupmod** 修改群组信息 + +``` +命令介绍 + groupmod - 修改组信息 + +命令语法 + groupmod [选项] GROUP + +命令选项 +-g GID 修改群组账号的标识符。GID 就是新的标识符。 +-n NEWNAME 用来修改群组的名称。NEWNAME 就是新的组名。 +``` + +- **groupdel** 删除群组账号 + +``` +命令介绍 + groupdel - 删除一个组 + +命令语法 + groupdel [选项] GROUP + +命令选项 +-f 强制 +``` + +**您不能移除现有用户的主组。在移除此组之前,必须先移除此用户。** \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \347\275\221\347\273\234\347\256\241\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \347\275\221\347\273\234\347\256\241\347\220\206.md" new file mode 100644 index 0000000..d007c6f --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \347\275\221\347\273\234\347\256\241\347\220\206.md" @@ -0,0 +1,229 @@ +现代人的生活越来越依赖网络,对于一个操作系统来讲,网络功能的支持和管理就更为重要了,本节课我们一起来看一下在CentOS8中如何对网络进行管理 + +## NetworkManager和常用工具和基本用法 + +### NetworkManager介绍 + +在linux系统中传统的网络管理方法是用过一个叫network的服务来实现,在CentOS7中依然有这个服务的身影,但是到了CentOS8中已经不使用network这个服务了,而是使用了一个叫NetworkManager的服务,这个服务可以简化我们管理有线和无线连接的工作,除此之外它还能管理不同类型的网络,包括物理网卡,虚拟网卡,以太网,非以太网等 + + + +#### 常用工具 + +- nmcli:命令行工具 +- nmtui:文本图形界面工具 +- cockpit:基于web的管理工具 + +#### nmcli基本用法 + +nmcli命令的用法类似linux中以前的ip命令,而且支持tab补全,另外也可以使用-h或者–help获取帮助 + +``` +[root@zutuanxue ~]# nmcli -h +[root@zutuanxue ~]# nmcli connection -h +可以看到,在不同的阶段获取到的帮助内容是不一样的,具体的用法我们后面会看到 + +nmcli这个工具有两个常用的命令 +nmcli connection(nmcli c) 与连接相关的操作 +[root@zutuanxue network-scripts]# nmcli connection +NAME UUID TYPE DEVICE +连接名 设备的UUID(通用唯一识别码) 设备类型 设备名称 +ens33 b5ecf570-543c-4da7-b082-bdc073b56acb ethernet ens33 +ens37 077945cb-1d12-4c06-bba3-562426336b67 ethernet -- +在查看时,有颜色的字体标注的是处于活跃状态的网卡,也就是连接的,正常颜色字体标记的是非活跃状态的网卡,也就是未连接的,未连接的不生效 +nmcli device (nmcli d) 与设备相关的操作 +[root@zutuanxue network-scripts]# nmcli device +DEVICE TYPE STATE CONNECTION +设备名 设备类型 设备状态 连接名称 +ens33 ethernet 已连接 ens33 +ens37 ethernet 已断开 -- +lo loopback 未托管 -- + +在日常使用中这两个命令相互配合,通过nmcli device可以查看到有哪些网络设备是被NetworkManager托管,通过nmcli connection控制网络设备的连接状态 +``` + +### 使用nmcli命令设置网卡信息 + +``` +查看网卡信息 +[root@zutuanxue ~]# nmcli +ens33: 已连接 to ens33 #设备状态和名称 + "Intel 82545EM" #设备型号 + ethernet (e1000), 00:0C:29:11:47:97, 硬件, mtu 1500 + ip4 默认 + inet4 192.168.1.55/24 + route4 0.0.0.0/0 + route4 192.168.1.0/24 + inet6 fe80::ea62:91c6:114:18bb/64 + route6 fe80::/64 + route6 ff00::/8 + +为网卡设置静态IP +[root@zutuanxue ~]# nmcli connection add type ethernet con-name ens-test1 ifname ens37 ipv4.addresses 192.168.18.100/24 ipv4.gateway 192.168.18.1 ipv4.method manual +连接 "ens-test1" (da7fdc9a-e7cc-4a1c-8b2c-7751ed2fc4d2) 已成功添加。 + + +启用新添加的连接 +[root@zutuanxue ~]# nmcli connection up ens-test1 +连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/16) + + +查看连接状态 +[root@zutuanxue ~]# nmcli connection +NAME UUID TYPE DEVICE +ens33 b5ecf5... ethernet ens33 +ens-test1 da7fdc... ethernet ens37 +ens37 077945... ethernet -- + +为网卡设置动态IP +[root@zutuanxue ~]# nmcli connection add type ethernet con-name ens-test2 ifname ens37 ipv4.method auto +连接 "ens-test2" (25b9dd2f-a4c0-452d-bd22-992cf12b55b2) 已成功添加。 +[root@zutuanxue ~]# nmcli connection up ens-test2 +连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/17) +[root@zutuanxue ~]# nmcli connection +NAME UUID TYPE DEVICE +ens33 b5ec... ethernet ens33 +ens-test2 25b9... ethernet ens37 +ens37 0779... ethernet -- +ens-test1 da7f... ethernet -- + + +交互式设置IP地址 +[root@zutuanxue ~]# nmcli connection edit ens-test1 +nmcli> goto ipv4.addresses +nmcli ipv4.addresses> change +编辑 "addresses" 值:192.168.20.100/24 +您是否也要将 "ipv4.method" 设为 "manual"?[yes]:yes +nmcli ipv4.addresses> back +nmcli ipv4> save +成功地更新了连接 "ens-test1" (da7fdc9a-e7cc-4a1c-8b2c-7751ed2fc4d2)。 +nmcli ipv4> activate +正在监视连接激活(按任意键继续) +连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/18) + +nmcli ipv4> quit + +[root@zutuanxue ~]# nmcli +ens37: 已连接 to ens-test1 + "Intel 82545EM" + ethernet (e1000), 00:0C:29:11:47:A1, 硬件, mtu 1500 + ip4 默认 + inet4 192.168.20.100/24 + route4 192.168.20.0/24 + route4 192.168.18.1/32 + route4 0.0.0.0/0 + inet6 fe80::11c3:e0a4:f62e:9f31/64 + route6 fe80::/64 + route6 ff00::/8 + + +启用和停用 +[root@zutuanxue ~]# nmcli connection up ens-test1 +连接已成功激活(D-Bus 活动路径:... +[root@zutuanxue ~]# nmcli connection down ens-test1 +成功停用连接 "ens-test1"(D-Bus 活动路... + +删除连接 +[root@zutuanxue ~]# nmcli connection delete ens-test1 +成功删除连接 "ens-test1" (4fc43f65-ea53-43a1-85d4-692e425fcd7d)。 +[root@zutuanxue ~]# nmcli connection +NAME UUID TYPE DEVICE +ens33 b5ec... ethernet ens33 +ens37 0779... ethernet ens37 +[root@zutuanxue ~]# nmcli connection show +NAME UUID TYPE DEVICE +ens33 b5ec... ethernet ens33 +ens37 0779... ethernet ens37 + +重新加载设置(不会立即生效) +[root@zutuanxue ~]# nmcli connection reload + +重新加载指定的设置(不会立即生效) +[root@zutuanxue ~]# nmcli connection load /etc/sysconfig/network-scripts/ifcfg-ens37 + + +生效方法 + +启用设备 +[root@zutuanxue ~]# nmcli connection up ens37 +连接已成功激活(D-Bus 活动路径... + +或者 + +连接设备并更新设备 +[root@zutuanxue ~]# nmcli device connect ens37 +[root@zutuanxue ~]# nmcli device reapply ens37 + + +查看设备&查看设备的详细信息 +[root@zutuanxue ~]# nmcli device +DEVICE TYPE STATE CONNECTION +ens37 ethernet 已连接 ens37 +ens33 ethernet 已连接 ens33 +lo loopback 未托管 -- +[root@zutuanxue ~]# nmcli device show ens33 +GENERAL.DEVICE: ens33 +GENERAL.TYPE: ethernet +GENERAL.HWADDR: 00:0C:29:11:47:97 +GENERAL.MTU: 1500 +GENERAL.STATE: 100(已连接) +GENERAL.CONNECTION: ens33 +GENERAL.CON-PATH: /org/freedesktop/NetworkMana... +WIRED-PROPERTIES.CARRIER: 开 +IP4.ADDRESS[1]: 192.168.1.55/24 +IP4.GATEWAY: -- +IP4.ROUTE[1]: dst = 192.168.1.0/24, nh = 0.0.0.0, mt = 102 +IP4.DNS[1]: 202.106.0.20 +IP4.DNS[2]: 114.114.114.114 +IP6.ADDRESS[1]: fe80::ea62:91c6:114:18bb/64 +IP6.GATEWAY: -- +IP6.ROUTE[1]: dst = fe80::/64, nh = ::, mt = 102 +IP6.ROUTE[2]: dst = ff00::/8, nh = ::, mt = 256, table=255 + +连接/断开网卡 +[root@zutuanxue ~]# nmcli device connect/disconnect ens37 + +开启/关闭无线网络 +[root@zutuanxue ~]# nmcli radio all on/off + +开启/关闭NetworkManager的网络管理功能 +[root@zutuanxue ~]# nmcli networking on/off + +监控网络状态 +[root@zutuanxue ~]# nmcli monitor (ctrl+c结束) +ens37: 停用中 +网络管理器现在处于 "已连接(仅本地)" 状态 +连接性现在是 "受限" +ens37: 已断开 + +询问NetworkManager网络连接状态(默认等待30秒) +[root@zutuanxue ~]# nm-online +正在连接............... 30s [online] +``` + +### 使用其他网络管理方式配置网络 + +- nmtui + +``` +[root@zutuanxue ~]# nmtui +``` + +![image20191128171950048.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602407640250.png) + +- cockpit + +``` +[root@zutuanxue ~]# rpm -qa | grep cockpit +cockpit-packagekit-184.1-1.el8.noarch +cockpit-system-185-2.el8.noarch +cockpit-185-2.el8.x86_64 +cockpit-bridge-185-2.el8.x86_64 +cockpit-ws-185-2.el8.x86_64 +cockpit-storaged-184.1-1.el8.noarch +[root@zutuanxue ~]# systemctl start cockpit +``` + +![image20191128172456779.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602407654490.png) + +![image20191128172540728.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602407665857.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \350\201\232\345\220\210\351\223\276\350\267\257.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \350\201\232\345\220\210\351\223\276\350\267\257.md" new file mode 100644 index 0000000..1266465 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \350\201\232\345\220\210\351\223\276\350\267\257.md" @@ -0,0 +1,238 @@ +## 聚合链路 + +聚合链路是将多块网卡逻辑地连接到一起从而允许故障转移或者提高吞吐率的方法。提高服务器网络可用性。 + +**bond**是将多块网卡虚拟成为一块网卡的技术,通过bond技术让多块网卡看起来是一个单独的以太网接口设备并具有相同的ip地址。在linux下配置bond,通过网卡绑定技术既能增加服务器的可靠性,又增加了可用网络宽带,为用户提供不间断的网络服务。 +**team**是另一种用来实现连路聚合和方法,类似于bond,team和bond的区别在于,支持hash加密,支持负载均衡,支持8块网卡,更好地支持IPV6 + +**实现方式** + +- bond +- team + +## bond聚合链路 + +### bond聚合链路模式 + +- mod=0 ,即:(balance-rr) Round-robin policy(轮询) + 聚合口数据报文按包轮询从物理接口转发。 + – 负载均衡—所有链路处于负载均衡状态,轮询方式往每条链路发送报文这模式的特点增加了带宽,同时支持容错能力,当有链路出问题,会把流量切换到正常的链路上。 + – 性能问题—一个连接或者会话的数据包如果从不同的接口发出的话,中途再经过不同的链路,在客户端很有可能会出现数据包无序到达的问题,而无序到达的数据包需要重新要求被发送,这样网络的吞吐量就会下降。Bond0在大压力的网络传输下,性能增长的并不是很理想。 + – 需要交换机进行端口绑定 +- mod=1,即: (active-backup) Active-backup policy(主-备份策略)只有Active状态的物理接口才转发数据报文。 + – 容错能力—只有一个slave是激活的(active)。也就是说同一时刻只有一个网卡处于工作状态,其他的slave都处于备份状态,只有在当前激活的slave故障后才有可能会变为激活的(active)。 + – 无负载均衡—此算法的优点是可以提供高网络连接的可用性,但是它的资源利用率较低,只有一个接口处于工作状态,在有 N 个网络接口的情况下,资源利用率为1/N。 +- mod=2,即:(balance-xor) XOR policy(平衡策略) + 聚合口数据报文按源目MAC、源目IP、源目端口进行异或HASH运算得到一个值,根据该值查找接口转发数据报文 + – 负载均衡—基于指定的传输HASH策略传输数据包。 + 容错能力—这模式的特点增加了带宽,同时支持容错能力,当有链路出问题,会把流量切换到正常的链路上。 + – 性能问题—该模式将限定流量,以保证到达特定对端的流量总是从同一个接口上发出。既然目的地是通过MAC地址来决定的,因此该模式在“本地”网络配置下可以工作得很好。如果所有流量是通过单个路由器,由于只有一个网关,源和目标mac都固定了,那么这个算法算出的线路就一直是同一条,那么这种模式就没有多少意义了。 + – 需要交换机配置为port channel +- mod=3,即:broadcast(广播策略) + 这种模式的特点是一个报文会复制两份往bond下的两个接口分别发送出去,当有对端交换机失效,我们感觉不到任何downtime,但此法过于浪费资源;不过这种模式有很好的容错机制。此模式适用于金融行业,因为他们需要高可靠性的网络,不允许出现任何问题。 +- mod=4,即:(802.3ad) IEEE 802.3ad Dynamic link aggregation(IEEE 802.3ad 动态链接聚合) + 在动态聚合模式下,聚合组内的成员端口上均启用LACP(链路汇聚控制协议)协议,其端口状态通过该协议自动进行维护。 + – 负载均衡—基于指定的传输HASH策略传输数据包。默认算法与blance-xor一样。 + – 容错能力—这模式的特点增加了带宽,同时支持容错能力,当有链路出问题,会把流量切换到正常的链路上。对比blance-xor,这种模式定期发送LACPDU报文维护链路聚合状态,保证链路质量。 + – 需要交换机支持LACP协议 +- mod=5,即:(balance-tlb) Adaptive transmit load balancing(适配器传输负载均衡) + 在每个物理接口上根据当前的负载(根据速度计算)分配外出流量。如果正在接收数据的物理接口口出故障了,另一个物理接口接管该故障物理口的MAC地址。 + 需要ethtool支持获取每个slave的速率 +- mod=6,即:(balance-alb) Adaptive load balancing(适配器适应性负载均衡) + 该模式包含了balance-tlb模式,同时加上针对IPV4流量的接收负载均衡,而且不需要任何switch(交换机)的支持。接收负载均衡是通过ARP协商实现的。bonding驱动截获本机发送的ARP应答,并把源硬件地址改写为bond中某个物理接口的唯一硬件地址,从而使得不同的对端使用不同的硬件地址进行通信。 + +``` +其实mod=6与mod=0的区别:mod=6,先把eth0流量占满,再占eth1,….ethX;而mod=0的话,会发现2个口的流量都很稳定,基本一 +样的带宽。而mod=6,会发现第一个口流量很高,第2个口只占了小部分流量 + +常用的模式为 0136 +mode 1、5、6不需要交换机设置 +mode 0、2、3、4需要交换机设置 +``` + +**案例:使用Bond方式设置聚合链路** + +**环境** +系统:CentOS8 +网卡名称: ens33(vmnet4) ens37(vmnet4) + +**step 1:** 查看环境 + +``` +[root@zutuanxue ~]# nmcli connection +NAME UUID TYPE DEVICE +ens33 f035d150-9e89-4ee9-a657-03598d4b0940 ethernet ens33 +ens37 7726249d-8281-45e8-a8e3-a6a023c64c66 ethernet ens37 +``` + +**step 2:** 创建bond虚拟网卡 + +``` +[root@zutuanxue ~]# nmcli connection add type bond con-name bond0 ifname bond0 mode 1 ipv4.addresses 192.168.98.200/24 ipv4.method manual autoconnect yes + +#type:创建的类型,这里选择bond类型 +#con-name:这里写链接名,就是show中第一列,这里写什么生成的文件就是什么名字 +#ifname:网卡名,这里bond0是虚拟出来的 +#mode:选择bond模式,常用的有主备,轮询,广播,还有其他模式,用tab补全可以看到所有,也可以使用数字0-6表示 +#ipv4.mehod:表示自动还是手动,就是使用dhcp还是自己配置地址,关联配置文件中的BOOTPROTO段 +#ipv4.address:设置ip地址,注意记得加上掩码 +#autoconnect 自动连接 +``` + +**step 3:** 为bond网卡添加成员(真实网卡) + +``` +[root@zutuanxue ~]# nmcli connection add type bond-slave ifname ens33 master bond0 +连接 "bond-slave-ens33" (9fb9b3fa-a477-4a6f-a3c1-79cbfe351c7d) 已成功添加。 +[root@zutuanxue ~]# nmcli connection add type bond-slave ifname ens37 master bond0 +连接 "bond-slave-ens37" (2b047e49-b606-4b67-9e5c-f721f1e2ff7a) 已成功添加。 +#类型为bond-slave,表示这块真实网卡属于一块附属的网卡,原有配置的属性都不能使用了,master表示这块从属网卡属于bond0这个组 +注意:如果你的网卡没有启用的话需要启用 +[root@zutuanxue ~]# nmcli connection +NAME UUID TYPE DEVICE +bond0 55e0afdc-d2a6-4c93-b346-0ce207947b81 bond bond0 +bond-slave-ens33 9fb9b3fa-a477-4a6f-a3c1-79cbfe351c7d ethernet ens33 +bond-slave-ens37 2b047e49-b606-4b67-9e5c-f721f1e2ff7a ethernet ens37 +ens33 f035d150-9e89-4ee9-a657-03598d4b0940 ethernet -- +ens37 7726249d-8281-45e8-a8e3-a6a023c64c66 ethernet -- +[root@zutuanxue ~]# ifconfig +bond0: ether 00:0c:29:a6:ad:95 txqueuelen 1000 (Ethernet) + +ens33: ether 00:0c:29:a6:ad:95 txqueuelen 1000 (Ethernet) + +ens37: ether 00:0c:29:a6:ad:95 txqueuelen 1000 (Ethernet) +[root@zutuanxue ~]# nmcli connection up bond-slave-ens33 +连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/81) +[root@zutuanxue ~]# nmcli connection up bond-slave-ens37 +连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/82) +[root@zutuanxue ~]# nmcli connection up bond0 +连接已成功激活(master waiting for slaves)(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/83) +``` + +**step 4:** 查看链接信息并测试 + +``` +#查看信息 +[root@zutuanxue ~]# cat /proc/net/bonding/bond0 +Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011) + +Bonding Mode: fault-tolerance (active-backup)#模式 +Primary Slave: None +Currently Active Slave: ens33 #当前设备 +MII Status: up #启用状态 +MII Polling Interval (ms): 100 +Up Delay (ms): 0 +Down Delay (ms): 0 + +Slave Interface: ens33 #从接口信息 +MII Status: up +Speed: 1000 Mbps +Duplex: full +Link Failure Count: 0 +Permanent HW addr: 00:0c:29:a6:ad:95 +Slave queue ID: 0 + +Slave Interface: ens37 #另外一个从接口信息 +MII Status: up +Speed: 1000 Mbps +Duplex: full +Link Failure Count: 0 +Permanent HW addr: 00:0c:29:a6:ad:9f +Slave queue ID: 0 + +或者 + +[root@zutuanxue ~]# ip add + +ens33: mtu 1500 qdisc fq_codel master bond0 state UP group default qlen 1000 + link/ether 00:0c:29:a6:ad:95 brd ff:ff:ff:ff:ff:ff + +ens37: mtu 1500 qdisc fq_codel master bond0 state UP group default qlen 1000 + link/ether 00:0c:29:a6:ad:95 brd ff:ff:ff:ff:ff:ff + +bond0: mtu 1500 qdisc noqueue state UP group default qlen 1000 + link/ether 00:0c:29:a6:ad:95 brd ff:ff:ff:ff:ff:ff + inet 192.168.98.200/24 brd 192.168.98.255 scope global noprefixroute bond0 + valid_lft forever preferred_lft forever +#找到另外一台主机使用ping进行测试 +[root@zutuanxue ~]# nmcli connection down bond-slave-xxx +或者直接断开虚拟的网络连接测试还能否ping通 +``` + +**删除** + +``` +nmcli connection delete bond0 bond-slave-ens33 bond-slave-ens37 +注意:在配置聚合链路的时候如果使用虚拟机可能会弹出与mac地址相关的信息提示,可以暂时不用去管,如果测试的时候发现断网卡之后无法ping通,则需要在相关网卡配置文件中添加参数,如: +[root@zutuanxue ~]# vim /etc/sysconfig/network-scripts/ifcfg-bond0 +#添加一行内容 +BONDING_OPTS="miimon=100 mode=1 fail_over_mac=1" +#miimon:链路检查时间为100ms +#mode:模式为1,要与bond的模式相同 +#fail_over_mac=1 mac地址跟随正常工作的网卡,当第一块网卡挂掉之后,自动将mac地址调整为第二块网卡的mac + +以上操作只有在虚拟机的环境中使用,生产环境一般不需要 +``` + +## team聚合链路 + +案例:使用team方式设置聚合链路 + +环境 +系统:CentOS8 +网卡名称: ens33(vmnet4) ens37(vmnet4) + +**step 1:** 建立 + +``` +[root@zutuanxue ~]# nmcli connection add type team con-name team0 ifname team0 config '{"runner":{"name":"activebackup","hwaddr_policy":"by_active"}}' ipv4.addresses 192.168.98.200/24 ipv4.method manual autoconnect yes + +#JSON语法格式如下:’{“runner”:{“name”:“METHOD”}}’其中METHOD 是以下的其中一个 +broadcast=mode3 +roundrobin=mode0 +activebackup=mode1 +loadbalance=mode256 +lacp=mode4 +#"hwaddr_policy":"by_active":硬件地址跟随活跃的网卡,也就是未故障的网卡 +#聚合链路获取mac的地址有两种方式,一种是从第一个活跃网卡中获取mac地址,然后其余的SLAVE网卡的mac地址都使用该mac地址;另一种是使用hwaddr_policy参数,team使用当前活跃网卡的mac地址,mac地址随活跃网卡的转换而变,虚机不支持第一种获取MAC地址的方式。 +``` + +**step 2:** 添加网卡 + +``` +[root@zutuanxue ~]# nmcli connection add type team-slave ifname ens33 master team0 +[root@zutuanxue ~]# nmcli connection add type team-slave ifname ens37 master team0 +``` + +**step 3:** 启用连接 + +``` +[root@zutuanxue ~]# nmcli connection up team-slave-ens33 +[root@zutuanxue ~]# nmcli connection up team-slave-ens37 +[root@zutuanxue ~]# nmcli connection up team0 +``` + +**step 4:** 查看状态 + +``` +[root@zutuanxue ~]# teamdctl team0 stat +setup: + runner: activebackup +ports: + ens33 + link watches: + link summary: up + instance[link_watch_0]: + name: ethtool + link: up + down count: 0 + ens37 + link watches: + link summary: up + instance[link_watch_0]: + name: ethtool + link: up + down count: 0 +runner: + active port: ens37 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \350\256\241\345\210\222\344\273\273\345\212\241.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \350\256\241\345\210\222\344\273\273\345\212\241.md" new file mode 100644 index 0000000..40d86ce --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \350\256\241\345\210\222\344\273\273\345\212\241.md" @@ -0,0 +1,312 @@ +## 一、什么是计划任务 + +每个人在生活当中或多或少都有一些工作,有的工作是按照一定周期循环的, 例如每天固定时间的闹铃、工作打卡等等; 有的工作则是临时发生的,例如刚好有亲友到访,需要你在一个特定的时间去车站迎接! 这个时候 Linux 的计划任务就可以派上场了! 在不考虑硬件与我们服务器的连接状态下,我们的 Linux 可以帮你提醒很多任务, 那么 Linux 的例行性工作是如何进行的? Linux 是通过 crontab 与 at 命令来实现的 + +**at :** + +at 是个可以处理仅执行一次就结束工作的命令,需要一个叫atd的服务支持,所以这个服务要启动 + +**crontab :** + +crontab 这个命令所设定的工作将会按照一定的周期去执行! 可循环的时间为分钟、小时、日期、每周、每月等。crontab 除了可以使用命令执行外,也可以通过编辑 /etc/crontab 来支持。与at相同,crontab也需要一个叫crond的服务 + +那么计划任务在系统当中到底有什么作用呢? + +**1、进行日志的切割 (log rotate):** +Linux 会主动的将系统所发生的各种信息都记录到日志中。随着使用时间的增长,日志文件会越来越大!我们知道大型文件不但占容量还会造成读写效能的困扰, 因此适时的将日志文件数据挪一挪,让旧的数据与新的数据分别存放,这样既能记录日志信息又能提高读写效率。这就是 logrotate 的任务! + +**2、日志文件分析 logwatch 的任务:** 如果系统发生了问题等,绝大部分的错误信息都会被记录到日志文件中, 因此系统管理员的重要任务之一就是分析日志。但你不可能手动通过 vim 等软件去查看日志文件,因为数据量太大! 我们可以通过一个叫“ logwatch ”的程序分析日志信息,在启动邮件服务的前提下,你的 root 老是会收到标题为 logwatch 的信件 + +**3、建立 locate 的数据库:** +有时候我们会通过locate命令来查询文件。而文件名数据库是放置到 /var/lib/mlocate/ 中。 这个数据库也是通过计划任务定期的执行updatedb命令去更新的 + +**4、RPM 软件日志文件的建立:** + +系统会经常安装或卸载软件包。为了方便查询,系统也会将这些软件包的名称进行记录! 所以计划任务也会定期帮助我们更新rpm数据库 + +**5、移除临时文件:** +软件在运行中会产生一些临时文件,但是当这个软件关闭时,这些临时文件可能并不会主动的被删除。有些时候这些文件对于系统来讲没有什么用处了,还占用磁盘空间。系统通过计划任务来定期来删除这些临时文件! + +## 二、仅执行一次的计划任务 + +首先,我们先来谈谈仅运行一次的计划任务at + +### 2.1、 atd 的启动与 at 运行的方式 + +在使用at之前我们要确保atd服务是运行的,这个需要我们去检查一下,因为并不是所有的发行版linux默认都是开启这个服务的,但是在CentOS中是默认开启的 + +``` +[root@zutuanxue ~]# systemctl status atd +● atd.service - Job spooling tools + Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; vendor preset: enabled) + Active: active (running) since Mon 2020-01-13 09:34:03 CST; 1h 17min ago +#查询atd服务的状态 + +[root@zutuanxue ~]# systemctl is-enabled atd +enabled + +#查询是否开启默认启动 + +如果没有启动 +[root@zutuanxue ~]# systemctl start atd +# 启动 +[root@zutuanxue ~]# systemctl enable atd +#设置为开启启动 +``` + +**at的工作模式** + +at在运行的时候会将定义好的工作以文本文件的方式写入 /var/spool/at/ 目录内,该工作便能等待 atd 这个服务的调用,但是出于安全考虑,并不是所有的人都可以使用 at 计划任务!所以系统给我们提供了两个文件 /etc/at.allow 与 /etc/at.deny 来进行 at 的使用限制! 加上这两个文件后, at 的工作情况其实是这样的: + +先找寻 /etc/at.allow 这个文件,写在这个文件中的用户才能使用 at ,没有在这个文件中的用户则不能使用 at (即使没有写在 at.deny 当中); + +如果 /etc/at.allow 不存在,就寻找 /etc/at.deny 这个文件,若写在这个 at.deny 的用户则不能使用 at ,而没有在这个 at.deny 文件中的用户,就可以使用 at ; + +如果两个文件都不存在,那么只有 root 可以使用 at 这个命令。 + +在大多数发行版当中,由于假设系统上的所有用户都是可信任的, 因此系统通常会保留一个空的 /etc/at.deny 文件,允许所有人使用 at 。如果有需要的话可以手动建立at.allow文件 + +### 2.2、at的使用 + +单一计划任务的进行就使用 at 这个命令!将 at 加上一个时间即可!基本的语法如下: + +``` +[root@zutuanxue ~]# at [-mldv] TIME +[root@zutuanxue ~]# at -c 工作序号 +选项与参数: +-m :当 at 的工作完成后,发邮件通知用户,需要mail服务 +-l :at -l 相当于 atq,查看用户使用at定制的工作 +-d :at -d 相当于 atrm ,删除一个工作; +-v :详细信息; +-c :查看指定工作的具体内容。 +TIME:时间格式 + HH:MM ex> 16:00 + 在今天指定的时刻进行,若该时刻已超过,则明天的这个时间进行此工作。 + HH:MM YYYY-MM-DD ex> 16:00 2021-07-30 + 指定在某年某月的某一天的时间进行该工作! + HH:MM[am|pm] [Month] [Date] ex> 04am Jun 15 另外一种年月日和时间的指定方式 + HH:MM[am|pm] + number [minutes|hours|days|weeks] ex> now + 5 minutes 五分钟之后 + ex> 04am + 3 days 三天后的上午四点 +``` + +at在使用过程中的时间指定很重要,另外在使用过程中如果涉及到路径的指定,强烈建议使用绝对路径,定义完成at之后使用键盘上的ctrl+d结束 + +**1、at 的管理** + +有的时候我用at定义完计划任务之后,发现命令有错误,此时我们就可以使用atq 与 atrm 进行管理。 + +``` +[root@zutuanxue ~]# atq +[root@zutuanxue ~]# atrm 工作编号 +[root@zutuanxue at]# atq +2 Fri Feb 21 16:00:00 2020 a root +# 在 2020-02-21 的 16:00 有一项工作,该项工作是root设置的,工作编号为2 +[root@zutuanxue ~]# atrm 2 +[root@zutuanxue ~]# atq # 没有任何信息,表示该工作被移除了! +``` + +这样,你可以利用 atq 来查询,利用 atrm 来删除,利用 at 来直接定义计划任务但是如果系统当前非常忙碌话,能不能让指定的工作在较闲的时候执行呢?那就是batch! + +**2、batch:系统有空时才进行后台任务** + +batch是at的一个辅助工具,也是利用at进行工作的,只是加入一些判断功能。它会在 CPU 的工作负载小于 0.8 的时候,才执行指定的工作! 这个负载指的是 CPU 在单一时间点所负责的工作数量。不是 CPU 的使用率! 比如说,如果我运行一个程序,这个程序可以使CPU 的使用率持续达到 100% , 但是 CPU 的负载接近与1,因为 CPU 仅负责一个工作,而我同时运行了两个这样的程序,那么 CPU 的使用率还是 100% ,但是工作负载则变成 2 了。 + +也就是说,当 CPU 的负载越大,CPU 必须要在不同的工作之间进行频繁的切换。所以会非常忙碌! 而用户还要额外进行 at 完成工作,就不太合理!所以才有 batch 命令的产生! + +CentOS从7开始,batch 已经不再支持时间参数了,所以我们在使用batch定制计划任务的时候可以这样输入 + +``` +root@zutuanxue at]# batch +warning: commands will be executed using /bin/sh +at> cp /etc/passwd /root +at> +job 4 at Mon Jan 13 11:31:00 2020 +[root@zutuanxue at]# cd +[root@zutuanxue ~]# ls +公共 模板 视频 图片 文档 下载 音乐 桌面 anaconda-ks.cfg initial-setup-ks.cfg passwd +``` + +所以,batch可以通过cpu负载自动判断是否可以执行指定的工作。 + +## 三、周期执行的计划任务 + +相对于 at 是仅执行一次的工作,周期执行的计划任务则是由 crond这个系统服务来控制的。同样各位在使用的时候也要确认一下此服务的状态 + +``` +[root@zutuanxue ~]# systemctl status crond +● crond.service - Command Scheduler + Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled) + Active: active (running) since Mon 2020-01-13 09:34:03 CST; 2h 0min ago +[root@zutuanxue ~]# systemctl is-enabled crond +enabled +``` + +### 3.1、如何使用 + +用户使用的是 crontab 这个命令来定义周期性的计划任务,但是为了安全性的问题, 与 at 同样的,我们可以限制使用 crontab 的用户账号!使用的限制数据有: + +**/etc/cron.allow:** +将可以使用 crontab 的账号写入其中,若不在这个文件内的用户则不可使用 crontab; + +**/etc/cron.deny:** +将不可以使用 crontab 的账号写入其中,若未记录到这个文件当中的用户,就可以使用 crontab 。 + +与 at 一样,以优先级来说, /etc/cron.allow 比 /etc/cron.deny 要高, 一般系统默认是提供 /etc/cron.deny , 你可以将允许使用 crontab 用户写入 /etc/cron.deny 当中,一个账号一行。crontab 建立计划任务会存放在 /var/spool/cron/ 目录中, + +crontab 的使用: + +``` +[root@zutuanxue ~]# crontab +-u :只有root可以使用,指定其它用户的名称 +-e :建立计划任务 +-l :查看计划任务 +-r :删除所有计划任务,若只删除一项,只能使用-e进行编辑 +[root@zutuanxue ~]# crontab -e +#执行后会打开一个vim的页面,每个任务一行 +0 12 * * * cp /etc/passwd /root +分 时 日 月 周 工作内容 +``` + +编辑完毕之后输入“ :wq ”保存退出, 在cron中每项工作 (每行) 的格式都是具有六个字段,这六个字段的意义为: + +| 意义 | 分钟 | 小时 | 日期 | 月份 | 周 | 命令 | +| ---- | ---- | ---- | ---- | ---- | ---- | -------- | +| 范围 | 0-59 | 0-23 | 1-31 | 1-12 | 0-7 | 工作内容 | + +比较有趣的是那个『周』!周的数字为 0 或 7 时,都代表『星期天』的意思!另外,还有一些辅助的字符,大概有底下这些: + +| 特殊字符 | 含义 | +| :------- | :----------------------------------------------------------- | +| *(星号) | 代表任何时刻 | +| ,(逗号) | 代表分隔时段的意思。如3:00 与 6:00 时,就是:0 3,6 * * * | +| -(减号) | 代表一段时间范围内,如:8 点到 12 点之间的每小时的 20 分都进行一项工作:20 8-12 * * * | +| /n(斜线) | n 代表数字,间隔的单位的意思,如每五分钟进行一次,则:*/5 * * * * 也可以写成 0-59/ | + +``` +[root@zutuanxue ~]# crontab -l #查看root的计划任务 +0 16 1 * * cp /etc/passwd /root +root@zutuanxue ~]# crontab -u oracle -l +#查看指定用户的计划任务 +no crontab for oracle +[root@zutuanxue ~]# crontab -r #删除所有计划任务 +[root@zutuanxue ~]# crontab -l +no crontab for root +``` + +注意:crontab在使用的时候如果遇到路径,同样建议使用绝对路径,如果只是要删除某个项目,使用 crontab -e 来重新编辑,如果使用 -r 的参数,是会将所有的 crontab 内容都删掉。 + +### 3.2、系统的配置文件: /etc/crontab, /etc/cron.d/* + +crontab -e是针对用户 来设计的,系统的计划任务是通过/etc/crontab文件来实现的,我们只要编辑/etc/crontab 这个文件就可以,由于cron的最低检测时间是分钟,所以编辑好这个文件,系统就会自动定期执行了 + +``` +[root@zutuanxue ~]# cat /etc/crontab +SHELL=/bin/bash +PATH=/sbin:/bin:/usr/sbin:/usr/bin +MAILTO=root + +# For details see man 4 crontabs + +# Example of job definition: +# .---------------- minute (0 - 59) +# | .------------- hour (0 - 23) +# | | .---------- day of month (1 - 31) +# | | | .------- month (1 - 12) OR jan,feb,mar,apr ... +# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat +# | | | | | +# * * * * * user-name command to be executed +``` + +与crontab -e的内容类似,但是多了几个部分 + +``` +SHELL=/bin/bash shell类型 +PATH=/sbin:/bin:/usr/sbin:/usr/bin 执行文件搜索位置 +MAILTO=root 发生错误时通知邮件发送给谁 + +* * * * * user-name command to be executed +#比crontab -e多了一个执行者的身份,因为并不是所有工作都需要root用户去执行 +``` + +**额外的文件** + +crond有三个相关联的地方,他们分别是: + +/etc/crontab 系统计划任务的配置文件 + +/etc/cron.d/ 此目录和下面的几个目录都是系统计划任务存放运行脚本的位置。 + +/etc/cron.hourly/ + +/etc/cron.daily/ + +/etc/cron.weekly/ + +/etc/cron.monthly/ + +/var/spool/cron/* 用户定制的计划任务存放位置 + +## 四、anacron + +有些时候,在cron需要执行相应工作的时候,你的系统关机了,该如何处理?这个时候就需要使用anacron + +### 4.1、什么是 anacron + +anacron 并不是用来取代 crontab 的,anacron 存在的目的就在于处理由于一些原因导致cron无法完成的工作 + +其实 anacron 也是每个小时被 crond 执行一次,然后 anacron 再去检测相关的工作任务有没有被执行,如果有未完成的工作, 就执行该工作任务,执行完毕或无须执行任何工作时,anacron 就停止了。我们可以通过/etc/cron.d/0hourly的内容查看到 + +``` +[root@zutuanxue ~]# cat /etc/cron.d/0hourly +# Run the hourly jobs +SHELL=/bin/bash +PATH=/sbin:/bin:/usr/sbin:/usr/bin +MAILTO=root +01 * * * * root run-parts /etc/cron.hourly +``` + +由于 anacron 默认会以一天、七天、一个月为期去检测系统未进行的 crontab 任务,因此对于某些特殊的使用环境非常有帮助。 + +那么 anacron 又是怎么知道我们的系统何时关机?这就得要使用 anacron 读取的时间记录文件 (timestamps) 了! anacron 会去分析现在的时间与时间记录文件所记载的上次执行 anacron 的时间,两者比较后若发现有差异, 那就是在某些时刻没有进行 crontab !此时 anacron 就会开始执行未进行的 crontab 任务了! + +## 4.2、anacron 与 /etc/anacrontab + +anacron 其实是一个程序并非一个服务!这个程序在系统当中已经加入 crontab 的工作!同时 anacron 会每个小时被主动执行一次!所以 anacron 的配置文件应该放置在 /etc/cron.hourly目录中 + +``` +[root@zutuanxue ~]# cat /etc/cron.hourly/0anacron +#!/bin/sh +# Check whether 0anacron was run today already +. +. +. +/usr/sbin/anacron -s +实际上,也仅仅是执行anacron -s命令,这个命令会根据/etc/anacrontab文件的定义去执行各项工作 +``` + +**anacrontab** + +``` +[root@zutuanxue ~]# cat /etc/anacrontab +# /etc/anacrontab: configuration file for anacron + +# See anacron(8) and anacrontab(5) for details. + +SHELL=/bin/sh +PATH=/sbin:/bin:/usr/sbin:/usr/bin +MAILTO=root +# the maximal random delay added to the base delay of the jobs +RANDOM_DELAY=45 #最大随机延迟时间,单位是分钟 +# the jobs will be started during the following hours only +START_HOURS_RANGE=3-22 #仅执行延迟多少个小时之内的任务 + +#period in days delay in minutes job-identifier command +1 5 cron.daily nice run-parts /etc/cron.daily +7 25 cron.weekly nice run-parts /etc/cron.weekly +@monthly 45 cron.monthly nice run-parts /etc/cron.monthly +间隔时间(天) 延迟时间(分钟) 工作名称 执行的内容 +``` + +以 /etc/cron.daily/ 那一行的为例 + +每隔一天,在开机后的第5分钟去执行cron.daily目录下的脚本 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \350\267\257\347\224\261\347\256\241\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \350\267\257\347\224\261\347\256\241\347\220\206.md" new file mode 100644 index 0000000..4679c95 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \350\267\257\347\224\261\347\256\241\347\220\206.md" @@ -0,0 +1,66 @@ +在前面的课程中我们知道使用route命令可以添加主机的路由信息,但是一旦系统重启相关的设置信息就会丢失,那么如何设置一个重启也不会丢失的路由信息呢? + +``` +[root@zutuanxue ~]# ifconfig +ens33: flags=4163 mtu 1500 + inet 192.168.98.200 netmask 255.255.255.0 broadcast 192.168.98.255 + inet6 fe80::2386:3dbd:531c:7bc1 prefixlen 64 scopeid 0x20 + ether 00:0c:29:a6:ad:95 txqueuelen 1000 (Ethernet) + RX packets 0 bytes 0 (0.0 B) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 37 bytes 4386 (4.2 KiB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +ens37: flags=4163 mtu 1500 + inet 192.168.123.123 netmask 255.255.255.0 broadcast 192.168.123.255 + inet6 fe80::a848:f674:db3b:a83e prefixlen 64 scopeid 0x20 + ether 00:0c:29:a6:ad:9f txqueuelen 1000 (Ethernet) + RX packets 5 bytes 1758 (1.7 KiB) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 38 bytes 4390 (4.2 KiB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +#我现在有两块网卡,这两块网卡的ip地址分别是192.168.98.200和192.168.123.123,假如发送到192.168.1.0/24这个网段的数据包需要通过200这块网卡发送出去,而发送到192.168.100.0/24这个网段的数据包需要通过123这块网卡发送出去,我该如何设置呢?使用命令的话我们可以 +[root@zutuanxue ~]# route add -net 192.168.1.0/24 gateway 192.168.98.1 dev ens33 +[root@zutuanxue ~]# route add -net 192.168.100.0/24 gateway 192.168.123.1 dev ens37 +[root@zutuanxue ~]# route -n +Kernel IP routing table +Destination Gateway Genmask Flags Metric Ref Use Iface +192.168.1.0 192.168.98.1 255.255.255.0 UG 0 0 0 ens33 +192.168.98.0 0.0.0.0 255.255.255.0 U 100 0 0 ens33 +192.168.100.0 192.168.123.1 255.255.255.0 UG 0 0 0 ens37 +192.168.123.0 0.0.0.0 255.255.255.0 U 101 0 0 ens37 +#这种方式只是临时的,我们来看一下该如何永久添加 +[root@zutuanxue ~]# route del -net 192.168.100.0/24 gateway 192.168.123.1 dev ens37 +[root@zutuanxue ~]# route del -net 192.168.1.0/24 gateway 192.168.98.1 dev ens33 +[root@zutuanxue ~]# route -n +Kernel IP routing table +Destination Gateway Genmask Flags Metric Ref Use Iface +192.168.98.0 0.0.0.0 255.255.255.0 U 100 0 0 ens33 +192.168.123.0 0.0.0.0 255.255.255.0 U 101 0 0 ens37 + + + +[root@zutuanxue ~]# vim /etc/sysconfig/network-scripts/route-ens33 +192.168.1.0/24 via 192.168.98.1 dev ens33 +[root@zutuanxue ~]# vim /etc/sysconfig/network-scripts/route-ens37 +192.168.100.0/24 via 192.168.123.1 dev ens37 +[root@zutuanxue ~]# systemctl restart NetworkManager + +[root@zutuanxue ~]# nmcli connection down ens33 ens37 +成功停用连接 "ens33"(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/1) + +成功停用连接 "ens37"(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/2) + +[root@zutuanxue ~]# nmcli connection up ens33 +连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/3) +[root@zutuanxue ~]# nmcli connection up ens37 +连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/4) +[root@zutuanxue network-scripts]# route -n +Kernel IP routing table +Destination Gateway Genmask Flags Metric Ref Use Iface +192.168.1.0 192.168.98.1 255.255.255.0 UG 100 0 0 ens33 +192.168.98.0 0.0.0.0 255.255.255.0 U 100 0 0 ens33 +192.168.100.0 192.168.123.1 255.255.255.0 UG 101 0 0 ens37 +192.168.123.0 0.0.0.0 255.255.255.0 U 101 0 0 ens37 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \350\277\233\347\250\213\347\256\241\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \350\277\233\347\250\213\347\256\241\347\220\206.md" new file mode 100644 index 0000000..81fbc65 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \350\277\233\347\250\213\347\256\241\347\220\206.md" @@ -0,0 +1,415 @@ +## 一、进程介绍 + +在说进程如何管理之前我们要涉及到进程的一些相关概念 + +**什么是进程**?进程(Process)是一个程序在其自身的虚拟地址空间中的一次执行活动。之所以要创建进程,就是为了使多个程序可以并发的执行,从而提高系统的资源利用率和吞吐量。简单来说进程就是一个程序的执行活动。 + +**进程和程序有什么不同?** + +程序:只是一个静态的指令集合;而进程是一个程序的动态执行过程,它具有生命期,是动态的产生和消亡的。 + +进程:是资源申请、调度和独立运行的单位,因此,它使用系统中的运行资源;而程序不能申请系统资源、不能被系统调度、也不能作为独立运行的单位,因此,它不占用系统的运行资源。 + +程序和进程无一一对应的关系。一方面一个程序可以由多个进程所共用,即一个程序在运行过程中可以产生多个进程;另一方面,一个进程在生命期内可以顺序的执行若干个程序。 + +**进程的属性** + + 在Linux系统中总是有很多进程同时在运行,每一个进程都有一个识别号,叫做PID(Process ID),用以区分不同的进程。 + +除了进程识别号外,每个进程还有另外四个识别号。它们是实际用户识别号(real user ID)、实际组识别号以及有效用户识别号(effect user ID),和有效组识别号(effect group ID)。实际用户识别号和实际组识别号的作用是识别正在运行此进程的用户和组。一个进程的实际用户识别号和实际组识别号就是运行此进程的用户的识别号(UID)和组的识别号(GID)。有效用户识别号和有效组识别号的作用是确定一个进程对其访问的文件的权限和优先权。一般有效用户识别号和有效组识别号和实际用户识别号及实际组识别号相同。除非程序被设置了SUID位或SGID位。 + +**进程间的父子关系** + +进程之间是有关联性的,有的进程会衍生出额外的进程,这时,这组进程之间就存在了父子关系,衍生出来的进程叫子进程,而原本的进程叫做父进程。 + +## 二、linux的工作调度 + +由于linux是一个多人多任务的操作系统,所以用户在使用linux的时候就会出现有些工作我们需要盯着完成的进度,而有些工作我们直接放在后台执行就可以了,这里面我们就涉及到任务的前后台执行的问题,那么,如何将一个任务放到后台去执行呢? + +#### 开启一个在后台执行的工作 + +``` +[root@zutuanxue ~]# cd / +[root@zutuanxue /]# tar -czf /tmp/test.tar.gz etc & (&表示后台执行) +[1] 13568 [1]工作序号;13568进程号(PID) +[root@zutuanxue /]# ls tmp/ | grep test +test.tar.gz + +执行完成后,会在下次敲回车的时候给用户一个反馈 +[1]+ 已完成 tar -czpf /tmp/test.tar.gz etc +``` + +#### 将当前的工作调到后台 + +``` +[root@zutuanxue /]# cd +[root@zutuanxue ~]# ls +公共 视频 文档 音乐 anaconda-ks.cfg +模板 图片 下载 桌面 initial-setup-ks.cfg +[root@zutuanxue ~]# vim anaconda-ks.cfg 按键盘上的ctrl+z是调到后台 + +[1]+ 已停止 vim anaconda-ks.cfg +注意由ctrl+z调到后台的工作状态为暂停 +``` + +那么如何将后台工作的状态更改为运行?如何查看后台有哪些工作呢? + +#### 后台工作的查看及状态的更改 + +``` +[root@zutuanxue ~]# jobs 查看后台工作 +[1]- 已停止 vim anaconda-ks.cfg +[2]+ 已停止 find / -print +[root@zutuanxue ~]# jobs -l 查看后台工作,并显示进程号 +[1]- 13663 停止 vim anaconda-ks.cfg +[2]+ 13732 停止 find / -print +[root@zutuanxue ~]# jobs -s 仅查看状态为停止的后台工作 +[1]- 已停止 vim anaconda-ks.cfg +[2]+ 已停止 find / -print +[root@zutuanxue ~]# jobs -r 仅查看状态为运行的后台工作 + ++: 当使用命令将后台任务调到前台时,默认调用有此标记的任务,也就是最近被调到后台的 +-: 倒数第二个被调到后台的任务 + + +[root@zutuanxue ~]# fg %工作序号(%可省略) 将后台指定的工作调到前台 +[root@zutuanxue ~]# find / -name \*a\* > /tmp/test.txt +^Z 执行一个命令,迅速使用ctrl+z将任务调到后台 +[2]+ 已停止 find / -name \*a\* > /tmp/test.txt +[root@zutuanxue ~]# bg %2;jobs 连续执行两条命令,1.使用bg命令将之前的工作状态更改为运行;2.立即使用jobs命令查看状态 +[2]+ find / -name \*a\* > /tmp/test.txt & +[1]+ 已停止 vim anaconda-ks.cfg +[2]- 运行中 find / -name \*a\* > /tmp/test.txt & + +注意:更改后台工作状态和查看后台工作状态的命令也可以在终端分别输入,但是如果命令执行的较快的话可能会出现下面的这种情况,也就是状态显示为已完成 +[root@zutuanxue ~]# find / -name \*a\* > /tmp/test.txt +^Z +[2]+ 已停止 find / -name \*a\* > /tmp/test.txt +[root@zutuanxue ~]# jobs +[1]- 已停止 vim anaconda-ks.cfg +[2]+ 已停止 find / -name \*a\* > /tmp/test.txt +[root@zutuanxue ~]# bg %2 +[2]+ find / -name \*a\* > /tmp/test.txt & +[root@zutuanxue ~]# jobs +[1]+ 已停止 vim anaconda-ks.cfg +[2]- 已完成 find / -name \*a\* > /tmp/test.txt +``` + +#### 管理后台工作 + +我们可以通过kill命令配合适当的信号来管理后台的工作,信号是进程间通信的最原始机制,不同的信号,有不同的作用,比如说,一个进程接收到了一个让它打开指定文件的信号,那这个进程就去打开这个文件,而不会去考虑原因 + +``` +[root@zutuanxue ~]# kill %工作序号 + -l 查看 + -1 重新加载,systemctl reload servername + -2 保存数据并结束 ctrl+c + -9 强制结束不管其状态 常用在无法正常终止的程序上 + -15 正常结束(默认值) systemctl stop servername +[root@zutuanxue ~]# jobs +[1]+ 已停止 vim anaconda-ks.cfg +[root@zutuanxue ~]# kill -9 %1 +[1]+ 已停止 vim anaconda-ks.cfg +[root@zutuanxue ~]# jobs +[1]+ 已杀死 vim anaconda-ks.cfg +[root@zutuanxue ~]# jobs +``` + +## 三、进程的查看与管理 + +在linux中,我们可以通过fg、bg、jobs、kill等来对工作进行管理和调度,这些工作都是我们手动执行的,而那些由系统开启的工作该如何管理呢?管理这些后台工作我们可以使用两种命令ps和top + +``` +[root@zutuanxue ~]# ps #静态进程管理命令,可以帮助我们查看到ps命令在执行那一刻后台进程的状态 +-A 所有进程,等同于-ax +-a 显示所有进程(与终端有关的除外) +-x 与参数a一起使用等同于-A +-u 显示指定用户的进程 +-l 长格式 +-f 完整输出 +-t 从指定终端启动的进程 +-C 执行指定命令的进程 +[root@zutuanxue ~]# ps aux #查看系统后台的所有进程 +USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND +root 1 0.0 0.1 252828 11580 ? Ss 10月23 0:04 /us... +root 2 0.0 0.0 0 0 ? S 10月23 0:00 [kthreadd] +root 3 0.0 0.0 0 0 ? I< 10月23 0:00 [rcu_gp] +root 4 0.0 0.0 0 0 ? I< 10月23 0:00 [rcu_par_gp] +root 6 0.0 0.0 0 0 ? I< 10月23 0:00 [kworker/0:0H-kblockd] +root 8 0.0 0.0 0 0 ? I< 10月23 0:00 [mm_percpu_wq] +root 9 0.0 0.0 0 0 ? S 10月23 0:00 [ksoftirqd/0] + + +USER 开启进程的用户 +PID 进程的识别号 +%CPU 进程的cpu占用率 +%MEM 进程的物理内存占用率 +VSZ 虚拟内存用量,单位Kbytes +RSS 物理内存占用量 Kbytes +TTY 那个终端开启的 +STAT 进程的状态 +START 开启时间 +TIME CPU占用时间 +COMMAND 执行具体内容 + +[root@zutuanxue ~]# ps -l 查看当前用户开启的进程 +F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD +0 S 0 5191 5189 0 80 0 - 6994 - pts/1 00:00:02 bash +0 R 0 14972 5191 0 80 0 - 11240 - pts/1 00:00:00 ps + +F 进程标识 4=权限为root 1=从父进程派生出来但是没有执行 5=1+4 0=没有被设置 +S 进程状态 R=运行 S=睡眠,可被唤醒 D=睡眠,不可被唤醒(资源不足引起)T=停止 + Z=僵尸进程 +UID 用户识别号 +PID 进程识别号 +PPID 父进程号 +C cpu使用率 % +PRI 内核调度优先级 +NI 用户设置优先级 +ADDR 加载到内存的位置,如果是运行的会用-表示 +SZ 用掉的内存页的大小,1个内存页=4096Bytes 也就是6994x4=27976K内存 +WCHAN 当前进程在哪个内核函数上睡眠,-表示正在运行,没有睡眠 +TTY 由哪个终端开启的 pts/n=图形界面或远程 ttyn=字符界面 ?=系统进程 +TIME 用掉的CPU时间 +CMD 执行的命令 +``` + +ps只能显示它运行的那一刻的进程的统计信息,如果你想动态的查看就需要使用top + +top动态查看 + +``` +[root@zutuanxue ~]# top +-d 指定两次刷新的时间间隔,默认是3秒 +-p 后面跟进程号,查看指定进程的状态,最多20个PID +-n 刷新指定次数后退出 +-b 批量模式,可以让top将内容输出到指定的位置 +top的按键 +? 显示帮助 +空格&enter 刷新 +E 切换统计信息部分,内存显示的单位 +e 切换任务列表的内存显示的单位 +l 显示或隐藏摘要信息中的负载统计(第一行内容) +t 切换显示或隐藏摘要信息中任务和CPU统计信息(第2,3行内容) +m 切换显示或隐藏摘要信息中内存统计(第4,5行内容) +u 查看指定用户的进程 +M 根据内存排序 +P 根据cpu排序 +N 根据PID排序 +R 反向排序 +F/f 调整任务列表显示的内容,默认只有PID,USER,PR,NI....COMMAND等这些,可 以自定义还需要显示哪些内容,如果显示的列比较多可以使用进行左右移动 +shift+按照下一列的内容排序,比如说当前按照PID排序如果按下shift+>,则按照用户名 排序,再次按下就会按照PR排序,一次类推 +T 根据cpu使用时间排序 +k 杀死进程 +r 修改进程的nice值(优先级) +z 将不同的位置标记颜色 +x 高亮显示排序字段 +y 高亮显示正在运行的任务 +b 将高亮显示部分加上背景色 +Z 自定义颜色 +L 搜索指定字段,&下一个 +H 在进程和线程间切换显示和统计方式,默认为进程 +V 树形显示统计信息 +J 显示内容左对齐或右对齐 +c 切换COMMAND列的显示形式,程序名/命令格式 +i 显示或隐藏空闲进程 +u/U 查看指定用户的进程 +d 设置刷新间隔,默认3秒刷新一次 +W 将当前的设置写入到~/.config/procps/toprc中 +q 退出top +[root@zutuanxue ~]# top -d 1 +1 top - 18:57:05 up 12:56, 3 users, load average: 0.00, 0.00, 0.00 +2 Tasks: 280 total, 1 running, 279 sleeping, 0 stopped, 0 zombie +3 %Cpu(s): 1.5 us,1.5 sy,0.0 ni,97.0 id,0.0 wa,0.0 hi,0.0 si,0.0 st +4 MiB Mem : 3918.6 total, 160.1 free, 1264.5 used, 2494.0 buff/cache +5 MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 2356.6 avail Mem +6 +7PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND + 1 root 20 0 244408 13740 9100 S 0.0 0.3 0:08.77 systemd + 2 root 20 0 0 0 0 S 0.0 0.0 0:00.04 kthreadd 3 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_gp 4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 cu_par_gp + +1-6行显示的内容为 +1 当前时间为18:57:05;系统一共开机12小时56分;当前有3个用户登录;系统在1,5,15分钟的平均负载,越小表示系统越空闲 + +2 系统中进程的统计信息 总计280个,1个运行,279睡眠,0个停止,0个僵尸 + +3 cpu的负载 按键盘上的“1”可以按照CPU核心数显示 + us: 用户空间进程占用CPU时间百分比 + sy: 内核进程占用CPU时间百分比 + ni: 用户空间内改变过优先级的进程占用CPU时间百分比 + id: 空闲CPU时间百分比(100%表示系统完全空闲) + wa: I/O等待占用的CPU时间百分比 + hi: 硬件中断占用CPU时间百分比 + si: 软件中断占用CPU时间百分比 + st: 虚拟化hypervisor从当前虚拟机偷走的时间(如果这个值很高的话,说明你的提 供商的CPU资源有限,而你没能抢过别人,很有可能就是VPS提供商超售了.) +4&5 物理内存和虚拟内存相关的统计信息,尤其要注意swap,如果被大量占用,说明你物理内 存不足了 +6 在top中输入命令时,会显示在这里 +7 系统进程的信息 + PID: 进程ID + USER 进程所有者 + PR 进程优先级 + NI nice值,负数表示高优先级,正数表示低优先级 + VIRT 虚拟内存使用量,单位为KB。 + RES 进程使用的、未被换出的物理内存大小,单位为KB。 + SHR 进程使用共享内存大小,单位为KB。 + S 进程状态 + %CPU 进程对CPU的使用率。 + %MEM 进程对内存的使用率 + TIME+ 进程使用CPU时间总结,单位秒。 + COMMAND 命令 + +top显示的内容有些看不到怎么办? +[root@zutuanxue ~]# top -b -n1 > /tmp/top.txt +有些时候想查看的进程资源占用很低,在top中显示的比较靠后,怎么办? +[root@zutuanxue ~]# top -d 2 -p 3562 +Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie +%Cpu(s): 2.2 us, 3.9 sy, 0.0 ni, 93.3 id, 0.0 wa, 0.5 hi, 0.1 si, 0.0 st +MiB Mem : 3918.6 total, 1495.1 free, 1407.0 used, 1016.5 buff/cache +MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 2258.4 avail Mem + +PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND +3562 root 20 0 49296 6380 4448 S 0.0 0.2 0:00.08 bash +``` + +上面所提到的两个查看系统进程的命令,静态的ps和动态的top,他们所显示的内容比较多,有的时候我只想查看一下进程之间的关系,这个时候我可以使用另外的一条命令 + +``` +[root@zutuanxue ~]# pstree + A 进程之间使用ASCII字符连接 + U 进程之间使用UTF-8编码连接 + p 显示进程号 + u 显示用户 +[root@zutuanxue ~]# pstree -A | more +systemd-+-ModemManager---2*[{ModemManager}] + |-NetworkManager---2*[{NetworkManager}] + |-VGAuthService + |-accounts-daemon---2*[{accounts-daemon}] + |-alsactl + |-atd + |-auditd-+-sedispatch + | `-2*[{auditd}] +[root@zutuanxue ~]# pstree -U | more +systemd─┬─ModemManager───2*[{ModemManager}] + ├─NetworkManager───2*[{NetworkManager}] + ├─VGAuthService + ├─accounts-daemon───2*[{accounts-daemon}] + ├─alsactl + ├─atd + ├─auditd─┬─sedispatch + │ └─2*[{auditd}] +[root@zutuanxue ~]# pstree -pu | more +systemd(1)-+-ModemManager(916)-+-{ModemManager}(943) + | `-{ModemManager}(949) + |-NetworkManager(1040)-+-{NetworkManager}(1050) + | `-{NetworkManager}(1053) + |-VGAuthService(902) + |-accounts-daemon(1010)-+-{accounts-daemon}(1013) + | `-{accounts-daemon}(1015) + |-alsactl(909) + |-atd(1076) + |-auditd(862)-+-sedispatch(864) + | |-{auditd}(863) + | `-{auditd}(865) + |-avahi-daemon(910,avahi)---avahi-daemon(953) +``` + +我们现在可以通过三种方法来查看后台的进程,那么后台的进程该如何管理呢?管理后台的进程,除了我们前面提到的kill命令之外还可以使用killall + +``` +[root@zutuanxue ~]# kill PID +需要注意的是,kill后面如果加的是%num代表杀死后台指定序号的工作,如果不加%代表的是杀死指定进程号的进程,这两个是有区别的 +[root@zutuanxue ~]# killall + e 精确匹配,最多不能超过15个字符 + i 询问用户是否杀死指定名称的进程 + I 进程的名称忽略大小写 +[root@zutuanxue ~]# cat /dev/zero > /dev/null & +[1] 102245 +[root@zutuanxue ~]# ps -l +F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD +0 S 0 3562 3559 0 80 0 - 12324 - pts/1 00:00:00 bash +0 R 0 102245 3562 97 80 0 - 1908 - pts/1 00:00:01 cat +0 R 0 102246 3562 0 80 0 - 11240 - pts/1 00:00:00 ps +[root@zutuanxue ~]# killall -ei cat +杀死 cat(102870) ? (y/N) y +[1]+ 已终止 cat /dev/zero > /dev/null +``` + +## 四、进程的优先级 + +之前我们在查看进程的时候看到两个东西,一个是PRI一个是NI,这两个东西是用来控制进程的优先级,而优先级又决定了CPU先处理谁的数据,后处理谁的数据。一起来看下如何调整进程的优先级 + +``` +[root@zutuanxue ~]# ps -l +F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD +0 S 0 3562 3559 0 80 0 - 12522 - pts/1 00:00:00 bash +0 R 0 85520 3562 0 80 0 - 11240 - pts/1 00:00:00 ps +``` + +linux当中的每一个程序都有一个优先级,也就是PRI,这个数值越小则代表优先级越高,而PRI这个值是由内核控制的,用户无法更改,用户如果想调整程序的优先级就只能调整NI的值,所以linux中优先级的算法就是 新的优先级=旧的优先级+NI的值,比如说我bash那个进程,PRI是80,并且假定内核不会动态调整这个值,如果我将NI值更改为-10的话,那么新的PRI的值就是70,数值变小,意味着这个进程的优先级提高了。但是如果内核在这个过程中动态调整了,最终的值就不确定了。 + +这个NI的值都可以设置成多少呢? + +root用户:-20~19 + +普通用户:0~19 + +``` +[root@zutuanxue ~]# nice 指定新执行的进程的优先级 + -n 指定优先级 +[root@zutuanxue ~]# vim 1& +[1] 108831 +[root@zutuanxue ~]# ps -l +F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD +0 S 0 3562 3559 0 80 0 - 12522 - pts/1 00:00:00 bash +0 T 0 108831 3562 0 80 0 - 9058 - pts/1 00:00:00 vim +0 R 0 108832 3562 0 80 0 - 11240 - pts/1 00:00:00 ps + +[1]+ 已停止 vim 1 +[root@zutuanxue ~]# nice -n 10 vim 2& +[2] 109328 +[root@zutuanxue ~]# ps -l +F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD +0 S 0 3562 3559 0 80 0 - 12522 - pts/1 00:00:00 bash +0 T 0 108831 3562 0 80 0 - 9058 - pts/1 00:00:00 vim +0 T 0 109328 3562 0 90 10 - 9058 - pts/1 00:00:00 vim +0 R 0 109396 3562 0 80 0 - 11240 - pts/1 00:00:00 ps + +[2]+ 已停止 nice -n 10 vim 2 +[root@zutuanxue ~]# nice -n -20 vim 3 & +[3] 109470 +[root@zutuanxue ~]# ps -l +F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD +0 S 0 3562 3559 0 80 0 - 12522 - pts/1 00:00:00 bash +0 T 0 108831 3562 0 80 0 - 9058 - pts/1 00:00:00 vim +0 T 0 109328 3562 0 90 10 - 9058 - pts/1 00:00:00 vim +4 T 0 109470 3562 0 60 -20 - 9058 - pts/1 00:00:00 vim +0 R 0 109471 3562 0 80 0 - 11240 - pts/1 00:00:00 ps + +[3]+ 已停止 nice -n -20 vim 3 + +那如何调整一个已经启动的进程的优先级呢? +[root@zutuanxue ~]# vim 1 & +[1] 115098 +[root@zutuanxue ~]# vim 2 & +[2] 115099 + +[1]+ 已停止 vim 1 +[root@zutuanxue ~]# ps -l +F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD +0 S 0 3562 3559 0 80 0 - 12522 - pts/1 00:00:00 bash +0 T 0 115098 3562 0 80 0 - 9058 - pts/1 00:00:00 vim +0 T 0 115099 3562 0 80 0 - 9058 - pts/1 00:00:00 vim +0 R 0 115100 3562 0 80 0 - 11240 - pts/1 00:00:00 ps + +[2]+ 已停止 vim 2 +[root@zutuanxue ~]# renice 10 115098 +115098 (process ID) 旧优先级为 0,新优先级为 10 +[root@zutuanxue ~]# renice -10 115099 +115099 (process ID) 旧优先级为 0,新优先级为 -10 +[root@zutuanxue ~]# ps -l +F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD +0 S 0 3562 3559 0 80 0 - 12522 - pts/1 00:00:00 bash +0 T 0 115098 3562 0 90 10 - 9058 - pts/1 00:00:00 vim +0 T 0 115099 3562 0 70 -10 - 9058 - pts/1 00:00:00 vim +0 R 0 115736 3562 0 80 0 - 11240 - pts/1 00:00:00 ps +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \351\232\220\350\227\217\346\235\203\351\231\220.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \351\232\220\350\227\217\346\235\203\351\231\220.md" new file mode 100644 index 0000000..72dcc3e --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux \351\232\220\350\227\217\346\235\203\351\231\220.md" @@ -0,0 +1,43 @@ +## 隐藏权限的介绍 + +有时候你发现即时使用的是root用户也不能修改某个文件,大部分原因是因为使用过chattr命令锁定了该文件,这个命令的作用很大,通过chattr可以提高系统的安全性,但是这个命令并不适合所有的目录,如/dev,/tmp,/var。与我们前面看到的chmod这些命令修改权限不同的是chattr修改的是更底层的属性,这里面我们所提到的隐藏权限指的就是使用chattr来设置属性 + +## 隐藏权限的设置和查看 + +chattr的用户与我们之前讲的chmod,chow这些命令相似,都是直接对需要修改的文件进行操作就可以了 + +- **chattr命令:为文件设置隐藏权限** + +``` +命令选项 ++ 增加权限 +- 删除权限 += 赋予什么权限,文件最终权限 +A 文件或目录的atime不可被修改 +S 硬盘I/O同步选项,功能类似sync。 +a 只能向文件中添加数据,而不能删除,多用于服务器日志文件安全,只有root才能设定这个属性。 +d 文件不能成为dump程序的备份目标。 +i 设定文件不能被删除、改名、设定链接关系,同时不能写入或新增内容。 +``` + +- **lsattr命令: 查看文件隐藏权限** + +通过案例学习命令用法: + +``` +给file1文件添加AaiSd权限 +[root@zutuanxue test]# chattr +AaiSd file1 + +查看文件file1隐藏权限 +[root@zutuanxue test]# lsattr file1 +--S-iadA---------- file1 + +设置删除file1文件隐藏权限 +- 可以使用-号 +- 可以使用=为空设置 +[root@zutuanxue test]# chattr = file1 +[root@zutuanxue test]# lsattr file1 +------------------ file1 +``` + +通过上面的例子可以看到查看的时候使用的是lsattr,chattr还有很多参数,各位可以在man手册中获取到帮助,另外有些参数的使用是有局限性的。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\345\210\206\345\214\272\346\214\202\350\275\275.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\345\210\206\345\214\272\346\214\202\350\275\275.md" new file mode 100644 index 0000000..dd303eb --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\345\210\206\345\214\272\346\214\202\350\275\275.md" @@ -0,0 +1,193 @@ +磁盘在linux中经过分区、格式化后是无法直接使用的,因为该分区在系统中是以一个设备文件的形式存在的。我们如果希望使用这个磁盘分区还得经过最后一步,就是将这个分区设备挂载到系统中的某个文件夹下。这样你往这个挂载文件夹里存东西其实即使往分区里存东西了。 +接下来我们来看看linux下挂载磁盘分区的方式 + +- 手动挂载 +- 开机自动挂载 +- 触发挂载 + +## 一、手动挂载 + +mount挂载命令 + +``` +mount - mount a filesystem + +命令语法 +mount device dir + +命令选项 +-a 挂载所有文件系统,参考文件 /etc/fstab +-l 显示当前挂载 +-t 文件系统类型 +-o 指定挂载权限 + +##用法说明 +mount [options] 需要挂载的设备 挂载点 +特点:系统重启后需要重新挂载;手动卸载后需要手动挂载 + +-o:挂载选项 ro,sync,rw,remount +-t:文件系统类型 +mount -t nfs=mount.nfs +mount -t cifs=mount.cifs +``` + +挂载分区演示 + +``` +#案列1:以只读的方式重新挂载/u02分区 +[root@zutuanxue ~]# mount -o remount,ro /u02 //可以是挂载点也可以是设备 +remount:重新挂载一个正在挂载的设备 + +# mount -o remount,ro /dev/sdb1 +# mount -o remount,ro /u01 +注意:后面可以根挂载点也可以跟设备本身 + + +#案例2: 如果希望将本机的某个文件夹挂到另一个文件夹 +mount -o bind /etc /opt/data3 +``` + +设备表示方法: + +- 设备文件 +- 设备UUID +- 设备的卷标 + +``` +#设备文件: +/dev/sdb +/dev/sdb1 + +#通过UUID表示设备 +[root@zutuanxue ~]# blkid /dev/sdb1 //查看设备的UUID和文件系统类型 +/dev/sdb1: UUID="96b67b7b..." TYPE="xfs" PARTUUID="80e196f2-01" +[root@zutuanxue ~]# blkid /dev/sdb2 +/dev/sdb2: UUID="6821-049E" TYPE="vfat" PARTUUID="80e196f2-02" + + +#通过卷标表示设备 +#不同类型分区卷标管理与查看 +ext*设置&查看卷标 +[root@zutuanxue ~]# e2label /dev/sdb1 DISK1 ext*设置卷标 +[root@zutuanxue ~]# e2label /dev/sdb1 ext*查看卷标 + +xfs设置&查看卷标 +[root@zutuanxue ~]# xfs_admin -L DISK1 /dev/sdb1 xfs设置卷标 +[root@zutuanxue ~]# xfs_admin -l /dev/sdb1 xfs查看卷标 +label = "DISK1" + +vfat设置&查看卷标 +[root@zutuanxue ~]# dosfslabel /dev/sdb2 hello +[root@zutuanxue ~]# dosfslabel /dev/sdb2 + +也可以使用blkid查看卷标 +[root@zutuanxue ~]# blkid /dev/sdb1 +/dev/sdb1: LABEL="DISK1" UUID="96.." TYPE="xfs" PARTUUID="80..-01" +[root@zutuanxue ~]# blkid /dev/sdb2 +/dev/sdb2: LABEL="disk2" UUID="6..." TYPE="vfat" PARTUUID="8e.2-02" +``` + +umount设备卸载命令 +命令详解 + +``` +umount - 卸载文件系统 + +umount 设备挂载点|设备源 + +-l 懒惰卸载 +``` + +命令用法演示 + +``` +卸载设备:umount +[root@zutuanxue ~]# umount /u01 +[root@zutuanxue ~]# umount /dev/sdb2 +``` + +## 二、开机自动挂载: + +自动挂载 /etc/fstab文件 +特点:系统开机或重启会自动挂载;手动卸载后,使用mount -a自动挂载 + +``` +文件内容格式: +要挂载的资源路径 挂载点 文件系统类型 挂载选项 dump备份支持 文件系统检测 +UUID=289370eb-9459-42a8-8cee-7006507f1477 / ext4 defaults 1 1 + +#字段说明 +1段:挂载的设备(磁盘设备的文件名或设备的卷标或者是设备的UUID) +2段:挂载点(建议用一个空目录),建议不要将多个设备挂载到同一个挂载点上 +3段:文件系统类型(ext3、ext4、vfat、ntfs(安装软件包)、swap等等) +4段:挂载选项 +dev/nodev 被挂载的设备上的设备文件,是否被识别为设备文件 +async/sync 异步/同步 同步利于数据保存 异步利于提高性能 +auto/noauto 自动/非自动: +rw/ro 读写/只读: +exec/noexec 被挂载设备中的可执行文件是否可执行 +remount 重新挂在一个已经挂载的文件系统,常用于修改挂载参数 +user/nouser 允许/不允许其他普通用户挂载: +suid/nosuid 具有/不具有suid权限:该文件系统是否允许SUID的存在。 +usrquota 这个是在启动文件系统的时候,让其支持磁盘配额,这个是针对用户的。 +grpquota 支持用户组的磁盘配额。 +.... +defaults 同时具有rw, dev, exec, async,nouser等参数。 +更多挂载选项可以通过 man mount -o 命令选项可以找到详细信息 + +5段:是否支持dump备份。//dump是一个用来备份的命令,0代表不要做dump备份,1代表要每天进行dump的动作,2也代表其他不定日期的dump备份。通常这个数值不是0就是1。数字越小优先级越高。 + +6段:是否用 fsck 检验扇区。//开机的过程中,系统默认会用fsck检验文件系统是否完整。0是不要检验,1表示最先检验(一般只有根目录会设定为1),2也是要检验,只是1是最先,2是其次才进行检验。 + +# fsck -f /dev/sdb2 强制检验/dev/sdb2上文件系统 + +说明: +要挂载的资源路径可以是文件系统的UUID,设备路径,文件系统的标签 ,光盘镜像文件(iso),亦或是来自网络的共享资源等 +``` + +## 三、自动挂载 Automount: + +特点:挂载是由访问产生;卸载是由超时产生;依赖于后台的autofs服务 + +思路: + +1. 所有的监控都是由一个程序完成 autofs +2. 服务启动后才会监控挂载的设备 +3. 修改配置文件来指定需要监控的设备 + +案例演示 +需求:让系统自动挂载/dev/sdb2设备,如果2分钟没有被用自动卸载 + +``` +步骤: +1)安装autofs软件 +[root@zutuanxue ~]# rpm -q autofs +package autofs is not installed +[root@zutuanxue ~]# dnf install autofs + +[root@zutuanxue ~]# rpm -q autofs +autofs-5.1.4-29.el8.x86_64 +2)修改配置文件(指定需要监控的设备和挂载的目录) +vim /etc/auto.master //定义一级挂载点/u01和子配置文件 +/u01 /etc/auto.test -t 120 或者 --timeout 120 单位秒 (设置超时时间去卸载) + +vim /etc/auto.test //子配置文件自己创建,定义二级挂载点和需要挂载的设备 +test -fstype=ext4,ro :/dev/sdb2 + + +3)重启服务 +[root@zutuanxue ~]# systemctl restart autofs + +4)测试验证 +[root@zutuanxue ~]# ls /u01/test +[root@zutuanxue ~]# df -h + + +后续补充: +如果想要将/dev/sdb2挂载到/u01下,怎么做? +vim /etc/auto.master +/- /etc/auto.test + +vim /etc/auto.test +/u01 -fstype=ext4 :/dev/sdb2 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\345\220\257\345\212\250\345\270\270\350\247\201\351\227\256\351\242\230.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\345\220\257\345\212\250\345\270\270\350\247\201\351\227\256\351\242\230.md" new file mode 100644 index 0000000..d513c92 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\345\220\257\345\212\250\345\270\270\350\247\201\351\227\256\351\242\230.md" @@ -0,0 +1,96 @@ +## 一、忘记root密码 + +日常生活中,我们会接触到很多账号和密码,而这些账号和密码我们不能都很好的记忆,对于linux也是一样的,如果root密码忘记了怎么办?岂不是都无法登陆使用Linux了?现在我就教各位,在不知道root密码的前提下,如何给root设置一个新的密码 + +step 1 重启你的linux系统,在下图这个界面中按“E” + +![image20200112153327155.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996319687.png) + +step 2 将光标移动到开头为linux这行的行位,删除rhgb quiet并添加rd.break + +![image20200112153507293.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996339150.png) + +step 3 按键盘上的ctrl+x组合键继续启动linux,等待出现提示符后执行mount命令 + +![image20200112153640666.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996350235.png) + +step 4 执行chroot命令将根目录切换为/sysroot(因为硬盘上的数据都存放在/sysroot目录中) + +![image20200112153755987.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996365227.png) + +step 5 看到提示符发生变化后执行passwd命令修改root密码 + +![image20200112153933632.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996379180.png) + +注:由于字符编码问题可能会出现不能正常显示的情况,如: + +![image-20200112154028844](第九章 启动流程.assets/image-20200112154028844.png)没有关系,不影响密码的设置 + +step 6 修改完密码之后,建立autorelabel文件 + +![image20200112154548103.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996393570.png) + +step 7 输入两次exit退出,系统会继续启动 + +![image20200112154627704.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996407104.png) + +启动完成之后就可以用我们刚才设置的账号及密码进行登录了 + +## 二、GRUB2加密 + +前面我们知道了,如果不知道root密码的话,也是可以以root身份登录系统,那这样岂不是很危险?所以GRUB2又提供了一种保护机制,这种保护机制就是为grub2设置密码,如果用户不知道这个密码,是无法编辑启动时所看到的那个菜单的,这样也就组织了root密码被修改的问题,那么如何为grub2加密呢? + +setp 1 以root用户的身份登录系统并打开终端,在终端中输入grub2-setpassword命令,系统就会提示我们设置一个密码,这个密码就是grub2的密码 + +![image20200112155155252.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996426298.png) + +step 2 重启系统,验证是否加密成功 +![image20200112155226916.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996443802.png) + +step 3 在启动菜单界面按"E"编辑内容时,系统会提示输入用户名和密码,这个用户名是root,密码就是我们前面设置的grub2密码 + +![image20200112155403705.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996455058.png) + +注意:密码在输入的时候是不会显示任何信息的 + +step 4 如果密码输入错误就会返回启动菜单界面 + +![image20200112155529537.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996465934.png) + +## 三、删除/修改GRUB2密码 + +前面我们学会了如何为grub2设置密码,这样能有效的避免root用户密码被修改,但是如果我忘记了grub2的密码怎么办呢? + +如果忘记了grub2密码,你可以让系统正常启动,然后用root用户登录系统,登录完成后使用grub2-setpassword命令重新设置一个grub2密码,或者删除/boot/grub2/user.cfg文件将密码删除。 + +但是如果连root密码也不知道呢?这个时候,我们就需要用到修复模式了 + +step 1 插入系统光盘,选择从光盘启动 + +![image20200112160255030.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996486589.png) + +step 2 选择故障排除(troubleshooting) + +![image20200112160449625.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996498711.png) + +step 3 选择修复系统 + +![image20200112160639592.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996515055.png) + +step 4 启动完成后,系统提示我们,修复模式会查找硬盘上是否安装有Linux系统,并将其挂载到/mnt/sysimage目录下,我们希望它如何操作,选择1是以读写的形式挂载,选择2是以只读的形式挂载,选择3是直接获取一个shell,选择4是重启,这里面我们选择1 + +![image20200112161205845.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996527693.png) + +step 5 稍微等一下之后系统会提示我们已经挂载到/mnt/sysimage目录下了,按“enter”会得到一个shell + +![image20200112161319135.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996543674.png) + +step 6 执行chroot /mnt/sysimage将工作目录切换到硬盘中 + +![image20200112161421279.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996554318.png) + +step 7 接下来就像没有忘记root密码一样,可以重新设置grub2密码,或者删除user.cfg文件了,然后输入两次exit重启 + +![image20200112161615836.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996566428.png) + +![image20200112161628253.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602996588086.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\345\237\272\346\234\254\346\235\203\351\231\220.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\345\237\272\346\234\254\346\235\203\351\231\220.md" new file mode 100644 index 0000000..29541f0 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\345\237\272\346\234\254\346\235\203\351\231\220.md" @@ -0,0 +1,137 @@ +Linux系统是一个典型的多用户操作系统,不同的用户处于不同的地位,为了保护系统的安全性,linux系统对于不同用户访问同一个文件或目录做了不同的访问控制。而这种控制就是通过权限实现的,本节课我们介绍linux权限的使用 + +## 一、基本权限的介绍 + +Linux中每个文件或目录都有3个基本权限位,控制三种访问级别用户的读、写、执行,所以linux的基本权限位一共有9个。基本权限位和另外3个可以影响可执行程序运行的3个特殊权限位一起构成了文件访问模式。三个属性规定了对应三种级别的用户能够如何使用这个文件,这三个基本权限位对于文件和目录的含义有所差别的,我们一起来看一下 + +| 字符 | 权限 | 对文件的含义 | 对目录的含义 | +| ---- | ---- | -------------------------------------------- | ---------------------------- | +| r | 读 | 意味着我们可以查看阅读 | 可以列出目录中的文件列表 | +| w | 写 | 意味着,对文件可以修改或删除 | 可以在该目录中创建、删除文件 | +| x | 执行 | 如果是文件就可以运行,比如二进制文件或脚本。 | 可以使用cd命令进入该目录 | + +那三种访问级别都有哪些呢?每个文件都有三组不同的读、写和执行权限,分别适用于三种访问级别,其中每组中的三个栏位分别使用读取权限(r)、写入权限(w)、执行权限(x)或没有相应的权限(-)来表示,共9位来表示。 + +![1571370358704.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602399589987.png) + +- 第一组:适用于文件的属主,图中属主的权限是rwx。 +- 第二组:适用于文件的属组,图中属组的权限是r-x。 +- 第三组:使用于其它用户权限位,图中其它用户权限位是r-x。 + +当有人试图访问一个文件的时候,linux系统会按顺序执行如下步骤: + +(1)使用者拥有这个文件吗?如果是,启用用户权限。 + +(2)用户是组所有者成员吗?如果是,启用组权限 + +(3)如果以上两个都不是,启用其它人权限 + +上面我们提到的是第一种表示方法,在linux中还有另外一种表示方法,八进制表示法,我们来看下字母和八进制表示方法的对应关系 + +| 字符表示法 | 八进制表示法 | 含义 | +| ---------- | ------------ | ---- | +| r | 4 | 读 | +| w | 2 | 写 | +| x | 1 | 执行 | + +所以上面给出的权限rwxr-xr-x换成数字的表示方式就是755,那权限如何设置呢? + +## 二、基本权限的设置和查看 + +通过前面的学习我们知道,用户分为所有者,所有者组,其他人这三类,而每一类有包含三种基本权限,他们的对应关系是 + +| 权限位 | 含义 | +| -------------- | ------------------------------------------------------------ | +| 属主权限位 | 用于限制文件或目录的创建者 | +| 属组权限位 | 用于限制文件或目录所属组的成员 | +| 其它用户的权限 | 用于限制既不是属主又不是所属组的能访问该文件或目录的其他人员 | + +当我们使用命令来查看文件或目录时,会看如下内容 + +``` +[root@zutuanxue ~]# ls -l +总用量 13804 +drwxr-xr-x. 2 root root 6 10月 11 06:36 公共 +drwxr-xr-x. 2 root root 6 10月 11 06:36 模板 +drwxr-xr-x. 2 root root 6 10月 11 06:36 视频 +drwxr-xr-x. 2 root root 6 10月 11 06:36 图片 +drwxr-xr-x. 2 root root 6 10月 11 06:36 文档 +drwxr-xr-x. 2 root root 6 10月 11 06:36 下载 +drwxr-xr-x. 2 root root 6 10月 11 06:36 音乐 +drwxr-xr-x. 2 root root 6 10月 11 06:36 桌面 +-rw-------. 1 root root 1214 10月 11 06:12 anaconda-ks.cfg +-rw-r--r--. 1 root root 1369 10月 11 06:17 initial-setup-ks.cfg +``` + +每一行显示一个文件或目录的信息,这些信息包括文件的类型(1位)、文件的权限(9位)、文件的连接数、文件的属主(第3列)、文件的所属组(第4列),大小以及相关时间和文件名。其中Linux 文件的权限标志位九个,分为3 组,分别代表文件拥有者的权限,文件所属用户组的权限和其它用户的权限,现在我们知道文件有三种权限((r)读取、(w)写入和(x)执行)和三种访问级别((u)用户、(g)主要组和(o)其它人)决定文件可以被如何使用。那如何修改? + +- **chmod命令:修改文件权限** + +![1571375694210.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602399812604.png) + +| 缩写 | 含义 | +| ---- | -------------- | +| u | User(用户) | +| g | Group (组) | +| o | Other(其它) | +| a | All(所有) | +| + | Add(加) | +| - | Remove(减去) | +| = | Set (设置) | +| r | Read (可读) | +| w | Write (可写) | +| x | Execute (执行) | + +| 命令 | 作用 | 结果权限 | +| ------------------- | ------------------------------------ | ---------- | +| chmod o-r a.file | 取消其他人的可读权限 | rw-rw— | +| chmod g-w a.file | 取消组的写入权限 | rw-r–r-- | +| chmod ug+w a.file | 赋予用户和组写入权限 | rwxrwxr– | +| chmod o+w a.file | 赋予其他人写入权限 | rw-rw-rw- | +| chmod go-rwx a.file | 取消组和其他人的阅读、写入和执行权限 | rw------- | +| chmod a-w a.file | 取消所有人的写入权限 | r-- r-- r– | +| chmod uo-r a.file | 取消用户和其它人的阅读权限 | -w-rw–w- | +| chmod go=rw a.file | 将组和其他人的权限设置为阅读和写入 | rw-rw-rw- | + +使用数字的表示方式类似chmod 755 a,执行完成后a这个文件的权限对应就是 -rwxr-xr-x,这是文件权限的两种修改方式,如果你想修改文件的所有者和所有者组需要使用的命令就是chown,chgrp + +- **chown命令:改变文件或文件夹的所有者** + +``` +[root@zutuanxue test]# ll +总用量 0 +-rw-r--r-- 1 root root 0 10月 18 01:26 file1 +[root@zutuanxue test]# chown oracle file1 +[root@zutuanxue test]# ll +总用量 0 +-rw-r--r-- 1 oracle root 0 10月 18 01:26 file1 +``` + +- **chgrp命令: 改变文件或文件夹属组** + +``` +[root@zutuanxue test]# chgrp oracle file1 +[root@zutuanxue test]# ll +总用量 0 +-rw-r--r-- 1 oracle oracle 0 10月 18 01:26 file1 +``` + +这里,我们涉及到了三条与权限修改相关的命令 + +| 操作 | 可以执行的用户 | +| ----- | -------------------------------------- | +| chmod | Root用户和文件的所有者 | +| chgrp | Root用户和文件的所有者(必须是组成员) | +| chown | 只有root用户 | + +以上是三种基本权限 -R + +## 三、文件或目录的默认权限 + +每一个新产生的文件都会有一个默认的权限,这个权限是通过系统中的umask来控制的 + +文件的最大权限是666 + +目录的权限是777 + +使用umask查看 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\346\226\207\344\273\266\345\216\213\347\274\251\344\270\216\350\247\243\345\216\213.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\346\226\207\344\273\266\345\216\213\347\274\251\344\270\216\350\247\243\345\216\213.md" new file mode 100644 index 0000000..5e53575 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\346\226\207\344\273\266\345\216\213\347\274\251\344\270\216\350\247\243\345\216\213.md" @@ -0,0 +1,200 @@ +## 压缩工具的介绍 + +说到文件管理,就不得不说到tar,因为tar可以压缩和解压缩linux文件,所以要先了解一下压缩和解压缩。 + +由于以前的计算机磁盘容量比较小,业内人士绞尽脑汁,终于开发出了一个能帮助用户节省磁盘的工具,就是压缩工具,我们知道计算机在存储数据的时候都是使用bytes来计算的,但是实际上1byte=8bits,在日常使用中并不是所有的数据都能把这个1byte用完,有的可能用了三个bits,有的可能用了四个bits,而他们的实际占用空间是2bytes=16bits,剩余的空间就浪费了,压缩工具就是通过算法,将占用三个bits的数据和占用四个bits的数据放在一个byte里,这样我们就能节省出来1byte,这种空间的节省,当你在压缩一个包含了很多文本文件的目录时是非常明显的。其实就像没有人知道早高峰的公交车里有多少人一样,一个人理论上占用的公交车内的空间,跟实际占用的空间,往往有很大差别,因为挤挤总能上去的。 + +压缩工具诞生的初衷和原理我们说完了,那现在它就没用了么?依然有用,只不过现在我们使用压缩工具的目的,更多的是便于存储和传输,在linux系统中压缩工具有很多,不同的工具压缩后的后缀名和大小都有差异,从远古时代说起,linux都出现了以下这些格式的压缩文件 + +*.Z 使用compress压缩的文件 + +*.zip 使用zip压缩的文件 + +*.gz 使用gzip压缩 + +*.bz2 使用bzip2压缩 + +*.xz 使用xz压缩 + +*.tar 使用tar工具打包,没有压缩 + +*.tar.gz 使用tar工具打包,经过gzip压缩 + +*.tar.bz2 使用tar工具打包,经过bzip2压缩 + +*.tar.xz 使用tar工具打包,经过xz压缩 + +其中,compress已经过时了,因为太老,个别版本的linux已经不支持了,linux下的压缩工具还是以gzip和bzip2以及后加入的xz作为主力,但是由于这些工具,最早不能压缩目录,只能针对单一文件进行压缩,所以在日常使用中,他们都是配合着tar这个打包工具,由tar把目录中的很多文件打包成一个文件,再经由对应的工具进行压缩,所以我们会看上面的那些tar.*的压缩包。好了我们先来学习下这些压缩工具如何使用 + +``` +压缩文件的好处有如下几点: + +- 文件更小,便于网络传输,效率高; +- 避免杂乱,可以减少文件个数,多个文件一起压缩; +- 有些文件不能直接传输,比如安装程序,压缩后就可以传输了 +``` + +### 压缩工具的使用 + +- gzip + +``` +[root@zutuanxue ~]# gzip -h +Usage: gzip [OPTION]... [FILE]... + -c 保留源文件 + -d 解压缩 + -h 显示帮助 + -t 检查压缩文件的数据一致性,用来确定压缩文件是否有错误 + -v 显示压缩包的相关信息,包括压缩比等 + -V 显示版本号 + -1 压缩最快,压缩比低 + -9 压缩最慢,压缩比高 +例子: +[root@zutuanxue test]# pwd +/root/test +[root@zutuanxue test]# cp /etc/services ./ +[root@zutuanxue test]# gzip -v services +services: 79.4% -- replaced with services.gz +[root@zutuanxue test]# ll /etc/services services.gz +-rw-r--r--. 1 root root 692241 Sep 10 2018 /etc/services +-rw-r--r-- 1 root root 142549 Oct 20 23:32 services.gz +[root@zutuanxue test]# zcat services.gz +由于service文件本来就是一个文本文档,所以还可以使用zmore,zless去查看内容 +[root@zutuanxue test]# ls +services.gz +[root@zutuanxue test]# gzip -d services.gz +[root@zutuanxue test]# ls +services +我们可以看到,gzip这个工具压缩文件和源文件默认只保留一个,所以还可以 +[root@zutuanxue test]# gzip -1 -c services > test.gz +[root@zutuanxue test]# ls +services test.gz +[root@zutuanxue test]# zgrep -n ssh test.gz +44:ssh 22/tcp # The Secure Shell (SSH) Protocol +45:ssh 22/udp # The Secure Shell (SSH) Protocol +你也可以使用zgrep找出指定的关键字在压缩文件的那几行 +``` + +- bzip2 + +``` +[root@zutuanxue test]# bzip2 -h + -h 帮助 + -d 解压 + -z 压缩 默认值 + -k 保留源文件 + -v 查看版本信息 + -1 ..-9 同gzip相同 + bzip2的使用与gzip相同,两种工具的区别就是压缩算法不同,bzip2的压缩比更好一些,bzip的包查看的时候使用的是bzcat,bzmore,bzless,bzgrep同gzip用法相同 +[root@zutuanxue test]# gzip -c services > services.gz +[root@zutuanxue test]# bzip2 -k services +[root@zutuanxue test]# ll +总用量 948 +-rw-r--r-- 1 root root 692241 10月 21 01:31 services +-rw-r--r-- 1 root root 129788 10月 21 01:31 services.bz2 +-rw-r--r-- 1 root root 142549 10月 21 01:32 services.gz +``` + +- xz + 虽然bzip2的压缩效果相对比gzip已经提升很多,但是技术是永无止境的,于是出现了xz,它的用法跟gzip和bzip2一样 + +``` +[root@zutuanxue test]# xz -h + -d 解压缩 + -t 检查压缩文件的完整性 + -l 查看压缩文件的相关信息 + -k 保留源文件 + -c 将信息输出到显示器上 + -0 ... -9 指定压缩级别 + -h 显示帮助 +[root@zutuanxue test]# xz -k services +[root@zutuanxue test]# ll +总用量 1052 +-rw-r--r-- 1 root root 692241 10月 21 01:31 services +-rw-r--r-- 1 root root 129788 10月 21 01:31 services.bz2 +-rw-r--r-- 1 root root 142549 10月 21 01:32 services.gz +-rw-r--r-- 1 root root 105872 10月 21 01:31 services.xz +可以看到,在使用默认压缩比压缩的情况下,xz压缩完的文件体积更小 +[root@zutuanxue test]# xz -l services.xz 查看相关信息 +Strms Blocks Compressed Uncompressed Ratio Check Filename + 1 1 103.4 KiB 676.0 KiB 0.153 CRC64 services.xz +[root@zutuanxue test]# xzcat services.xz 查看文件内容 +[root@zutuanxue test]# xz -d services.xz 解压缩 + +虽然xz的压缩算法更好,但是相对来说时间也比较长 +[root@zutuanxue test]# time gzip -c services > services.gz +real 0m0.023s +user 0m0.020s +sys 0m0.003s +[root@zutuanxue test]# time bzip2 -k services +real 0m0.047s +user 0m0.043s +sys 0m0.003s +[root@zutuanxue test]# time xz -k services +real 0m0.264s +user 0m0.258s +sys 0m0.003s +我们可以使用time这个命令去对比一下时间gzip,bzip2,xz的时间分别是0.023,0.047,0.264,可以看到xz所使用的时间是比较长的,而这个时间会跟文件体积成正比,所以这三种压缩方式大家在使用的时候也要把时间成本考虑在内,除非你很富有。 +``` + +- tar + 前面我们提到了,大多数压缩工具只能针对单一文件进行操作,如果你要压缩目录的话就会很麻烦,这时候我们可以使用tar这个打包工具,将目录内的多个文件打包成一个文件,再进行压缩。 + +``` +[root@zutuanxue test]# tar --help +用法: tar [选项...] [FILE]... + -C 解压到指定目录 + -c 建立tar包 + -t 查看tar包内的文件 + -x 解压tar包 + -p 不修改文件属性 + -f 指定文件名称 + -j 使用bzip2算法 + -J 使用xz算法 + -z 使用gzip算法 + -P 允许压缩路径中包含有"/" + -v 显示详细信息 + -?, --help 查看帮助 + --exclude 压缩过程中排除指定的文件 +例: +压缩 +[root@zutuanxue test]# tar -czf etc.tar.gz etc +[root@zutuanxue test]# ls +etc etc.tar.gz +解压缩 +[root@zutuanxue test]# ls +etc.tar.gz +[root@zutuanxue test]# tar -xf etc.tar.gz +[root@zutuanxue test]# ls +etc etc.tar.gz +查看压缩包内容 +[root@zutuanxue test]# tar -tf etc.tar.gz +etc/ +etc/libreport/ +etc/libreport/workflows.d/ +etc/libreport/workflows.d/report_uploader.conf +etc/libreport/workflows.d/anaconda_event.conf +. +. +. +查询压缩包里面的文件信息 +[root@zutuanxue test]# tar -tvf etc.tar.gz |more +drwxr-xr-x root/root 0 2019-10-21 04:35 etc/ +drwxr-xr-x root/root 0 2019-10-21 04:35 etc/libreport/ +drwxr-xr-x root/root 0 2019-10-21 04:35 etc/libreport/workflows.d/ +. +. +. +解压压缩包指定的文件 +[root@zutuanxue test]# tar -tvf etc.tar.gz | grep shadow +---------- root/root 792 2019-10-21 04:35 etc/gshadow +---------- root/root 1506 2019-10-21 04:35 etc/shadow +---------- root/root 781 2019-10-21 04:35 etc/gshadow- +---------- root/root 1374 2019-10-21 04:35 etc/shadow- +-rw-r--r-- root/root 214 2019-10-21 04:35 etc/pam.d/sssd-shadowutils +[root@zutuanxue test]# tar -xf etc.tar.gz etc/shadow +[root@zutuanxue test]# ls +etc etc.tar.gz +[root@zutuanxue test]# ls etc +shadow +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\346\227\245\345\277\227\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\346\227\245\345\277\227\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262.md" new file mode 100644 index 0000000..81094a8 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\346\227\245\345\277\227\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262.md" @@ -0,0 +1,87 @@ +## 集中式日志服务器介绍 + +如果你负责管理数台的 Linux,你得登录每一台Linux 后,才能阅读其中的信息! 这样是不是很麻烦?? 那有没有什么更好的方案呢? + +Linux 的系统日志服务,允许你把信息传递到某一台 Linux 的系统日志服务中;那你就可以把一台 Linux 作为日志服务器 (*Log Server*),而其他的 Linux 则当作日志客户端。此时,在作为日志服务器中就可以保存所有日志客户端产生的信息,因此,你就可以在日志服务器中阅读信息,而不用登录到其他的主机了。 + +### **搭建流程** + +#### 环境准备: + +server:192.168.1.55 + +client:192.168.1.18 + +#### 关闭SELinux和防火墙 + +``` +关闭SELinux +[root@zutuanxue ~]# vim /etc/sysconfig/selinux +SELINUX=disabled +[root@zutuanxue ~]# reboot + +关闭防火墙 +[root@zutuanxue ~]# systemctl stop firewalld +[root@zutuanxue ~]# systemctl disable firewalld +``` + +#### 流程 + +**setp 1 修改server端rsyslog服务配置文件** + +``` +server +[root@zutuanxue ~]# vim /etc/rsyslog.conf +开放通过UDP协议514端口接收日志信息功能 + 19 module(load="imudp") + 20 input(type="imudp" port="514") +开放通过TCP协议514端口接收日志信息功能 + 24 module(load="imtcp") + 25 input(type="imtcp" port="514") +``` + + +**step 2 重启server端rsyslog服务** + +``` +[root@zutuanxue ~]# systemctl restart rsyslog #重启日志服务 +[root@zutuanxue ~]# systemctl status rsyslog #确认服务启动状态 +``` + +**step 3 修改client端rsyslog服务配置文件** + +``` +client +[root@zutuanxue ~]# vim /etc/rsyslog.conf + 67 *.* @192.168.1.55 + #告知客户端将所有日志信息使用UDP协议传送到日志服务器,日志服务器的ip地址为192.168.1.55 + + + + 68 #*.* @@192.168.1.55 + #也可以使用@@告诉客户端将所有日志信息使用TCP协议传送到日志服务器 +``` + +**step 4 重启client端rsyslog服务** + +``` +[root@zutuanxue ~]# systemctl restart rsyslog #重启日志服务 +[root@zutuanxue ~]# systemctl status rsyslog #查看服务状态 +``` + + **step 5 测试** + +``` +server端使用tail命令查看日志信息 +[root@zutuanxue ~]# tail -f /var/log/messages + +client使用logger工具产生测试日志 +[root@zutuanxue ~]# logger "this is a test from 192.168.1.18" + +如果在server端能查看到logger工具产生的内容就证明集中式日志服务器搭建成功 +Dec 6 21:18:21 localhost root[2519]: this is a test from 192.168.1.18 + + +注:其它的client端的设置都是相同的,这样我们就可以将很多台linux主机的日志信息都收集到一台主机上,方便查阅和后期的日志备份 +工作。 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\346\227\245\345\277\227\347\256\241\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\346\227\245\345\277\227\347\256\241\347\220\206.md" new file mode 100644 index 0000000..99864da --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\346\227\245\345\277\227\347\256\241\347\220\206.md" @@ -0,0 +1,295 @@ +## 一、日志服务的介绍 + +### 日志介绍 + +程序执行的时候,可以通过标准输出(stdout, Standard Output)与标准错误输出 (stderr, Standard Error Output)来输送信息,用户就可以了解该程序执行时发生了什么状况;可是对于在后台执行的服务器程序,或者Linux 内核本身来说,就没有办法这样做了。服务与内核启动后,会切断与终端机(Terminal) 或控制台(Console)的联机,如此一来,即使有信息通过标准输出、标准错误输出传送出去,用户也未必能从屏幕上看到信息。 + +更何况,用户根本不可能全天候在计算机前面,盯着屏幕上显示的信息啊!为了让 管理者可以随时监控服务所产生的信息,Linux 提供了一个日志服务,该服务可以收集(Collect)任何服务传递过来的信息,储存成为记录文件(Log File) 、或直接传送给某些用户,甚至也可以传送到其他计算机的系统日志服务。 + +### 日志的作用 + +**系统方面的问题** + +linux系统长时间运行,可能会出现一些软件,硬件方面的问题,这些问题都会记录到日志文件中,我们可以通过查看相应的日志文件,找出问题所在 + +**网络服务的问题** + +网络服务在运行过程中产生的信息都会记录到日志文件中,一旦服务出现问题,无法正常运行,我们可以通过查看相应的日志文件就知道服务出现了什么问题 + +**历史事件查询** + +由于日志服务每天都会将系统运行的信息保存到日志文件当中,所以我们也可以通过日志信息去追溯之前的系统运行状况 + +## 二、相关软件包和文件 + +### 软件包 + +``` +[root@zutuanxue ~]# rpm -qa | grep rsyslog +rsyslog-gssapi-8.37.0-9.el8.x86_64 +rsyslog-relp-8.37.0-9.el8.x86_64 +rsyslog-8.37.0-9.el8.x86_64 +rsyslog-gnutls-8.37.0-9.el8.x86_64 +``` + +### 相关文件 + +``` +配置文件:/etc/rsyslog.conf + +辅助配置文件:/etc/rsyslog.d/*.conf + +日志文件存放位置: /var/log/ + +执行文件:/usr/sbin/rsyslogd + +模块路径:/usr/lib64/rsyslog/ + +服务单元:/usr/lib/systemd/system/rsyslog.service +``` + +## 三、配置文件说明 + +### /etc/rsyslog.conf + +``` +[root@zutuanxue yum.repos.d]# grep '####' /etc/rsyslog.conf +#### MODULES ####定义模块 +#### GLOBAL DIRECTIVES ####定义全局环境 +#### RULES #### 定义规则 + + +模块定义 +module(load="imuxsock" # 提供对本地系统日志的支持 + SysSock.Use="off") # 关闭通过本地日志接口的信息接收功能,日志信息接收通过下面的imjournal模块 +module(load="imjournal" # 提供对systemd日志的访问 + StateFile="imjournal.state") # 定义状态文件,rsyslog用于记录文件上传进度,避免日志内容混乱 + + +全局环境设置 +# 定义工作目录 +global(workDirectory="/var/lib/rsyslog") + +# 使用默认的时间戳格式 +module(load="builtin:omfile" Template="RSYSLOG_TraditionalFileFormat") + +# 定义辅助配置文件位置 +include(file="/etc/rsyslog.d/*.conf" mode="optional") + +规则设置 +信息来源.安全级别 处理方式 + +信息来源 + kern:内核相关的日志 + user:用户相关的日志 + mail:邮件相关的日志 + daemon:系统服务相关的日志 + lpr: 打印相关的日志 + cron:计划任务相关的日志 + authpriv:认证相关的日志 + news:新闻相关的日志 + uucp:文件copy相关的日志 + local0-local7:自定义相关的日志信息 + *: 所有 +安全级别 + debug: 调试 + info: 消息 + notice: 注意 + warn,warning: 警告 + err,error: 错误 + crit: 严重级别 + alert: 需要立即修改该的信息 + emerg,panic: 内核崩溃,系统接近崩溃 + *:所有日志级别 + none:没有任何级别,也就是不记录日志信息 + +表达形式 +mail.err err+crit+alert+emerg +mail.=err err +mail.!err 除了err + +处理方式 +/PATH/FILENAME:将信息储存至 /PATH/FILENAME文件中。注意,如果要系统日志服务把信息储存到文件,该文件必须以 +斜线(/) 开头的绝对路径命名之。 +USERNAME:将信息送给已登录的用户。 +@HOSTNAME:代表使用udp协议将信息转送到远端的日志服务器。 +@@hostname:代表使用tcp协议将信息传送到远端的日志服务器 +*:将信息传送给所有已登录的用户。 +``` + +### 常见的日志文件及作用 + +/var/log/boot.log 系统启动时的日志。 + +/var/log/dnf.* dnf软件包管理器相关日志 + +/var/log/firewalld 防火墙日志 + +/var/log/lastlog 所有用户最后一次登录信息,需要使用lastlog命令查看 + +/var/log/maillog 电子邮件系统相关日志 + +/var/log/messages 整体的系统日志,具体记录范围取决于服务的配置文件 + +/var/log/wtmp 记录当前登录和过去登录的用户信息,使用last命令查看 + +### 日志文件的安全设置 + +``` +[root@zutuanxue ~]# chattr +a /var/log/messages +[root@zutuanxue ~]# lsattr /var/log/messages +-----a------------ /var/log/messages +``` + +### 日志的格式 + +``` +[root@zutuanxue ~]# tail /var/log/messages +Dec 6 03:29:09 localhost systemd[1]: Started PackageKit Daemon. +Dec 6 03:43:44 localhost systemd[1]: Starting dnf makecache... +Dec 6 03:43:44 localhost dnf[7594]: 元数据缓存近期已刷新。 +Dec 6 03:43:44 localhost systemd[1]: Started dnf makecache. + + +DATE TIME HOSTNAME APP(NAME)[PID]: MESSAGES + +每一个字段的意义如下说明: +DATE:信息发生的日期。 +TIME:信息发生的时间。 +HOSTNAME:信息发生的主机。 +APP:产生信息的软件。 +NAME:软件的名称,或是软件组件(Component)的名称。可以省略。 +PID:进程标识符 (Process ID)。可以省略。 +MESSAGES:信息的内容。 +``` + +## 四、日志切割 + +**日志切割介绍** + +随着系统时间使用的增长,日志文件的体积会越来越大,过大的日志文件对于查看或者备份来讲都是极为不便的。所以linux系统提供了一个日志切割工具,这个工具就是logrotate,用户可以用过这个工具对日志文件进行切割,系统也利用这个工具配合计划任务服务,定期的对系统日志进行切割。 + +**相关文件** + +``` +/etc/logrotate.conf 主配置文件,定义日志切割规则 +/etc/logrotate.d/ 辅助配置文件,可以让用户针对不类型的信息,定义不同的切割规则 +``` + +**主配置文件说明** + +``` +[root@zutuanxue ~]# vim /etc/logrotate.conf +weekly #定义切割周期为每周一次 +rotate 4 #默认保留四个文件 +create #切割完成后,建立一个新的文件继续存储日志信息 +dateext #定义切割后的文件名中要包含日期信息 +include /etc/logrotate.d #辅助配置文件的存放位置 +``` + +**辅助配置文件说明** + +``` +格式 +日志文件的名称(绝对路径) { + 额外的设置 +} + + +[root@zutuanxue ~]# vim /etc/logrotate.d/syslog +/var/log/cron +/var/log/maillog +/var/log/messages +/var/log/secure +/var/log/spooler +{ + missingok #如果文件丢失,转到下一个文件,不报告错误信息 + sharedscripts #定义执行的脚本,需要与endscript结合使用 + postrotate #定义执行完logrotate操作之后,执行的操作 + /usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true #重启日志服务 + endscript #定义执行的脚本,需要sharedscripts结合使用。 +} +``` + +**logrotate** + +``` +[root@zutuanxue ~]# logrotate -vf /etc/logrotate.conf +#参数说明 +v 显示详细信息 +f 强制切割 + +[root@zutuanxue ~]# logrotate -vf /etc/logrotate.conf +[root@zutuanxue log]# cd /var/log/ +[root@zutuanxue log]# ls +secure-20191206 boot.log-20191206 maillog-20191206 +btmp-20191206 messages-20191206 spooler-20191206 +wtmp-20191206 cron-20191206 +``` + +**系统如何使用logrotate** + +``` +linux系统通过计划任务去定期的执行切割动作 +[root@zutuanxue ~]# cat /etc/cron.daily/logrotate +#!/bin/sh + +/usr/sbin/logrotate /etc/logrotate.conf +EXITVALUE=$? +if [ $EXITVALUE != 0 ]; then + /usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]" +fi +exit $EXITVALUE +此文件定义了如果切割的操作执行成功的话,会调用logger命令记录一条标签为logrotate的日志信息到日志文件里 +``` + +## 五、systemd-journald.service + +很早之前,日志信息是需要等到开机完成并启动日志服务之后才会开始记录的,这种方式会导致开机过程中的信息无法记录,为了避免这种情况,内核用一个叫klogd的服务来记录开机过程中产生的日志信息,然后等到日志服务启动完再将这些信息交给日志服务。 + + 现在linux系统采用systemd来管理系统服务,而systemd又是第一个启动的服务,所以现在我们通过一个systemd自带的,名字叫systemd-journald的服务来协助记录日志信息。那是不是就意味着我们可以不使用rsyslog这个服务了呢?不能,因为systemd-journald服务使用内存来记录相关日志信息,断电之后内容消失,所以我们不能停止rsyslog服务,而且rsyslog服务有一个很重要的功能,可以对日志内容进行分类。 + + **journalctl命令** + +``` +systemd-journald提供了一个叫journalctl的工具用来查询它所记录的信息 +[root@zutuanxue ~]# journalctl + -n 显示最后的几行内容,默认为10行 + -r 倒序输出,最新的日志先输出 + -S/--since 开始的时间 + -U/--until 结束的时间 + -p 指定日志等级0-7,(0=emerg,1=alert,2=crit,3=err,4=warninig,5=notice,6=info,7=debug)如:4代表的就是0-4 +-f 持续输出,类似于tail的-f 使用ctrl+c结束 +--disk-usage 磁盘空间占用 +-u 指定单元,如 -u crond.service +--vacuum-size 释放日志文件占用的空间,如 --vacuum-size 1G +_PID=0 查看指定PID的信息 +_UID=0 查看指定UID的信息 + +[root@zutuanxue ~]# journalctl --since "YYYY-MM-DD 00:00:00" --until "YYYY-MM-DD 00:00:00" +[root@zutuanxue ~]# journalctl --since today +[root@zutuanxue ~]# journalctl --since yesterday --until today +[root@zutuanxue ~]# journalctl -u crond.service +[root@zutuanxue ~]# journalctl _SYSTEM_UNIT=crond.service +``` + +## 六、日志分析工具 + +虽然我们有相关的工具来查看日志信息,但是如果信息量过大的话查看起来也是比较费时的,所以linux系统给我们提供了一个日志分析工具,这个工具叫logwatch,它会每天分析日志信息,并将信息通过邮件的形式发送给root用户 + +**安装logwatch及相关软件包** + +``` +[root@zutuanxue ~]# dnf install logwatch -y +[root@zutuanxue ~]# dnf install sendmail -y +[root@zutuanxue ~]# systemctl start sendmail +[root@zutuanxue ~]# ll /etc/cron.daily/0logwatch +-rwxr-xr-x 1 root root 434 5月 11 2019 /etc/cron.daily/0logwatch +[root@zutuanxue ~]# /etc/cron.daily/0logwatch +[root@zutuanxue ~]# mail +Heirloom Mail version 12.5 7/5/10. Type ? for help. +"/var/spool/mail/root": 2 messages 1 new +1 logwatch@zutuanxue.l Sat Dec 7 01:50 57/2011 "Logwatch for localhos" +>N 2 logwatch@zutuanxue.l Sat Dec 7 01:52 56/2000 "Logwatch for localhos" +输入数字查看对应的邮件,输入q退出 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\346\234\215\345\212\241\347\256\241\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\346\234\215\345\212\241\347\256\241\347\220\206.md" new file mode 100644 index 0000000..7595d7e --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\346\234\215\345\212\241\347\256\241\347\220\206.md" @@ -0,0 +1,405 @@ +## systemctl命令 + +### 管理服务 + +我们一起来看一下在服务管理方面systemctl这个工具如何使用 + +``` +[root@zutuanxue ~]# systemctl start servername +start 启动服务 +stop 停止服务 +restart 重启服务(没启动的服务会启动) +try-restart 只重启正在运行的服务(没有运行则不启动) +reload 重载配置文件(修改完服务的配置文件后使用) +status 检查服务状态 +is-active 检查服务是否已经启动 +enable 设置服务开机时启动 +disable 设置服务开机时不启动 +is-enabled 查看服务是否开机自动启动 +mask 屏蔽一个服务 +unmask 取消屏蔽 + + +[root@zutuanxue ~]# systemctl status httpd +● httpd.service - The Apache HTTP Server 服务名称 + Loaded: loaded 加载到内存中;error加载失败;bad-setting无法理解单元配置文件中的设置;masked被屏蔽 (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled) 服务开机时是否启动 enabled为启动;disabled为不启动 + Active: active (running) since Mon 2019-11-18 15:56:46 CST; 1h 11min ago 服务当前的状态,active(running)为运行;active(exited)运行一次就退出了;active(waiting)运行中,但是再等待其它程序结束才能继续;inactive(dead)为没有运行;activating为启动中,deactivating停止中;failed启动失败 + Docs: man:httpd.service(8) 服务的帮助文档 + Main PID: 57779 (httpd) 服务的主进程号 + Status: "Running, listening on: port 80" 额外的状态信息 + Tasks: 213 (limit: 24882) 任务数量,含进程+线程 + Memory: 22.4M 当前占用的内存 + CGroup: /system.slice/httpd.service + ├─57779 /usr/sbin/httpd -DFOREGROUND + ├─57780 /usr/sbin/httpd -DFOREGROUND + ├─57781 /usr/sbin/httpd -DFOREGROUND + ├─57782 /usr/sbin/httpd -DFOREGROUND + └─57783 /usr/sbin/httpd -DFOREGROUND + Control Groups额外信息 +11月 18 15:56:46 localhost.localdomain systemd[1]: Starting The Apache HTTP Server... +11月 18 15:56:46 localhost.localdomain httpd[57779]: AH00558: httpd: Could not reliably determ> +11月 18 15:56:46 localhost.localdomain httpd[57779]: Server configured, listening on: port 80 +11月 18 15:56:46 localhost.localdomain systemd[1]: Started The Apache HTTP Server. + + +例: +[root@zutuanxue ~]# systemctl is-active atd +inactive +[root@zutuanxue ~]# systemctl start atd +[root@zutuanxue ~]# systemctl status atd +● atd.service - Job spooling tools + Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; vendor preset: enabled) + Active: active (running) since Mon 2019-11-18 18:36:26 CST; 7s ago + Main PID: 60620 (atd) + Tasks: 1 (limit: 24882) + Memory: 504.0K + CGroup: /system.slice/atd.service + └─60620 /usr/sbin/atd -f + +11月 18 18:36:26 localhost.localdomain systemd[1]: Started Job spooling tools. +[root@zutuanxue ~]# systemctl stop atd +[root@zutuanxue ~]# systemctl status atd +● atd.service - Job spooling tools + Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; vendor preset: enabled) + Active: inactive (dead) since Mon 2019-11-18 18:36:43 CST; 6s ago + Process: 60620 ExecStart=/usr/sbin/atd -f $OPTS (code=exited, status=0/SUCCESS) + Main PID: 60620 (code=exited, status=0/SUCCESS) + +11月 18 18:36:26 localhost.localdomain systemd[1]: Started Job spooling tools. +11月 18 18:36:43 localhost.localdomain systemd[1]: Stopping Job spooling tools... +11月 18 18:36:43 localhost.localdomain systemd[1]: Stopped Job spooling tools. +[root@zutuanxue ~]# systemctl is-enabled atd +enabled +[root@zutuanxue ~]# systemctl disable atd +Removed /etc/systemd/system/multi-user.target.wants/atd.service. +[root@zutuanxue ~]# systemctl is-enabled atd +disabled +[root@zutuanxue ~]# systemctl enable atd +Created symlink /etc/systemd/system/multi-user.target.wants/atd.service → /usr/lib/systemd/system/atd.service. +[root@zutuanxue ~]# systemctl is-enabled atd +enabled + +[root@zutuanxue ~]# systemctl stop atd +[root@zutuanxue ~]# systemctl mask atd +Created symlink /etc/systemd/system/atd.service → /dev/null. +[root@zutuanxue ~]# systemctl status atd +● atd.service + Loaded: masked (Reason: Unit atd.service is masked.) + Active: inactive (dead) + +11月 05 18:12:41 localhost.localdomain systemd[1]: Started Job spooling tools. +11月 18 18:34:15 localhost.localdomain systemd[1]: Stopping Job spooling tools... +11月 18 18:34:15 localhost.localdomain systemd[1]: Stopped Job spooling tools. +11月 18 18:36:26 localhost.localdomain systemd[1]: Started Job spooling tools. +11月 18 18:36:43 localhost.localdomain systemd[1]: Stopping Job spooling tools... +11月 18 18:36:43 localhost.localdomain systemd[1]: Stopped Job spooling tools. +[root@zutuanxue ~]# systemctl unmask atd +Removed /etc/systemd/system/atd.service. +[root@zutuanxue ~]# systemctl status atd +● atd.service - Job spooling tools + Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; vendor preset: enabled) + Active: inactive (dead) + +11月 05 18:12:41 localhost.localdomain systemd[1]: Started Job spooling tools. +11月 18 18:34:15 localhost.localdomain systemd[1]: Stopping Job spooling tools... +11月 18 18:34:15 localhost.localdomain systemd[1]: Stopped Job spooling tools. +11月 18 18:36:26 localhost.localdomain systemd[1]: Started Job spooling tools. +11月 18 18:36:43 localhost.localdomain systemd[1]: Stopping Job spooling tools... +11月 18 18:36:43 localhost.localdomain systemd[1]: Stopped Job spooling tools +``` + +### 查看服务 + +``` +[root@zutuanxue ~]#systemctl command --type=xxx --all +list-units 查看所有加载到内存中的单元 +list-unit-files 查看系统中所有安装的单元文件(存放在/usr/lib/systemd/system)的启用状态 +--type=xxx 单元类型 +--all 列出系统中所有加载的,不管状态为何 +[root@zutuanxue ~]# systemctl +UNIT LOAD ACTIVE SUB DESCRIPTION +sys.. loaded active plugged /sys..... +sys.. loaded active plugged /sys..... +sys.. loaded active plugged /sys..... +sys.. loaded active plugged /sys..... +sys.. loaded active plugged /sys..... +sys.. loaded active plugged /sys..... + +UNIT: 单元名称 +LOAD: 是否被加载 +ACTIVE: 高优先级单元状态,与SUB结合就是使用status查看的状态 +SUB: 低优先级单元状态 +DESCRIPTION:简介 + +[root@zutuanxue ~]# systemctl list-unit-files +UNIT FILE STATE +proc... static +-.mount generated +boot.mount generated +dev-hugepages.mount static +dev-mqueue.mount static +proc-fs-nfsd.mount static +proc-... static +sys-f... static +sys-... static +sys-ke.. static +tmp.mount static +var-lib.. static +var-lib.. static +cups.path.. enabled +systemd.. static + +查看指定类型的服务 +[root@zutuanxue ~]# systemctl --type target --all + UNIT LOAD ACTIVE SUB DESCRIPTION + basic.target loaded active active Basic System + bluetooth.target loaded active active Bluetooth + cryptsetup.target loaded active active Local... +● dbus.target not-found inactive dead dbus.target +[root@zutuanxue ~]# systemctl --type=target --all + UNIT LOAD ACTIVE SUB DESCRIPTION + basic.target loaded active active Basic System + bluetooth.target loaded active active Bluetooth + cryptsetup.target loaded active active Local... +● dbus.target not-found inactive dead dbus.target +[root@zutuanxue ~]# systemctl list-units --type=target --all + UNIT LOAD ACTIVE SUB DESCRIPTION + basic.target loaded active active Basic System + bluetooth.target loaded active active Bluetooth + cryptsetup.target loaded active active Local... +● dbus.target not-found inactive dead dbus.target + +使用systemctl切换运行级别 +[root@zutuanxue ~]# systemctl list-units --type target --all + UNIT LOAD ACTIVE SUB DESCRIPTION + basic.target loaded active active Basic System + bluetooth.target loaded inactive dead Bluetooth + cryptsetup.target loaded active active Local .. +● dbus.target not-found inactive dead dbus.target + emergency.target loaded inactive dead Emergency Mode + getty-pre.target loaded inactive dead Login.. + getty.target loaded active active Login Prompts + graphical.target loaded inactive dead Graphica..Interface +常用的target +graphical.target:图形模式 +multi-user.target:字符模式 +rescue.target:救援模式 +emergency.target:紧急模式,无法进入到救援模式时使用 +shutdown.target:关机 + +[root@zutuanxue ~]# systemctl get-default 查看默认运行级别 +graphical.target +[root@zutuanxue ~]# systemctl set-default multi-user.target 设置 +Removed /etc/systemd/system/default.target. +Created symlink /etc/systemd/system/default.target → /usr/lib/systemd/system/multi-user.target. +[root@zutuanxue ~]# systemctl isolate multi-user.target 切换 + + +除了可以使用上述方法设置和查看之外 系统还给我们提供了几个简单的命令,方便操作 +[root@zutuanxue ~]# systemctl poweroff 关机 +[root@zutuanxue ~]# systemctl reboot 重启 +[root@zutuanxue ~]# systemctl suspend 挂起 +[root@zutuanxue ~]# systemctl hibernate 休眠 +[root@zutuanxue ~]# systemctl rescue 进入到救援模式 +[root@zutuanxue ~]# systemctl emergency 进入到紧急模式 + + +查看服务之间的依赖关系 +[root@zutuanxue ~]# systemctl list-dependencies multi-user.target +查看multi-user.target依赖谁 +multi-user.target +● ├─atd.service +. +. +. +● ├─basic.target +● │ ├─-.mount +● │ ├─microcode.service +● │ ├─paths.target +● │ ├─slices.target +● │ │ ├─-.slice +● │ │ └─system.slice +● │ ├─sockets.target +● │ │ ├─avahi-daemon.socket +. +. +. +[root@zutuanxue ~]# systemctl list-dependencies multi-user.target --reverse 查看谁依赖multi-user.target +multi-user.target +● └─graphical.target +``` + +### 服务与端口 + + 我们知道在服务中分为系统服务和网络服务,系统服务是本机使用的,网络服务是给网络中的其它客户端使用的,那其它客户端是如何连接上的网络服务的呢?端口和协议,协议在我们之前的课程中了解过,那端口是什么呢? + +端口:设备与外界通讯的出口,分为虚拟端口和物理端口,物理端口又叫接口,比如电脑中可以插网线的RJ45接口等,而虚拟端口指的就是网络服务使用的通讯接口,是不可见的,这些每个虚拟端口都有一个编号,我们称之为端口号,系统当中有一个文件记录的服务和端口号以及协议的对应关系 + +``` +[root@zutuanxue ~]# cat /etc/services | more +服务名称 端口号/协议 描述 +ftp-data 20/tcp +ftp-data 20/udp +# 21 is registered to ftp, but also used by fsp +ftp 21/tcp +ftp 21/udp fsp fspd +ssh 22/tcp +ssh 22/udp +telnet 23/tcp +telnet 23/udp + +我们还可以使用netstat工具去查看自己的系统打开了哪些端口 +[root@zutuanxue ~]# netstat -antulp +a 查看所有服务以及对应的端口号 +n 将输出结果以数字的形式表示,而不是主机名,服务名等 +t 使用tcp协议 +u 使用udp协议 +l 只显示处于监听状态的 +p 显示程序的名称与进程号 +c 指定自动更新的间隔时间 秒 +r 查看路由表信息 +[root@zutuanxue ~]# netstat -antlup +Proto:协议 +Recv-Q:接收队列,如果接收队列阻塞,可能是受到拒绝服务攻击 +Send-Q:发送队列,如果发送队列不能很快清零,可能是有应用向外发送数据包过快,或者对方接收数据包不够快 +Recv-Q和Send-Q通常应该为0,如果不为0可能意味着有问题,数据包有堆积状态,可以接受短暂的非0状态 +Local Address:本地的地址和端口号 +Foreign Address: 外部地址和状态 +State: 端口状态 + CLOSED 端口未被使用中。 + LISTEN 监听中,可以连接 + SYN_SEND 处在TCP三次握手期间,已经发送SYN包后,等待对方的ACK包。 + SYN_RECV 处在TCP三次握手期间,已经收到SYN包后,进入SYN_RECV状态。 + ESTABLISHED 完成TCP三次握手,进入ESTABLISHED状态。可以进行通信。 + FIN_WAIT_1 在TCP四次挥手时,主动关闭端发送FIN包后,进入此状态。 + FIN_WAIT_2 在TCP四次挥手时,主动关闭端收到ACK包后,进入此状态。 + TIME_WAIT 在TCP四次挥手时,主动关闭端发送了ACK包之后,进入此状态, + 等待一段时间,让被动关闭端收到ACK包。 + CLOSING 在TCP四次挥手时,主动关闭端发送了FIN包后,没有收到对应的ACK 包,却收到对方的FIN包,此时,进入CLOSING状态。 + CLOSE_WAIT 在TCP四次挥手期间,被动关闭端收到FIN包后,进入此状态。 + LAST_ACK 在TCP四次挥手时,被动关闭端发送FIN包后,等待对方的ACK包。 + UNKNOWN 未知状态 +PID/Program name: 进程号/程序名称 + + +通过netstat命令可以看到自己的linux系统打开了哪些服务及端口号,如果有些端口不想被占用可以关闭相应的网络服务 +[root@zutuanxue ~]# systemctl list-units --all | grep avahi +avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack +avahi-daemon.socket loaded active running Avahi mDNS/DNS-SD Stack Activation Socket +可以看到这个服务的作用是为内网提供域名解析的 +[root@zutuanxue ~]# systemctl stop avahi-daemon.service +Warning: Stopping avahi-daemon.service, but it can still be activated by: + avahi-daemon.socket +[root@zutuanxue ~]# systemctl stop avahi-daemon.socket +[root@zutuanxue ~]# systemctl disable avahi-daemon.service avahi-daemon.socket +Removed /etc/systemd/system/multi-user.target.wants/avahi-daemon.service. +Removed /etc/systemd/system/sockets.target.wants/avahi-daemon.socket. +Removed /etc/systemd/system/dbus-org.freedesktop.Avahi.service. +``` + +### 服务设置相关文件 + +我们现在知道了服务的管理是通过systemctl,而它的设置文件存放在/usr/lib/systemd/system/目录下,但是官方不建议我们修改这个目录下的文件,如果需要修改的话,建议我们修改/etc/systemd/system/目录内的相关文件 + +``` +[root@zutuanxue ~]# yum install dhcp-server +[root@zutuanxue ~]# systemctl enable dhcpd +Created symlink /etc/systemd/system/multi-user.target.wants/dhcpd.service → /usr/lib/systemd/system/dhcpd.service. +[root@zutuanxue ~]# cd /etc/systemd/system/ +[root@zutuanxue system]# ls +在此目录中包含的文件有三种功能 +*.service 服务的设置文件 +*.wants 此单元可选的依赖,启动指定单元后,建议启动此目录内的单元 +*.requires 此单元必要的依赖,启动指定单元前,需要启动此目录内的单元 + +服务的设置文件 +[root@zutuanxue system]# vim /etc/systemd/system/multi-user.target.wants/dhcpd.service + +[Unit] 对于此单元的简介 +Description=DHCPv4 Server Daemon +Documentation=man:dhcpd(8) man:dhcpd.conf(5) +Wants=network-online.target +After=network-online.target +After=time-sync.target + +Unit部分会出现的常见内容 + Description 简介 + Documentation 如何进一步查询相关信息 + Wants 与当前单元配合的单元,如果这些单元没有运行,此单元不会启动失败 + After 在哪些单元之后启动此单元 + Befor 在哪些单元之前启动此单元 + Requires 当前单元依赖的单元,如果这些单元没有运行,此单元启动失败 + Conflicts 哪些单元与此单元冲突 +[Service] 这是一个服务还可能是Socket、Timer、Mount等 +Type=notify +EnvironmentFile=-/etc/sysconfig/dhcpd +ExecStart=/usr/sbin/dhcpd -f -cf /etc/dhcp/dhcpd.conf -user dhcpd -group dhcpd --no-pid $DHCPDARGS +StandardError=null + +Service部分会出现的内容 + Type 启动时,相关进程的行为 + simple 默认值 + oneshot 一次性进程,systemd会等待当前服务结束,再继续执行 + notify 启动完毕后通知systemd + idle 所有其它任务执行完毕后,此服务才会运行 + EnviromentFile 指定环境变量配置文件 + Enviroment 指定环境变量 + ExecStart 执行什么命令启动当前服务 + ExecStartPre 启动当前服务之前执行什么命令 + ExecStartPost 启动当前服务之后执行什么命令 + ExecStop 执行什么命令停止当前服务 + ExecStopPost 停止当前服务后执行什么命令 + ExecReload 执行什么命令重新加载服务的配置文件 + Restart 服务正常退出、异常退出、被杀死、超时的时候是否重启。常用值 + no 不重启 + always 无条件重启 + on-failure 异常退出时重启 + RestartSec 自动重启服务的间隔时间 + RemainAfterExit 此服务的进程全部退出之后,是否依然将服务的状态视为active状态 + TimeoutSec 定义服务启动或停止的超时时间 + KillMode 服务停止时,杀死进程的方法 + +[Install] 将此单元放到哪一个目标(target)当中 +WantedBy=multi-user.target 此服务所在的target,当执行systemctl enabled dhcpd时,dhcpd.service的链接会放在/etc/systemd/system/multi-user.target.wants/中 + +Install字段出现的内容 +WantedBy=multi-user.target 此服务所在的target,当执行systemctl enabled dhcpd时,dhcpd.service的链接会放 在/etc/systemd/system/multi-user.target.wants/中Also附加单元,当用户使用systemctl enable/disabled时,也自动启用或者停用附加单元 +Alias 定义别名 +``` + +### 服务多实例 + +``` +[root@zutuanxue yum.repos.d]# dnf install vsftpd -y 安装一个服务 +[root@zutuanxue yum.repos.d]# systemctl start vsftpd +[root@zutuanxue yum.repos.d]# netstat -antulp | grep vsftpd +tcp6 0 0 :::21 :::* LISTEN 6331/vsftpd +[root@zutuanxue yum.repos.d]# cd /etc/systemd/system/ +[root@zutuanxue system]# cp /usr/lib/systemd/system/vsftpd.service ./vsftpd2.service +[root@zutuanxue system]# cd /etc/vsftpd/ +[root@zutuanxue vsftpd]# cp vsftpd.conf vsftpd2.conf +[root@zutuanxue vsftpd]# vim vsftpd2.conf +listen_port=2100 + +[root@zutuanxuet vsftpd]# vim /etc/systemd/system/vsftpd2.service +[Unit] +Description=the second Vsftpd ftp daemon 修改简介 +After=network.target + +[Service] +Type=forking +ExecStart=/usr/sbin/vsftpd /etc/vsftpd/vsftpd2.conf 修改配置文件 + +[Install] +WantedBy=multi-user.target +[root@zutuanxue system]# systemctl list-unit-files | grep vsftpd +vsftpd.service disabled +vsftpd2.service disabled +vsftpd@zutuanxue.service indirect +vsftpd.target disabled +[root@zutuanxue system]# systemctl start vsftpd +[root@zutuanxue system]# systemctl start vsftpd2 +[root@zutuanxue system]# netstat -antulp | grep vsftpd +tcp6 0 0 :::21 :::* LISTEN 7388/vsftpd +tcp6 0 0 :::2100 :::* LISTEN 7392/vsftpd +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\224\250\346\210\267\347\256\241\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\224\250\346\210\267\347\256\241\347\220\206.md" new file mode 100644 index 0000000..da8718e --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\224\250\346\210\267\347\256\241\347\220\206.md" @@ -0,0 +1,232 @@ +## 一、用户和组的相关概念 + +### 账号的概念和分类 + +- **账号**:是一种用来记录单个用户或是多个用户的数据。Linux中每一个合法的用户都必须要拥有账号,才能使用 。它不仅可以用来验证用户身份,还决定了一个用户在系统中可以从事什么工作 + +在Linux 上的账号可以分成两类: + +- **用户账号** 用来储存单一用户的数据,你可以使用一个用户账号,来储存某一个用户的数据。 +- **群组账号** 用来储存多个用户的信息,每一个群组账号可以用来记录一组用户的数据。 + +我们可以把 Linux 的所有账号依照下面两种方法进行分类: + +- 依照账号的位置。 +- 依照账号的功能。 + +**依照账号存储的位置** + +账号数据存放在不同的地方,其可使用的范围就会不太一样,账号的使用范围我们称为视野。依照账号储存的位置与视野不同,我们可以区分本机账号与网域账号两种: + +**本机账号:** 账号密码储存于本机硬盘中,我们称为本机账号。 +本机账号使用范围只能在账号建立的 Linux 系统上,如果超出范围时,本机账号将无法使用。比如:你在自己电脑上登录用的账号和密码,正常是无法在其它的电脑上使用的。 + +- 本机账号的优点:是简单易用,你无须作额外的设置,就可以直接建立本机账号; +- 本机账号的缺点:则是无法具备延展性(*Scalability*)。比如:你在一个拥有很多主机的环境中,想拥有一个在每台主机都可以登录的账号时,你就需要在所有的主机上都建立相关的用户 + +**网域账号:** 你也可以把大量的计算机组织成为一个网域,然后在网域中的某一台 Linux 上建立账号数据,并且通过某些通信协议,将账号数据分享出来。当其他计算机需要取得账号数据时,再通过网络调用这些分享的账号即可。这种账号我们称为网域账号 (*Domain Account*)。 + +- 网域账号的优点:在于具备延展性。在大规模的环境中,使用网域账号往往能节省管理账号的时间; +- 但网域账号也有缺点,其最大的缺点就是要配置网域账号前,你必须先建立“域”的环境才行。 + +**依照账号的功能** + +不管是本机账号或是网域账号,我们还可以把所有账号依照功能分成下面几类 + +![1571285802298.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602392635606.png) + +**用户账号部分:** 包含了超级用户、普通用户;而普通用户中还可细分为系统用户、真实用户两种。 + +- 超级用户:在Linux 系统上拥有完整的控制能力,常被称为系统管理员,在 系统上拥有完整的控制能力,你可以利用超级用户读取或写入 上任何文件、安装或删除软硬件、启动或停止服务,甚至关机与停止系统的执行。 通常只有在管理系统时才会使用超级用户账号登录,所以超级用户常被称为系统管理员 (*System Administrator*)。由于超级用户的权限不受任何限制,你可以使用该账号来管理 系统;但是,也可能因为操作错误,或者打错命令而造成无法挽救的伤害。 + 在此,强烈建议你“除非有必要,否则请不要轻易以超级用户身份使用 Linux”! + + **在 Linux 系统中,默认超级用户的用户为 root,其 UID(用户ID号)一定为 0。** + +- 普通用户账号:行为能力会受到限制,只能调用具备权限的文件,如果没有足够的权限,普通用户是完全无法调用的;所以,普通用户账号不太容易危害 Linux 系统。普通用户账号中,我们又可分为两大类: + +- 系统账号 + 这种类型的账号仅提供给Linux 系统本身使用。在某些软件执行的时候,需要你提供一个普通用户类型的账号。为了满足这些软件而建立的账号,我们称为系统账号 (*System Account*)。 + +- 真实用户 + 系统用户账号是给软件或程序使用的,那么,什么账号是让我们登录Linux 时使用的呢?答案就是真实用户(*Real User*)。真实用户账号是为了让其他人登录系统使用的 + +**群组账号部分:** 包含了超级用户群组、系统群组以及用户自定义组三大类。 + +- 超级用户群组:Linux 有一个叫做 root 的群组,因为这个群组的名称与 root 这个超级用户的名称相同,所以,我们习惯把 root 群组叫做超级用户群组。超级用户群组的 GID 为 0。 +- 系统群组: 与系统账号一样,系统群组是给 Linux 系统本身,或是某个软件所使用 +- 用户自定义组:除了上述的群组外其余的所有群组,皆是由管理者自行定义,因此我们把这些群组称之为用户自定义组 + +另外,Linux 系统的“用户自定义组“类型中,还有一种名为**用户私有群组** (*UPG, User Private Group*)的群组。什么是 **用户私有群组**呢?用户私有群组(*UPG, User Private Group*)是指 “与用户账号名称相同,且为用户的主要群组”的群组。当你建立新的用户账号时,Linux 会自动建立该用户的私有群组。如,当你建立 test 这个用户账号时,Linux 会自动建立了一个名为 test 的群组,并且让 test群组成为 test 用户账号的主要群组,test 群组即是 test 的私有群组。 + +了解完账号的基本概念后,我们一起来看下账号到底记录了哪些信息 + +## 二、用户账号管理 + +- **useradd命令** + 用户创建命令,创建一个linux用户。 + +``` +命令介绍 + useradd - 创建一个新用户或更新默认新用户信息 + +命令语法 + useradd [选项] 登录 + + useradd -D + + useradd -D [选项] + +命令选项 + -D 默认 + ­ + -u UID 用来指定账号的 UID,如果省略这个参数,useradd会自动以最后一个可用的 UID 作为新账号的 UID。 + + -o 告诉 useradd 允许重复的 UID。 + + -g gid 定义用户的主要群组。使用 -g 参数前,GROUP 必须已经存在。 + + -d HOME 指定用户的主目录。默认的主目录是建立在 /home/ 目录下,而且目录名称与用户名称相同。 + + -s SHELL 指定用户登录执行的程序。 + + -c COMMENT 指定用户的批注说明。如果批注文字包含空白,请记得使用双引号 (") 包起来。 + + -r 这个参数用来指出建立一个系统用户的账号。 + + -M 不创建家目录 + + -N 不创建同名组 + + + +#相关文件 + /etc/passwd + 用户账户信息。 + + /etc/shadow + 安全用户账户信息。 + + /etc/group + 组账户信息。 + + /etc/gshadow + 安全组账户信息。 + + /etc/default/useradd + 账户创建的默认值。 + + /etc/skel/ + 包含默认文件的目录。 + + /etc/subgid + Per user subordinate group IDs. + + /etc/subuid + Per user subordinate user IDs. + + /etc/login.defs + Shadow 密码套件配置。 +``` + +这些参数大多数可以同时使用,可以根据自己的需求指定,例如 +**创建一个linux用户hello** +– uid为 1500 +– 附加组为 hello +– 家目录为 /home/hello +– 登陆shell为 /bin/bash +– 描述为 “this is a test user” + +``` +useradd -u 1500 -G hello -d /home/hello -s /bin/bash -c "this is a test user" hello +``` + +**关于linux本机用户** +本机的用户账号数据储存于/etc/passwd文件中。与其他的配置文件一样,passwd 也是一个文本文件,因此,你可以直接使用文字处理程序,例如 cat 或 less 浏览其中的内容。 + +``` +root:x:0:0:root:/root:/bin/bash +bin:x:1:1:bin:/bin:/sbin/nologin +daemon:x:2:2:daemon:/sbin:/sbin/nologin +``` + +/etc/passwd 权限必须是0644,每一行代表一个用户的账号数据,每一行又使用冒号(:)分隔为几个部分 + +``` +USERNAME:PASSWORD:UID:GID:COMMENT:HOMEDIR:SHELL + +- USERNAME:用户识别名称,也是登录的名称 +- PASSWORD:密码位,用于存储用户的密码,为了安全起见,密码放在另一个文件中,这里统一用x +- UID:用户识别号,0表示为管理员,非0为普通用户 +- GID:组识别号,用来识别用户组的身份,同样0为管理员组,非0为系统群组或者自定义组 +- COMMENT:描述信息 +- HOMEDIR:家目录位置 +- SHELL:shell类型 +``` + +- **usermod命令** + 是用来修改用户相关信息的,和useradd使用的参数很多是相同的,用法也是一样的,除此之外usermod命令还有一些额外的参数 + +``` +命令介绍 + usermod - 修改一个用户账户 + +命令语法 + usermod [选项] 登录 + +命令选项 +-l NEWNAME 修改账号的用户名称,NEWNAME 即是新的账号名称。 + +-L 锁定账号,一经锁定的账号将无法用来登录系统。 + +-U 解除锁定。 +``` + +- **userdel命令** + 删除linux用户 + +``` +命令介绍 + userdel - 删除用户账户和相关文件 + +命令语法 + userdel [选项] 登录 + +命令选项 +-r 用户主目录中的文件将随用户主目录和用户邮箱一起删除。在其它文件系统中的文件必须手动搜索并删除。 + +-f 强制 +``` + +**删除tom用户以及其家目录文件** + +``` +[root@zutuanxue ~]# userdel -r tom +``` + +## 三、用户查询命令 + +- **id命令:查询用户uid、gid信息** + +``` +[root@zutuanxue ~]# id hello +uid=1500(hello) gid=1500(hello) 组=1500(hello) + +[root@zutuanxue ~]# id -u hello +1500 +``` + +- **whoami命令:查询当前登录用户** + +``` +[root@zutuanxue ~]# whoami +root +``` + +- **w命令:查询linux系统中登陆的所有用户** + +``` +[root@zutuanxue ~]# w + 18:21:43 up 2:01, 1 user, load average: 0.00, 0.00, 0.00 +USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT +root pts/0 192.168.1.17 16:16 3.00s 0.08s 0.00s w +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\243\201\347\233\230\344\275\277\347\224\250\345\256\236\346\210\230\346\241\210\344\276\213.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\243\201\347\233\230\344\275\277\347\224\250\345\256\236\346\210\230\346\241\210\344\276\213.md" new file mode 100644 index 0000000..fc2885b --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\243\201\347\233\230\344\275\277\347\224\250\345\256\236\346\210\230\346\241\210\344\276\213.md" @@ -0,0 +1,119 @@ +**案例需求:** + +添加一块硬盘,需要将其分区,最终需要使用2G空间。 + +**案例思路** + +1. 增加一块硬盘 +2. 使用fdisk命令进行分区 +3. 格式化指定分区 +4. 创建一个空的目录作为挂载点 +5. 挂载使用 +6. 创建新的挂载点 +7. 挂载使用 + +``` +步骤: +1. 增加硬盘 +增加完硬盘记得重启系统 +# lsblk 查看硬盘是否添加成功 +... +sdb 8:16 0 20G 0 disk +[root@zutuanxue ~]# fdisk -l /dev/sdb +Disk /dev/sdb:20 GiB,21474836480 字节,41943040 个扇区 +单元:扇区 / 1 * 512 = 512 字节 +扇区大小(逻辑/物理):512 字节 / 512 字节 +I/O 大小(最小/最佳):512 字节 / 512 字节 + +2. 使用fdisk命令分区 +[root@zutuanxue ~]# fdisk /dev/sdb + +欢迎使用 fdisk (util-linux 2.32.1)。 +更改将停留在内存中,直到您决定将更改写入磁盘。 +使用写入命令前请三思。 + +设备不包含可识别的分区表。 +创建了一个磁盘标识符为 0x0c7799c3 的新 DOS 磁盘标签。 + +命令(输入 m 获取帮助):p +Disk /dev/sdb:20 GiB,21474836480 字节,41943040 个扇区 +单元:扇区 / 1 * 512 = 512 字节 +扇区大小(逻辑/物理):512 字节 / 512 字节 +I/O 大小(最小/最佳):512 字节 / 512 字节 +磁盘标签类型:dos +磁盘标识符:0x0c7799c3 + +命令(输入 m 获取帮助):n +分区类型 + p 主分区 (0个主分区,0个扩展分区,4空闲) + e 扩展分区 (逻辑分区容器) +选择 (默认 p):p +分区号 (1-4, 默认 1): +第一个扇区 (2048-41943039, 默认 2048): +上个扇区,+sectors 或 +size{K,M,G,T,P} (2048-41943039, 默认 41943039): +1G + +创建了一个新分区 1,类型为“Linux”,大小为 1 GiB。 + +命令(输入 m 获取帮助):p +Disk /dev/sdb:20 GiB,21474836480 字节,41943040 个扇区 +单元:扇区 / 1 * 512 = 512 字节 +扇区大小(逻辑/物理):512 字节 / 512 字节 +I/O 大小(最小/最佳):512 字节 / 512 字节 +磁盘标签类型:dos +磁盘标识符:0x80e196f2 + +设备 启动 起点 末尾 扇区 大小 Id 类型 +/dev/sdb1 2048 2099199 2097152 1G 83 Linux + +命令(输入 m 获取帮助):n +分区类型 + p 主分区 (1个主分区,0个扩展分区,3空闲) + e 扩展分区 (逻辑分区容器) +选择 (默认 p):p +分区号 (2-4, 默认 2): 2 +第一个扇区 (2099200-41943039, 默认 2099200): +上个扇区,+sectors 或 +size{K,M,G,T,P} (2099200-41943039, 默认 41943039): +1G + +创建了一个新分区 2,类型为“Linux”,大小为 1 GiB。 + +命令(输入 m 获取帮助):p +Disk /dev/sdb:20 GiB,21474836480 字节,41943040 个扇区 +单元:扇区 / 1 * 512 = 512 字节 +扇区大小(逻辑/物理):512 字节 / 512 字节 +I/O 大小(最小/最佳):512 字节 / 512 字节 +磁盘标签类型:dos +磁盘标识符:0x80e196f2 + +设备 启动 起点 末尾 扇区 大小 Id 类型 +/dev/sdb1 2048 2099199 2097152 1G 83 Linux +/dev/sdb2 2099200 4196351 2097152 1G 83 Linux + +命令(输入 m 获取帮助):w +分区表已调整。 +将调用 ioctl() 来重新读分区表。 +正在同步磁盘。 + + + +3. 再次查看分区情况 +# lsblk +sdb 8:16 0 20G 0 disk +├─sdb1 8:17 0 1G 0 part +└─sdb2 8:18 0 1G 0 part + +4. 刷新分区表信息 +[root@zutuanxue ~]# partprobe /dev/sdb + + +5. 格式化分区 +[root@zutuanxue ~]# mkfs.xfs /dev/sdb1 +[root@zutuanxue ~]# mkfs.vfat /dev/sdb2 + +6. 创建新的挂载点 +[root@zutuanxue ~]# mkdir /u01 +[root@zutuanxue ~]# mkdir /u02 + +7. 挂载使用 +[root@zutuanxue ~]# mount /dev/sdb1 /u01 +[root@zutuanxue ~]# mount /dev/sdb2 /u02 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\243\201\347\233\230\345\237\272\346\234\254\347\256\241\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\243\201\347\233\230\345\237\272\346\234\254\347\256\241\347\220\206.md" new file mode 100644 index 0000000..ea183ce --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\243\201\347\233\230\345\237\272\346\234\254\347\256\241\347\220\206.md" @@ -0,0 +1,204 @@ +## 一、磁盘介绍 + +磁盘:计算机中的外部存储设备,负责存储计算机数据,并且断电后也能保持数据不丢失。 + +**磁盘分类:** + +按照物理结构: + +- 机械磁盘 +- 固态磁盘 + +按照接口: + +- IDE +- SCSI +- SATA +- SAS +- mSATA +- M.2 +- NVME +- PCIe + +按照尺寸: + +- 机械硬盘:1.8寸 2.5寸 3.5寸 +- 固态硬盘:SATA: 2.5寸 +- M.2: 2242、2260、2280 + +## 二、熟悉磁盘的工作原理 + +**机械磁盘的读写数据依靠电机带动盘片转动来完成数据读写的。** + +#### 机械磁盘剖析图 + +![机械硬盘结构.jpeg](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602986110096.jpeg) + +``` +为了使磁盘内部清洁,磁盘是在真空特殊环境中制作的,不能随意拆卸,拆开后基本报废了 +``` + +机械磁盘工作是依靠马达带动盘片转动,通过磁头来读取磁盘上的数据。 + +### 磁盘术语 + +##### 磁盘 + +硬盘中一般会有多个盘片组成,每个盘片包含两个面,每个盘面都对应地有一个读/写磁头。受到硬盘整体体积和生产成本的限制,盘片数量都受到限制,一般都在5片以内。盘片的编号自下向上从0开始,如最下边的盘片有0面和1面,再上一个盘片就编号为2面和3面。 + +##### 磁头 + +负责读取盘面数据的设备 + +##### 磁道 + +从盘片的最内侧向外有很多同心圆圈,我们称为磁道 + +##### 扇区 + +从圆心向外画直线,可以将磁道划分为若干个弧段,称之为扇区,一个扇区通常为**512B** + +![disk2.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602986039811.png) + +##### 磁柱 + +硬盘通常由重叠的一组盘片构成,每个盘面都被划分为数目相等的磁道,并从外缘的“0”开始编号,具有相同编号的磁道形成一个圆柱,称之为磁盘的柱面。磁盘的柱面数与一个盘面上的磁道数是相等的。由于每个盘面都有自己的磁头,因此,盘面数等于总的磁头数。 + +![disk3.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602986025858.png) + +## 三、磁盘的性能指标 + +#### 影响磁盘性能的指标 + +**寻道时间(seek time)**【和 转速 相关】:Tseek,是指将读写磁头移动至正确的磁道上所需要的时间。寻道时间越短,I/O操作越快,目前磁盘的平均寻道时间一般在3-15ms + +**旋转延迟**:Trotation,是指盘片旋转将请求数据所在的扇区移动到读写磁头下方所需要的时间。旋转延迟取决于磁盘转速,通常用磁盘旋转一周所需时间的1/2表示。比如:7200rpm的磁盘平均旋转延迟大约为60*1000/7200/2 = 4.17ms,而转速为15000rpm的磁盘其平均旋转延迟为2ms。 + +**数据传输时间**:Ttransfer,是指完成传输所请求的数据所需要的时间 + +#### 衡量磁盘性能的指标 + +**IOPS**:IOPS(Input/Output Per Second)即每秒的输入输出量(或读写次数),即指每秒内系统能处理的I/O请求数量。随机读写频繁的应用,如小文件存储等,关注随机读写性能,IOPS是关键衡量指标。可以推算出磁盘的IOPS = 1000ms / (Tseek + Trotation + Transfer),如果忽略数据传输时间,理论上可以计算出随机读写最大的IOPS。常见磁盘的随机读写最大IOPS为: + +- 7200rpm的磁盘 IOPS = 76 IOPS +- 10000rpm的磁盘IOPS = 111 IOPS +- 15000rpm的磁盘IOPS = 166 IOPS + +**throughput :** 吞吐量指单位时间内可以成功传输的数据数量。 单位为(m/s G/s) + +![3.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602986155314.png) + +**文件系统:**是告知操作系统使用何种方法和数据结构在存储设备或分区上读写数据的;是分区数据管家,负责如何将数据写入磁盘或者从磁盘读出 + +NTFS EXT3 EXT4 XFS ISO9660 + +具体有多少 man mount -t + +``` + adfs, affs, autofs, cifs, coda, coherent, cramfs,debugfs, devpts, efs, ext, ext2, ext3, ext4, hfs, hfsplus, hpfs,iso9660, jfs, minix, msdos, ncpfs, nfs, nfs4, ntfs, proc, qnx4,ramfs, reiserfs, romfs, squashfs, smbfs, sysv, tmpfs, ubifs,udf, ufs, umsdos, usbfs, vfat, xenix, xfs, xiafs. +``` + +**文件系统可以根据应用场景去选择使用哪一款,如果不会选择,推荐ext4或者XFS** + +**page cache** + +其实就是内存上空闲的部分 用来缓存数据,比如buffer cache + +作用:对IO读写做优化 + +测试缓存对读写的影响 + +``` +写 +[root@zutuanxue ~]# echo 3 > /proc/sys/vm/drop_caches +[root@zutuanxue ~]# free -m + total used free shared buff/cache available +Mem: 1980 95 1807 9 77 1754 +Swap: 2047 0 2047 +[root@zutuanxue ~]# dd if=/dev/zero of=/tmp/big bs=1M count=1000 +记录了1000+0 的读入 +记录了1000+0 的写出 +1048576000字节(1.0 GB)已复制,10.2412 秒,102 MB/秒 +[root@zutuanxue ~]# free -m + total used free shared buff/cache available +Mem: 1980 95 779 9 1105 1698 +Swap: 2047 0 2047 +[root@zutuanxue ~]# dd if=/dev/zero of=/tmp/big1 bs=1M count=1000 +记录了1000+0 的读入 +记录了1000+0 的写出 +1048576000字节(1.0 GB)已复制,7.89978 秒,133 MB/秒 + +读 +[root@zutuanxue ~]# echo 3 > /proc/sys/vm/drop_caches +[root@zutuanxue ~]# free -m + total used free shared buff/cache available +Mem: 1980 95 1805 9 79 1753 +Swap: 2047 0 2047 +[root@zutuanxue ~]# dd if=/tmp/big of=/dev/null +记录了2048000+0 的读入 +记录了2048000+0 的写出 +1048576000字节(1.0 GB)已复制,2.23965 秒,468 MB/秒 +[root@zutuanxue ~]# free -m + total used free shared buff/cache available +Mem: 1980 95 800 9 1084 1710 +Swap: 2047 0 2047 +[root@zutuanxue ~]# dd if=/tmp/big of=/dev/null +记录了2048000+0 的读入 +记录了2048000+0 的写出 +1048576000字节(1.0 GB)已复制,1.92811 秒,544 MB/秒 +``` + +## 四、linux磁盘的使用方法 + +### **4.1、磁盘初始化** + + **一块新的磁盘使用必须初始化为MBR或者GPT分区。** + +- **MBR <2TB fdisk** **4个主分区或者3个主分区+1个扩展分区(N个逻辑分区)** + +MBR(Master Boot Record)的缩写,由三部分组成,即: + +1. Bootloader(主引导程序)= + + 446字节 + + - 引导操作系统的主程序 + +2. DPT分区表(Disk Partition Table)= + + 64字节 + + - 分区表保存了硬盘的分区信息,操作系统通过读取分区表内的信息,就能够获得该硬盘的分区信息 + - 每个分区需要占用16个字节大小,保存有文件系统标识、起止柱面号、磁头号、扇区号、起始扇区位置(4个字节)、分区总扇区数目(4个字节)等内容 + - 分区表中保存的分区信息都是主分区与扩展分区的分区信息,扩展分区不能直接使用,需要在扩展分区内划分一个或多个逻辑分区后才能使用 + - 逻辑分区的分区信息保存在扩展分区内而不是保存在MBR分区表内,这样,就可以突破MBR分区表只能保存4个分区的限制 + +3. 硬盘有效标志(校验位)=2个字节 + +- **GPT >2TB gdisk(parted) 128个主分区** + +注意:从MBR转到GPT,或从GPT转换到MBR会导致**数据全部丢失**! + +### **4.2、分区** + + **将磁盘合理分区,能使计算机或者使用者更快的存取数据** + + MBR 主分区+扩展分区<=4 + + GPT 主分区<=128 + +### **4.3、格式化** + + **装载文件系统(相当于库管,负责数据的写入和读出)。** + + 常见的文件系统:NTFS EXT EXT2 EXT3 EXT4 XFS vfat + +### **4.4、挂载** + + **linux中设备不能直接使用,需要挂载到文件夹才可以。** + +挂载方式: + +1. 手动挂载 +2. 开机挂载 +3. 自动挂载 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\243\201\347\233\230\347\256\241\347\220\206-RAID\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\243\201\347\233\230\347\256\241\347\220\206-RAID\344\273\213\347\273\215.md" new file mode 100644 index 0000000..ea0ebea --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\243\201\347\233\230\347\256\241\347\220\206-RAID\344\273\213\347\273\215.md" @@ -0,0 +1,98 @@ +## 一、RAID介绍 + +RAID(Redundant Array of Independent Disk 独立冗余磁盘阵列)技术是加州大学伯克利分校1987年提出,最初是为了组合小的廉价磁盘来代替大的昂贵磁盘,同时希望磁盘失效时不会使对数据的访问受损失而开发出一定水平的数据保护技术。RAID就是一种由多块廉价磁盘构成的冗余阵列,在操作系统下是作为一个独立的大型存储设备出现。RAID可以充分发挥出多块硬盘的优势,可以提升硬盘速度,增大容量,提供容错功能,能够确保数据安全性,易于管理的优点,在任何一块硬盘出现问题的情况下都可以继续工作,不会 受到损坏硬盘的影响。 + +## 二、常见的RAID级别 + +### 2.1、 RAID0 + +![raid0.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602994630063.png) + +**RAID0特点:** + +- 至少需要两块磁盘 +- 数据条带化分布到磁盘,高的读写性能,100%高存储空间利用率 +- 数据没有冗余策略,一块磁盘故障,数据将无法恢复 +- 应用场景: + - 对性能要求高但对数据安全性和可靠性要求不高的场景,比如音频、视频等的存储。 + +### 2.2、 RAID1 + +![raid1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602994658333.png) + +**RAID1特点:** + +- 至少需要2块磁盘 +- 数据镜像备份写到磁盘上(工作盘和镜像盘),可靠性高,磁盘利用率为50% +- 读性能可以,但写性能不佳 +- 一块磁盘故障,不会影响数据的读写 +- 应用场景: + - 对数据安全可靠要求较高的场景,比如邮件系统、交易系统等。 + +### 2.3、 RAID5 + +![raid5.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602994685133.png) + +**RAID5特点:** + +- 至少需要3块磁盘 +- 数据条带化存储在磁盘,读写性能好,磁盘利用率为(n-1)/n +- 以奇偶校验(分散)做数据冗余 +- 一块磁盘故障,可根据其他数据块和对应的校验数据重构损坏数据(消耗性能) +- 是目前综合性能最佳的数据保护解决方案 +- 兼顾了存储性能、数据安全和存储成本等各方面因素(性价比高) +- 适用于大部分的应用场景 + +### 2.4、 RAID6 + +![raid6.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602994696875.png) + +**RAID6特点:** + +- 至少需要**4**块磁盘 +- 数据条带化存储在磁盘,读取性能好,容错能力强 +- 采用双重校验方式保证数据的安全性 +- 如果2块磁盘同时故障,可以通过两个校验数据来重建两个磁盘的数据 +- 成本要比其他等级高,并且更复杂 +- 一般用于对数据安全性要求非常高的场合 + +### 2.5、 RAID10 + +![raid10.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602994712492.png) + +**RAID10特点:** + +- RAID10是raid1+raid0的组合 +- 至少需要4块磁盘 +- 两块硬盘为一组先做raid1,再将做好raid1的两组做raid0 +- 兼顾数据的冗余(raid1镜像)和读写性能(raid0数据条带化) +- 磁盘利用率为50%,成本较高 + +## 三、RAID总结 + +| 类型 | 读写性能 | 可靠性 | 磁盘利用率 | 成本 | +| ------ | --------------------------------- | ----------------- | ----------- | ----------------- | +| RAID0 | 最好 | 最低 | 100% | 较低 | +| RAID1 | 读快;写一般 | 高 | 50% | 高 | +| RAID5 | 读:近似RAID0 写:多了校验 | RAID0RAID5 | RAID6RAID1 | +| RAID10 | 读:RAID10=RAID0 写:RAID10=RAID1 | 高 | 50% | 最高 | + +## 四、RAID分类 + +### 软RAID + +软RAID运行于操作系统底层,将SCSI或者IDE控制器提交上来的物理磁盘,虚拟成虚拟磁盘,再提交给管理程序来进行管理。软RAID有以下特点: + +- 节省成本,系统支持就可以使用相应功能 +- 占用内存空间 +- 占用CPU资源 +- 如果程序或者操作系统故障就无法运行 + +### 硬RAID + +通过用硬件来实现RAID功能的就是硬RAID,独立的RAID卡,主板集成的RAID芯片都是硬RAID。RAID卡就是用来实现RAID功能的板卡。硬RAID的特点: + +- 硬RAID有独立的运算单元,性能好 +- 可能需要单独购买额外的硬件 +- 不同RAID卡支持的功能不同,需要根据自己的需求选择 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\275\221\347\273\234\346\225\205\351\232\234\346\216\222\346\237\245.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\275\221\347\273\234\346\225\205\351\232\234\346\216\222\346\237\245.md" new file mode 100644 index 0000000..578df84 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\275\221\347\273\234\346\225\205\351\232\234\346\216\222\346\237\245.md" @@ -0,0 +1,180 @@ +在日常使用中,经常会出现无法连通的情况,这个时候我们就需要找到问题出在哪里,这里面给各位提供一个生产环境排查网络故障的大体思路,一般情况下如果遇到网络故障,都是通过筛选的方式一点一点的确定问题所在,首先判断是本机的问题还是网络上其它设备的问题,如果同一网络环境中的其它主机正常的,要去其它网络设备(路由器)上查看一下是否对网络有问题的主机设置了限制,如果没有的话,问题出在本机,这里面我们主要看下下本机容易出现哪些问题导致页面无法访问 + +## 一、网线和网卡设置 + +检查网卡的灯是否亮起,普通服务器的话应该是绿灯常亮为正常,交换机绿灯闪烁表示正在传输数据。也可以通过命令ethtool ethX来查看某一网卡的链路是否物理连通。 + +命令介绍 + +ethtool + +``` +[root@zutuanxue ~]# ethtool ens33 +Settings for ens33: + Supported ports: [ TP ] + #接口类型 + #TP RJ45接口双绞线 + #AUI “D”型15针接口 + #BNC 细同轴电缆接口,类似于以前的有线电视 + #MII 媒体独立接口,一种以太网行业标准 + #FIBRE 光纤 + Supported link modes: 10baseT/Half 10baseT/Full + 100baseT/Half 100baseT/Full + 1000baseT/Full + #支持的链接模式 + Supported pause frame use: No + #是否支持暂停帧--一种网卡流量控制技术 + Supports auto-negotiation: Yes + #是否支持自动协商,网络设备相互告知对方自己的工作方式,包括传输速度,双工状态等,然后选择一个最佳的 + Supported FEC modes: Not reported + #编码纠错模式,支持编码纠错可提高数据通讯可信度 + Advertised link modes: 10baseT/Half 10baseT/Full + 100baseT/Half + 100baseT/Full + 1000baseT/Full + #宣告的链接模式 + Advertised pause frame use: No + #宣告的是否支持帧暂停 + Advertised auto-negotiation: Yes + #宣告的是否支持自动协商 + Advertised FEC modes: Not reported + #宣告的是否FEC + Speed: 1000Mb/s + #当前速度 + Duplex: Full + #全双工还是半双工 + Port: Twisted Pair + #线缆类型为双绞线 + PHYAD: 0 + #PHY地址,主要指PHY芯片,用来发送和接收数据帧 + Transceiver: internal + #收发器类型 internal/external(内部外部)是否是板载的 + Auto-negotiation: on + #自动协商功能开启 + MDI-X: off (auto) + #自适应功能 + Supports Wake-on: d + #是否支持远程唤醒 d=禁用,p\u\m\b\a\g=不同唤醒方式 + Wake-on: d + Current message level: 0x00000007 (7) drv probe link + Link detected: yes + #网卡已连接 + + + ##############常用参数 +#-a 查看网卡中 接收模块RX、发送模块TX和Autonegotiate模块的状态:启动on 或 停用off。主要指接收暂停,发送暂停和自动协商暂停功能,也就是暂停帧,主要用于控制数据路停止发送,可以防止瞬间压力过大导致缓冲区溢出而引发的帧丢失(丢包) +#[root@zutuanxue ~]# ethtool -a ens33 +Pause parameters for ens33: +Autonegotiate: on +RX: off +TX: off + +#-A 修改网卡中 接收模块RX、发送模块TX和Autonegotiate模块的状态:启动on 或 停用off。 +[root@zutuanxue ~]# ethtool -A ens33 rx/tx/autoneg on + +#-i 显示网卡驱动的信息,如驱动的名称、版本等。 +[root@zutuanxue ~]# ethtool -i ens33 +driver: e1000 +version: 7.3.21-k8-NAPI +firmware-version: +expansion-rom-version: +bus-info: 0000:02:01.0 +supports-statistics: yes +supports-test: yes +supports-eeprom-access: yes +supports-register-dump: yes +supports-priv-flags: no + +#-k 显示网卡各项功能的支持和协议状态,如支持某个协议的功能是否开启等 +#-p 用于区别不同ethX对应网卡的物理位置,常用的方法是使网卡port上的led不断的闪;N为网卡闪的持续时间,以秒为单位。 +[root@zutuanxue ~]# ethtool -p ens33 10 + +#-r 如果自动协商状态为on,则重启自动协商功能。 +[root@zutuanxue ~]# ethtool -r ens33 + +#-S 显示统计参数,如网卡接收/发送的字节数、接收/发送的广播包个数等。 +[root@zutuanxue ~]# ethtool -S ens33 +NIC statistics: + rx_packets: 609 + tx_packets: 130 + rx_bytes: 121330 + tx_bytes: 16066 + rx_broadcast: 0 + +#-s 修改网卡的部分配置,包括网卡速度、单工/全双工模式、mac地址等。 + ethtool –s ethX [speed 10|100|1000] + #设置网口速率10/100/1000M + [duplex half|full] + #设置网口半/全双工 + [autoneg on|off] + #设置网口是否自协商 + [port tp|aui|bnc|mii] + #设置网口类型 +[root@zutuanxue ~]# ethtool -s ens33 speed 1000 duplex full autoneg on port tp +``` + +## 二、selinux&防火墙 + +这两个是最容易产生干扰的项目,selinux和防火墙如何关闭,我们在前面的课程中有涉及,这里就不重复了 + +## 三、查看网卡ip地址,网关设置 + +使用ifconfig或者nmcli命令查看/设置ip地址和网关 + +## 四、使用ping命令测试连通性 + +``` +-c<完成次数>:设置完成要求回应的次数; +-f:洪水ping只有root可以使用 +-i<间隔秒数>:指定收发信息的间隔时间; +-n:只输出数值,不尝试去查找主机名 +-s<数据包大小>:设置数据包的大小; +-I 指定源地址(源地址必须是本地网卡上存在的配置) +[root@zutuanxuers1 ~]# ping -c 3 -i 0.5 -n -s 1024 -I 192.168.2.220 192.168.2.220 +PING 192.168.2.220 (192.168.2.220) from 192.168.2.220 : 1024(1052) bytes of data. +1032 bytes from 192.168.2.220: icmp_seq=1 ttl=64 time=0.047 ms +1032 bytes from 192.168.2.220: icmp_seq=2 ttl=64 time=0.060 ms +1032 bytes from 192.168.2.220: icmp_seq=3 ttl=64 time=0.053 ms + +--- 192.168.2.220 ping statistics --- +3 packets transmitted, 3 received, 0% packet loss, time 13ms +rtt min/avg/max/mdev = 0.047/0.053/0.060/0.008 ms +``` + +## 五、路由 + +使用route命令查看或设置路由及网关,也可以通过修改静态路由配置文件实现 + +## 六、DNS + +- /etc/hosts&/etc/resolv.conf +- nslookup +- dig +- host + +## 七、追踪数据包 + +``` +tracepath [参数选项] hostname,域名或 IP地址 +#替代了以前的traceroute +参数选项: +-4 使用IPV4 +-6 使用IPV6=tracepath6 +-l 设置初始包的大小 默认IPV4 65535,ipv6 128000 +-m 设置检测数据包的TTL,默认值为30次; +-n 显示IP地址,不查主机名。当DNS不起作用时常用到这个参数; +-b 显示主机名和IP地址 +-p port 探测包使用的基本UDP端口设置为port ,默认值是33434 +[root@zutuanxuers1 ~]# tracepath -b www.baidu.com -l 1000 -m 5 + 1: localhost (192.168.0.1) 18.324ms + 2: localhost (192.168.1.1) 15.622ms + 3: localhost (10.70.0.1) 18.640ms + 4: 114.244.94.25 (114.244.94.25) 7.213ms + 5: 124.65.56.141 (124.65.56.141) 16.020ms + Too many hops: pmtu 1000 + Resume: pmtu 1000 +``` + +## 八、硬件故障 + +更换硬件 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\275\221\347\273\234\347\233\270\345\205\263\350\256\276\347\275\256.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\275\221\347\273\234\347\233\270\345\205\263\350\256\276\347\275\256.md" new file mode 100644 index 0000000..6e12ccf --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\347\275\221\347\273\234\347\233\270\345\205\263\350\256\276\347\275\256.md" @@ -0,0 +1,122 @@ +## 网络配置文件 + +/etc/NetworkManager/NetworkManager.conf + +NetworkManager服务配置文件,如果没有特殊需求不建议调整,如果需要调整的话,调整之前备份,调整完成重新启动服务 + +/etc/sysconfig/network-scripts/ifcfg-xx网卡配置文件 + +``` +网卡配置文件中的关键参数 +[root@zutuanxue ~]# cat /etc/sysconfig/network-scripts/ifcfg-ens33 +TYPE="Ethernet" 网卡类型 +BOOTPROTO="dhcp" IP获取方式,dhcp/static(none) +DEFROUTE="yes" 是否设置为IPV4默认路由 +NAME="ens33" 连接名称 +UUID="b5ecf570-543c-4da7-b082-bdc073b56acb" 网卡识别号 +DEVICE="ens33" 设备名称 +ONBOOT="yes" 是否开机自动启动此网络连接 + + +额外设置参数 +NM_CONTROLLED=yes 是否被NetworkManager服务管理,默认yes +IPADDR ip地址 +NETMASK 子网掩码 +GATEWAY 定义网关 +DNS1 dns地址 优先级高于/etc/resolv.conf +DNS2 dns地址 +USERCTL 是否允许普通用户控制此设备 +PEERDNS 是否允许自动修改dns配置文件/etc/resolv.conf +PREFIX 掩码长度 +``` + +/etc/hostname 主机名配置文件 + +``` +[root@zutuanxue ~]# cat /etc/hostname +hello +``` + +/etc/resolv.conf DNS配置文件 + +``` +[root@zutuanxue ~]# cat /etc/resolv.conf +# Generated by NetworkManager +search localdomain +nameserver 192.168.17.2 +nameserver 202.106.0.20 +nameserver 114.114.114.114 +``` + +## 其它命令 + +- ifconfig命令:查看网卡信息 + +``` +[root@zutuanxue ~]# ifconfig +ens33: flags=4163 mtu 1500 连接信息 + inet 192.168.1.55 netmask 255.255.255.0 broadcast 192.168.1.255 IPV4地址信息 + inet6 fe80::ea62:91c6:114:18bb prefixlen 64 scopeid 0x20 IPV6地址信息 + ether 00:0c:29:11:47:97 txqueuelen 1000 (Ethernet) mac地址 + RX packets 174914 bytes 51397660 (49.0 MiB) + RX errors 0 dropped 0 overruns 0 frame 0 接收到的数据包统计 + TX packets 24446 bytes 3114546 (2.9 MiB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 发送的数据包统计 +停用网卡 +[root@zutuanxue ~]# ifconfig ens37 down +启用网卡 +[root@zutuanxue ~]# ifconfig ens37 up +设置一个临时IP +[root@zutuanxue ~]# ifconfig ens37 192.168.18.100 +``` + +- route命令:设置路由 + +``` +[root@zutuanxue ~]# route + -n 以数字的形式显示路由信息 + add/del 添加/删除路由信息,需要配合下面参数使用 + -net 指定为一个网络 + -host 指定为一台主机 + netmask 指定掩码 + gw 指定网关 + dev 指定设备 + +Destination Gateway Genmask Flags Metric Ref Use Iface +0.0.0.0 192.168.1.1 0.0.0.0 UG 102 0 0 ens33 +192.168.1.0 0.0.0.0 255.255.255.0 U 102 0 0 ens33 +192.168.20.0 0.0.0.0 255.255.255.0 U 100 0 0 ens37 + +主要信息 +Destination 目的地址 +Gateway 网关 +Genmask 掩码 +Flags 标识 U=启用,H=主机,G=网关 +Iface 接口 +添加路由信息 +[root@zutuanxue ~]#route add -net 192.168.20.0/24 dev ens37 +删除路由信息 +[root@zutuanxue ~]#route del -net 192.168.20.0/24 dev ens37 + +dhclient获取与释放IP地址 +[root@zutuanxue ~]# dhclient -r ens37 +[root@zutuanxue ~]# dhclient ens37 + +ping连通性测试工具 +[root@zutuanxue ~]# ping + c 指定次数 + n 以数字的形式显示结果 + f 洪水ping,以最快的速度收发数据包,慎用 + +[root@zutuanxue ~]# ping -c 5 -n www.163.com +PING z163ipv6.v.bsgslb.cn (111.202.34.27) 56(84) bytes of data. +64 bytes from 111.202.34.27: icmp_seq=1 ttl=128 time=5.25 ms +64 bytes from 111.202.34.27: icmp_seq=2 ttl=128 time=8.54 ms +64 bytes from 111.202.34.27: icmp_seq=3 ttl=128 time=6.22 ms +64 bytes from 111.202.34.27: icmp_seq=4 ttl=128 time=5.78 ms +64 bytes from 111.202.34.27: icmp_seq=5 ttl=128 time=5.60 ms + +--- z163ipv6.v.bsgslb.cn ping statistics --- +5 packets transmitted, 5 received, 0% packet loss, time 13ms +rtt min/avg/max/mdev = 5.253/6.278/8.536/1.173 ms +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\350\275\257\344\273\266\345\214\205\347\256\241\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\350\275\257\344\273\266\345\214\205\347\256\241\347\220\206.md" new file mode 100644 index 0000000..6e33061 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/linux\350\275\257\344\273\266\345\214\205\347\256\241\347\220\206.md" @@ -0,0 +1,510 @@ +在linux系统中我们经常涉及到软件包的删除和添加,那一起来看下在linux系统中软件包的管理方式都有哪些 + +- rpm软件 +- yum软件仓库 +- 源码软件 + +## 一、rpm软件包 + +### rpm的介绍 + +前面的课程我们提到过源码包安装需要解决系统环境、权限等等,这些对于初学者而言都是噩梦一般的存在,所以linux厂商推出了一种类似windows系统中的安装方式,有开发者直接在已知的系统中编译好,使用者可以直接下载并进行安装,升级,卸载等操作。在linux中能够提供这些功能的软件有两种,rpm和dpkg,而在CentOS中使用的是RPM + +rpm最早是由redhat开发出来,由于很好用,所以很多发行版也利用rpm来进行软件包的管理。RPM全名RedHat Package Manager,最大的特点就是把需要安装的软件提前编译,打包,然后在rpm包里面存放了用以记录软件依赖关系的相关数据,当用户安装时,优先查看这些数据,如果系统满足数据要求就安装软件包,否则不能安装,安装完成后,将软件包相关信息记录到rpm自己的数据库中,便于查询和卸载等。所以说rpm的优点是方便安装,卸载,查询,缺点就是只能在指定的操作系统上使用,所以不同厂商的rpm包,甚至同一厂商不同版本操作系统的rpm包都不通用。 + +**rpm包的命名** + +``` +dhcp-server- 4.3.6 -30 .el8 .x86_64 .rpm +软件名称 版本 编译次数 适用的系统 适用的平台 后缀名 + +软件名 就是软件包的名称 +版本 每次更新版本号都会改变,用来帮助用户判断软件包新旧的 +编译次数 也是帮助用户判断软件包新旧的 +适用的系统 在哪个系统上可以安装,CentOS和rhel的多数软件包都是通用的 +适用的平台 指的是硬件平台,比如如果你是32位的CPU就无法安装这个软件包 +``` + +### rpm的使用 + +rpm包的相关文件一般都会放在对应的目录中,比如rpm包安装后,配置文件会放在/etc下,执行文件会放在/usr/bin下,链接库文件会放在/usr/lib下,帮助与说明文档会放在/usr/share/man和/usr/share/doc目录下 + +**安装** + +``` +[root@zutuanxue Packages]# rpm -ivh dhcp-server-4.3.6-30.el8.x86_64.rpm +-i 安装 +-v 显示详细信息 +-h 显示安装进度 +-e 卸载 +-U 升级,如果系统中有低版本的就会升级,如果系统没有安装相应的包,则安装 +-F 有条件的升级,会检测用户指定的软件包是否已安装到linux中 +--nodeps 忽略软件包之间的依赖关系 +--replacefiles 覆盖文件 +--replacepkgs 修复 +--force 强制 +--test 测试 +-q 查询指定的软件包是否安装 +-qi 查看指定的软件包的信息,包括开发商,版本,说明 +-ql 查看指定软件包中所包含的文件列表 +-qc 查看指定软件包的配置文件 +-qa 查看本机安装的所有包 +-qf 查看一个文件归属于哪个已安装的软件包 +``` + +rpm的内容我们就介绍到这里,接下来我们看下一个yum + +## 二、yum软件仓库 + +### yum的介绍 + +YUM(*Yellow dog Updater, Modified*)是一个基于rpm却更胜于rpm的管理工具,让你可以更轻松的管理Red Hat Enterprise Linux系统中的软件。你可以使用YUM来安装或卸载软件、也可以利用YUM来更新你的系统,更可以利用YUM来搜索一个尚未安装的软件。不管是安装、更新或者删除,YUM都会自动的帮你解决软件间的依赖性问题。通过YUM会比单纯使用rpm来得更加方便。 + +YUM包含下列几项组件: + +- YUM下载源:如果把所有RPM文件放在某一个目录中,这个目录就可称为“YUM下载源(*YUM Repository*)”。你也可以把YUM下载源,通过HTTP、FTP等方式分享给其他计算机使用;当然,你也可以直接使用别人建好的YUM下载源来取得需安装的软件。 +- YUM工具:YUM提供了一个名为yum的命令,你可以使用yum来使用YUM提供的众多功能。 +- YUM插件:YUM还允许第三方厂商(*3rd Party*)开发YUM的插件(*Plug-in*),让用户可以任意的扩充YUM的功能,比如说有的插件可以帮助选择最快的yum源 +- YUM缓存:YUM运行时,会从YUM下载源获得软件信息与文件,并且暂存于本机的硬盘上。这个暂存的目录,称为“YUM缓存(*YUM cache*)”。缓存目录为/var/cache/yum + +### yum的使用 + +yum源的配置 + + 由于yum有下载源这个东西,所以我们在使用yum之前需要告诉它去什么地方获取这些软件包,也就是说需要先配置一个yum源 + +``` +[root@zutuanxue ~]# cd /etc/yum.repos.d/ +[root@zutuanxue yum.repos.d]# ls +CentOS-AppStream.repo CentOS-CR.repo CentOS-fasttrack.repo CentOS-Sources.repo +CentOS-Base.repo CentOS-Debuginfo.repo CentOS-Media.repo CentOS-Vault.repo +CentOS-centosplus.repo CentOS-Extras.repo CentOS-PowerTools.repo +在CentOS8中yum的下载源配置文件统一都放到/etc/yum.repos.d/目录下,在这个目录中有些默认的下载源 +我不使用这些自带的下载源,我想配置一个自己的下载源,让yum使用光盘镜像里的软件包,为了避免干扰,我们把这些自带的下载源都放到一个目录里 +[root@zutuanxue yum.repos.d]# mkdir repos +[root@zutuanxue yum.repos.d]# ls +CentOS-AppStream.repo CentOS-CR.repo CentOS-fasttrack.repo CentOS-Sources.repo +CentOS-Base.repo CentOS-Debuginfo.repo CentOS-Media.repo CentOS-Vault.repo +CentOS-centosplus.repo CentOS-Extras.repo CentOS-PowerTools.repo repos +[root@zutuanxue yum.repos.d]# mv *.repo repos +[root@zutuanxue yum.repos.d]# clear +[root@zutuanxue yum.repos.d]# ls +repos +然后使用vim命令建立自己的下载源配置文件 +[root@zutuanxue repos]# vim server.repo +[server-BaseOS] yum源的名称 +name=server-BaseOS 完整名称 +enabled=1 是否启用 +gpgcheck=0 是否检查rpm包的数字签名 +baseurl=file:///mnt/BaseOS 下载源地址 +[server-AppStream] +name=server-AppStream +enabled=1 +gpgcheck=0 +baseurl=file:///mnt/AppStream +[root@zutuanxue ~]# mount /dev/cdrom /mnt/ 将光盘挂载到指定位置 +由于CentOS8的软件包存放在光盘根目录的BaseOS和AppStream目录中,所以这里面为了保证需要的软件包能正确安装我们配置了两个yum源,这两部分内容你可以放到一个文件里,也可以分别放在两个文件中 +``` + +以上就是yum源配置文件,我们接下来看下如何建立下载源目录 + +``` +将下载好的rpm软件包存放到一个指定的目录中 +[root@zutuanxue ~]# cp /mnt/AppStream/Packages/* myrepo/ + +从光盘镜像中安装createrepo工具 +[root@zutuanxue ~]# yum install createrepo + +利用createrepo工具生成软件包之间的依赖关系数据文件 +[root@zutuanxue ~]# createrepo myself/ + +建立针对此目录的下载源配置文件 +[root@zutuanxue ~]# vim /etc/yum.repos.d/myrepo.repo +[myself] +name=packages +enabled=1 +gpgcheck=0 +baseurl=file:///root/myself + +从新的下载源安装软件包 +[root@zutuanxue ~]# yum install httpd +``` + +yum插件安装 + +``` +[root@zutuanxue ~]# yum install 插件名称 +插件配置文件存放位置/etc/yum/pluginconf.d/xxx.conf + +插件的启用和停用 +修改/etc/yum/pluginconf.d/xxx.conf文件中的enabled字段 1=启用 0=停用 +[root@zutuanxue ~]# yum [OPTIONS...] COMMAND [ARGVS...] +-y 如果遇到问题,代替回答yes +--installroot=/path 指定软件包安装的根目录 +``` + +清除yum缓存 + +``` +[root@zutuanxue ~]# yum clean all +如果有些时候你发现yum运行不太正常,这可能是yum缓存数据错误导致的,所以你需要将yum的缓存清除 +查看软件包 +[root@zutuanxue ~]# yum list + +查看有哪些可用组 +[root@zutuanxue ~]# yum grouplist + +查看dhcp-server这个包的信息 +[root@zutuanxue ~]# yum info dhcp-server + +搜索dhcp-server这个软件包 +[root@zutuanxue ~]# yum search dhcp-server +``` + +yum安装 + +``` +安装dhcp-server软件包 +[root@zutuanxue ~]# yum install dhcp-server -y + +安装一组软件包 +[root@zutuanxue ~]# yum groupinstall '系统工具' -y +``` + +卸载软件包 + +``` +删除一个软件包 +[root@zutuanxue ~]# yum remove dhcp-server -y + +删除一组软件包 +[root@zutuanxue ~]# yum groupremove '系统工具' -y +``` + +使用epel源 + +EPEL是一个自由开源的附加软件包仓库,可用于 CentOS 和 RHEL 服务器。顾名思义,EPEL 仓库提供了额外的软件包,这些软件在 CentOS 8 和 RHEL 8 的默认软件包仓库中不可用。 + +安装epel源 + +epel地址:https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm + +``` +[root@zutuanxue ~]# yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm +``` + +## 三、源码包的安装 + +在linux系统中,很多新版本的软件包的更新都会优先提供tar包版本的,然后各linux厂商拿到这个tar包之后再给自己的操作系统提供官方的rpm或者dpkg类型的软件包,而这种tar工具打包的软件包我们一般称之为源码包,在这些源码包中一般包含有,程序源代码文件,配置文件(configure),安装使用说明(INSTALL,HOWTO,README) + +那这种tar包源码包如何安装呢?简单的流程就是 + +- 获取软件包 +- 解压文件 +- 检查当前系统是否满足软件包安装需求 +- 使用gcc进行编译,生成主要的二进制文件 +- 将二进制文件安装到主机 + +这些步骤看起来很简单,但是在使用过程中有很多问题需要解决,比如说需要解决系统环境,权限问题等等,不同类型的软件在安装方法上会有差异,但是整体步骤就是我们上面所提到的。接下来我们通过一个案例来学习源码安装软件。 + +**案例:源码安装一个nginx软件** + +### 获取软件包 + +软件包获取的方式有很多,最常见的就是拷贝或者下载这两种方式,拷贝咱们就不说了,因为用的太多了;接下来我给大家说一下如何从网络下载软件包。 + +- wget命令:文本界面的下载命令 + +``` +[root@zutuanxue ~]# wget http://nginx.org/download/nginx-1.19.3.tar.gz +--2020-10-11 15:59:45-- http://nginx.org/download/nginx-1.19.3.tar.gz +正在解析主机 nginx.org (nginx.org)... 3.125.197.172, 52.58.199.22, 2a05:d014:edb:5704::6, ... +正在连接 nginx.org (nginx.org)|3.125.197.172|:80... 已连接。 +已发出 HTTP 请求,正在等待回应... 200 OK +长度:1052581 (1.0M) [application/octet-stream] +正在保存至: “nginx-1.19.3.tar.gz” + +nginx-1.19.3.tar.gz 100%[===================>] 1.00M 21.4KB/s 用时 43s + +2020-10-11 16:00:28 (24.1 KB/s) - 已保存 “nginx-1.19.3.tar.gz” [1052581/1052581]) +``` + +- 解压软件包 + +``` +[root@zutuanxue ~]# tar xf nginx-1.19.3.tar.gz + +[root@zutuanxue ~]# ls +公共 视频 文档 音乐 anaconda-ks.cfg nginx-1.19.3 +模板 图片 下载 桌面 initial-setup-ks.cfg nginx-1.19.3.tar.gz +``` + +- configure命令:检查当前系统是否满足软件包安装需求,这步的主要目的: + – 检查环境 是否 满足安装条件 依赖解决 + – 指定安装方式 配置文件 命令文件 各种文件放哪里 开启模块功能【内置模块 三方模块】 + – 指定软件安装在那里 + +``` +- 安装GCC编译软件 以及nginx依赖,有人问我为啥要安装pcre-devel zlib-devel这两个包,因为你不了解,如果你自己安装过一次就知道在检查当前系统的时候会报错,说没有这两个软件,这里我就直接装上了。大家学习的时候可以试试,是不是我说的这样。 +[root@zutuanxue ~]# yum -y install gcc pcre-devel zlib-devel + +- 检查系统是否满足安装需求 +[root@zutuanxue ~]# cd nginx-1.19.3/ +[root@zutuanxue nginx-1.19.3]# ./configure --prefix=/usr/local/nginx +checking for OS + + Linux 4.18.0-193.el8.x86_64 x86_64 +checking for C compiler ... found + + using GNU C compiler + + gcc version: 8.3.1 20191121 (Red Hat 8.3.1-5) (GCC) +checking for gcc -pipe switch ... found +checking for -Wl,-E switch ... found +checking for gcc builtin atomic operations ... found +checking for C99 variadic macros ... found +checking for gcc variadic macros ... found + +.........此处省略10000个字 + +Configuration summary + + using system PCRE library + + OpenSSL library is not used + + using system zlib library + + nginx path prefix: "/usr/local/nginx" + nginx binary file: "/usr/local/nginx/sbin/nginx" + nginx modules path: "/usr/local/nginx/modules" + nginx configuration prefix: "/usr/local/nginx/conf" + nginx configuration file: "/usr/local/nginx/conf/nginx.conf" + nginx pid file: "/usr/local/nginx/logs/nginx.pid" + nginx error log file: "/usr/local/nginx/logs/error.log" + nginx http access log file: "/usr/local/nginx/logs/access.log" + nginx http client request body temporary files: "client_body_temp" + nginx http proxy temporary files: "proxy_temp" + nginx http fastcgi temporary files: "fastcgi_temp" + nginx http uwsgi temporary files: "uwsgi_temp" + nginx http scgi temporary files: "scgi_temp" + + +备注: +/configure --prefix=/usr/local/nginx +--prefix= 指定软件安装到哪个目录 +``` + +- make命令:使用gcc进行编译,生成主要的二进制文件 + +``` +[root@zutuanxue nginx-1.19.3]# make -j4 +make -f objs/Makefile +make[1]: 进入目录“/root/nginx-1.19.3” +cc -c -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -I src/core -I src/event -I src/event/modules -I src/os/unix -I objs \ + -o objs/src/core/ngx_inet.o \ + src/core/ngx_inet.c + ...........省略过程 + +-ldl -lpthread -lcrypt -lpcre -lz \ +-Wl,-E +make[1]: 离开目录“/root/nginx-1.19.3” + + +备注: make -j4 +-j 指定几个cpu一起编译 -j4 那就是4个一起干活,默认一个干活,这样速度更快 +``` + +- make install 命令将二进制文件安装到主机 + +``` +[root@zutuanxue nginx-1.19.3]# make install +make -f objs/Makefile install +make[1]: 进入目录“/root/nginx-1.19.3” +test -d '/usr/local/nginx' || mkdir -p '/usr/local/nginx' +test -d '/usr/local/nginx/sbin' \ + || mkdir -p '/usr/local/nginx/sbin' +test ! -f '/usr/local/nginx/sbin/nginx' \ + || mv '/usr/local/nginx/sbin/nginx' \ + '/usr/local/nginx/sbin/nginx.old' +cp objs/nginx '/usr/local/nginx/sbin/nginx' +test -d '/usr/local/nginx/conf' \ + || mkdir -p '/usr/local/nginx/conf' +cp conf/koi-win '/usr/local/nginx/conf' +cp conf/koi-utf '/usr/local/nginx/conf' +cp conf/win-utf '/usr/local/nginx/conf' +test -f '/usr/local/nginx/conf/mime.types' \ + || cp conf/mime.types '/usr/local/nginx/conf' +cp conf/mime.types '/usr/local/nginx/conf/mime.types.default' +test -f '/usr/local/nginx/conf/fastcgi_params' \ + || cp conf/fastcgi_params '/usr/local/nginx/conf' +cp conf/fastcgi_params \ + '/usr/local/nginx/conf/fastcgi_params.default' +test -f '/usr/local/nginx/conf/fastcgi.conf' \ + || cp conf/fastcgi.conf '/usr/local/nginx/conf' +cp conf/fastcgi.conf '/usr/local/nginx/conf/fastcgi.conf.default' +test -f '/usr/local/nginx/conf/uwsgi_params' \ + || cp conf/uwsgi_params '/usr/local/nginx/conf' +cp conf/uwsgi_params \ + '/usr/local/nginx/conf/uwsgi_params.default' +test -f '/usr/local/nginx/conf/scgi_params' \ + || cp conf/scgi_params '/usr/local/nginx/conf' +cp conf/scgi_params \ + '/usr/local/nginx/conf/scgi_params.default' +test -f '/usr/local/nginx/conf/nginx.conf' \ + || cp conf/nginx.conf '/usr/local/nginx/conf/nginx.conf' +cp conf/nginx.conf '/usr/local/nginx/conf/nginx.conf.default' +test -d '/usr/local/nginx/logs' \ + || mkdir -p '/usr/local/nginx/logs' +test -d '/usr/local/nginx/logs' \ + || mkdir -p '/usr/local/nginx/logs' +test -d '/usr/local/nginx/html' \ + || cp -R html '/usr/local/nginx' +test -d '/usr/local/nginx/logs' \ + || mkdir -p '/usr/local/nginx/logs' +make[1]: 离开目录“/root/nginx-1.19.3” +``` + +到此我们就把nginx安装到/usr/local目录下了,可以使用ls命令看看有没有东西 + +``` +[root@zutuanxue nginx-1.19.3]# ls /usr/local/nginx/ +conf html logs sbin +``` + +- 验证安装 + 软件已经安装了,我们看看结果吧! + +``` +启动软件 +[root@zutuanxue nginx-1.19.3]# /usr/local/nginx/sbin/nginx +``` + +打开虚拟机浏览器输入:http://localhost回车 + +![nginx访问.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602404129693.png) + +## 四、CentOS 8 dnf命令 + +### dnf介绍 + +DNF是新一代的rpm软件包管理器。最早出现在 Fedora 18 这个发行版中,在Fedora 22中正式取代了yum + +DNF器克服了YUM的一些瓶颈,提升了包括用户体验,内存占用,依赖分析,运行速度等多方面的内容。 + +### dnf安装 + +在CentOS7中需要单独安装 + +``` +yum install epel-release -y +yum install dnf +``` + +在CentOS8中系统默认使用的是DNF,我们所看到的yum只是dnf的一个软连接 + +``` +[root@zutuanxue ~]# which yum +/usr/bin/yum +[root@zutuanxue ~]# ll /usr/bin/yum +lrwxrwxrwx. 1 root root 5 5月 14 2019 /usr/bin/yum -> dnf-3 +``` + +#### **相关目录和使用** + +- **目录** + +/etc/dnf/dnf.conf 配置文件 + +/etc/dnf/aliases.d/ 为相关命令定义别名的如dnf alias add rm=remove + +/etc/dnf/modules.d&/etc/dnf/modules.defaults.d 模块的设置 + +/etc/dnf/plugins/ 插件的设置 + +/etc/dnf/protected.d/ 受保护的软件包的设置 + +/etc/dnf/vars/ 变量设置 + +- **dnf用法展示** + +``` +查看DNF的版本 +[root@zutuanxue ~]# dnf --version + +查看dnf的可用软件仓库 +[root@zutuanxue ~]# dnf repolist + +查看所有软件仓库 +[root@zutuanxue ~]# dnf repolist all + +查看已安装的软件包 +[root@zutuanxue ~]# dnf list installed + +查看可安装的软件包 +[root@zutuanxue ~]# dnf list available + +搜索dhcp-server +[root@zutuanxue ~]# dnf search dhcp-server + +查询一个文件是由哪个软件包提供的 +[root@zutuanxue ~]# dnf provides /usr/sbin/dhclient + +查询软件包详细信息 +[root@zutuanxue ~]# dnf info dhcp-server + +安装软件包 +[root@zutuanxue ~]# dnf install dhcp-server + +升级软件包 +[root@zutuanxue ~]# dnf update systemd + +检查软件包的更新 +[root@zutuanxue ~]# dnf check-update + +升级所有可升级的软件包 +[root@zutuanxue ~]# dnf update + +升级所有可升级的软件包 +[root@zutuanxue ~]# dnf upgrade + +卸载软件包 +[root@zutuanxue ~]# dnf remove dhcp-server +[root@zutuanxue ~]# dnf erase dhcp-server + +删除无用孤立的软件包 +[root@zutuanxue ~]# dnf autoremove + +清除缓存中的无用数据 +[root@zutuanxue ~]# dnf clean all + +获取某一个命令的帮助 +[root@zutuanxue ~]# dnf help clean + +获取dnf命令的帮助 +[root@zutuanxue ~]# dnf help + +查看历史命令 +[root@zutuanxue ~]# dnf history + +重新执行历史命令中的第19条 +[root@zutuanxue ~]# dnf history redo 19 + +查看软件包组 +[root@zutuanxue ~]# dnf grouplist + +安装一组软件包 +[root@zutuanxue ~]# dnf groupinstall '系统工具' + +升级一组软件包 +[root@zutuanxue ~]# dnf groupupdate '系统工具' + +删除一组软件包 +[root@zutuanxue ~]# dnf groupremove '系统工具' + +从特定的软件仓库安装软件包 +[root@zutuanxue ~]# dnf --enablerepo=epel install zabbix + +将软件包更新到最新的稳定版 +[root@zutuanxue ~]# dnf distro-sync + +重新安装指定的软件包 +[root@zutuanxue ~]# dnf reinstall dhcp-server + +降级软件包 +[root@zutuanxue ~]# dnf downgrade dhcp-server +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/shell \346\225\260\346\215\256\345\244\204\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/shell \346\225\260\346\215\256\345\244\204\347\220\206.md" new file mode 100644 index 0000000..a6dd51b --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/shell \346\225\260\346\215\256\345\244\204\347\220\206.md" @@ -0,0 +1,820 @@ +## 一、linux中的常用符号 + +| | | +| ------------------------------------- | ------------------------------------------------------------ | +| * | 代表任意字符串 | +| ? | 代表任意字符 | +| / | 代表根目录或作为路径间隔符使用 | +| \ | 转义字符。 | +| \ | 续行符。可以使用续行符将一个命令行分写在多行上 | +| $ | 变量值置换,如:$PATH表示环境变量PATH的值 | +| ’ | 在’…'中间的字符都会被当做普通字符处理 | +| ‘’ | 在’’…’'中间的字符会被当做文字处理并允许变量值置换 | +| `| 命令替换,置换\`…`中命令的执行结果 | | +| < | 输入重定向字符 | +| > | 输出重定向字符 | +| \| | 管道字符 | +| & | 后台执行字符。在一个命令之后加上字符“&”,该命令就会以后台方式执行 | +| ; | 按照顺序执行的多个命令 | +| () | 在子Shell中执行命令 | +| {} | 在当前Shell中执行命令 | +| ! | 执行命令历史记录中的命令 | +| ~ | 代表登录用户的宿主目录(自家目录) | + +## 二、历史记录 + +linux系统在shell中保留了用户键入的每一个命令的历史记录,并且提供了很多种方法让用户通过历史记录找到曾经使用过的命令,并且调用这个历史记录的命令。 + +``` +[root@zutuanxue ~]# history + 1 ifconfig + 2 nmcli connection modify ens33 ipv4.addresses 192.168.2.220/24 ipv4.gateway 192.168.2.1 ipv4.method manual autoconnect yes + 3 route -n + 4 nmcli connection down ens33 + . + . + . +``` + +| 语法 | 替换 | +| ----- | --------------------- | +| !! | 前一个命令 | +| !n | 命令号n | +| !-n | 倒数第n个命令 | +| !cmd | 最后用来启动cmd的命令 | + +**与历史记录相关的文件和变量** + +``` +[root@zutuanxue ~]# echo $HISTFILE +/root/.bash_history +#用户的历史记录保存的位置 +[root@zutuanxue ~]# echo $HISTFILESIZE +1000 +#启动时,从历史记录中读取的记录条数 +[root@zutuanxue ~]# echo $HISTSIZE +1000 +#退出时,被写入历史记录的最大条数 +``` + +**历史记录技巧** + +``` +esc+./alt+. 调用上一条命令的最后一部分内容 +ctrl+r 在历史记录中搜索给出关键字的命令 +``` + +## 三、标准输入、标准输出、标准错误 + +在linux系统中,大多数时候我们从键盘读取输入,在终端显示输出,而我们在键盘中输入的内容,多数都是执行命令,这些命令属于终端程序,除了终端程序还有图形程序和屏幕程序(如vim),不管是哪一种程序都会涉及到输入,输出,错误,多数情况下,我们在键盘输入信息,在显示器查看信息(正确的信息和错误的信息),这些输入的信息我们称之为标准输入(可以用0表示),输出的信息我们称之为标准输出(可以用1表示),而错误的信息(可以用2表示),我们称之为标准错误。在日常使用中我们除了可以使用键盘输入信息,从显示器读取信息之外,还可以指定程序从键盘以外的地方读取需要输入的内容,也可以让程序将信息输出到显示器以外的地方。 + +**重定向输入和输出** + +``` +#重定向输出 +[root@zutuanxue ~]# mkdir a +[root@zutuanxue ~]# cd a +[root@zutuanxue a]# mkdir aa ab ac +[root@zutuanxue a]# cd aa +[root@zutuanxue aa]# touch bb bc bd +[root@zutuanxue ~]# ls a/ > test +[root@zutuanxue ~]# cat test +aa +ab +ac +[root@zutuanxue ~]# ls a/aa/ >> test +[root@zutuanxue ~]# cat test +aa +ab +ac +bb +bc +bd + +>覆盖 +>>追加 +#重定向输入 +[root@zutuanxue ~]# wc -l test +6 hello +[root@zutuanxue ~]# wc -l < test +6 +注意:第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容。 +``` + +我们知道标准输入可以用0来表示,标准输出可以用1来表示,标准错误可以用2来表示,而有些时候这些输出的信息中即包含了正确的信息,也包含了错误的信息,如: + +``` +[root@zutuanxue ~]# ls /etc/rc.d/ +init.d rc0.d rc1.d rc2.d rc3.d rc4.d rc5.d rc6.d rc.local +[root@zutuanxue ~]# head -1 /etc/rc.d/* +==> /etc/rc.d/init.d <== +head: 读取'/etc/rc.d/init.d' 时出错: 是一个目录 + +==> /etc/rc.d/rc0.d <== +head: 读取'/etc/rc.d/rc0.d' 时出错: 是一个目录 + +==> /etc/rc.d/rc1.d <== +head: 读取'/etc/rc.d/rc1.d' 时出错: 是一个目录 + +==> /etc/rc.d/rc2.d <== +head: 读取'/etc/rc.d/rc2.d' 时出错: 是一个目录 + +==> /etc/rc.d/rc3.d <== +head: 读取'/etc/rc.d/rc3.d' 时出错: 是一个目录 + +==> /etc/rc.d/rc4.d <== +head: 读取'/etc/rc.d/rc4.d' 时出错: 是一个目录 + +==> /etc/rc.d/rc5.d <== +head: 读取'/etc/rc.d/rc5.d' 时出错: 是一个目录 + +==> /etc/rc.d/rc6.d <== +head: 读取'/etc/rc.d/rc6.d' 时出错: 是一个目录 + +==> /etc/rc.d/rc.local <== +#!/bin/bash +``` + +我们通过ls命令查看/etc/rc.d这个目录的时候,我们发现,这个目录中即有目录,也有文件,而当我们使用“head -1”命令去查看文件的第一行内容的时候, 很显然目录是无法查看第一行的,这时就会有报错,当我想把这些信息都写入到一个指定的文件中而不想看到这些内容我该如何去做? + +``` +[root@zutuanxue ~]# head -1 /etc/rc.d/* > test +head: 读取'/etc/rc.d/init.d' 时出错: 是一个目录 +head: 读取'/etc/rc.d/rc0.d' 时出错: 是一个目录 +head: 读取'/etc/rc.d/rc1.d' 时出错: 是一个目录 +head: 读取'/etc/rc.d/rc2.d' 时出错: 是一个目录 +head: 读取'/etc/rc.d/rc3.d' 时出错: 是一个目录 +head: 读取'/etc/rc.d/rc4.d' 时出错: 是一个目录 +head: 读取'/etc/rc.d/rc5.d' 时出错: 是一个目录 +head: 读取'/etc/rc.d/rc6.d' 时出错: 是一个目录 +[root@zutuanxue ~]# cat test +==> /etc/rc.d/init.d <== +==> /etc/rc.d/rc0.d <== +==> /etc/rc.d/rc1.d <== +==> /etc/rc.d/rc2.d <== +==> /etc/rc.d/rc3.d <== +==> /etc/rc.d/rc4.d <== +==> /etc/rc.d/rc5.d <== +==> /etc/rc.d/rc6.d <== +==> /etc/rc.d/rc.local <== +#!/bin/bash +``` + +我们可以利用之前的>将输出的信息重定向到一个指定的文件,但是仍然会收到错误提示,这是为什么呢?因为在linux当中正确的输出和错误的输出实际上是两种数据流,默认情况下这两种数据流都会在显示器上打印出来,而我们使用的>相当于1>,也就是将正确的信息写入到了test文件中,错误的信息依旧会看到。利用前面的提到0,1,2这三个数字,我们可以这样做 + +``` +[root@zutuanxue ~]# head -1 /etc/rc.d/* > test 2> test.err +[root@zutuanxue ~]# cat test +==> /etc/rc.d/init.d <== +==> /etc/rc.d/rc0.d <== +==> /etc/rc.d/rc1.d <== +==> /etc/rc.d/rc2.d <== +==> /etc/rc.d/rc3.d <== +==> /etc/rc.d/rc4.d <== +==> /etc/rc.d/rc5.d <== +==> /etc/rc.d/rc6.d <== +==> /etc/rc.d/rc.local <== +#!/bin/bash +[root@zutuanxue ~]# cat test.err +head: 读取'/etc/rc.d/init.d' 时出错: 是一个目录 +head: 读取'/etc/rc.d/rc0.d' 时出错: 是一个目录 +head: 读取'/etc/rc.d/rc1.d' 时出错: 是一个目录 +head: 读取'/etc/rc.d/rc2.d' 时出错: 是一个目录 +head: 读取'/etc/rc.d/rc3.d' 时出错: 是一个目录 +head: 读取'/etc/rc.d/rc4.d' 时出错: 是一个目录 +head: 读取'/etc/rc.d/rc5.d' 时出错: 是一个目录 +head: 读取'/etc/rc.d/rc6.d' 时出错: 是一个目录 +``` + +但是这依然是两个文件,能不能将这些信息都写入到一个文件中呢? + +``` +[root@zutuanxue ~]# head -1 /etc/rc.d/* > test.both 2>&1 +[root@zutuanxue ~]# cat test.both +==> /etc/rc.d/init.d <== +head: 读取'/etc/rc.d/init.d' 时出错: 是一个目录 +==> /etc/rc.d/rc0.d <== +head: 读取'/etc/rc.d/rc0.d' 时出错: 是一个目录 +==> /etc/rc.d/rc1.d <== +head: 读取'/etc/rc.d/rc1.d' 时出错: 是一个目录 +==> /etc/rc.d/rc2.d <== +head: 读取'/etc/rc.d/rc2.d' 时出错: 是一个目录 +==> /etc/rc.d/rc3.d <== +head: 读取'/etc/rc.d/rc3.d' 时出错: 是一个目录 +==> /etc/rc.d/rc4.d <== +head: 读取'/etc/rc.d/rc4.d' 时出错: 是一个目录 +==> /etc/rc.d/rc5.d <== +head: 读取'/etc/rc.d/rc5.d' 时出错: 是一个目录 +==> /etc/rc.d/rc6.d <== +head: 读取'/etc/rc.d/rc6.d' 时出错: 是一个目录 +==> /etc/rc.d/rc.local <== +#!/bin/bash + +或者 + +[root@zutuanxue ~]# head -1 /etc/rc.d/* >& test.both1 +[root@zutuanxue ~]# cat test.both1 +==> /etc/rc.d/init.d <== +head: 读取'/etc/rc.d/init.d' 时出错: 是一个目录 +==> /etc/rc.d/rc0.d <== +head: 读取'/etc/rc.d/rc0.d' 时出错: 是一个目录 +==> /etc/rc.d/rc1.d <== +head: 读取'/etc/rc.d/rc1.d' 时出错: 是一个目录 +==> /etc/rc.d/rc2.d <== +head: 读取'/etc/rc.d/rc2.d' 时出错: 是一个目录 +==> /etc/rc.d/rc3.d <== +head: 读取'/etc/rc.d/rc3.d' 时出错: 是一个目录 +==> /etc/rc.d/rc4.d <== +head: 读取'/etc/rc.d/rc4.d' 时出错: 是一个目录 +==> /etc/rc.d/rc5.d <== +head: 读取'/etc/rc.d/rc5.d' 时出错: 是一个目录 +==> /etc/rc.d/rc6.d <== +head: 读取'/etc/rc.d/rc6.d' 时出错: 是一个目录 +==> /etc/rc.d/rc.local <== +#!/bin/bash + +这两种使用方式都是告诉shell将错误信息写入到正确信息所写入的文件中。 +如果这些错误信息是我们早就知道的,并且还不想看到的呢? +[root@zutuanxue ~]# head -1 /etc/rc.d/* 2> /dev/null +==> /etc/rc.d/init.d <== +==> /etc/rc.d/rc0.d <== +==> /etc/rc.d/rc1.d <== +==> /etc/rc.d/rc2.d <== +==> /etc/rc.d/rc3.d <== +==> /etc/rc.d/rc4.d <== +==> /etc/rc.d/rc5.d <== +==> /etc/rc.d/rc6.d <== +==> /etc/rc.d/rc.local <== +#!/bin/bash + +/dev/null:表示的是一个黑洞,通常用于丢弃不需要的数据输出 +``` + +综上所述针对于输入输出重定向与合并的用法有 + +| 语法 | 作用 | +| ------------- | ---------------------------------------------------------- | +| cmd < file | 从file重定向标准输入 | +| cmd > file | 把标准输出重定向到file中,如果file存在的话,覆盖(损坏)它 | +| cmd>>file | 把标准输出重定向到file中,如果file存在,附加给它 | +| cmd 2>file | 把标准错误重定向到file,如果file 存在,覆盖(损坏)它 | +| cmd 2>> file | 把标准错误重定向到file中,如果file 存在,附加给他 | +| cmd>file 2>&1 | 合并标准输出和标准错误,并且重定向到file中(可移植的语法) | +| cmd >& file | 合并标准输出和标准错误,并且重定向到file中(方便的语法) | + +## 四、管道 + +在前面,我们已经看到,进程的输出可以被重定向到终端显示器以外的地方,或者可以让进程从终端键盘以外的地方读取输入。一种最常用,最有力的重定向形式是把这二者结合起来,在这种形式下,一个命令的输出(标准输出)被直接“用管道输送”到另一个命令的输入(标准输入)中,从而构成了 Linux(和Unix)所谓的管道(pipe)。当两个命令用管道连接起来时,第一个进程的标准输出流被直接连接到第二个进程的标准输入序列。为了用bash创建管道,用一个垂直的小节线 | 把这两个命令连接起来。 + +![image20200323144226709.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603601398337.png) + +``` +[root@zutuanxue ~]# pwd +/root +[root@zutuanxue ~]# ls | grep ana +anaconda-ks.cfg +注意:从管道读数据是一次性操作,数据一旦被读,它就从管道中被抛弃,释放空间以便写更多的数据。它只能处理经由前面一个指令传出的正确输出信息,对错误信息信息没有直接处理能力。然后,传递给下一个命令,作为标准的输入。 +``` + +## 五、数据处理常用工具 + +### 5.1、find文件查找命令 + +. 代表当前目录 + +~ 代表用户家目录 + +**find命令选项** + +``` +-name 按照文件名查找文件。 +[root@zutuanxue ~]# find ~ -name "test.*" +/root/test.err +/root/test.both +/root/test.both1 + + +-perm 按照文件权限来查找文件。 +[root@zutuanxue ~]# chmod 777 hello +[root@zutuanxue ~]# find . -perm 777 +./hello + + +-user 按照文件属主来查找文件。 +-group 按照文件所属的组来查找文件。 +-uid 查找指定uid +-gid 查找指定gid +[root@zutuanxue ~]# chown hello.hello test +[root@zutuanxue ~]# find . -user hello +./test +[root@zutuanxue ~]# find . -group hello +./test +[root@zutuanxue ~]# chown root.hello hello +[root@zutuanxue ~]# find . -user root -group hello +./hello +[root@zutuanxue ~]# find . -uid 1000 +./test +[root@zutuanxue ~]# find . -gid 1000 +./test + + +-mtime -n +n 按照文件的更改时间来查找文件, -n表示n天以内,+n表示n天以前。还有-atime和-ctime 选项 +-amin/-cmin/-mmin n 查找系统中最后N分钟 + +   +#如果-mtime +2 表示当前时间-2day以前的mtime的文件。即文件的mtime小于 sysdate -2 +#如果-mtime -2 表示当前时间-2day以后的mtime的文件。即文件的mtime大于 sysdate -2 +#如果-mtime 2 表示文件mtime在sysdate -2 与 sysdate-1 之间的文件。 +#!!!!!实际上再记不住,记住一般删除旧数据,一定是选择+。 + +[root@zutuanxue ~]# find /etc -mtime -2 +/etc +/etc/cups +/etc/cups/subscriptions.conf +/etc/resolv.conf + + + +-nogroup 查找无有效所属组的文件,即该文件所属的组在/etc/groups中不存在。 +-nouser 查找无有效属主的文件,即该文件的属主在/etc/passwd中不存在。 +[root@zutuanxue ~]# chown 1400.1400 hello +[root@zutuanxue ~]# ll hello +-rwxrwxrwx 1 1400 1400 8 3月 22 23:25 hello +[root@zutuanxue ~]# find . -nogroup +./hello +[root@zutuanxue ~]# find . -nouser +./hello + +-newer file1 查找更改时间比文件file1新的文件。 +[root@zutuanxue ~]# find /etc -newer initial-setup-ks.cfg +/etc +/etc/dnf/modules.d +/etc/dnf/modules.d/httpd.module +/etc/logrotate.d +还有anewer和cnewer + + + + +-type 查找某一类型的文件,诸如: +b - 块设备文件。 +d - 目录。 +c - 字符设备文件。 +p - 管道文件。 +l - 符号链接文件。 +f - 普通文件。 + + +[root@zutuanxue ~]# find /etc -newer initial-setup-ks.cfg -type f +/etc/dnf/modules.d/httpd.module +/etc/logrotate.d/glusterfs +/etc/pki/nssdb/cert9.db +/etc/pki/nssdb/key4.db +/etc/yum.repos.d/server.repo + + +-size n[bcwkMG] 查找文件长度为n块的文件,带有c时表示文件长度以字节计。 + b 512字节一块 + c 字节 + w 字(2字节) + k k字节(1024) + M M字节(1024x1024字节) + G G字节(1024x1024x1024字节) +[root@zutuanxue ~]# find . -size +1M +./.cache/tracker/meta.db +./.cache/tracker/meta.db-wal +./.cache/mozilla/firefox/mduza4q4.default/startupCache/startupCache.8.little +./.cache/mozilla/firefox/mduza4q4.default/startupCache/scriptCache-child-current.bin +./.cache/mozilla/firefox/mduza4q4.default/startupCache/scriptCache-current.bin +./.mozilla/firefox/mduza4q4.default/places.sqlite +./.mozilla/firefox/mduza4q4.default/favicons.sqlite +# 在使用的时候注意一下单位,如find . -size 4k使用4k时会显示所有大与3k小于等于4k的文件,如果使用的是4096c则是查找大小为4k的文件 +[root@zutuanxue ~]# find . -size 4k +. +./.cache/mozilla/firefox/mduza4q4.default/startupCache/urlCache-current.bin +./.cache/mozilla/firefox/mduza4q4.default/startupCache/urlCache.bin +./.cache/mozilla/firefox/mduza4q4.default/safebrowsing +./.config/pulse +./.mozilla/firefox/mduza4q4.default +./.mozilla/firefox/mduza4q4.default/datareporting/archived/2020-02 +./.mozilla/firefox/mduza4q4.default/saved-telemetry-pings +[root@zutuanxue ~]# find . -size 4096c +. +./.cache/mozilla/firefox/mduza4q4.default/safebrowsing +./.config/pulse +./.mozilla/firefox/mduza4q4.default +./.mozilla/firefox/mduza4q4.default/datareporting/archived/2020-02 +./.mozilla/firefox/mduza4q4.default/saved-telemetry-pings +[root@zutuanxue ~]# find . -size 4k |wc -l +8 +[root@zutuanxue ~]# find . -size 4096c |wc -l +6 +[root@zutuanxue ~]# ll -h .cache/mozilla/firefox/mduza4q4.default/startupCache/urlCache-current.bin +-rw-r--r-- 1 root root 3.1K 2月 24 02:34 .cache/mozilla/firefox/mduza4q4.default/startupCache/urlCache-current.bin + + +-follow:如果find命令遇到符号链接文件,就跟踪至链接所指向的文件。 +[root@zutuanxue ~]# ln -s /etc/ linketc +[root@zutuanxue ~]# find . -name passwd +[root@zutuanxue ~]# find . -name passwd -follow +./linketc/pam.d/passwd +./linketc/passwd + +-exec command {} \; —–将查到的文件执行command操作,{} 和 \;之间有空格 +-ok 和-exec相同,只不过在操作前要询用户 +[root@zutuanxue ~]# find /etc -name passwd -exec grep "hello" {} \; +hello:x:1000:1000:hello:/home/hello:/bin/bash +[root@zutuanxue ~]# find /etc -name passwd -ok grep "hello" {} \; +< grep ... /etc/pam.d/passwd > ? y +< grep ... /etc/passwd > ? y +hello:x:1000:1000:hello:/home/hello:/bin/bash + + +-empty 查找空文件或目录 +[root@zutuanxue ~]# find /etc -empty +/etc/crypttab +/etc/dnf/aliases.d +/etc/dnf/modules.defaults.d + + +-inum 查找i节点编号为指定数值的文件 +-samefile 查找相同的文件 + +[root@zutuanxue ~]# ln hello hello1 +[root@zutuanxue ~]# ln hello hello2 +[root@zutuanxue ~]# ll -i hello +34510098 -rwxrwxrwx 3 1400 1400 8 3月 22 23:25 hello +[root@zutuanxue ~]# find . -inum 34510098 +./hello +./hello1 +./hello2 + +[root@zutuanxue ~]# find . -samefile hello +./hello +./hello1 +./hello2 +``` + +### 5.2、grep&egrep 数据检索命令 + +一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来,最常用。egrep是grep的扩展,支持更多的正则表达式元字符,等同于grep -E。 + +useradd HELLO + +useradd helo + +useradd helllo + +**grep 与 正则表达式符号** + +``` +^ 行的开始 如:'^grep'匹配所有以grep开头的行。 +[root@zutuanxue ~]# grep '^he' /etc/passwd + +$ 行的结束 如:'grep$'匹配所有以grep结尾的行。 +[root@zutuanxue ~]# grep 'sh$' /etc/passwd + +. 匹配一个非换行符('\n')的字符如:'gr.p'匹配gr后接一个任意字符,然后是p。 +[root@zutuanxue ~]# grep 't.e' /etc/passwd + +* 匹配零个或多个先前字符 如:' *grep' (注意*前有空格)匹配所有零个或多个空格后紧跟grep的行,需要用egrep 或者grep带上 -E 选项。 .*一起用代表任意字符。 +[root@zutuanxue ~]# grep -E 'el*lo' /etc/passwd + +[] 匹配一个指定范围内的字符,如'[Gg]rep'匹配Grep和grep。 +[root@zutuanxue ~]# grep '[Hh]el' /etc/passwd + +[^] 匹配一个不在指定范围内的字符,如:'[^A-FH-Z]rep'匹配不包含A-F和H-Z的一个字母开头,紧跟rep的行。 +[root@zutuanxue ~]# grep '[^A-Z]ello' /etc/passwd +[root@zutuanxue ~]# grep '[^a-z]ello' /etc/passwd + +\? 匹配零个或一个先前的字符。如:'gre\?p'匹配gr后跟一个或零个e字符,然后是p的行。 +[root@zutuanxue ~]# grep 'hell\?o' /etc/passwd +hello:x:1000:1000:hello:/home/hello:/bin/bash +helo:x:1002:1002::/home/helo:/bin/bash + +x\{m\} 重复字符x,m次,如:'o\{5\}'匹配包含5个o的行。 +[root@zutuanxue ~]# grep 'l\{2\}' /etc/passwd + +x\{m,\} 重复字符x,至少m次,如:'o\{5,\}'匹配至少有5个o的行。 +[root@zutuanxue ~]# grep 'l\{2,\}' /etc/passwd + +x\{m,n\} 重复字符x,至少m次,不多于n次,如:'o\{5,10\}'匹配5--10个o的行。 +[root@zutuanxue ~]# grep 'l\{1,3\}' /etc/passwd + +\b 单词锁定符,如: '\bgrep\b'只匹配grep。 +[root@zutuanxue ~]# grep 'hell' /etc/passwd +hello:x:1000:1000:hello:/home/hello:/bin/bash +helllo:x:1003:1003::/home/helllo:/bin/bash +[root@zutuanxue ~]# grep '\bhell\b' /etc/passwd + + +egrep和 grep -E的扩展集 ++ 匹配一个或多个先前的字符。如:'[a-z]+able',匹配一个或多个小写字母后跟able的串. +[root@zutuanxue ~]# grep -E '[a-z]+llo' /etc/passwd +hello:x:1000:1000:hello:/home/hello:/bin/bash +helllo:x:1003:1003::/home/helllo:/bin/bash +[root@zutuanxue ~]# grep -E '[a-z]+lo' /etc/passwd + +? 作用同\?,如:'gre?p'匹配gr后跟一个或零个e字符,然后是p的行。 +[root@zutuanxue ~]# grep -E 'hel?lo' /etc/passwd +hello:x:1000:1000:hello:/home/hello:/bin/bash +helo:x:1002:1002::/home/helo:/bin/bash +[root@zutuanxue ~]# grep 'hel?lo' /etc/passwd +[root@zutuanxue ~]# grep 'hel\?lo' /etc/passwd +hello:x:1000:1000:hello:/home/hello:/bin/bash +helo:x:1002:1002::/home/helo:/bin/bash + +a|b|c 匹配a或b或c。如:grep|sed匹配grep或sed +[root@zutuanxue ~]# grep -E 'llo|lllo' /etc/passwd +hello:x:1000:1000:hello:/home/hello:/bin/bash +helllo:x:1003:1003::/home/helllo:/bin/bash + +* 0次或多次 +? 0次或1次 ++ 1次或多次 + +-E 支持扩展正则,相当于egrep +-i 不区分大小写 +-v 取反,显示不匹配的 +--color=auto 高亮显示 +``` + +### 5.3、sort 对文件内容进行排序 + +**常用命令选项** + +``` +-b 忽略每行前面开始出的空格字符。 +[root@zutuanxue ~]# sort passwd +apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin +bin:x:1:1:bin:/bin:/sbin/nologin +daemon:x:2:2:daemon:/sbin:/sbin/nologin +dbus:x:81:81:System message bus:/:/sbin/nologin + hello:x:1000:1000:hello:/home/hello:/bin/bash + HELLO:x:1001:1001::/home/HELLO:/bin/bash + helo:x:1002:1002::/home/helo:/bin/bash +lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin +nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin +root:x:0:0:root:/root:/bin/bash +[root@zutuanxue ~]# sort -b passwd +apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin +bin:x:1:1:bin:/bin:/sbin/nologin +daemon:x:2:2:daemon:/sbin:/sbin/nologin +dbus:x:81:81:System message bus:/:/sbin/nologin + hello:x:1000:1000:hello:/home/hello:/bin/bash + HELLO:x:1001:1001::/home/HELLO:/bin/bash + helo:x:1002:1002::/home/helo:/bin/bash +lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin +nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin +root:x:0:0:root:/root:/bin/bash + +-c 检查文件是否已经按照顺序排序。 +[root@zutuanxue ~]# sort -c passwd +sort:passwd:2:无序: bin:x:1:1:bin:/bin:/sbin/nologin + +-t 用指定的符号做为分隔符 +-k 指定区间 +-n 依照数值的大小排序。 +-r 以相反的顺序来排序。 +[root@zutuanxue ~]# sort -t ':' -k 3 -r -n passwd +nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin + helo:x:1002:1002::/home/helo:/bin/bash + HELLO:x:1001:1001::/home/HELLO:/bin/bash + hello:x:1000:1000:hello:/home/hello:/bin/bash +dbus:x:81:81:System message bus:/:/sbin/nologin + apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin +lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin +daemon:x:2:2:daemon:/sbin:/sbin/nologin +bin:x:1:1:bin:/bin:/sbin/nologin +root:x:0:0:root:/root:/bin/bash +或者 +[root@zutuanxue ~]# sort -t ':' -k 3rn passwd +nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin + helo:x:1002:1002::/home/helo:/bin/bash + HELLO:x:1001:1001::/home/HELLO:/bin/bash + hello:x:1000:1000:hello:/home/hello:/bin/bash +dbus:x:81:81:System message bus:/:/sbin/nologin + apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin +lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin +daemon:x:2:2:daemon:/sbin:/sbin/nologin +bin:x:1:1:bin:/bin:/sbin/nologin +root:x:0:0:root:/root:/bin/bash + + +-o<输出文件> 将排序后的结果存入指定的文件。 +[root@zutuanxue ~]# sort -t ':' -k 3 -r -n passwd -o /root/passwd-sort +[root@zutuanxue ~]# cat /root/passwd-sort +nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin + helo:x:1002:1002::/home/helo:/bin/bash + HELLO:x:1001:1001::/home/HELLO:/bin/bash + hello:x:1000:1000:hello:/home/hello:/bin/bash +dbus:x:81:81:System message bus:/:/sbin/nologin + apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin +lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin +daemon:x:2:2:daemon:/sbin:/sbin/nologin +bin:x:1:1:bin:/bin:/sbin/nologin +root:x:0:0:root:/root:/bin/bash +``` + +### 5.4、uniq 数据去重 + +一般配合sort使用 + +**案例文档** + +``` +[root@zutuanxue ~]# cat testuniq +192.168.98.2 +192.168.98.8 +192.168.98.3 +192.168.98.3 +192.168.98.9 +192.168.98.8 +192.168.98.8 +192.168.98.0 +192.168.98.3 +``` + +**常用命令选项** + +``` +-c 在每列旁边显示该行重复出现的次数。 +[root@zutuanxue ~]# uniq -c testuniq + 1 192.168.98.2 + 1 192.168.98.8 + 2 192.168.98.3 + 1 192.168.98.9 + 2 192.168.98.8 + 1 192.168.98.0 + 1 192.168.98.3 + +[root@zutuanxue ~]# uniq -c testuniq | sort + 1 192.168.98.0 + 1 192.168.98.2 + 1 192.168.98.3 + 1 192.168.98.8 + 1 192.168.98.9 + 2 192.168.98.3 + 2 192.168.98.8 + +-d 仅显示重复出现的行列。 +[root@zutuanxue ~]# uniq -d testuniq +192.168.98.3 +192.168.98.8 + +-u 仅显示出一次的行列。 +[root@zutuanxue ~]# uniq -u testuniq +192.168.98.2 +192.168.98.8 +192.168.98.9 +192.168.98.0 +192.168.98.3 +[root@zutuanxue ~]# uniq -u testuniq | sort +192.168.98.0 +192.168.98.2 +192.168.98.3 +192.168.98.8 +192.168.98.9 +``` + +### 5.5、tree 以树状结构列出目录内容 + +``` +-a 显示所有文件和目录,默认不显示隐藏文件 +[root@zutuanxue ~]# tree -a + +-C 在文件和目录清单加上色彩,便于区分各种类型。 +[root@zutuanxue ~]# tree -C + +-d 只显示目录。 +[root@zutuanxue ~]# tree -d + +-D 列出文件或目录的更改时间。 +[root@zutuanxue ~]# tree -D +. +├── [Feb 4 15:07] 公共 +├── [Feb 4 15:07] 模板 + +-f 在每个文件或目录之前,显示完整的路径名称。 +[root@zutuanxue ~]# tree -f +. +├── ./公共 +├── ./模板 + +-F 加上文件类型标记,在执行文件,目录,Socket,管道名称名称,各自加上"*","/","@","|"号。 +[root@zutuanxue ~]# tree -F +. +├── 公共/ +├── 模板/ + +-g -u 列出文件或目录的所属群组、主名称,没有对应的名称时,则显示群组、主的识别码。 +[root@zutuanxue ~]# tree -g +. +├── [root ] 公共 +├── [root ] 模板 + +-i 不以阶梯状列出文件或目录名称。 +[root@zutuanxue ~]# tree -i +. +公共 +模板 +视频 + +-n 不在文件和目录清单加上色彩。 +[root@zutuanxue ~]# tree -n +. +├── 公共 +├── 模板 + +-p 列出权限标示。 +[root@zutuanxue ~]# tree -p +. +├── [drwxr-xr-x] 公共 +├── [drwxr-xr-x] 模板 + +-s 列出文件或目录大小。 +[root@zutuanxue ~]# tree -s +. +├── [ 6] 公共 +├── [ 6] 模板 + +-t 用文件和目录的更改时间排序。 +[root@zutuanxue ~]# tree -t +. +├── anaconda-ks.cfg +├── initial-setup-ks.cfg +├── 公共 + +-u 列出文件或目录的拥有者名称,没有对应的名称时,则显示用户识别码。 +[root@zutuanxue ~]# tree -u +. +├── [root ] 公共 +├── [root ] 模板 + +-L 显示目录层数,数值为正整数 +[root@zutuanxue ~]# tree -a -L 2 +. +├── .cache +│ ├── dconf +│ ├── event-sound-cache.tdb.d5b6fe70a77f4945aa0999abdd33e686.x86_64-redhat-linux-gnu +│ ├── evolution +│ ├── gnome-shell +│ ├── gnome-software +``` + +### 5.6、xargs命令 + +xargs 是给命令传递参数的一个过滤器,也是组合多个命令的一个工具。用于一些不支持管道输入的命令如ls + +**案例文件** + +``` +[root@zutuanxue ~]# cat xargtest +a a a +b b b +c c c +d d d +e +f +g +h +i +j +k +l +``` + +**常用命令选项** + +``` +-n num 后面加列数 +[root@zutuanxue ~]# cat xargtest | xargs -n 2 +a a +a b +b b +c c +c d +d d +e f +g h +i j +k l +[root@zutuanxue ~]# cat xargtest | xargs +a a a b b b c c c d d d e f g h i j k l + +-I 指定替换的字符串,并在后续的命令中用指定的字符串表示接收到的输入内容,并执行,可以用任意字符代替(不推荐有特殊含义的字符,如*等,如果使用请记得转意),一般为[]或{} +[root@zutuanxue ~]# mkdir testx +[root@zutuanxue ~]# find /var/ -name "*.log" | xargs -I a cp a ./testx +[root@zutuanxue ~]# ls testx | wc -l +39 + +-i 类似-I,相当于固定就是使用{}来表示接收到的输入内容 +[root@zutuanxue ~]# find /var/ -name "*.log" | xargs -i cp {} ./testx +[root@zutuanxue ~]# ls testx | wc -l +39 + + +-d 指定分隔符 +[root@zutuanxue ~]# echo "a9b9c9d9" | xargs -d 9 +a b c d +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\345\210\233\345\273\272\344\270\200\344\270\252\350\275\257raid\351\230\265\345\210\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\345\210\233\345\273\272\344\270\200\344\270\252\350\275\257raid\351\230\265\345\210\227.md" new file mode 100644 index 0000000..9df1352 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\345\210\233\345\273\272\344\270\200\344\270\252\350\275\257raid\351\230\265\345\210\227.md" @@ -0,0 +1,309 @@ +## 环境准备 + +添加一个20G的虚拟硬盘,分成10个2G的分区 + +## 一、创建raid0 + +``` +系统中如果没有mdadm命令请安装相关工具: +[root@zutuanxue ~]# which mdadm +/usr/sbin/mdadm +[root@zutuanxue ~]# rpm -qf /usr/sbin/mdadm +mdadm-4.1-4.el8.x86_64 +[root@zutuanxue ~]# dnf install -y mdadm + +创建raid0: +[root@zutuanxue ~]# mdadm --create /dev/md0 --raid-devices=2 /dev/sdb1 /dev/sdb2 --level=0 +mdadm: Defaulting to version 1.2 metadata +mdadm: array /dev/md0 started. +或者 +[root@zutuanxue ~]# mdadm -C /dev/md0 -l 0 -n 2 /dev/sdb1 /dev/sdb2 +-C:创建软raid +-l:指定raid级别 +-n:指定raid中设备个数 + +查看RAID信息: +/proc/mdstat文件记录了所有raid信息 +[root@zutuanxue ~]# cat /proc/mdstat +Personalities : [raid0] +md0 : active raid0 sdb2[1] sdb1[0] +#md0为raid0,两个成员sdb2(第二个成员),sdb1(第一个成员) + 41905152 blocks super 1.2 512k chunks +#一共有多少个块(每块1K) 数据段的大小是512K +#chunk决定了阵列中每个成员盘写入的数据量,大于这个值才会到下一个盘读写 +unused devices: + +查看指定的RAID信息: +[root@zutuanxue ~]# mdadm -D/--detail /dev/md0 +[root@zutuanxue ~]# mdadm --detail /dev/md0 +/dev/md0: #名称 + Version : 1.2 #工具版本 + Creation Time : Wed Dec 11 03:05:31 2019 #建立时间 + Raid Level : raid0 #类型 + Array Size : 41905152 (39.96 GiB 42.91 GB)#容量 + Raid Devices : 2 #组成RAID的硬盘数量 + Total Devices : 2#成员总数,包含备用磁盘 + Persistence : Superblock is persistent + + Update Time : Wed Dec 11 03:05:31 2019 + State : clean #raid的状态 + Active Devices : 2 #活跃的设备数量 + Working Devices : 2 #工作的设备数量 + Failed Devices : 0 #故障的数量 + Spare Devices : 0 #备用设备数量 + + Chunk Size : 512K + + Consistency Policy : none + + Name : localhost.localdomain:0 (local to host localhost.localdomain) + UUID : 06b2d3b2:3ace3ddf:b5b65dd7:eb40b040 + Events : 0 + +Number Major Minor RaidDevice State + 0 8 17 0 active sync /dev/sdb1 + 1 8 33 1 active sync /dev/sdb2 + +格式化挂载使用: +[root@zutuanxue ~]# mkfs.ext4 /dev/md0 +[root@zutuanxue ~]# mkdir /md0 +[root@zutuanxue ~]# mount /dev/md0 /md0/ + + +查看空间使用情况: +[root@zutuanxue ~]# df -h +文件系统 容量 已用 可用 已用% 挂载点 +/dev/md0 3.9G 16M 3.7G 1% /md0 +#可用空间100% + + +测试: +[root@zutuanxue ~]# iostat -m -d /dev/sdb1 /dev/sdb2 2 +[root@zutuanxue ~]# dd if=/dev/zero of=/md0/file bs=1M count=1024 +``` + +## 二、创建RAID1 + +``` +创建raid1: +[root@zutuanxue ~]# mdadm -C /dev/md1 -l 1 -n 2 /dev/sdb3 /dev/sdb4 +查看状态信息: +root@zutuanxue ~]# watch -n1 "cat /proc/mdstat" watch命令监控该文件变化情况,1秒钟显示一次 +或者直接查看 +[root@zutuanxue ~]# cat /proc/mdstat +Personalities : [raid0] [raid1] +md1 : active raid1 sdb4[1] sdb3[0] + 20953024 blocks super 1.2 [2/2] [UU] + #两个UU说明状态ok,一个盘故障则显示_U + [==============>......] resync = 73.5% (15404032/20953024) finish=0.4min speed=205582K/sec +unused devices: + #以上信息说明两块盘在进行同步,100%说明同步完成 + +查看raid1详细信息 +[root@zutuanxue ~]# mdadm -D /dev/md1 + +格式化挂载使用: +[root@zutuanxue ~]# mkfs.ext4 /dev/md1 +[root@zutuanxue ~]# mount /dev/md1 /md1 + +查看空间使用情况: +[root@zutuanxue ~]# df -h +文件系统 容量 已用 可用 已用% 挂载点 +/dev/md1 2.0G 6.0M 1.9G 1% /md1 +#可用空间50% + +测试验证热插拔: +1. 模拟一块盘故障(将磁盘标记为失效) +[root@zutuanxue ~]# mdadm /dev/md1 -f /dev/sdb3 +mdadm: set /dev/sdb1 faulty in /dev/md1 + +#-f or --fail 表示失效 + +2. 查看raid1状态 +[root@zutuanxue ~]# cat /proc/mdstat +Personalities : [raid0] [raid1] +md1 : active raid1 sdb4[1] sdb3[0](F) F表示失效失败 + 20953024 blocks super 1.2 [2/1] [_U] + #_表示有一块盘失效 +unused devices: + +[root@zutuanxue ~]# mdadm -D /dev/md1 +。。。 +Number Major Minor RaidDevice State +- 0 0 0 removed +1 8 33 1 active sync /dev/sdb4 +0 8 17 - faulty /dev/sdb3 + #失效盘等待移除 + +3. 移除故障或者失效硬盘(热拔) +[root@zutuanxue ~]# mdadm /dev/md1 -r /dev/sdb3 +mdadm: hot removed /dev/sdb3 from /dev/md1 + +#-r or --remove 表示移除 + +[root@zutuanxue ~]# mdadm -D /dev/md1 +。。。 + Number Major Minor RaidDevice State + - 0 0 0 removed + 1 8 33 1 active sync /dev/sdb4 + +4. 加入新的磁盘到raid1中(热插) +[root@zutuanxue ~]# mdadm /dev/md1 -a /dev/sdb5 +mdadm: added /dev/sdd5 + +#-a or --add 表示增加 + +[root@zutuanxue ~]# cat /proc/mdstat +``` + +## 三、创建RAID5 + +``` +创建raid5: +[root@zutuanxue ~]# mdadm -C /dev/md5 -l 5 -n 3 -x 1 /dev/sdb{6,7,8,9} + +#-x, --spare-devices= 表示指定热备盘 + +[root@zutuanxue ~]# cat /proc/mdstat +Personalities : [raid0] [raid1] [raid6] [raid5] [raid4] +md5 : active raid5 sdb8[4] sdb9[3](S) sdb7[1] sdb6[0] #S备用盘 + 4188160 blocks super 1.2 level 5, 512k chunk, algorithm 2 [3/3] [UUU] + +unused devices: + + +说明:热备盘表示当其中一块盘故障后,热备盘会立马顶上去,而不需要人为手动干预。 + +[root@zutuanxue ~]# mdadm -D /dev/md5 查看详细信息 +。。。 + Number Major Minor RaidDevice State + 0 8 22 0 active sync /dev/sdb6 + 1 8 23 1 active sync /dev/sdb7 + 4 8 24 2 active sync /dev/sdb8 + + 3 8 25 - spare /dev/sdb9 + + +格式化挂载使用: +[root@zutuanxue ~]# mkfs.ext4 /dev/md5 +[root@zutuanxue ~]# mkdir /md5 +[root@zutuanxue ~]# mount /dev/md5 /md5/ + + +查看空间使用情况: +[root@zutuanxue ~]# df -h +文件系统 容量 已用 可用 已用% 挂载点 +/dev/md5 3.9G 16M 3.7G 1% /md5 +#可用空间 (磁盘数量-1)x 单一磁盘容量 + +测试热备磁盘作用: +1. 标记一块活动盘失效 +[root@zutuanxue /]# mdadm /dev/md5 -f /dev/sdb6 +mdadm: set /dev/sdb6 faulty in /dev/md5 + +立即查看状态: +[root@zutuanxue /]# cat /proc/mdstat +Personalities : [raid0] [raid1] [raid6] [raid5] [raid4] +md5 : active raid5 sdb8[4] sdb9[3] sdb7[1] sdb6[0](F) +说明: +sdb6(F)失效后,原来的sdb9(S)热备盘立马顶上去同步数据 + 4188160 blocks super 1.2 level 5, 512k chunk, algorithm 2 [3/2] [_UU] + [==>..................] recovery = 13.0% .. +unused devices: + +[root@zutuanxue /]# mdadm -D /dev/md5 +... + Number Major Minor RaidDevice State + 3 8 25 0 active sync /dev/sdb9 + 1 8 23 1 active sync /dev/sdb7 + 4 8 24 2 active sync /dev/sdb8 + + 0 8 22 - faulty /dev/sdb6 + + +2. 移除失效的盘 +[root@zutuanxue /]# mdadm /dev/md5 -r /dev/sdb6 +mdadm: hot removed /dev/sdb6 from /dev/md5 + + +3. 为了日后考虑,再次添加一个热备盘到raid5中 +[root@zutuanxue /]# mdadm /dev/md5 -a /dev/sdb6 +mdadm: added /dev/sdb6 +``` + +## 四、 保存RAID信息 + +问:为什么要保存raid信息? +答:如果不做信息的保存,在CentOS6中,重启系统后raid不能自动被识别到,7,8系统中不会出现这种状况。 + +``` +1. 创建配置文件 +[root@zutuanxue ~]# mdadm -D --scan >> /etc/mdadm.conf +[root@zutuanxue ~]# cat /etc/mdadm.conf +ARRAY /dev/md/1 metadata=1.2 name=localhost.localdomain:1 UUID=170d690d:4f7ccd02:646c3ce0:8f6012be +ARRAY /dev/md/0 metadata=1.2 name=localhost.localdomain:0 UUID=a845702e:9251cae9:25d1bc8b:9a337df2 +ARRAY /dev/md/5 metadata=1.2 spares=1 name=localhost.localdomain:5 UUID=d49e6cca:5312271b:7e8e83d5:adac4ed5 +``` + +#### raid停止与启动 + +``` +以RAID5为例说明: +停止raid: +1. 卸载raid +[root@zutuanxue ~]# umount /md5 +2. 使用命令停止raid +[root@zutuanxue ~]# mdadm --stop /dev/md5 +mdadm: stopped /dev/md5 + +启动raid: +1. 配置文件(/etc/mdadm.conf)存在如下启动 +[root@zutuanxue ~]# mdadm -A /dev/md5 +mdadm: /dev/md5 has been started with 3 drives and 1 spare. + +#-A:Assemble a pre-existing array 表示装载一个已存在的raid + +2. 配置文件(/etc/mdadm.conf)不存在如下启动 +[root@zutuanxue ~]# mdadm -A /dev/md5 /dev/sdb[6789] +mdadm: /dev/md5 has been started with 3 drives and 1 spare. + +3. 如果设备名不知道,可以去查看每个设备的raid信息,使用uuid把raid设备重新组合 +[root@zutuanxue ~]# mdadm -E /dev/sdb6 | grep UUID + Array UUID : d49e6cca:5312271b:7e8e83d5:adac4ed5 + Device UUID : b933b8d5:04a6e003:90e9b230:d13cacf5 + + 说明:同一个raid里每个磁盘查看的UUID都是这个值 +。。。 +[root@zutuanxue ~]# mdadm -E /dev/sdb7 | grep UUID + Array UUID : d49e6cca:5312271b:7e8e83d5:adac4ed5 + Device UUID : b8ca85bd:7809faa4:48882a21:98ef9349 + +通过以上方法找到后进行重新组合,如下: +[root@zutuanxue ~]# mdadm -A --uuid=d49e6cca:5312271b:7e8e83d5:adac4ed5 /dev/md5 +mdadm: /dev/md5 has been started with 3 drives and 1 spare. +``` + +#### raid的删除 + +``` +1. 卸载设备 +[root@zutuanxue ~]# umount /md5/ +2. 移除所有磁盘 +[root@zutuanxue ~]# mdadm /dev/md5 -f /dev/sdb[6789] +mdadm: set /dev/sdb6 faulty in /dev/md5 +mdadm: set /dev/sdb7 faulty in /dev/md5 +mdadm: set /dev/sdb8 faulty in /dev/md5 +mdadm: set /dev/sdb9 faulty in /dev/md5 +[root@zutuanxue ~]# mdadm /dev/md5 -r /dev/sdb[6789] +mdadm: hot removed /dev/sdb6 from /dev/md5 +mdadm: hot removed /dev/sdb7 from /dev/md5 +mdadm: hot removed /dev/sdb8 from /dev/md5 +mdadm: hot removed /dev/sdb9 from /dev/md5 + +3. 停止raid +[root@zutuanxue ~]# mdadm --stop /dev/md5 +mdadm: stopped /dev/md5 + +4. 擦出超级块(superblock)清除相关信息 +[root@zutuanxue ~]# mdadm --zero-superblock /dev/sdb[6789] +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\345\210\233\345\273\272\351\253\230\345\217\257\347\224\250\351\200\273\350\276\221\345\215\267.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\345\210\233\345\273\272\351\253\230\345\217\257\347\224\250\351\200\273\350\276\221\345\215\267.md" new file mode 100644 index 0000000..3ceedb0 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\345\210\233\345\273\272\351\253\230\345\217\257\347\224\250\351\200\273\350\276\221\345\215\267.md" @@ -0,0 +1,189 @@ +## 一、逻辑卷条带化: + +把保存到逻辑卷的数据分成n等分,分别写到不同的物理卷,可以提高数据的读写效率;如果任何一个涉及到的物理卷出现故障,数据都会无法恢复。 + +``` +创建物理卷 +[root@manage01 ~]# pvcreate /dev/sdb[12] + +查看物理卷 +[root@manage01 ~]# pvs +/dev/sdb1 lvm2 a-- 2.01g 2.01g +/dev/sdb2 lvm2 a-- 2.01g 2.01g + + +创建卷组: +[root@manage01 ~]# vgcreate vg01 /dev/sdb[12] + +[root@manage01 ~]# pvs /dev/sdb[12] + PV VG Fmt Attr PSize PFree + /dev/sdb1 vg01 lvm2 a-- 2.00g 2.00g + /dev/sdb2 vg01 lvm2 a-- 2.00g 2.00g + + +创建实现条带化的逻辑卷: +[root@zutuanxue ~]# lvcreate -n lv1 -L 1G vg01 -i 2 /dev/sdb{1,2} + +-i 参数:给出条带化的数量 +[root@zutuanxue ~]# lvs /dev/vg01/lv01 + + +格式化挂载使用: +[root@zutuanxue ~]# mkfs.ext4 /dev/vg1/lv1 +[root@zutuanxue ~]# mount /dev/vg1/lv1 /lv1 + + +测试: +[root@zutuanxue ~]# dnf install sysstat -y +[root@zutuanxue ~]# iostat -m -d /dev/sdb[12] 2 +-d 查看磁盘 +-m 以什么速度显示,每秒M + 2 每隔2s显示一次 + 如果后面还有数字则代表总共显示多少次 + +[root@zutuanxue ~]# dd if=/dev/zero of=/lv1/test bs=1M count=1000 模拟写数据 +[root@zutuanxue ~]# iostat -m -d /dev/sdb[12] 1 +. +. +. +Device tps MB_read/s MB_wrtn/s MB_read MB_wrtn +sdb1 4015.00 0.01 364.38 0 364 +sdb2 4005.00 0.00 364.33 0 364 +``` + +## 二、逻辑卷实现镜像 + +镜像是一种文件存储形式,是冗余的一种类型,一个磁盘上的数据在另一个磁盘上存在一个完全相同的副本即为镜像。对某个逻辑卷的数据做镜像,起到数据备份的作用。 + +``` +当前环境: +[root@zutuanxue ~]# lsblk +├─sdb3 8:19 0 2G 0 part +├─sdb4 8:20 0 2G 0 part + + +创建物理卷: +[root@zutuanxue ~]# pvcreate /dev/sdb[34] +[root@zutuanxue ~]# pvs + PV VG Fmt Attr PSize PFree + /dev/sdb3 lvm2 --- 2.00g 2.00g + /dev/sdb4 lvm2 --- 2.00g 2.00g + + + 将物理卷加入到vg1卷组: +[root@zutuanxue ~]# vgextend vg1 /dev/sdb[34] + Volume group "vg1" successfully extended +[root@zutuanxue ~]# vgs + VG #PV #LV #SN Attr VSize VFree + vg1 4 1 0 wz--n- 7.98g 6.98g + + +创建实现镜像的逻辑卷: +[root@zutuanxue ~]# lvcreate -n lv2 -L 1G vg1 -m 1 /dev/sdb[34] + Logical volume "lv2" created. + +-m参数:给出镜像的个数;1表示1个镜像 + +[root@zutuanxue ~]# lvs -a -o +devices +[root@zutuanxue ~]# lvs -a -o +devices + LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert Devices + root cl -wi-ao---- <17.00g /dev/sda2(512) + swap cl -wi-ao---- 2.00g /dev/sda2(0) + lv1 vg1 -wi-ao---- 1.00g /dev/sdb1(0),/dev/sdb2(0) + lv2 vg1 rwi-a-r--- 1.00g 100.00 lv2_rimage_0(0),lv2_rimage_1(0) + [lv2_rimage_0] vg1 iwi-aor--- 1.00g /dev/sdb3(1) + [lv2_rimage_1] vg1 iwi-aor--- 1.00g /dev/sdb4(1) + [lv2_rmeta_0] vg1 ewi-aor--- 4.00m /dev/sdb3(0) + [lv2_rmeta_1] vg1 ewi-aor--- 4.00m /dev/sdb4(0) + +说明: Cpy%Sync 18.77该值是100%说明复制ok + + +格式化逻辑卷: +[root@zutuanxue ~]# mkfs.ext4 /dev/vg1/lv2 +挂载使用 +[root@zutuanxue ~]# mount /dev/vg1/lv2 /lv2/ + +[root@zutuanxue ~]# touch /lv2/file{1..10} +[root@zutuanxue ~]# mkdir /lv2/dir{1..10} + + +测试验证: +思路:损坏一个磁盘,测试数据是否在第二个物理卷中 +1. 使用dd命令破坏一个物理卷 +[root@zutuanxue ~]# dd if=/dev/zero of=/dev/sdb3 bs=1M count=100 + +2. 再次查看物理卷发现有一个unknown Device pvs命令 + [unknown] vg1 lvm2 a-m <2.00g 1016.00m + +3. 将损坏的盘从卷组中移除 +[root@zutuanxue ~]# vgreduce vg1 --removemissing --force + +4. 再次查看挂载点/lv2数据依然存在 + +自己也可以再次测试: +1. 再拿刚刚人为损坏的盘做成物理卷再次加入到vg1卷组中 +[root@zutuanxue /]# pvcreate /dev/sdb3 + +[root@zutuanxue /]# vgextend vg1 /dev/sdb3 + + +2. 修复 +[root@zutuanxue /]# lvconvert --repair /dev/vg1/lv2 /dev/sdb[34] +``` + +## 三、逻辑卷快照 + +快照的作用:保存做快照那一刻数据的状态,方便用户实现数据回滚,避免重要数据被覆盖。 + +快照的大小:快照需要占用卷组空间,快照的大小决定了允许有多少数据发生改变,如果制作快照时分配的容量与对应的逻辑卷相同,那么就允许逻辑卷中所有的数据发生改变。 + +COW:copy on write 当系统检测到做快照的逻辑卷当中的数据发生了改变,会在改变前将逻辑卷中的PE的数据复制到快照中的PE,然后再写入新的数据 + +``` +1. 创建快照 (EXT4) +[root@zutuanxue /]# lvcreate -L 200M -s -n lv1-snap /dev/vg1/lv1 给lv1逻辑卷创建快照 +[root@zutuanxue /]# mount -o ro /dev/vg1/lv1-snap /lv1-snap/ 挂载快照 + +[root@zutuanxue /]# lvscan + ACTIVE Original '/dev/vg1/lv1' [2.00 GiB] inherit + ACTIVE Snapshot '/dev/vg1/lv1-snap' [200.00 MiB] inherit + + +[root@zutuanxue /] dmsetup ls --tree +vg1-lv2--snap (252:5) + ├─vg1-lv1--snap-cow (253:4) 保存原卷改变前的数据 + │ └─ (8:17) + └─vg1-lv1-real (253:3) 真实的逻辑卷(原卷) + ├─ (8:17) + └─ (8:18) +vg1-lv1 (253:2) + └─vg1-lv1-real (253:3) + ├─ (8:17) + └─ (8:18) + +2. 修改原卷的数据 +[root@zutuanxue /]# dd if=/dev/zero of=/lv1/test bs=1M count=30 + +3. 观察Snapshot +[root@zutuanxue /]# lvs /dev/vg1/lv1-snap + LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert + lv1-snap vg1 swi-aos--- 200.00m lv1 0.02 +[root@zutuanxue /]# lvs /dev/vg1/lv1-snap + LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert + lv1-snap vg1 swi-aos--- 200.00m lv1 15.10 + + +XFS: +[root@node1 ~]# mount -o nouuid,ro /dev/vg1/lv1-snap /lv1-snap +挂载快照,尽量使用ro的方式,将不会破坏快照卷中的数据 + + +快照实现自动扩容: +/etc/lvm/lvm.conf +snapshot_autoextend_threshold = 80 +snapshot_autoextend_percent = 20 +//当快照使用到80%时,自动扩容20%;当snapshot_autoextend_threshold = 100表示关闭自动扩容 + +修改完成后建议重启 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\227\245\345\277\227\347\256\241\347\220\206\346\234\215\345\212\241\345\231\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\227\245\345\277\227\347\256\241\347\220\206\346\234\215\345\212\241\345\231\250.md" new file mode 100644 index 0000000..383d22e --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\227\245\345\277\227\347\256\241\347\220\206\346\234\215\345\212\241\345\231\250.md" @@ -0,0 +1,201 @@ +我们可以通过集中式日志服务器将多台机器的日志收集在一个日志服务器,然后通过脚本或者其他方式去分析,但是真正做过运维的小伙伴明白,日子收集在硬盘上,硬盘的空间有限且大文件分析起来IO压力超级大,分析日志需要高超的技术,一般运维人员分析起来会很困难,更无法实时的去查看某个机器的日志。这样的话我们的日志收集就变成了真正意义上的收集了,收集起来如何利用就变成了一个难题,总结一下主要的问题就是以下几点: + +- 日志文件巨大,硬盘IO压力大 +- 无法实时分析 +- 分析需要消耗很多计算机资源且困难 + +如何解决这个问题呢? + +- IO压力:我们可以将日志收集在数据库中,海量的日志通过分布式存储的底层支撑加上数据库对数据的高效管理,使得数据读写变得轻松,避免了原理日志服务器的IO压力。 +- 无法实时分析:可以部署一个日志分析系统来辅助分析,苦难的分析工作瞬间变得简单。 +- 分析需要消耗很多计算机资源:分布式处理分担处理压力 + +接下来我就给大家介绍一款高性能的日志收集、存储、分析架构, +同时也是一个可以使用web页面查看日志的可视化架构: + +### rsyslog+mariadb+loganalyzer + +环境准备:与前面课程提到的集中式日志服务器的架构一样,只是这个架构是在server上搭建的,也就是IP地址为192.168.1.55的这台主机上 + +### server端的环境准备和设置 + +**setp 1 安装所需要的软件包** + +``` +[root@zutuanxue ~]# dnf install mariadb mariadb-server rsyslog-mysql -y +``` + +**step 2 启动mariadb服务** + +``` +[root@zutuanxue ~]# systemctl restart mariadb +[root@zutuanxue ~]# systemctl status mariadb +``` + +**step 3 设置mariadb ** + +``` +##将mariadb的管理员密码设置为‘123456’ +[root@zutuanxue ~]# mysqladmin -u root password 123456 + + +##建立日志服务需要用到的数据库 +[root@zutuanxue ~]# cd /usr/share/doc/rsyslog/ +[root@zutuanxue rsyslog]# mysql -u root -p < mysql-createDB.sql +Enter password: + + +##进入到mariadb中验证一下是否有一个叫Syslog的数据库,如果有就代表前面的操作成功 +[root@zutuanxue rsyslog]# mysql -u root -p +Enter password: +MariaDB [(none)]> show databases; ++--------------------+ +| Database | ++--------------------+ +| Syslog | +``` + +**step 4 为后面将要用到的用户进行授权,允许用户访问mairadb中的Syslog库** + +``` +#允许一个叫syslogroot的用户从127.0.0.1、192.168.1.55、192.168.1.18这三个ip地址访问我的数据库,密码为syslogpass,设置完成之后刷新一下并退出(如果你的架构中还有其它的主机,只要修改数据库语句中的IP地址即可) +MariaDB [(none)]> grant all on Syslog.* to 'syslogroot'@'127.0.0.1'identified by 'syslogpass'; +Query OK, 0 rows affected (0.000 sec) + +MariaDB [(none)]> grant all on Syslog.* to 'syslogroot'@'192.168.1.55'identified by 'syslogpass'; +Query OK, 0 rows affected (0.000 sec) + +MariaDB [(none)]> grant all on Syslog.* to 'syslogroot'@'192.168.1.18'identified by 'syslogpass'; +Query OK, 0 rows affected (0.000 sec) + +MariaDB [(none)]> flush privileges; +Query OK, 0 rows affected (0.000 sec) + +MariaDB [(none)]> quit +Bye +``` + +**setp 5 修改rsyslog服务的配置文件** + +``` +[root@zutuanxue ~]# vim /etc/rsyslog.conf +7 #### MODULES #### +. +. +. + 24 module(load="imtcp") # needs to be done just once + 25 input(type="imtcp" port="514") + 26 module(load="ommysql")#加载一个叫ommysql的模块是日志服务可以连接mariadb + . + . + 65 local7.* /var/log /boot.log + 66 + #告诉日志服务通过ommysql模块,将日志信息发送到192.168.1.55的Syslog库中,使用的用户名和密码就是我们在前一步设置的syslogroot,syslogpass + 67 *.* :ommysql:192.168.1.55,Syslog,syslogroot,syslogpass + + ##重启日志服务 + [root@zutuanxue ~]# systemctl restart rsyslog +``` + +**step 6 测试一下日志信息能否记录到数据库中** + +``` +[root@zutuanxue ~]# logger "hello test test test" +[root@zutuanxue ~]# mysql -u root -p +Enter password: +MariaDB [(none)]> use Syslog; +Database changed +MariaDB [Syslog]> select * from SystemEvents\G +*************************** 8. row *************************** + ID: 8 + CustomerID: NULL + ReceivedAt: 2019-12-07 03:22:31 +DeviceReportedTime: 2019-12-07 03:22:31 + Facility: 1 + Priority: 5 + FromHost: localhost + Message: hello test test test +###如果可以看到我们之前使用logger产生的日志信息及代表rsyslog可以将日志信息存入数据库中 +``` + +**step 7 设置client(192.168.1.18),此步骤是唯一一步需要对client的做出的设置** + +``` +##安装软件包 +[root@zutuanxue ~]# dnf install rsyslog-mysql -y + +##修改服务的配置文件添加相应内容(与server端添加的内容一致) +[root@zutuanxue ~]# vim /etc/rsyslog.conf +module(load="ommysql") +*.* :ommysql:192.168.1.55,Syslog,syslogroot,syslogpass +[root@zutuanxue ~]# systemctl restart rsyslog + +###测试一下client的日志信息能否在server端的数据库中查看 +###client +[root@zutuanxue ~]# logger "hello this is a test from client 18" + + +####server端使用与刚才相同的方法去查看内容 +MariaDB [Syslog]> select * from SystemEvents\G +*************************** 28. row *************************** + ID: 28 + CustomerID: NULL + ReceivedAt: 2019-12-07 03:30:28 +DeviceReportedTime: 2019-12-07 03:30:28 + Facility: 1 + Priority: 5 + FromHost: localhost + Message: hello this is a test from client 18 +``` + +**step 8 server端安装支持web页面查看日志的工具loganalyzer** + +``` +[root@zutuanxue ~]# dnf install httpd php php-mysqlnd php-gd -y +[root@zutuanxue ~]# tar fx loganalyzer-4.1.8.tar.gz +[root@zutuanxue ~]# cp -r loganalyzer-4.1.8/src/* /var/www/html/ +[root@zutuanxue ~]# cp loganalyzer-4.1.8/contrib/* /var/www/html/ +[root@zutuanxue ~]# cd /var/www/html/ +[root@zutuanxue html]# sh configure.sh +[root@zutuanxue html]# systemctl restart httpd +``` + +**step 9 在mariadb中创建lyzeruser工具需要用到的库、用户并授权** + +``` +[root@zutuanxue html]# mysql -u root -p +Enter password: +MariaDB [(none)]> create database loganalyzer; +Query OK, 1 row affected (0.000 sec) + +MariaDB [(none)]> grant all on loganalyzer.* to lyzeruser@'192.168.1.55' identified by 'lyzeruser'; +Query OK, 0 rows affected (0.000 sec) + +MariaDB [(none)]> flush privileges; +Query OK, 0 rows affected (0.001 sec) + +MariaDB [(none)]> quit +Bye +``` + +**step 10 打开浏览器,部署loganalyzer** + +![image20191207164609190.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602984849790.png) + +![image20191207164635046.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602984863824.png) + +![image20191207164704698.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602984880250.png) + +![image20191207164929730.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602984908167.png) + +![image20191207164950624.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602984925448.png) + +![image20191207165010297.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602984941240.png) + +![image20191207165056960.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602984960364.png) + +![image20191207165711728.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602984992390.png) + +![image20191207165220988.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602985008601.png) + +![image20191207165748067.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1602985020468.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\346\267\261\345\205\245\347\220\206\350\247\243linux\346\226\207\344\273\266.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\346\267\261\345\205\245\347\220\206\350\247\243linux\346\226\207\344\273\266.md" new file mode 100644 index 0000000..84224fc --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\346\267\261\345\205\245\347\220\206\350\247\243linux\346\226\207\344\273\266.md" @@ -0,0 +1,145 @@ +## 一、linux的文件存储 + +假如有一个用户在linux系统中编辑了一个文件,编辑完内容后,关闭编辑器时会问用户改如何命名这个文件,设置完名称之后会选择一个目录将该文件保存到指定目录下,在这个例子中包含了linux系统中与文件相关的三个组成部分 + +- 数据:就是文件的内容,保存在一个叫data(数据块)的结构中 +- 元数据:保存一个文件的特征的系统数据,用来保存除了文件内容和文件名以外的与文件相关的信息, 诸如文件的创建者,日期,大小等等,保存在一个叫inode(i节点)的结构中。 +- 文件名:用来保存文件名称,文件名保存在一个叫dentry(目录项)的结构中。 + +## 二、i节点介绍 + +通过前面的课程我们知道,inode是用来保存文件的元数据的,除此之外还保存文件相关属性信息,如链接数等。我们通过类似stat hello.txt这条命令查看指定文件的inode信息。 + +## 三、链接文件介绍 + + Linux中如果用户想把同一个文件保存在两个地方,或用两个不同的文件名保存,除了复制之外还有另外一种选择,就是链接,在linux系统中链接分为硬链接,软链接,空链接,递归链接等 + +**链接命令: ln** + +语法: +ln 源文件路径 链接位置路径 + +常用命令选项: + +``` +-s 创建软连接 + +-f 强制执行 + +-i 交互模式,文件存在则提示用户是否覆盖 + +-n 把符号链接视为一般目录,显示为一般文件 + +-v 显示详细的处理过程 +``` + +- 硬链接:允许一个文件拥有多个有效路径名,这样用户就可以建立硬链接到重要的文件,以防止“误删”源数据,不过硬链接只能在同一文件系统中的文件之间进行连接 +- 软链接 : 也叫符号链接,类似于windows系统中的快捷方式,与硬链接不同,软链接就是一个普通文件,软链接可对文件或目录创建。 + +这是概念上的描述,我们用一句话来将这两种链接进行总结: + +a、硬链接不能链目录,不能跨文件系统,软链接可以; + +b、源文件删除后软链接失效,硬链接依然可用; + +我们通过下面的例子可以看到硬链接和软链接的创建方式以及基本对比 + +**软连接** + +``` +# 在root家目录下创建一个文件ztx +[root@zutuanxue ~]# touch ztx + +# 为/root/ztx文件创建一个软连接文件在/tmp目录下 +[root@zutuanxue ~]# ln -s /root/ztx /tmp/ + +# 验证快捷方式是否创建成功 +[root@zutuanxue ~]# ls -l /tmp/ztx +lrwxrwxrwx 1 root root 9 11月 26 15:06 /tmp/ztx -> /root/ztx + +# 查看源文件和链接文件的i节点信息 +[root@zutuanxue ~]# ls -i /root/ztx /tmp/ztx +674632 /root/ztx 929916 /tmp/ztx # 发现软连接的文件i节点不同 + +# 删除源文件 +[root@zutuanxue ~]# rm -f /root/ztx + +# 验证链接文件是否可用 +[root@zutuanxue ~]# cat /tmp/ztx +cat: /tmp/ztx: 没有那个文件或目录 #删除源文件发现链接文件失效 +``` + +**硬链接** + +``` +# 创建一个源文件 名字为组团学 +[root@zutuanxue ~]# touch zutuanxue + +# 为/root/zutuanxue文件创建一个硬链接文件 到/tmp/zutuanxue +[root@zutuanxue ~]# ln /root/zutuanxue /tmp/zutuanxue + +# 查看源文件和链接文件的i节点 +[root@zutuanxue ~]# ls -i /root/zutuanxue /tmp/zutuanxue +674632 /root/zutuanxue 674632 /tmp/zutuanxue # 硬链接的i节点和源文件的i节点一致 + +# 删除源文件,看看硬链接文件是否可用 +[root@zutuanxue ~]# echo test > /root/zutuanxue +[root@zutuanxue ~]# rm /root/zutuanxue +rm:是否删除普通文件 "/root/zutuanxue"?y +[root@zutuanxue ~]# cat /tmp/zutuanxue +test #删除硬链接源文件后,发现链接文件依然可以使用 +``` + +除了上面我们说到的硬链接和软链接之外还有 + +- 空链接,所谓的空链接就是软链接指向的源文件不存在了,包括源文件被删除,改名。 +- 递归链接:递归链接不如空链接常见,如果想看的话几乎需要专门寻找,如果用户创建两个软链接,linka与linkb关联,而linkb又与linka关联,这时候就会出现递归链接,比如 + +![1571130770456.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602391513564.png) + +- 绝对软链接和相对软链接:主要指的是用户在创建软链接的时候使用的是绝对路径还是相对路径来指定链接目标,如果链接创建完成之后不会移动,那么这两种方法可以随意使用,但是如果链接文件需要被移动,那么建议还是使用绝对路径,比如 + +![1571132049532.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602391531255.png) + +好了链接我们就说到这里,下面我们看一下时间戳 + +## 四、时间戳 + +时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总毫秒数。通俗的讲, 时间戳是一份能够表示一份数据在一个特定时间点已经存在的完整的可验证的数据。 它的提出主要是为用户提供一份电子证据, 以证明用户的某些数据的产生时间。 当我们使用stat命令查看文件的时候除了创建时间你会发现有三个跟时间戳相关的信息 + +![1571133239914.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602391546471.png) + +![1571133272500.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/11/1602391560592.png) + +| 缩写 | 命令 | 目的 | +| ----- | -------- | ---------------------------------- | +| Atime | 访问时间 | 文件数据每次被阅读后的更新 | +| Ctime | 改变时间 | 文件的i-节点信息每次被改变后都更新 | +| Mtime | 修改时间 | 文件数据每次被改变后的更新 | + +## 五、常用目录管理命令总结 + +- **目录:** + +| 命令 | 用法 | 功能 | +| ----- | -------------- | ---------------- | +| mkdir | mkdir 目录名称 | 创建一个目录 | +| rmdir | rmdir 目录名称 | 删除一个空目录 | +| cd | cd 目录名称 | 进入一个目录 | +| ls | ls 目录名称 | 列出一个目录内容 | + +- **文件:** + +| 命令 | 用法 | 功能 | +| ----- | ------------ | ---------------- | +| touch | touch 文件名 | 新建一个文件 | +| rm | rm 文件名 | 删除一个文件 | +| cat | cat 文件名 | 打印一个文件内容 | + +- **其他:** + +| 命令 | 用法 | 功能 | +| ---- | ----------------- | --------------------------- | +| cp | mkdir file folder | 将文件file拷贝到目录folder | +| mv | mv A B | 移动A到B目录或者从命名 A为B | +| ln | ln -s A B | 给A做一个快捷方式,放到B位置 | \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-swap\345\210\206\345\214\272.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-swap\345\210\206\345\214\272.md" new file mode 100644 index 0000000..c38ccc2 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-swap\345\210\206\345\214\272.md" @@ -0,0 +1,101 @@ +swap分区在系统的运行内存不够用的时候,把运行内存中的一部分空间释放出来,以供当前运行的程序使用。那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被释放的空间被临时保存到swap分区中,等到那些程序要运行时,再从Swap分区中恢复保存的数据到内存中。可以缓解物理内存不足的压力,如果物理内存不足,还没有swap空间,会宕机 + +## 扩容swap空间 + +方法1: 增加一个设备(硬盘,分区,逻辑卷)来扩容swap空间 + +``` +查看swap空间大小: +[root@zutuanxue ~]# free -m + total used free shared buff/cache available +Mem: 3918 1309 2002 15 606 2358 +Swap: 2047 0 2047 + +[root@zutuanxue ~]# swapon -s +文件名 类型 大小 已用 权限 +/dev/dm-1 partition 2097148 0 -2 +[root@zutuanxue ~]# mkswap /dev/sdb4 +正在设置交换空间版本 1,大小 = 2 GiB (2147479552 个字节) +无标签,UUID=8235e59a-1043-4251-8694-ba619cb36f1c + +[root@zutuanxue ~]# blkid /dev/sdb4 +/dev/sdb4: UUID="8...c" TYPE="swap" PARTUUID="b...e" + +//激活swap分区。swap空间不能手动挂载 +[root@zutuanxue ~]# swapon /dev/sdb4 +[root@zutuanxue ~]# swapon -s +文件名 类型 大小 已用 权限 +/dev/dm-1 partition 2097148 0 -2 +/dev/sdb4 partition 2097148 0 -3 + + +[root@zutuanxue ~]# free -m + total used free shared buff/cache available +Swap: 4095 0 4095 + +LVM形式 +[root@zutuanxue ~]# mkswap /dev/vg1/swap #创建swap +[root@zutuanxue ~]# swapon /dev/vg1/swap #开启swap +[root@zutuanxue ~]# lvextend -L 4G /dev/vg1/swap #放大LVM形式的swap +[root@zutuanxue ~]# swapoff /dev/vg1/swap #关闭lvm形式的swap +[root@zutuanxue /]# mkswap /dev/vg1/lv-swap #重新制作swap +[root@zutuanxue ~]# swapon /dev/vg1/swap #开启lvm形式的swap +[root@zutuanxue ~]# free -m #确认swap分区是否放大 +``` + +方法2: 使用dd命令模拟大文件来扩容swap + +``` +[root@zutuanxue ~]# dd if=/dev/zero of=/tmp/swapfile bs=1M count=2048 + +if=源文件,in file指定从哪里读入数据 +of=目标文件,out file指定将数据写入什么位置 +bs=复制数据的大小,block size +count=复制的个数 + +注意: +1. 一般可以使用dd命令做块设备文件的备份 +2. /dev/zero 特殊设备,一般用来模拟一个大文件,源源不断的二进制的数据流; +/dev/null 空设备,类似黑洞 + +步骤: +1. 使用dd命令模拟大文件 +# dd if=/dev/zero of=/tmp/swapfile bs=1M count=2048 +2. 格式化大文件 +[root@zutuanxue ~]# mkswap /tmp/swapfile +mkswap: /tmp/swapfile:不安全的权限 0644,建议使用 0600。 +正在设置交换空间版本 1,大小 = 2 GiB (2147479552 个字节) +无标签,UUID=3d855316-c97c-42ca-9c52-9df26a4517a0 +[root@zutuanxue ~]# ll /tmp/swapfile +-rw-r--r-- 1 root root 2147483648 12月 10 21:02 /tmp/swapfile +[root@zutuanxue ~]# chmod 600 /tmp/swapfile + +3.激活大文件 +[root@zutuanxue ~]# swapon -p1 /tmp/swapfile +-p:指定优先级,数字越大优先级越高,-1~32767 + +4. 查看 +[root@zutuanxue ~]# swapon -s +文件名 类型 大小 已用 权限 +/dev/dm-1 partition 2097148 268 -2 +/dev/sdb4 partition 2097148 0 -3 +/tmp/swapfile file 2097148 0 1 +[root@zutuanxue ~]# free -m + total used free shared buff/cache available +Swap: 6143 0 6143 + + + +如果开机自动挂载,需要修改文件:/etc/fstab +[root@zutuanxue ~]# vim /etc/fstab +/dev/sda4 swap swap defaults 0 0 +/tmp/swapfile swap swap dfaults,pri=1 0 0 +[root@zutuanxue ~]# swapon -a + +关闭swap +[root@zutuanxue ~]# swapoff /dev/sdb4 +[root@zutuanxue ~]# swapoff /tmp/swapfile +或者 +#关闭所有swap****慎用***** +[root@zutuanxue ~]# swapoff -a +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-\345\205\266\344\273\226\345\270\270\350\247\201\346\223\215\344\275\234.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-\345\205\266\344\273\226\345\270\270\350\247\201\346\223\215\344\275\234.md" new file mode 100644 index 0000000..fe9eafe --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-\345\205\266\344\273\226\345\270\270\350\247\201\346\223\215\344\275\234.md" @@ -0,0 +1,104 @@ +## LVM中有PV出现了坏道 + +``` +#LVM中有PV出现了坏道 +#数据拷贝 将/dev/sdc1拷贝到/dev/sdd1 +[root@zutuanxue ~]#lvchange -an /dev/baism/abc + +[root@zutuanxue ~]# pvmove /dev/sdc1 /dev/sdd1 + /dev/sdc1: Moved: 2.7% + /dev/sdc1: Moved: 100.0% + +[root@zutuanxue ~]# vgchange -a n /dev/baism + 0 logical volume(s) in volume group "baism" now active + +[root@zutuanxue ~]# vgreduce baism /dev/sdc1 + Removed "/dev/sdc1" from volume group "baism" + +[root@zutuanxue ~]# vgchange -a y /dev/baism + 1 logical volume(s) in volume group "baism" now active + +[root@zutuanxue ~]#lvchange -ay /dev/baism/abc + +#卷组迁移 +#导出卷组 old machine +[root@zutuanxue ~]# vgexport /dev/baism + Volume group "baism" successfully exported + +#导入卷组 new machine +[root@zutuanxue ~]# pvscan +[root@zutuanxue ~]# vgimport /dev/baism + Volume group "baism" successfully imported + +[root@zutuanxue ~]# vgchange -a y /dev/baism + 1 logical volume(s) in volume group "baism" now active + +[root@zutuanxue ~]#lvchange -ay /dev/baism/abc +``` + +## volume merged lv合并 + +``` +root@zutuanxue lvm]# vgcreate baism1 /dev/sdc1 + Volume group "baism1" successfully created +[root@zutuanxue lvm]# vgcreate baism2 /dev/sdd1 + Volume group "baism2" successfully created +[root@zutuanxue lvm]# vgmerge -v baism1 baism2 + Checking for volume group "baism1" + Checking for volume group "baism2" + Archiving volume group "baism2" metadata (seqno 1). + Archiving volume group "baism1" metadata (seqno 1). + Writing out updated volume group + Creating volume group backup "/etc/lvm/backup/baism1" (seqno 2). + Volume group "baism2" successfully merged into "baism1" +``` + +## volume spilt lv分割 + +``` +[root@zutuanxue ~]# vgsplit baism1 baism2 /dev/sdd1 + New volume group "baism2" successfully split from "baism1" + +baism1 Old volume +baism2 New volume /dev/sdd1 +``` + +## 逻辑卷从旧机器迁移到新机器 + +``` +#########Backing Up Volume Group Metadata: + +当创建vg的时候,系统默认会自动备份Metadata。/etc/lvm/backup下面存放的是metadata的备份信息,而/etc/lvm/archive下面存放的是metadata的archive信息。 + + +[root@zutuanxue backup]# pwd +/etc/lvm/backup + +[root@zutuanxue backup]# strings baism2 +# Generated by LVM2 version 2.02.87(2)-rhel7 (2011-10-12): Mon Jan 14 22:27:02 2013 +contents = "Text Format Volume Group" +version = 1 + +description = "Created *after* executing 'vgsplit baism1 baism2 /dev/sdd1'" #warn + +creation_host = "rhel7" # Linux rhel7 2.6.32-220.el6.x86_64 #1 SMP Wed Nov 9 08:03:13 EST 2011 x86_64 +creation_time = 1358173622 # Mon Jan 14 22:27:02 2013 +baism2 { + id = "Ft0eD7-oVca-mwY6-6FeK-TwW2-hTrj-aYxYbq" + seqno = 2 + status = ["RESIZEABLE", "READ", "WRITE"] + flags = [] + extent_size = 8192 # 4 Megabytes + max_lv = 0 + max_pv = 0 + metadata_copies = 0 + physical_volumes { + pv0 { + id = "m7aKrr-D0r9-jOJ2-aK51-ec25-4rwH-4ccbbh" + device = "/dev/sdd1" # Hint only + status = ["ALLOCATABLE"] + flags = [] + dev_size = 4192902 # 1.99933 Gigabytes + pe_start = 2048 + pe_count = 511 # 1.99609 Gigabytes +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-\351\200\273\350\276\221\345\215\267\345\272\224\347\224\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-\351\200\273\350\276\221\345\215\267\345\272\224\347\224\250.md" new file mode 100644 index 0000000..357d6c5 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-\351\200\273\350\276\221\345\215\267\345\272\224\347\224\250.md" @@ -0,0 +1,171 @@ +## 案例需求: + +创建一个2.5G大小的逻辑卷 + +## 案例思路: + +1. 物理的设备 +2. 将物理设备做成物理卷 +3. 创建卷组并将物理卷加入其中 +4. 创建逻辑卷 +5. 格式化逻辑卷 +6. 挂载使用 + +## 案例实现 + +``` +步骤: +1. 物理设备 +[root@zutuanxue ~]# lsblk /dev/sdb +NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT +sdb 8:16 0 20G 0 disk +├─sdb1 8:17 0 2G 0 part /disk1 +├─sdb2 8:18 0 2G 0 part +├─sdb3 8:19 0 2G 0 part +├─sdb4 8:20 0 2G 0 part +└─sdb5 8:21 0 2G 0 part + + +2. 创建物理卷 +[root@zutuanxue ~]# pvcreate /dev/sdb{1,2} + Physical volume "/dev/sdb1" successfully created. + Physical volume "/dev/sdb2" successfully created. +查看物理卷: +[root@zutuanxue ~]# pvs + PV VG Fmt Attr PSize PFree + /dev/sda2 cl lvm2 a-- <19.00g 0 + /dev/sdb1 lvm2 --- 2.00g 2.00g + /dev/sdb2 lvm2 --- 2.00g 2.00g +[root@zutuanxue ~]# pvscan + PV /dev/sda2 VG cl lvm2 [<19.00 GiB / 0 free] + PV /dev/sdb1 lvm2 [2.00 GiB] + PV /dev/sdb2 lvm2 [2.00 GiB] + Total: 3 [<23.00 GiB] / in use: 1 [<19.00 GiB] / in no VG: 2 [4.00 GiB] + +[root@zutuanxue ~]# pvdisplay /dev/sdb1 + "/dev/sdb1" is a new physical volume of "2.00 GiB" + --- NEW Physical volume --- + PV Name /dev/sdb1 #物理卷名称 + VG Name #卷组名称 + PV Size 2.00 GiB #大小 + Allocatable NO #是否已分配出去 + PE Size 0 #PE大小 + Total PE 0 #PE总数 + Free PE 0 #空闲PE + Allocated PE 0 #可分配PE + PV UUID 3M4...lT #UUID + + +3. 创建卷组并将物理卷加入其中 +[root@zutuanxue ~]# vgcreate vg1 /dev/sdb{1,2} + Volume group "vg1" successfully created +查看卷组信息: +[root@zutuanxue ~]# vgs vg1 + VG #PV #LV #SN Attr VSize VFree + vg1 2 0 0 wz--n- 3.99g 3.99g + +[root@zutuanxue ~]# vgscan #扫描系统中有哪些卷组 + Reading all physical volumes. This may take a while... + Found volume group "vg1" using metadata type lvm2 + Found volume group "cl" using metadata type lvm2 + + [root@zutuanxue ~]# vgdisplay vg1 + --- Volume group --- + VG Name vg1 + System ID + Format lvm2 + Metadata Areas 2 + Metadata Sequence No 1 + VG Access read/write + VG Status resizable + MAX LV 0 + Cur LV 0 + Open LV 0 + Max PV 0 + Cur PV 2 + Act PV 2 + VG Size 3.99 GiB #卷组大小 + PE Size 4.00 MiB #PE大小 + Total PE 1022 #PE数量 + Alloc PE / Size 0/0 #已分配的PE/容量 + Free PE / Size 1022/3.99 GiB #可分配的PE/容量 + VG UUID CQ6p...K9I + +4. 创建逻辑卷 +[root@zutuanxue ~]# lvcreate -n lv1 -L 2.5G vg1 + Logical volume "lv1" created. +在操作系统层面映射两个地方: +[root@zutuanxue ~]# ll /dev/mapper/vg1-lv1 +lrwxrwxrwx 1 root root 7 12月 10 05:47 /dev/mapper/vg1-lv1 -> ../dm-2 +[root@zutuanxue ~]# ll /dev/vg1/lv1 +lrwxrwxrwx 1 root root 7 12月 10 05:47 /dev/vg1/lv1 -> ../dm-2 +[root@zutuanxue ~]# ll /dev/dm-2 +brw-rw---- 1 root disk 253, 2 12月 10 05:47 /dev/dm-2 + +lvcreate参数 +-n:指定逻辑卷的名字 +-L:指定逻辑卷的大小 +-l:指定逻辑卷的大小 +举例: +-l 100 100个PE,每个PE大小默认4M,故逻辑卷大小为400M +-l 50%free 卷组剩余空间的50% +[root@zutuanxue ~]# vgs vg1 + VG #PV #LV #SN Attr VSize VFree + vg1 2 1 0 wz--n- 3.99g 1.49g + +创建大小为200M的逻辑卷lv02;每个PE为4M,-l 50指定50个PE,大小为200M +[root@zutuanxue ~]# lvcreate -n lv2 -l 50 vg1 + Logical volume "lv2" created. +[root@zutuanxue ~]# vgs vg1 + VG #PV #LV #SN Attr VSize VFree + vg1 2 2 0 wz--n- 3.99g <1.30g + +[root@manage01 ~]# lvs /dev/vg01/lv02 + LV VG Attr LSize Pool Origin Data% Move Log Cpy%Sync Convert + lv02 vg01 -wi-a----- 200.00m + +创建大小为剩余卷组vg01空间的50%的逻辑卷lv03 +[root@zutuanxue ~]# lvcreate -n lv3 -l 50%free vg1 + Logical volume "lv3" created. +[root@zutuanxue ~]# vgs vg1 + VG #PV #LV #SN Attr VSize VFree + vg1 2 3 0 wz--n- 3.99g 664.00m + +查看逻辑卷的信息: +[root@zutuanxue ~]# lvs /dev/vg1/lv1 + LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert + lv1 vg1 -wi-a----- 2.50g +[root@zutuanxue ~]# lvs /dev/vg1/lv2 + LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert + lv2 vg1 -wi-a----- 200.00m +[root@zutuanxue ~]# lvs /dev/vg1/lv3 + LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert + lv3 vg1 -wi-a----- 664.00m +[root@zutuanxue ~]# lvdisplay /dev/vg1/lv1 + --- Logical volume --- + LV Path /dev/vg1/lv1 + LV Name lv1 + VG Name vg1 + LV UUID jj9Sj1-zHuo-qpBZ-Dkk1-LVYB-HyUH-LQ6edW + LV Write Access read/write + LV Creation host, time localhost.localdomain, 2019-12-10 05:46:59 -0500 + LV Status available + # open 0 + LV Size 2.50 GiB + Current LE 640 + Segments 2 + Allocation inherit + Read ahead sectors auto + - currently set to 8192 + Block device 253:2 + + +5. 格式化逻辑卷 +[root@zutuanxue ~]# mkfs.ext4 /dev/vg1/lv1 + +6. 挂载使用 +1)创建一个空的挂载点 +[root@zutuanxue /]# mkdir /lv1 +2)挂载使用 +[root@zutuanxue /]# mount /dev/vg1/lv1 /lv1/ +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-\351\200\273\350\276\221\345\215\267\346\211\251\345\256\271.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-\351\200\273\350\276\221\345\215\267\346\211\251\345\256\271.md" new file mode 100644 index 0000000..b5cac67 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-\351\200\273\350\276\221\345\215\267\346\211\251\345\256\271.md" @@ -0,0 +1,90 @@ +## 案例需求 + +将/lv1目录动态扩容到3G + +## 案例思路 + +1. 查看/lv1目录所对应的逻辑卷是哪一个 /dev/mapper/vg1-lv1 +2. 查看当前逻辑卷所在的卷组vg1剩余空间是否足够 +3. 如果vg1空间不够,得先扩容卷组,再扩容逻辑卷 +4. 如果vg1空间足够,直接扩容逻辑卷 + +## 案例实现 + +``` +步骤: +1. 查看/lv1目录属于哪个卷组 +[root@zutuanxue /]# df -h +文件系统 容量 已用 可用 已用% 挂载点 +/dev/mapper/vg1-lv1 2.4G 7.5M 2.3G 1% /lv1 + +[root@zutuanxue /]# lvs + LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert + root cl -wi-ao---- <17.00g + swap cl -wi-ao---- 2.00g + lv1 vg1 -wi-ao---- 2.50g + lv2 vg1 -wi-a----- 200.00m + lv3 vg1 -wi-a----- 664.00m +2. 卷组的剩余空间 +[root@zutuanxue /]# vgs + VG #PV #LV #SN Attr VSize VFree + cl 1 2 0 wz--n- <19.00g 0 + vg1 2 4 0 wz--n- 3.99g 664.00m +结果:当前卷组空间不足我扩容 + +3. 扩容逻辑卷所在的卷组 +1)首先得有物理设备 /dev/sdb3 +2) 将物理设备做成物理卷 +[root@zutuanxue /]# pvcreate /dev/sdb3 + Physical volume "/dev/sdb3" successfully created. +[root@zutuanxue /]# pvs + PV VG Fmt Attr PSize PFree + /dev/sda2 cl lvm2 a-- <19.00g 0 + /dev/sdb1 vg1 lvm2 a-- <2.00g 0 + /dev/sdb2 vg1 lvm2 a-- <2.00g 464.00m + /dev/sdb3 lvm2 --- 2.00g 2.00g + 3)将物理卷加入到卷组中(卷组扩容) +[root@zutuanxue /]# vgextend vg1 /dev/sdb3 + Volume group "vg1" successfully extended +[root@zutuanxue /]# pvs + PV VG Fmt Attr PSize PFree + /dev/sda2 cl lvm2 a-- <19.00g 0 + /dev/sdb1 vg1 lvm2 a-- <2.00g 0 + /dev/sdb2 vg1 lvm2 a-- <2.00g 464.00m + /dev/sdb3 vg1 lvm2 a-- <2.00g <2.00g + +注意: +正常情况下,应该先将/dev/sdb3物理设备创建为物理卷再加入到卷组中;如果直接加入卷组,系统会自动帮你将其做成物理卷。 + +[root@zutuanxue /]# vgs + VG #PV #LV #SN Attr VSize VFree + cl 1 2 0 wz--n- <19.00g 0 + vg1 3 4 0 wz--n- <5.99g <2.45g + +4. 扩容逻辑卷 +[root@zutuanxue /]# lvextend -L 3G /dev/vg1/lv1 + -L 3G最终的大小 +或者 +[root@zutuanxue /]# lvextend -L +1.5G /dev/vg1/lv1 -L +1.5G 扩容1.5G + +5. 查看结果 +[root@zutuanxue /]# lvs + LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert + root cl -wi-ao---- <17.00g + swap cl -wi-ao---- 2.00g + lv1 vg1 -wi-ao---- 3.00g 已经扩容到了3G + +[root@zutuanxue /]# df -h +文件系统 容量 已用 可用 已用% 挂载点 +/dev/mapper/vg1-lv1 2.4G 7.5M 2.3G 1% /lv1 + 实际并没有改变 + +6. 同步文件系统 +[root@zutuanxue /]# resize2fs /dev/vg1/lv1 #该命令适用于ext分区 +[root@manage01 ~]# xfs_growfs /dev/vg1/lv1 #该命令适用于xfs分区 +7. 再次查看验证 +[root@zutuanxue /]# df -h +文件系统 容量 已用 可用 已用% 挂载点 +/dev/mapper/vg1-lv1 2.9G 7.5M 2.8G 1% /lv1 + 扩容成功 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-\351\200\273\350\276\221\345\215\267\350\243\201\345\211\252.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-\351\200\273\350\276\221\345\215\267\350\243\201\345\211\252.md" new file mode 100644 index 0000000..2be7622 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\256\236\346\210\230\346\241\210\344\276\213-\351\200\273\350\276\221\345\215\267\350\243\201\345\211\252.md" @@ -0,0 +1,116 @@ +## 案例需求 + +将lv1逻辑卷由原来的3G缩小为2G + +## 案例思路 + +1、卸载逻辑卷 +2、扫描逻辑卷 +3、裁剪率lv1文件系统 +4、裁剪逻辑卷lv1 +5、挂载使用 + +## 案例实现 + +### ext分区逻辑卷裁剪 + +``` +[root@zutuanxue /]# umount /lv1 +[root@zutuanxue /]# e2fsck -f /dev/vg1/lv1 检验文件系统 +[root@zutuanxue /]# resize2fs /dev/vg1/lv1 2G 裁剪文件系统到2G +[root@zutuanxue /]# lvreduce /dev/vg1/lv1 -L 2G 裁剪逻辑卷 +[root@zutuanxue /]# mount /dev/vg1/lv1 /lv1/ 挂载使用 +[root@zutuanxue /]# df -h +文件系统 容量 已用 可用 已用% 挂载点 +/dev/mapper/vg1-lv1 2.0G 9.0M 1.8G 1% /lv1 +``` + +### xfs分区逻辑卷裁剪 + +**案例思路:** +1、将lv2的文件系统格式化为xfs +2、将/dev/vg1/lv2挂载到/lv2 +3、在/lv2中建立一个文件,写入内容 +4、备份数据 +5、卸载分区并裁剪逻辑卷 +6、格式化裁剪后的逻辑卷 +7、导入数据 + +``` +1)备份数据命令 +xfsdump +2)备份数据 +[root@zutuanxue /]# xfsdump -f /root/lv2.img /lv2 +#挂载点目录后面不要加"/" +xfsdump: using file dump (drive_simple) strategy +xfsdump: version 3.1.8 (dump format 3.0) - type ^C for status and control + + ============================= dump label dialog ============================== + +please enter label for this dump session (timeout in 300 sec) + -> lv2 +session label entered: "lv2" + + --------------------------------- end dialog --------------------------------- + +xfsdump: level 0 dump of localhost.localdomain:/lv2 +xfsdump: dump date: Tue Dec 10 06:33:44 2019 +xfsdump: session id: 15936371-b967-4c2c-8995-49eb702792fe +xfsdump: session label: "lv2" +xfsdump: ino map phase 1: constructing initial dump list +xfsdump: ino map phase 2: skipping (no pruning necessary) +xfsdump: ino map phase 3: skipping (only one dump stream) +xfsdump: ino map construction complete +xfsdump: estimated dump size: 20800 bytes + + ============================= media label dialog ============================= + +please enter label for media in drive 0 (timeout in 300 sec) + -> lv2 +media label entered: "lv2" + + --------------------------------- end dialog --------------------------------- + +xfsdump: creating dump session media file 0 (media 0, file 0) +xfsdump: dumping ino map +xfsdump: dumping directories +xfsdump: dumping non-directory files +xfsdump: ending media file +xfsdump: media file size 21016 bytes +xfsdump: dump size (non-dir files) : 0 bytes +xfsdump: dump complete: 14 seconds elapsed +xfsdump: Dump Summary: +xfsdump: stream 0 /root/lv2.img OK (success) +xfsdump: Dump Status: SUCCESS + + +3)裁剪 +[root@zutuanxue ~]# umount /lv2 +[root@zutuanxue ~]# lvreduce /dev/vg1/lv2 -L 100M + WARNING: Reducing active logical volume to 2.00 GiB. + THIS MAY DESTROY YOUR DATA (filesystem etc.) +Do you really want to reduce vg01/lv01? [y/n]: y + Size of logical volume vg01/lv01 changed from 7.00 GiB (1792 extents) to 2.00 GiB (512 extents). + Logical volume vg01/lv01 successfully resized. + +4)格式化 +[root@zutuanxue ~]# mkfs.xfs -f /dev/vg1/lv2 +[root@zutuanxue ~]# mount /dev/vg1/lv2 /lv2 + +5)恢复数据 -f source +[root@zutuanxue ~]# xfsrestore -f /root/lv2.img /lv2 +. +. +. +xfsrestore: Restore Status: SUCCESS + + +root@zutuanxue ~]# df -h +文件系统 容量 已用 可用 已用% 挂载点 +/dev/mapper/vg1-lv2 95M 6.0M 89M 7% /lv2 + + + +[root@zutuanxue ~]# cat /lv2/filea +hahaha +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\270\270\347\224\250\345\221\275\344\273\244.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\270\270\347\224\250\345\221\275\344\273\244.md" new file mode 100644 index 0000000..e73ac5e --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\347\256\241\347\220\206\345\256\235\345\205\270/\351\200\273\350\276\221\345\215\267\345\270\270\347\224\250\345\221\275\344\273\244.md" @@ -0,0 +1,131 @@ +## 一、物理卷管理 + +### 1.1、物理卷的创建:pvcreate命令 + +``` +pvcreate [命令选项] [参数] +将物理分区转换为物理卷 + +命令选项 +-f:强制创建物理卷,不需要用户确认; +-u:指定设备的UUID; +-y:所有的问题都回答“yes”; +-Z:是否利用前4个扇区。 +``` + +### 1.2、物理卷的移除:pvremove命令 + +``` +pvremove [命令选项] [参数] +将物理卷转换为普通linux分区 + +命令选项 +-d 调试模式 +-f 强制删除 +-y 对提问回答“yes” +``` + +### 1.3、物理卷查看命令:pvscan + +``` +pvs 显示PV简况 +pvdisplay 显示PV详细信息 +``` + +### 1.4、物理卷扫描命令:pvscan + +``` +pvscan 扫描pv设备 +``` + +### 删除物理卷: pvremove + +``` +# 删除PV sdb1 sdc1 +[root@zutuanxue ~]# pvremove /dev/sdb1 /dev/sdc1 +``` + +## 二、卷组管理 + +将多个物理卷组成一个卷组,形成一个存储池 + +### 2.1、卷组创建:vgcreate命令 + +``` +# 将pv sdb1 sdc1创建成卷组VG1000 PE大小为32M +[root@zutuanxue ~]# vgcreate -s 32 vg1000 /dev/sdb1 /dev/sdc1 +``` + +### 2.2、删除卷组中的PV:vgreduce命令 + +``` +# 将vg1000卷组中的PV sdb1删除 +[root@zutuanxue ~]# vgreduce /dev/vg1000 /dev/sdb1 +``` + +### 2.3、扩容卷组:vgextend命令 + +``` +# 将pv sdb1 加入卷组vg1000 +[root@zutuanxue ~]# vgextend /dev/vg1000 /dev/sdb1 +``` + +### 2.4、删除卷组:vgremove命令 + +``` +# 删除vg1000卷组 +[root@zutuanxue ~]# vgremove /dev/vg1000/ +``` + +## 三、逻辑卷管理 + +### 3.1、逻辑卷创建:lvcreate命令 + +``` +# 从卷组vg1000上创建一个lv99的逻辑卷,容量为3G。 +[root@zutuanxue ~]# lvcreate -n lv99 -L 3G /dev/vg1000 +``` + +### 3.2、逻辑卷扩容: lvextend命令 + +``` +# 注意扩容顺序,不能颠倒 +# a、扩容逻辑卷 +[root@zutuanxue ~]# lvextend -L 3.5G /dev/vg1000/lv99 +# b、扩容文件系统 +[root@zutuanxue ~]# resize2fs /dev/vg1000/lv99 +``` + +### 3.3、逻辑卷缩小:lvreduce命令 + +``` +# 注意扩容顺序,不能颠倒 +# a、扫描逻辑卷文件系统,清晰该逻辑卷的使用情况,注意只能缩未使用的空间 +[root@zutuanxue ~]# e2fsck -f /dev/vg1000/lv99 +# b、缩小文件系统 +[root@zutuanxue ~]# resize2fs /dev/vg1000/lv99 2G +# c、缩小逻辑卷 +[root@zutuanxue ~]# lvreduce -L 2G /dev/vg1000/lv99 (lvresize) +``` + +### 3.4、逻辑卷移除 + +``` +#remove LVM +# 卸载分区 +[root@zutuanxue ~]# umount /dev/vg1000/lv99 +# 删除逻辑卷 +[root@zutuanxue ~]# lvremove /dev/vg1000/lv99 +``` + +注意: + +PE 和 LE的说明及应用策略 + +PE(physicalextent) +每一个物理卷被划分为称为PE(PhysicalExtents)的基本单元,具有唯一编号的PE是可以被LVM寻址的最小单元。PE的大小是可配置的,默认为4MB。 + +LE(logicalextent) +逻辑卷也被划分为被称为LE(LogicalExtents)的可被寻址的基本单位。在同一个卷组中,LE的大小和PE是相同的,并且一一对应。 + +设置使用大小为4MB的PE(默认为4MB),这表示卷组上创建的所有逻辑卷都以4MB为增量单位来进行扩充 或缩减。由于内核原因,PE大小决定了逻辑卷的最大大小,4MB的PE决定了单个逻辑卷最大容量为256GB,若希望使用大于256G的逻辑卷则创建卷组 时指定更大的PE。PE大小范围为8KB到512MB,并且必须总是2的倍数 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\350\265\204\346\272\220\351\231\220\345\210\266\344\270\216\345\212\240\345\233\272/Cgroups\350\265\204\346\272\220\351\231\220\345\210\266.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\350\265\204\346\272\220\351\231\220\345\210\266\344\270\216\345\212\240\345\233\272/Cgroups\350\265\204\346\272\220\351\231\220\345\210\266.md" new file mode 100644 index 0000000..db5da6d --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Linux\347\263\273\347\273\237\350\265\204\346\272\220\351\231\220\345\210\266\344\270\216\345\212\240\345\233\272/Cgroups\350\265\204\346\272\220\351\231\220\345\210\266.md" @@ -0,0 +1,189 @@ +## 一、Cgroups介绍 + +### Cgroups是什么? + +Cgroups是control groups的缩写,是Linux内核提供的一种可以限制、记录、隔离进程组(process groups)所使用的物理资源(如:cpu,memory,IO等等)的机制。最初由google的工程师提出,后来被整合进Linux内核。Cgroups也是LXC为实现虚拟化所使用的资源管理手段,可以说没有cgroups就没有LXC。 + +### Cgroups可以做什么? + +Cgroups最初的目标是为资源管理提供的一个统一的框架,既整合现有的cpuset等子系统,也为未来开发新的子系统提供接口。现在的cgroups适用于多种应用场景,从单个进程的资源控制,到实现操作系统层次的虚拟化(OS Level Virtualization)。Cgroups提供了一下功能: + +- 限制进程组可以使用的资源数量(Resource limiting )。比如:memory子系统可以为进程组设定一个memory使用上限,一旦进程组使用的内存达到限额再申请内存,就会出发OOM(out of memory)。 +- 进程组的优先级控制(Prioritization )。比如:可以使用cpu子系统为某个进程组分配特定cpu share。 +- 记录进程组使用的资源数量(Accounting )。比如:可以使用cpuacct子系统记录某个进程组使用的cpu时间 +- 进程组隔离(Isolation)。比如:使用ns子系统可以使不同的进程组使用不同的namespace,以达到隔离的目的,不同的进程组有各自的进程、网络、文件系统挂载空间。 +- 进程组控制(Control)。比如:使用freezer子系统可以将进程组挂起和恢复。 + +### Cgroups相关概念及其关系 + +- 相关概念 + 1.任务(task)。在cgroups中,任务就是系统的一个进程。 + 2.控制族群(control group)。控制族群就是一组按照某种标准划分的进程。Cgroups中的资源控制都是以控制族群为单位实现。一个进程可以加入到某个控制族群,也从一个进程组迁移到另一个控制族群。一个进程组的进程可以使用cgroups以控制族群为单位分配的资源,同时受到cgroups以控制族群为单位设定的限制。 + 3.层级(hierarchy)。控制族群可以组织成hierarchical的形式,既一颗控制族群树。控制族群树上的子节点控制族群是父节点控制族群的孩子,继承父控制族群的特定的属性。 + 4.子系统(subsytem)。一个子系统就是一个资源控制器,比如cpu子系统就是控制cpu时间分配的一个控制器。子系统必须附加(attach)到一个层级上才能起作用,一个子系统附加到某个层级以后,这个层级上的所有控制族群都受到这个子系统的控制。 +- 相互关系 + 1.每次在系统中创建新层级时,该系统中的所有任务都是那个层级的默认 cgroup(我们称之为 root cgroup ,此cgroup在创建层级时自动创建,后面在该层级中创建的cgroup都是此cgroup的后代)的初始成员。 + 2.一个子系统最多只能附加到一个层级。 + 3.一个层级可以附加多个子系统 + 4.一个任务可以是多个cgroup的成员,但是这些cgroup必须在不同的层级。 + 5.系统中的进程(任务)创建子进程(任务)时,该子任务自动成为其父进程所在 cgroup 的成员。然后可根据需要将该子任务移动到不同的 cgroup 中,但开始时它总是继承其父任务的cgroup。 + +## 二、Cgroups子系统介绍 + +blkio 这个子系统为块设备设定输入/输出限制,比如物理设备(磁盘,固态硬盘,USB 等等)。 +cpu 这个子系统使用调度程序提供对 CPU 的 cgroup 任务访问。 +cpuacct 这个子系统自动生成 cgroup 中任务所使用的 CPU 报告。 +cpuset 这个子系统为 cgroup 中的任务分配独立 CPU(在多核系统)和内存节点。 +devices 这个子系统可允许或者拒绝 cgroup 中的任务访问设备。 +freezer 这个子系统挂起或者恢复 cgroup 中的任务。 +memory 这个子系统设定 cgroup 中任务使用的内存限制,并自动生成由那些任务使用的内存资源报告。 +net_cls 这个子系统使用等级识别符(classid)标记网络数据包,可允许 Linux 流量控制程序(tc)识别从具体 cgroup 中生成的数据包。 +ns 名称空间子系统。 + +**理解三句话** +1)任何单一子系统最多可以附加到一个层级。 +2)单一层级可以被附加一个或多个子系统 比如:cpuset cpu memory 附加到cpu_and_memory层 +3)每次创建新的层级时,该系统中的所有进程都是那个层级的默认CGroup的初始成员。对于创建的任何单一层级,该系统中的每个进程都可以是那个层级中唯一一个CGroup的成员。单一进程可以在多个CGroup中时,只要保证每个CGroup不在相同层级中即可。当在同一级冲突时,进程作为第二个CGroup的成员,会将自己从第一个CGroup中删除 + +## 三、cgroups安装 + +**1、安装cgrou**p + +``` +[root@localhost ~]# yum -y install libcgroup +``` + +**2、启动前查看cgroup分层挂载** + +``` +[root@localhost ~]# lssubsys #显示为空 +``` + +**3、启动cgroup** + +``` +[root@localhost ~]# /etc/init.d/cgconfig start +Starting cgconfig service: [确定] +``` + +**4、验证安装** + +``` +#启动成功后再次执行 +[root@localhost ~]# lssubsys +cpuset +cpu +cpuacct +memory +devices +freezer +net_cls +blkio + +#查看挂载情况 +[root@localhost ~]# lssubsys -am 显示挂载情况 +ns +perf_event +net_prio +cpuset /cgroup/cpuset +cpu /cgroup/cpu +cpuacct /cgroup/cpuacct +memory /cgroup/memory +devices /cgroup/devices +freezer /cgroup/freezer +net_cls /cgroup/net_cls +blkio /cgroup/blkio + +#cgroup 目录不在为空 +[root@localhost ~]# ls /cgroup/ +blkio cpu cpuacct cpuset devices freezer memory net_cls +``` + +5、配置文件 + +``` +/etc/cgconfig.conf 定义挂载子系统 +``` + +## 三、限制进程资源使用 + +### 1、cgroup分组管理 + +**新建分组** +mkdir /cgroup/cpu/baism_test +or +[root@localhost opt]# cgcreate -g memory:/baism_test 使用命令创建 在内存分组下创建一个分组 baism_test + +**删除分组** +[root@localhost opt]# cgdelete -r cpu:/baism_test 删除分组 cpu/baism_test + +### 2、设置分组资源应用阈值 + +#### 2.1、限制一个进程使用cpu + +``` +[root@localhost opt]# echo 50000 > /cgroup/cpu/baism_test/cpu.cfs_quota_us 设置进程使用CPU的百分比是50% +``` + +**验证CPU设置** + +``` +#方法一 +创建一个跑CPU的进程 use_cpu.sh +#!/bin/bash +x=0 +echo "current_process_number is : $$" + +while [ True ];do + x=$x+1 +done + +将该进程的进程号加入资源分组baism_test +[root@localhost cgroup]# echo 5398 > /cgroup/cpu/baism_test/tasks 将运行的程序的进程号输入到task中就行 + +#通过TOP查看进程使用CPU在合理范围内 结束程序后 进程从tasks中消失 + + +#方法二 +使用cgexec命令对新启动的程序设置 限制 +[root@localhost opt]# cgexec -g cpu:/baism_test /opt/use_cpu.sh +``` + +#### 2.2、限制一个程序使用内存 最大1M 1048676字节 + +``` +[root@localhost cgroup]# echo 1048576 > memory/baism_test/memory.limit_in_bytes +``` + +**验证内存限制** + +``` +##将进程号加入资源分组 +[root@localhost cgroup]# echo 5584 > memory/baism_test/tasks +or +开启任务的时候直接加入资源分组 +[root@localhost opt]# cgexec -g memory:/baism_test /opt/use_memory.sh + +可以看出 程序使用到最大的时候 就会被Kill掉 +测试的时候 先运行程序在运行限制 就不会上来就是杀死状态了 +``` + +#### 2.3、限制进程对IO的使用 限制读为1M + +\#设置资源分组IO的限制 + +``` +[root@localhost opt]# cgcreate -g blkio:/baism_test +[root@localhost opt]# echo '8:0 1048676' > /cgroup/blkio/baism_test/blkio.throttle.read_bps_device +``` + +**验证IO限制** + +``` +[root@localhost opt]# dd if=/dev/sda of=/dev/null & +[1] 5615 +[root@localhost opt]# echo 5615 > /cgroup/blkio/baism_test/tasks +[root@localhost opt]# + +通过iotop可以看出 读取下降到了1M +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DDL\350\257\255\345\217\245.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DDL\350\257\255\345\217\245.md" new file mode 100644 index 0000000..1888f92 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DDL\350\257\255\345\217\245.md" @@ -0,0 +1,627 @@ +数据库模式定义语言DDL(Data Definition Language),是用于描述数据库中要存储的现实世界实体的语言。 + +数据库模式定义语言并非程序设计语言,DDL数据库模式定义语言是SQL语言(结构化查询语言)的组成部分。DDL描述的模式,必须由计算机软件进行编译,转换为便于计算机存储、查询和操纵的格式,完成这个转换工作的程序称为模式编译器。 + +模式编译器处理模式定义主要产生两种类型的数据:数据字典以及数据类型和结构定义。 + +## 一、数据库操作-上 + +### 1.1、DDL概述 + +DDL(data definition language)数据库定义语言:其实就是我们在创建表的时候用到的一些sql,比如说:CREATE、ALTER、DROP等。DDL主要是用在操作数据库,定义或改变数据库表的结构,数据类型等初始化工作。 + +### 1.2、创建数据库 + +**直接创建数据库** + +```mysql +格式: +create database 数据库名; +``` + +**判断数据库是否已经存在,不存在则创建** + +```mysql +格式: +create database if not exists 数据库名; +``` + +**创建数据库并指定字符集** + +```mysql +格式: +create database 数据库名 character set 字符集; +``` + +**案例:** + +```mysql +#创建数据库 +mysql> create database zutuanxue; +Query OK, 1 rows affected (0.08 秒)#创建成功 +#在次创建同名数据库 +mysql> create database zutuanxue; +Can't create database 'zutuanxue'; database exists #无法创建数据库“zutuanxue”;数据库存在 +#判断是否存在,如果不存在则创建数据库zutuanxue +mysql> create database if not exists zutuanxue; +Query OK, 1 rows affected, 1 warnings (0.01 秒) +#创建数据库并指定字符集为 gbk +mysql> create database zutuanxue01 default character set gbk; +Query OK, 1 rows affected (0.03 秒) +``` + +**注意:** default 可以不要 + +**补充:了解字符集查看** + +```mysql +#查看字符集 +mysql> show character set; ++----------+---------------------------------+---------------------+--------+ +| Charset | Description | Default collation | Maxlen | ++----------+---------------------------------+---------------------+--------+ +| armscii8 | ARMSCII-8 Armenian | armscii8_general_ci | 1 | +| ascii | US ASCII | ascii_general_ci | 1 | +| big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 | +| binary | Binary pseudo charset | binary | 1 | +| cp1250 | Windows Central European | cp1250_general_ci | 1 | +| cp1251 | Windows Cyrillic | cp1251_general_ci | 1 | +| cp1256 | Windows Arabic | cp1256_general_ci | 1 | +| cp1257 | Windows Baltic | cp1257_general_ci | 1 | +| cp850 | DOS West European | cp850_general_ci | 1 | +| cp852 | DOS Central European | cp852_general_ci | 1 | +| cp866 | DOS Russian | cp866_general_ci | 1 | +| cp932 | SJIS for Windows Japanese | cp932_japanese_ci | 2 | +| dec8 | DEC West European | dec8_swedish_ci | 1 | +| eucjpms | UJIS for Windows Japanese | eucjpms_japanese_ci | 3 | +| euckr | EUC-KR Korean | euckr_korean_ci | 2 | +| gb18030 | China National Standard GB18030 | gb18030_chinese_ci | 4 | +| gb2312 | GB2312 Simplified Chinese | gb2312_chinese_ci | 2 | +| gbk | GBK Simplified Chinese | gbk_chinese_ci | 2 | +| geostd8 | GEOSTD8 Georgian | geostd8_general_ci | 1 | +| greek | ISO 8859-7 Greek | greek_general_ci | 1 | +| hebrew | ISO 8859-8 Hebrew | hebrew_general_ci | 1 | +| hp8 | HP West European | hp8_english_ci | 1 | +| keybcs2 | DOS Kamenicky Czech-Slovak | keybcs2_general_ci | 1 | +| koi8r | KOI8-R Relcom Russian | koi8r_general_ci | 1 | +| koi8u | KOI8-U Ukrainian | koi8u_general_ci | 1 | +| latin1 | cp1252 West European | latin1_swedish_ci | 1 | +| latin2 | ISO 8859-2 Central European | latin2_general_ci | 1 | +| latin5 | ISO 8859-9 Turkish | latin5_turkish_ci | 1 | +| latin7 | ISO 8859-13 Baltic | latin7_general_ci | 1 | +| macce | Mac Central European | macce_general_ci | 1 | +| macroman | Mac West European | macroman_general_ci | 1 | +| sjis | Shift-JIS Japanese | sjis_japanese_ci | 2 | +| swe7 | 7bit Swedish | swe7_swedish_ci | 1 | +| tis620 | TIS620 Thai | tis620_thai_ci | 1 | +| ucs2 | UCS-2 Unicode | ucs2_general_ci | 2 | +| ujis | EUC-JP Japanese | ujis_japanese_ci | 3 | +| utf16 | UTF-16 Unicode | utf16_general_ci | 4 | +| utf16le | UTF-16LE Unicode | utf16le_general_ci | 4 | +| utf32 | UTF-32 Unicode | utf32_general_ci | 4 | +| utf8 | UTF-8 Unicode | utf8_general_ci | 3 | +| utf8mb4 | UTF-8 Unicode | utf8mb4_0900_ai_ci | 4 | ++----------+---------------------------------+---------------------+--------+ +41 行于数据集 (0.02 秒) +``` + +### 1.3、查看数据库 + +**查看所有数据库** + +```mysql +格式: +show databases; +``` + +**查看某个数据库** + +```mysql +格式: +show create database 数据库名; +``` + +**案例:** + +```mysql +#查看所有数据库 +mysql> show databases; ++--------------------+ +| Database | ++--------------------+ +| information_schema | +| mb | +| mysql | +| performance_schema | +| sys | +| zutuanxue | +| zutuanxue01 | ++--------------------+ +7 行于数据集 (0.01 秒) +#查看数据库zutuanxue的信息 +mysql> show create database zutuanxue; ++----------+-------------------------------------------------------------------------------------------------+ +| Database | Create Database | ++----------+-------------------------------------------------------------------------------------------------+ +| zutuanxue | CREATE DATABASE `zutuanxue` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ | ++----------+-------------------------------------------------------------------------------------------------+ +1 行于数据集 (0.01 秒) +``` + +## 二、数据库操作-下 + +### 2.1、修改数据库 + +**修改字符集** + +```mysql +格式: +alter database 数据库名 character set 字符集; +``` + +**案例:** + +```mysql +#需求:将zutuanxue01数据库的字符集改成 utf8 +mysql> alter database zutuanxue01 character set utf8; +Query OK, 1 rows affected, 1 warnings (0.09 秒) +``` + +**注意:** + +为什么修改的不是数据库名? + +容易引起数据丢失。 + +```mysql +rename database 旧数据库名 to 新数据库名; +``` + +这个是5.1.7到5.1.23版本可以用,但是官方不推荐,会有丢失数据的危险 + +### 2.2、删除数据库 + +**删除数据库** + +```mysql +格式: +drop database 数据库名; +``` + +**案例:** + +```mysql +#需求:删除zutuanxue01数据库 +mysql> drop database zutuanxue01; +Query OK, 0 rows affected (0.07 秒) +#查看所有数据库 +mysql> show databases; ++--------------------+ +| Database | ++--------------------+ +| information_schema | +| mb | +| mysql | +| performance_schema | +| sys | +| zutuanxue | ++--------------------+ +6 行于数据集 (0.01 秒) +``` + +### 2.3、使用数据库 + +**查看当前数据库** + +```mysql +格式: +select database();#mysql中的全局函数 +``` + +**切换数据库** + +```mysql +格式: +use 数据库名; +``` + +**案例:** + +```mysql +#查看当前使用的数据库 +mysql> select database(); ++------------+ +| database() | ++------------+ +| NULL |#当前没有使用的数据库 ++------------+ +1 行于数据集 (0.01 秒) +#切换或指定当前使用的数据库 +mysql> use zutuanxue; +Query OK, 0 rows affected (0.01 秒) +#查看当前使用的数据库 +mysql> select database(); ++------------+ +| database() | ++------------+ +| zutuanxue |#当前使用的数据库为zutuanxue ++------------+ +1 行于数据集 (0.01 秒) +``` + +## 三、数据库表操作-上 + +### 3.1、创建表 + +**创建表结构** + +```mysql +格式: +create table 数据库表名( + 字段名1 字段类型1, + 字段名2 字段类型2, + ... + 字段名n 字段类型n +); +``` + +**关键字说明** + +create:创建 + +table:表 + +### 3.2、数据类型(mysql) + +**数字类型** + +![image20200206171122469.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603187353636.png) + +**日期类型** + +![image20200206171204522.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603187402867.png) + +**字符串类型** + +![image20200206171241199.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603187415619.png) + +**BLOB/TEXT** + +![image20200206171350662.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603187429998.png) + +**BINARY/VARBINARY** + +![image20200206171423603.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603187442067.png) + +**ENUM/SET** + +![image20200206171501339.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603187455034.png) + +**案例:** + +创建一个学生表,里面包含了编号、学生名字、出生年月等数据 + +**分析:** + +表名:students + +字段有:编号(id,int类型)、学生名字(sname,varchar()类型)、出生日期(birthday date类型) + +```mysql +create table students( + id int, -- 学生id + sname varchar(20), -- 学生名字 + birthday date -- 学生出生日期 +); +#想要创建数据库表先进入,数据库 +mysql> use zutuanxue; +Query OK, 0 rows affected (0.01 秒) +#创建表 +mysql> create table students(id int ,sname varchar(20),birthday date); +Query OK, 0 rows affected (0.05 秒) +#查看所有表 +mysql> show tables; ++--------------------+ +| Tables_in_zutuanxue | ++--------------------+ +| students | ++--------------------+ +1 行于数据集 (0.01 秒) +``` + +### 3.3、查看表 + +**查看所有表** + +```mysql +格式: +show tables; +``` + +**查看表结构** + +```mysql +格式: +desc 数据库表名; +``` + +**查看表SQL信息** + +```mysql +格式: +show create table 数据库表名; +``` + +**案例:** + +查看zutuanxue数据库下的所有表 + +```mysql +#进入mysql数据库 +mysql> use zutuanxue; +Query OK, 0 rows affected (0.01 秒) +#查看数据库里的所有表 +mysql> show tables; ++--------------------+ +| Tables_in_zutuanxue | ++--------------------+ +| students | ++--------------------+ +1 行于数据集 (0.01 秒) +``` + +查看students数据库表的结构 + +```mysql +mysql> desc students; ++----------+-------------+------+-----+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++----------+-------------+------+-----+---------+-------+ +| id | int(11) | YES | | NULL | | +| sname | varchar(20) | YES | | NULL | | +| birthday | date | YES | | NULL | | ++----------+-------------+------+-----+---------+-------+ +3 行于数据集 (0.01 秒) +``` + +查看students数据库表的信息 + +```mysql +#查看students数据库表SQL信息 +mysql> show create table students; ++----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Table | Create Table | ++----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| students | CREATE TABLE `students` ( + `id` int(11) DEFAULT NULL, + `sname` varchar(20) DEFAULT NULL, + `birthday` date DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci | ++----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +1 行于数据集 (0.01 秒) +``` + +## 4、数据库表操作-中 + +### 4.1、快速建表 + +**建新表** + +```mysql +格式: +create table 新数据库表名 like 旧数据库表名; +``` + +**案例:** + +创建一个students01表,要求表结构与students相同 + +```mysql +#创建一个新表与旧表结构相同 +mysql> create table students01 like students; +Query OK, 0 rows affected (0.11 秒) +#查看表结构 +mysql> desc students01; ++----------+-------------+------+-----+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++----------+-------------+------+-----+---------+-------+ +| id | int(11) | YES | | NULL | | +| sname | varchar(20) | YES | | NULL | | +| birthday | date | YES | | NULL | | ++----------+-------------+------+-----+---------+-------+ +3 行于数据集 (0.02 秒) +``` + +### 4.2、删除表 + +**直接删除表** + +```mysql +格式: +drop table 数据库表名; +``` + +**判断表是否存在,存在则删除** + +```mysql +格式: +drop table if exists 数据库表名; +``` + +**案例:** + +```mysql +#直接删除students01; +mysql> drop table students01; +Query OK, 0 rows affected (0.09 秒) +#有就删除students01,没有就不删除; +mysql> drop table if exists students01; +Query OK, 0 rows affected, 1 warnings (0.01 秒) +``` + +## 5、数据库表操作-下 + +### 5.1、修改表 + +**添加表字段** + +```mysql +格式: +alter table 数据库表名 add 字段名 字段类型; +``` + +**案例:** + +为students表添加一个字段性别(sex char类型) + +```mysql +#增加字段 +mysql> alter table students add sex char; +Query OK, 0 rows affected (0.05 秒) +#查看表结构 +mysql> desc students; ++----------+-------------+------+-----+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++----------+-------------+------+-----+---------+-------+ +| id | int(11) | YES | | NULL | | +| sname | varchar(20) | YES | | NULL | | +| birthday | date | YES | | NULL | | +| sex | char(1) | YES | | NULL | | ++----------+-------------+------+-----+---------+-------+ +4 行于数据集 (0.01 秒) +``` + +**修改表字段类型** + +```mysql +格式: +alter table 数据库表名 modify 字段名 新字段类型; +``` + +**案例:** + +将students表中字段性别(sex)的字段类型改为varchar(2) + +```mysql +#修改字段类型 +mysql> alter table students modify sex varchar(2); +Query OK, 0 rows affected (0.06 秒) +#查看表结构 +mysql> desc students; ++----------+-------------+------+-----+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++----------+-------------+------+-----+---------+-------+ +| id | int(11) | YES | | NULL | | +| sname | varchar(20) | YES | | NULL | | +| birthday | date | YES | | NULL | | +| sex | varchar(2) | YES | | NULL | | ++----------+-------------+------+-----+---------+-------+ +4 行于数据集 (0.01 秒) +``` + +**修改表字段名** + +```mysql +格式: +alter table 数据库表名 change 旧字段名 新字段名 字段类型; +``` + +**案例:** + +将students表中的性别(sex)改成班级(classes)类型为varchar(10) + +```mysql +#修改字段名 +mysql> alter table students change sex classes varchar(10); +Query OK, 0 rows affected (0.07 秒) +#查看表结构 +mysql> desc students; ++----------+-------------+------+-----+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++----------+-------------+------+-----+---------+-------+ +| id | int(11) | YES | | NULL | | +| sname | varchar(20) | YES | | NULL | | +| birthday | date | YES | | NULL | | +| classes | varchar(10) | YES | | NULL | | ++----------+-------------+------+-----+---------+-------+ +4 行于数据集 (0.02 秒) +``` + +**删除表中字段** + +```mysql +格式: +alter table 数据库表名 drop 字段名; +``` + +案例: + +删除students表中的班级(classes)字段 + +```mysql +#删除字段 +mysql> alter table students drop classes; +Query OK, 0 rows affected (0.05 秒) +#查看表结构 +mysql> desc students; ++----------+-------------+------+-----+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++----------+-------------+------+-----+---------+-------+ +| id | int(11) | YES | | NULL | | +| sname | varchar(20) | YES | | NULL | | +| birthday | date | YES | | NULL | | ++----------+-------------+------+-----+---------+-------+ +3 行于数据集 (0.01 秒) +``` + +**修改表名** + +```mysql +格式: +rename table 数据库表名 to 新数据库表; +``` + +**案例:** + +```mysql +#修改表名 +mysql> rename table students to student; +Query OK, 0 rows affected (0.04 秒) +#查看所有表 +mysql> show tables; ++--------------------+ +| Tables_in_zutuanxue | ++--------------------+ +| student | ++--------------------+ +1 行于数据集 (0.01 秒) +``` + +**修改字符集** + +```mysql +格式: +alter table 数据库表名 character set 字符集; +``` + +**案例:** + +修改student表的字符集 + +```mysql +#修改数据库表字符集 +mysql> alter table student character set gbk; +Query OK, 0 rows affected (0.07 秒) +#查看数据库表SQL信息 +mysql> show create table student; ++---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Table | Create Table | ++---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| student | CREATE TABLE `student` ( + `id` int(11) DEFAULT NULL, + `sname` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `birthday` date DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=gbk | ++---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +1 行于数据集 (0.01 秒) +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DML\350\257\255\345\217\245.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DML\350\257\255\345\217\245.md" new file mode 100644 index 0000000..6e996a4 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DML\350\257\255\345\217\245.md" @@ -0,0 +1,261 @@ +数据操纵语言DML(Data Manipulation Language),用户通过它可以实现对数据库的基本操作。就是我们最经常用到的UPDATE、INSERT、DELETE。 主要用来对数据库的数据进行一些操作。 + +## 一、表记录操作-上 + +### 1.1、DML概述 + +DML 操作是指对数据库中表记录的操作,主要包括表记录的插入(insert)、更新(update)和删除(delete),是开发人员日常使用最频繁的操作。 + +### 1.2、插入记录 + +```mysql +格式: +insert into 数据库表名 [字段名列表] values(字段值列表) +``` + +**说明:** + +**insert into 数据库表名:**指定增加记录的表 + +**[字段名列表]:**表示要给那些字段加入字段值,没有,就为所有字段 + +**values(字段值列表):**表示为对应的字段加入对应的字段值 + +**为所有字段插入值** + +```mysql +格式: +insert into 数据库表名(字段名1,字段名2...,字段名n)values(字段值1,字段值2...,字段值n); +或 +insert into 数据库表名 values(字段值1,字段值2...,字段值n); +``` + +**案例:** + +```mysql +#指定所有字段插入记录 +mysql> insert into student(id,sname,birthday)values(1,"林志颖","1974-10-18"); +Query OK, 1 rows affected (0.03 秒) +#不指定字段,默认所有字段插入记录 +mysql> insert into student values(2,"郭德纲","1973-01-18"); +Query OK, 1 rows affected (0.01 秒) +#查看数据库表中所有记录 +mysql> select * from student; ++------+-----------+------------+ +| id | sname | birthday | ++------+-----------+------------+ +| 1 | 林志颖 | 1974-10-18 | +| 2 | 郭德纲 | 1973-01-18 | ++------+-----------+------------+ +2 行于数据集 (0.01 秒) +``` + +**插入部分字段值** + +```mysql +格式: +insert into 数据库表名(字段名1,字段名2...)values(字段值1,字段值2...); +#注意:没有给定字段的值,为null; +``` + +案例: + +```mysql +#插入部分字段值 +mysql> insert into student(id,sname)values(3,"柳岩"); +Query OK, 1 rows affected (0.01 秒) +#查看数据库表中所有记录 +mysql> select * from student; ++------+-----------+------------+ +| id | sname | birthday | ++------+-----------+------------+ +| 1 | 林志颖 | 1974-10-18 | +| 2 | 郭德纲 | 1973-01-18 | +| 3 | 柳岩 | NULL | ++------+-----------+------------+ +3 行于数据集 (0.01 秒) +``` + +**注意:** + +只插入部份字段值时,前面必须带字段名字。 + +```mysql +mysql> insert into student values(4,"王宝强"); +Column count doesn't match value count at row 1#列计数与第1行的值计数不匹配 +``` + +## 二、表记录操作-下 + +### 2.1、更新记录 + +```mysql +格式: +update 数据库表名 set 字段名1=字段值1,字段名2=字段值2...,字段名n=字段值n [where 条件表达式]; +#注意:更新的数据可以是0-N条记录 +``` + +**说明:** + +**update 数据库表名:**指定需要更新的数据库表 + +**set 字段名=字段值:**修改指定的数据库表中字段的值 + +**[where 条件表达式]:**修改满足条件的记录的字段值,可省略 + +**不带条件记录更新** + +```mysql +格式: +update 数据库表名 set 字段名1=字段值1,字段名2=字段值2...,字段名n=字段值n; #表示修改表中所有记录 +``` + +**案例:** + +加入一个性别(sex varchar(2))字段,将sex的值都改为“男” + +```mysql +#在student表中增加字段sex +mysql> alter table student add sex varchar(2); +Query OK, 0 rows affected (0.24 秒) +#查看表结构 +mysql> desc student; ++----------+-------------+------+-----+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++----------+-------------+------+-----+---------+-------+ +| id | int(11) | YES | | NULL | | +| sname | varchar(20) | YES | | NULL | | +| birthday | date | YES | | NULL | | +| sex | varchar(2) | YES | | NULL | | ++----------+-------------+------+-----+---------+-------+ +4 行于数据集 (0.01 秒) +#修改student表中sex字段的值为'男' +mysql> update student set sex='男'; +Query OK, 3 rows affected (0.09 秒) +#查看表中所有记录 +mysql> select * from student; ++------+-----------+------------+------+ +| id | sname | birthday | sex | ++------+-----------+------------+------+ +| 1 | 林志颖 | 1974-10-18 | 男 | +| 2 | 郭德纲 | 1973-01-18 | 男 | +| 3 | 柳岩 | NULL | 男 | ++------+-----------+------------+------+ +3 行于数据集 (0.01 秒) +``` + +**带条件记录更新** + +```mysql +格式: +update 数据库表名 set 字段名1=字段值1,字段名2=字段值2...,字段名n=字段值n [where 条件表达式]; #表示修改表中满足条件的记录 +``` + +**案例:** + +修改id=3的记录,将sex改为’女’ + +```mysql +#修改id为3记录中的sex改为'女' +mysql> update student set sex='女' where id=3; +Query OK, 1 rows affected (0.01 秒) +#查看表中所有记录 +mysql> select * from student; ++------+-----------+------------+------+ +| id | sname | birthday | sex | ++------+-----------+------------+------+ +| 1 | 林志颖 | 1974-10-18 | 男 | +| 2 | 郭德纲 | 1973-01-18 | 男 | +| 3 | 柳岩 | NULL | 女 | ++------+-----------+------------+------+ +3 行于数据集 (0.01 秒) +``` + +修改id=3的记录,将sex改为’女’,birthday改为1980-11-08 + +```mysql +#修改id为3记录中的sex改为'女',birthday改为1980-11-08 +mysql> update student set sex='女',birthday='1980-11-08' where id=3; +Query OK, 1 rows affected (0.11 秒) +#查看表中所有记录 +mysql> select * from student; ++------+-----------+------------+------+ +| id | sname | birthday | sex | ++------+-----------+------------+------+ +| 1 | 林志颖 | 1974-10-18 | 男 | +| 2 | 郭德纲 | 1973-01-18 | 男 | +| 3 | 柳岩 | 1980-11-08 | 女 | ++------+-----------+------------+------+ +3 行于数据集 (0.01 秒) +``` + +### 2.2、删除记录 + +```mysql +格式: +delete from 数据库表名 [where 条件表达式]; +``` + +**说明:** + +**delete from 数据库表名:**指定删除记录的表 + +**[where 条件表达式]:**删除满足条件的记录的字段值,可省略 + +**带条件删除记录** + +```mysql +格式: +delete from 数据库表名 [where 条件表达式]; #删除满足条件的记录 +``` + +**案例:** + +删除id为1的记录 + +```mysql +#删除id=1的记录 +mysql> delete from student where id=1; +Query OK, 1 rows affected (0.08 秒) +#查看所有记录 +mysql> select * from student; ++------+-----------+------------+------+ +| id | sname | birthday | sex | ++------+-----------+------------+------+ +| 2 | 郭德纲 | 1973-01-18 | 男 | +| 3 | 柳岩 | 1980-11-08 | 女 | ++------+-----------+------------+------+ +2 行于数据集 (0.02 秒) +``` + +**不带条件删除记录** + +```mysql +格式: +delete from 数据库表名; #删除表中所有的记录 +或 +truncate table 数据库表名; #删除表中所有的记录 +``` + +**案例:** + +删除表中所有记录 + +```mysql +#删除所有记录 +mysql> delete from student; +Query OK, 2 rows affected (0.08 秒) +#查看所有记录 +mysql> select * from student; +空的数据集 (0.01 秒) +#删除所有记录 +mysql> truncate table student; +Query OK, 0 rows affected (0.08 秒) +#查看所有记录 +mysql> select * from student; +空的数据集 (0.01 秒) +``` + +**注意:** + +truncate删除的是表的结构,再创建一张表;delete删除的是表的记录; \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL-limit\345\210\206\351\241\265.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL-limit\345\210\206\351\241\265.md" new file mode 100644 index 0000000..f210d04 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL-limit\345\210\206\351\241\265.md" @@ -0,0 +1,106 @@ +在我们使用查询语句的时候,经常要返回前几条或者中间某几行数据,这个时候怎么办呢?不用担心,mysql已经为我们提供了这样一个功能-limit。 + +## 一、limit概述 + +Limit是限制的意思,所以limit的作用就是限制查询记录的条数。 + +## 二、limit语法 + +```mysql +格式: +select */字段列表 from 数据库表名 [limit offset,length]; +``` + +**说明:** + +offset:起始行数,从 0 开始计数,如果省略,默认就是 0 + +length: 返回的行数 + +## 三、limit应用 + +**案例:** + +查询学生信息表中前5条记录 + +```mysql +#offset可以省略,省略时,从0开始 +mysql> select * from students limit 5; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 1 | 张三 | 男 | 19 | 98.5 | 88.0 | 2017-09-01 | 他来自四川 | +| 2 | 李四 | 男 | 20 | 80.0 | 88.0 | 2017-09-01 | 他来自重庆 | +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 4 | 张八 | 男 | 18 | 80.0 | 85.0 | 2017-09-01 | 他来自天津 | +| 5 | 李三 | 男 | 19 | 60.0 | 88.0 | 2017-09-01 | 他来自湖北 | ++------+--------+------+------+---------+------+------------+-----------------+ +5 行于数据集 (0.02 秒) +``` + +查询学生信息表中从第3条记录开始,查询出5条记录 + +```mysql +mysql> select * from students limit 2,5; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 4 | 张八 | 男 | 18 | 80.0 | 85.0 | 2017-09-01 | 他来自天津 | +| 5 | 李三 | 男 | 19 | 60.0 | 88.0 | 2017-09-01 | 他来自湖北 | +| 6 | 王六 | 女 | 20 | 50.0 | 70.0 | 2017-09-01 | 他来自湖南 | +| 7 | 刘红 | 女 | 18 | 90.0 | 98.0 | 2017-09-01 | 他来自甘肃 | ++------+--------+------+------+---------+------+------------+-----------------+ +5 行于数据集 (0.01 秒) +``` + +## 四、limit分页 + +### 4.1、什么是分页 + +打开百度,输入我们想要查看的信息,查出来的数据会有成千上万条数据,那么这些数据在页面不能一次性展示,这个时候我们就需要用到分页。 + +![image20200209012451326.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603189560330.png) + +### 4.2、MySql中的分页 + +**案例:** + +查询学生信息表中的信息,按5条记录为一页展示 + +**第一页** + +```mysql +mysql> select * from students limit 0,5; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 1 | 张三 | 男 | 19 | 98.5 | 88.0 | 2017-09-01 | 他来自四川 | +| 2 | 李四 | 男 | 20 | 80.0 | 88.0 | 2017-09-01 | 他来自重庆 | +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 4 | 张八 | 男 | 18 | 80.0 | 85.0 | 2017-09-01 | 他来自天津 | +| 5 | 李三 | 男 | 19 | 60.0 | 88.0 | 2017-09-01 | 他来自湖北 | ++------+--------+------+------+---------+------+------------+-----------------+ +5 行于数据集 (0.01 秒) +``` + +**第二页** + +```mysql +mysql> select * from students limit 5,5; ++------+-----------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+-----------+------+------+---------+------+------------+-----------------+ +| 6 | 王六 | 女 | 20 | 50.0 | 70.0 | 2017-09-01 | 他来自湖南 | +| 7 | 刘红 | 女 | 18 | 90.0 | 98.0 | 2017-09-01 | 他来自甘肃 | +| 8 | 王五 | 男 | NULL | NULL | NULL | NULL | NULL | +| 9 | 李老六 | 男 | 19 | NULL | NULL | NULL | NULL | ++------+-----------+------+------+---------+------+------------+-----------------+ +4 行于数据集 (0.01 秒) +``` + +**注意:** + +limit中offset在发生着变化,第一页是0,第二页是(前一页的offset+length),而length并没有发生变化。 + +如果最后一页的记录数没有指定的length条,是有多少显示多少 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL-\346\250\241\347\263\212\346\237\245\350\257\242.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL-\346\250\241\347\263\212\346\237\245\350\257\242.md" new file mode 100644 index 0000000..9146130 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL-\346\250\241\347\263\212\346\237\245\350\257\242.md" @@ -0,0 +1,192 @@ +模糊查询即模糊检索,是指搜索系统自动按照用户输入关键词的同义词进行模糊检索,从而得出较多的检索结果。与之相反的是“精准搜索”。模糊检索也可以说是同义词检索,这里的同义词是用户通过“检索管理”中的“同义词典”来配置的。 + +用户在检索页面中输入同义词中任何一个词检索时,只要选中“模糊检索”复选框,则该关键词的所有同义词信息也都被检索出来。 + +举例:例如配置了“电脑”与“computer”为同义词后,检索“电脑”,则包含“computer”的网页也会出现在检索结果中。 + +## 一、模糊查询概述 + +### 1.1、什么是模糊查询 + +模糊查询是针对字符串操作的,类似正则表达式,没有正则表达式强大。 + +### 1.2、通配符 + +```mysql +%:表示任意0个或多个字符。 +_: 表示任意单个字符。 +[ ]:表示括号内所列字符中的一个(类似正则表达式)。 +[^ ] :表示不在括号所列之内的单个字符。 +``` + +### 1.3、回顾%和_ + +#### 1.3.1、%应用 + +可匹配任意类型和长度的字符,有些情况下若是中文,请使用两个百分号(%%)表示。 + +```mysql +格式: +select */字段列表 from 数据库表名 where 字段名 like %字符串%; +``` + +**案例:** + +查询出学生信息表中姓名里有‘三’的学生信息 + +```mysql +mysql> select * from students where sname like '%三%'; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 1 | 张三 | 男 | 19 | 98.5 | 88.0 | 2017-09-01 | 他来自四川 | +| 5 | 李三 | 男 | 19 | 60.0 | 88.0 | 2017-09-01 | 他来自湖北 | ++------+--------+------+------+---------+------+------------+-----------------+ +2 行于数据集 (0.02 秒) +``` + +#### 1.3.2、_应用 + +匹配单个任意字符,它常用来限制表达式的字符长度语句。 + +```mysql +格式: +select */字段列表 from 数据库表名 where 字段名 like _字符串_; +``` + +**案例:** + +查询学生信息表中姓名里含有‘红’字,二个字的学生信息 + +```mysql +mysql> select * from students where sname like '_红' or sname like '红_'; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 7 | 刘红 | 女 | 18 | 90.0 | 98.0 | 2017-09-01 | 他来自甘肃 | ++------+--------+------+------+---------+------+------------+-----------------+ +2 行于数据集 (0.01 秒) +``` + +## 二、模糊查询应用 + +### 2.1、[ ]应用 + +指定一个字符、字符串或范围,要求所匹配对象为它们中的任一个。 + +```mysql +格式: +select */字段列表 from 数据库表名 where 字段名 regexp [字符串]字符串; +``` + +**案例:** + +查询学生信息表中姓名里有张和李的人的信息 + +```mysql +mysql> select * from students where sname regexp '[张李]'; ++------+-----------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+-----------+------+------+---------+------+------------+-----------------+ +| 1 | 张三 | 男 | 19 | 98.5 | 88.0 | 2017-09-01 | 他来自四川 | +| 2 | 李四 | 男 | 20 | 80.0 | 88.0 | 2017-09-01 | 他来自重庆 | +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 4 | 张八 | 男 | 18 | 80.0 | 85.0 | 2017-09-01 | 他来自天津 | +| 5 | 三李 | 男 | 19 | 60.0 | 88.0 | 2017-09-01 | 他来自湖北 | +| 9 | 李老六 | 男 | 19 | NULL | NULL | NULL | NULL | ++------+-----------+------+------+---------+------+------------+-----------------+ +6 行于数据集 (0.02 秒) +``` + +查询学生信息表中姓名为张红和李红的人的信息 + +```mysql +#[张李]红 张红 李红 +mysql> select * from students where sname regexp '[张李]红'; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | ++------+--------+------+------+---------+------+------------+-----------------+ +1 行于数据集 (0.01 秒) +``` + +查询学生信息表中年龄包含789这几个数字的人的信息 + +```mysql +mysql> select * from students where age regexp '[789]'; ++------+-----------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+-----------+------+------+---------+------+------------+-----------------+ +| 1 | 张三 | 男 | 19 | 98.5 | 88.0 | 2017-09-01 | 他来自四川 | +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 4 | 张八 | 男 | 18 | 80.0 | 85.0 | 2017-09-01 | 他来自天津 | +| 5 | 三李 | 男 | 19 | 60.0 | 88.0 | 2017-09-01 | 他来自湖北 | +| 7 | 刘红 | 女 | 18 | 90.0 | 98.0 | 2017-09-01 | 他来自甘肃 | +| 9 | 李老六 | 男 | 19 | NULL | NULL | NULL | NULL | ++------+-----------+------+------+---------+------+------------+-----------------+ +6 行于数据集 (0.01 秒) +``` + +**注意:** + +如 [ ] 内有一系列字符(01234、abcde之类的)则可略写为“0-4”、“a-e” + +### 2.2、[^]应用 + +其取值和 [] 相同,但它要求所匹配对象为指定字符以外的任一个字符。 + +```mysql +格式: +select */字段列表 from 数据库表名 where 字段名 regexp [^字符串]字符串; +``` + +**案例:** + +查询学生信息表中姓名不是张红、李红,而是其他红的人的信息。 + +```mysql +mysql> select * from students where sname regexp '[^张李]红'; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 7 | 刘红 | 女 | 18 | 90.0 | 98.0 | 2017-09-01 | 他来自甘肃 | ++------+--------+------+------+---------+------+------------+-----------------+ +1 行于数据集 (0.01 秒) +``` + +查询学生信息表中年龄不包含7891这几个数字的人的信息 + +```mysql +mysql> select * from students where age regexp '[^7891]'; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 2 | 李四 | 男 | 20 | 80.0 | 88.0 | 2017-09-01 | 他来自重庆 | +| 6 | 王六 | 女 | 20 | 50.0 | 70.0 | 2017-09-01 | 他来自湖南 | ++------+--------+------+------+---------+------+------------+-----------------+ +2 行于数据集 (0.01 秒) +``` + +查询学生信息表中姓张和姓李的人的信息 + +```mysql +mysql> select * from students where sname regexp '^[张李]'; ++------+-----------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+-----------+------+------+---------+------+------------+-----------------+ +| 1 | 张三 | 男 | 19 | 98.5 | 88.0 | 2017-09-01 | 他来自四川 | +| 2 | 李四 | 男 | 20 | 80.0 | 88.0 | 2017-09-01 | 他来自重庆 | +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 4 | 张八 | 男 | 18 | 80.0 | 85.0 | 2017-09-01 | 他来自天津 | +| 9 | 李老六 | 男 | 19 | NULL | NULL | NULL | NULL | ++------+-----------+------+------+---------+------+------------+-----------------+ +5 行于数据集 (0.01 秒) +``` + +**注意:** + +``` + ^[]表示的是:字符串开始的第一个字符 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL-\350\201\232\345\220\210\345\207\275\346\225\260.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL-\350\201\232\345\220\210\345\207\275\346\225\260.md" new file mode 100644 index 0000000..fea89b7 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL-\350\201\232\345\220\210\345\207\275\346\225\260.md" @@ -0,0 +1,224 @@ +SQL基本函数,聚合函数对一组值执行计算,并返回单个值,也被称为组函数。 + +聚合函数对一组值执行计算并返回单一的值。除 COUNT 以外,聚合函数忽略空值,如果COUNT函数的应用对象是一个确定列名,并且该列存在空值,此时COUNT仍会忽略空值。 + +所有聚合函数都具有确定性。任何时候用一组给定的输入值调用它们时,都返回相同的值。聚合函数可以应用于查询语句的SELECT中,或者HAVING子句中,但不可用于WHERE语句中,因为WHERE是对逐条的行记录进行筛选。 + +## 一、聚合函数概述 + +### 1.1、什么是聚合函数 + +SQL基本函数,聚合函数对一组值执行计算,并返回单个值,也被称为组函数。 聚合函数经常与 SELECT 语句的 GROUP BY 子句的HAVING一同使用。 + +### 1.2、聚合函数的特点 + +除了 COUNT 以外,聚合函数忽略空值。 +聚合函数经常与 SELECT 语句的 GROUP BY 子句一同使用。 +所有聚合函数都具有确定性。任何时候用一组给定的输入值调用它们时,都返回相同的值。 + +### 1.3、常用聚合函数 + +```mysql +count(字段名):统计总行数 +sum(字段名):计算列总和 +avg(字段名):求某一列平均值 +min(字段名):求某一列的最小值 +max(字段名):求某一列的最大值 +``` + +### 1.4、聚合函数语法 + +```mysql +格式: +select 聚合函数(字段名) from 数据库表名; +``` + +## 二、聚合函数应用 + +### 2.1、聚合函数基础应用 + +**案例:** + +查看学生信息表中通过英语成绩统计所有的学生数 + +```mysql +mysql> select count(english) as 学生人数 from students; ++-----+ +| 总人数 | ++-----+ +| 7 | ++-----+ +1 行于数据集 (0.01 秒) +``` + +**注意:** + +null的记录是不会统计,如果要想统计null,可以用ifnull(字段名,默认值) + +默认值里设置:null用0表示 + +```mysql +mysql> select count(ifnull(english,0)) as 总人数 from students; ++-----+ +| 总人数 | ++-----+ +| 9 | ++-----+ +1 行于数据集 (0.02 秒) +``` + +除了前面这个方法可以统计学生人数外,我们还可以: + +```mysql +#比较常用的方法 +mysql> select count(*) from students; ++----------+ +| count(*) | ++----------+ +| 9 | ++----------+ +1 行于数据集 (0.01 秒) +``` + +查看学生信息表中年龄大于19的总人数 + +```mysql +mysql> select count(*) from students where age>19; ++----------+ +| count(*) | ++----------+ +| 2 | ++----------+ +1 行于数据集 (0.02 秒) +``` + +查看学生信息表中英语成绩的总分 + +```mysql +mysql> select sum(english) as 英语总分 from students; ++-------+ +| 英语总分 | ++-------+ +| 544.5 | ++-------+ +1 行于数据集 (0.01 秒) +``` + +查看学生信息表中英语成绩的平均分 + +```mysql +mysql> select avg(english) as 英语平均分 from students; ++----------+ +| 英语平均分 | ++----------+ +| 77.78571 | ++----------+ +1 行于数据集 (0.01 秒) +``` + +查看学生信息表中英语成绩的最高分 + +```mysql +mysql> select max(english) as 英语最高分 from students; ++-------+ +| 英语最高分 | ++-------+ +| 98.5 | ++-------+ +1 行于数据集 (0.01 秒) +``` + +查看学生信息表中英语成绩的最低分 + +```mysql +mysql> select min(english) as 英语最低分 from students; ++-------+ +| 英语最低分 | ++-------+ +| 50.0 | ++-------+ +1 行于数据集 (0.01 秒) +``` + +### 2.2、聚合函数分组应用 + +**案例:** + +统计学生信息表中男生的人数与女生的人数 + +```mysql +mysql> select count(*),sex from students group by sex; ++----------+------+ +| count(*) | sex | ++----------+------+ +| 6 | 男 | +| 3 | 女 | ++----------+------+ +2 行于数据集 (0.01 秒) +``` + +统计学生信息表中男生和女生的人数、英语总成绩、数学平均成绩 + +```mysql +mysql> select count(*),sex,sum(english),avg(math) from students group by sex; ++----------+------+--------------+-----------+ +| count(*) | sex | sum(english) | avg(math) | ++----------+------+--------------+-----------+ +| 6 | 男 | 318.5 | 87.25000 | +| 3 | 女 | 226.0 | 82.66667 | ++----------+------+--------------+-----------+ +2 行于数据集 (0.01 秒) +``` + +统计学生信息表中男生和女生的人数、英语总成绩、数学平均成绩,总人数超过3人显示 + +```mysql +mysql> select count(*) as n,sex,sum(english),avg(math) from students group by sex having n>3; ++---+------+--------------+-----------+ +| n | sex | sum(english) | avg(math) | ++---+------+--------------+-----------+ +| 6 | 男 | 318.5 | 87.25000 | ++---+------+--------------+-----------+ +1 行于数据集 (0.02 秒) +``` + +## 三、聚合函数应用扩展 + +### 3.1、group_concat + +group_concat(字段名)可以作为一个输出字段来使用,表示分组之后,根据分组结果,使用group_concat()来放置每一组的某字段的值的集合。 + +**案例:** + +统计学生信息表中男生和女生的人数、英语总成绩、数学平均成绩及数学成绩的集合 + +```mysql +mysql> select count(*),sex,sum(english),avg(math),group_concat(math) from students group by sex; ++----------+------+--------------+-----------+---------------------+ +| count(*) | sex | sum(english) | avg(math) | group_concat(math) | ++----------+------+--------------+-----------+---------------------+ +| 3 | 女 | 226.0 | 82.66667 | 80.0,70.0,98.0 | +| 6 | 男 | 318.5 | 87.25000 | 88.0,88.0,85.0,88.0 | ++----------+------+--------------+-----------+---------------------+ +2 行于数据集 (0.02 秒) +``` + +### 3.2、with rollup + +在最后新增一行,来记录当前列里所有记录的总和 + +**案例:** + +统计学生信息表中男生和女生的人数、英语总成绩、数学平均成绩及增加显示列的记录总和 + +```mysql +mysql> select count(*),sex,sum(english),avg(math) from students group by sex with rollup; ++----------+------+--------------+-----------+ +| count(*) | sex | sum(english) | avg(math) | ++----------+------+--------------+-----------+ +| 3 | 女 | 226.0 | 82.66667 | +| 6 | 男 | 318.5 | 87.25000 | +| 9 | NULL | 544.5 | 85.28571 | ++----------+------+--------------+-----------+ +3 行于数据集 (0.02 秒) +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL\350\257\255\345\217\245.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL\350\257\255\345\217\245.md" new file mode 100644 index 0000000..93cd3dc --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL\350\257\255\345\217\245.md" @@ -0,0 +1,606 @@ +DQL(Data QueryLanguage )数据查询语言,基本结构是由SELECT子句,FROM子句,WHERE子句组成的查询块。 + +## 一、DQL概述 + +### 1.1、什么是DQL + +DQL:数据查询语言,用于从数据库表中查询数据,并不会修改数据,只是一种显示数据的方式。由select语句构成。 + +### 1.2、记录查询格式 + +```mysql +格式: +select */字段列表 from 数据库表名 [where 条件表达式]; +``` + +**格式说明:** + +select */字段列表: 查询完后需要展示的字段 + +from 数据库表名: 指定要查询的数据库表 + +[where 条件表达式]: 查询满足条件的记录 + +## 二、记录查询 + +### 2.1、简单查询 + +**查询表中的记录和列** + +```mysql +格式: +select * from 数据库表名; #查询表中所有记录,显示所有列 +或 +select 字段名1,字段名2,...,字段名n from 数据库表名; #查询表中所有记录,显示指定列 +``` + +**案例:** + +查询student表中的所有记录,显示所有列 + +```mysql +#显示所有记录 +mysql> select * from student; ++------+-----------+------------+------+ +| id | sname | birthday | sex | ++------+-----------+------------+------+ +| 1 | 郭德纲 | 1973-01-18 | 男 | +| 2 | 林志颖 | 1974-10-18 | 男 | +| 3 | 柳岩 | 1980-11-08 | 女 | ++------+-----------+------------+------+ +3 行于数据集 (0.01 秒) +``` + +查询student表中的所有记录,显示所有姓名、性别列 + +```mysql +#显示所有记录,显示列为姓名、性别 +mysql> select sname,sex from student; ++-----------+------+ +| sname | sex | ++-----------+------+ +| 郭德纲 | 男 | +| 林志颖 | 男 | +| 柳岩 | 女 | ++-----------+------+ +3 行于数据集 (0.01 秒) +``` + +### 2.2、别名查询 + +别名有二种:字段别名、表别名 + +作用: + +字段别名查询出记录显示新的名字,并不影响表的结构。 + +表别名取了一个新的名字,可以代替表名使用。 + +**字段别名** + +```mysql +格式: +select 字段名1 as 别名1,字段名2 as 别名2,...,字段名n as 别名n from 数据库表名; +``` + +**案例:** + +查询student表中的sname和sex,以别名’姓名’和’性别’显示 + +```mysql +#使用字段别名显示姓名、性别 +mysql> select sname as 姓名,sex as 性别 from student; ++-----------+------+ +| 姓名 | 性别 | ++-----------+------+ +| 郭德纲 | 男 | +| 林志颖 | 男 | +| 柳岩 | 女 | ++-----------+------+ +3 行于数据集 (0.01 秒) +``` + +**表别名** + +```mysql +格式: +select 字段名1 as 别名1,字段名2 as 别名2,...,字段名n as 别名n from 数据库表名 as 别名; +``` + +案例: + +查询student表中的sname和sex,以别名’姓名’和’性别’显示,并为student表取了一个别名 s + +```mysql +#使用字段别名显示姓名、性别,表别名没有具体表现 +mysql> select sname as 姓名,sex as 性别 from student as s; ++-----------+------+ +| 姓名 | 性别 | ++-----------+------+ +| 郭德纲 | 男 | +| 林志颖 | 男 | +| 柳岩 | 女 | ++-----------+------+ +3 行于数据集 (0.01 秒) +``` + +**注意:** + +表别名一般用于多表查询,单表查询中没有具体体现。 + +### 2.3、清除重复记录查询 + +```mysql +格式: +select distinct 字段名 from 数据库表名; +``` + +**案例:** + +去掉性别重复的记录 + +去掉性别和姓名同时重复的记录 + +```mysql +#查看所有记录 +mysql> select * from student; ++------+-----------+------------+------+ +| id | sname | birthday | sex | ++------+-----------+------------+------+ +| 1 | 郭德纲 | 1973-01-18 | 男 | +| 2 | 林志颖 | 1974-10-18 | 男 | +| 3 | 柳岩 | 1980-11-08 | 女 | ++------+-----------+------------+------+ +3 行于数据集 (0.01 秒) +#查看sex不重复的记录 +mysql> select distinct sex from student; ++------+ +| sex | ++------+ +| 男 | +| 女 | ++------+ +2 行于数据集 (0.01 秒) +#查看sex,sname都不重复的记录 +mysql> select distinct sex,sname from student; ++------+-----------+ +| sex | sname | ++------+-----------+ +| 男 | 郭德纲 | +| 男 | 林志颖 | +| 女 | 柳岩 | ++------+-----------+ +3 行于数据集 (0.01 秒) +``` + +### 2.4、运算查询 + +**字段与固定值运算** + +```mysql +格式: +select 字段名+固定值 from 数据库表名; +``` + +**注意:** + +运算的字段必须是数值型 + +**案例:** + +查询student表中年龄减10岁,并显示sname和age + +```mysql +mysql> select age-10 as age ,sname from student; ++-----+--------+ +| age | sname | ++-----+--------+ +| 37 | 郭德纲 | +| 36 | 林志颖 | +| 30 | 柳岩 | ++-----+--------+ +3 rows in set +``` + +**字段与字段运算** + +```mysql +格式: +select 字段名+字段名 from 数据库表名; +``` + +**注意:** + +运算的字段必须是数值型 + +**案例:** + +查询student表中age与id的和,并显示出来age和id + +```mysql +mysql> select age+id,age,id + from student; ++--------+-----+----+ +| age+id | age | id | ++--------+-----+----+ +| 48 | 47 | 1 | +| 48 | 46 | 2 | +| 43 | 40 | 3 | ++--------+-----+----+ +3 rows in set +``` + +## 三、条件查询 + +### 3.1、条件查询前准备 + +新建学生信息表(students) + +**字段:**学生ID(sid)、学生姓名(sname)、学生性别(sex)、学生年龄(age)、英语成绩(english)、数学成绩(math)、入学时间(entertime)、备注(remark) + +```mysql +create table students( + sid int, + sname varchar(20), + sex varchar(2), + age int, + english double(4,1), + math double(4,1), + entertime date, + remark text +); +``` + +![image20200207010430241.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603187929354.png) + +**记录:** + +```mysql +insert into students values +(1,'张三','男',19,98.5,88,'2017-09-01','他来自四川'), +(2,'李四','男',20,80,88,'2017-09-01','他来自重庆'), +(3,'张红','女',19,86,80,'2017-09-01','他来自北京'), +(4,'张八','男',18,80,85,'2017-09-01','他来自天津'), +(5,'李三','男',19,60,88,'2017-09-01','他来自湖北'), +(6,'王六','女',20,50,70,'2017-09-01','他来自湖南'), +(7,'刘红','女',18,90,98,'2017-09-01','他来自甘肃'); +``` + +![image20200207011044328.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603187963975.png) + +### 3.2、基础比较运算符 + +```mysql +格式: +>、<、<=、>=、=、<> +``` + +**注意:** + +在SQL中“<>”,表示不等于,mysql中也可以用“!=”表示 + +在SQL中没有“==” + +**案例:** + +查询学生信息表中英语成绩大于80的学生信息 + +```mysql +mysql> select * from students where english>80; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 1 | 张三 | 男 | 19 | 98.5 | 88.0 | 2017-09-01 | 他来自四川 | +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 7 | 刘红 | 女 | 18 | 90.0 | 98.0 | 2017-09-01 | 他来自甘肃 | ++------+--------+------+------+---------+------+------------+-----------------+ +3 行于数据集 (0.02 秒) +``` + +查询学生信息表中英语成绩小于80的学生信息 + +```mysql +mysql> select * from students where english<80; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 5 | 李三 | 男 | 19 | 60.0 | 88.0 | 2017-09-01 | 他来自湖北 | +| 6 | 王六 | 女 | 20 | 50.0 | 70.0 | 2017-09-01 | 他来自湖南 | ++------+--------+------+------+---------+------+------------+-----------------+ +2 行于数据集 (0.01 秒) +``` + +查询学生信息表中年龄大于等于19岁的学生信息 + +```mysql +mysql> select * from students where age>=19; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 1 | 张三 | 男 | 19 | 98.5 | 88.0 | 2017-09-01 | 他来自四川 | +| 2 | 李四 | 男 | 20 | 80.0 | 88.0 | 2017-09-01 | 他来自重庆 | +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 5 | 李三 | 男 | 19 | 60.0 | 88.0 | 2017-09-01 | 他来自湖北 | +| 6 | 王六 | 女 | 20 | 50.0 | 70.0 | 2017-09-01 | 他来自湖南 | ++------+--------+------+------+---------+------+------------+-----------------+ +5 行于数据集 (0.01 秒) +``` + +查询学生信息表中年龄小于等于19岁的学生信息 + +```mysql +mysql> select * from students where age<=19; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 1 | 张三 | 男 | 19 | 98.5 | 88.0 | 2017-09-01 | 他来自四川 | +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 4 | 张八 | 男 | 18 | 80.0 | 85.0 | 2017-09-01 | 他来自天津 | +| 5 | 李三 | 男 | 19 | 60.0 | 88.0 | 2017-09-01 | 他来自湖北 | +| 7 | 刘红 | 女 | 18 | 90.0 | 98.0 | 2017-09-01 | 他来自甘肃 | ++------+--------+------+------+---------+------+------------+-----------------+ +5 行于数据集 (0.01 秒) +``` + +查询学生信息表中数学成绩等于88的学生信息 + +```mysql +mysql> select * from students where math=88; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 1 | 张三 | 男 | 19 | 98.5 | 88.0 | 2017-09-01 | 他来自四川 | +| 2 | 李四 | 男 | 20 | 80.0 | 88.0 | 2017-09-01 | 他来自重庆 | +| 5 | 李三 | 男 | 19 | 60.0 | 88.0 | 2017-09-01 | 他来自湖北 | ++------+--------+------+------+---------+------+------------+-----------------+ +3 行于数据集 (0.02 秒) +``` + +查询学生信息表中年龄不等于18岁的学生信息 + +```mysql +mysql> select * from students where age<>18; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 1 | 张三 | 男 | 19 | 98.5 | 88.0 | 2017-09-01 | 他来自四川 | +| 2 | 李四 | 男 | 20 | 80.0 | 88.0 | 2017-09-01 | 他来自重庆 | +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 5 | 李三 | 男 | 19 | 60.0 | 88.0 | 2017-09-01 | 他来自湖北 | +| 6 | 王六 | 女 | 20 | 50.0 | 70.0 | 2017-09-01 | 他来自湖南 | ++------+--------+------+------+---------+------+------------+-----------------+ +5 行于数据集 (0.02 秒) +``` + +查询学生信息表中年龄大于等于20岁的学生的姓名和性别 + +```mysql +mysql> select sname,sex from students where age>=20; ++--------+------+ +| sname | sex | ++--------+------+ +| 李四 | 男 | +| 王六 | 女 | ++--------+------+ +2 行于数据集 (0.01 秒) +``` + +### 3.3、提高比较运算符 + +```mysql +格式: +between...and... #在一定的范围内 +``` + +**注意:** + +包含头尾 + +**案例:** + +查询学生信息表中英语成绩80到90岁之间的学生信息 + +```mysql +mysql> select * from students where english between 80 and 90; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 2 | 李四 | 男 | 20 | 80.0 | 88.0 | 2017-09-01 | 他来自重庆 | +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 4 | 张八 | 男 | 18 | 80.0 | 85.0 | 2017-09-01 | 他来自天津 | +| 7 | 刘红 | 女 | 18 | 90.0 | 98.0 | 2017-09-01 | 他来自甘肃 | ++------+--------+------+------+---------+------+------------+-----------------+ +4 行于数据集 (0.01 秒) +格式: +in(值1,值2...,值n) #表示用n个值相等 +not in(值1,值2...,值n) #表示用n个值不相等 +``` + +**案例:** + +查询学生信息表中sid为1,3,5的信息 + +```mysql +mysql> select * from students where sid in(1,3,5); ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 1 | 张三 | 男 | 19 | 98.5 | 88.0 | 2017-09-01 | 他来自四川 | +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 5 | 李三 | 男 | 19 | 60.0 | 88.0 | 2017-09-01 | 他来自湖北 | ++------+--------+------+------+---------+------+------------+-----------------+ +3 行于数据集 (0.01 秒) +``` + +查询学生信息表中sid除了1,3,5的信息 + +```mysql +mysql> select * from students where sid not in(1,3,5); ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 2 | 李四 | 男 | 20 | 80.0 | 88.0 | 2017-09-01 | 他来自重庆 | +| 4 | 张八 | 男 | 18 | 80.0 | 85.0 | 2017-09-01 | 他来自天津 | +| 6 | 王六 | 女 | 20 | 50.0 | 70.0 | 2017-09-01 | 他来自湖南 | +| 7 | 刘红 | 女 | 18 | 90.0 | 98.0 | 2017-09-01 | 他来自甘肃 | ++------+--------+------+------+---------+------+------------+-----------------+ +4 行于数据集 (0.01 秒) +格式: +like '%值%' #模糊查询 +``` + +**注意:** + +``` +mysql通配符 + +% :匹配任意多个字符 + +_ :匹配一个字符 +``` + +**案例:** + +查询学生信息表中姓’张’的学生信息 + +```mysql +mysql> select * from students where sname like '张%'; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 1 | 张三 | 男 | 19 | 98.5 | 88.0 | 2017-09-01 | 他来自四川 | +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 4 | 张八 | 男 | 18 | 80.0 | 85.0 | 2017-09-01 | 他来自天津 | ++------+--------+------+------+---------+------+------------+-----------------+ +3 行于数据集 (0.01 秒) + +mysql> select * from students where sname like '张'; +空的数据集 (0.01 秒) +``` + +查询学生信息表中包含’红’字的学生信息 + +```mysql +mysql> select * from students where sname like '%红%'; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 7 | 刘红 | 女 | 18 | 90.0 | 98.0 | 2017-09-01 | 他来自甘肃 | ++------+--------+------+------+---------+------+------------+-----------------+ +2 行于数据集 (0.01 秒) +``` + +查询学生信息表中姓’王’的二个字的学生信息 + +```mysql +mysql> select * from students where sname like '王_'; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 6 | 王六 | 女 | 20 | 50.0 | 70.0 | 2017-09-01 | 他来自湖南 | ++------+--------+------+------+---------+------+------------+-----------------+ +1 行于数据集 (0.01 秒) +格式: +is null #表示某字段值为null +is not null #表示某字段值不为null +``` + +**注意:** + +不能写成:字段名=null + +**案例:** + +查询学生信息表中age为null学生信息 + +查询学生信息表中english为null学生信息 + +```mysql +mysql> select * from students where age is null; ++------+--------+------+------+---------+------+-----------+--------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+-----------+--------+ +| 8 | 王五 | 男 | NULL | NULL | NULL | NULL | NULL | ++------+--------+------+------+---------+------+-----------+--------+ +1 行于数据集 (0.01 秒) + +mysql> select * from students where english is null; ++------+-----------+------+------+---------+------+-----------+--------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+-----------+------+------+---------+------+-----------+--------+ +| 8 | 王五 | 男 | NULL | NULL | NULL | NULL | NULL | +| 9 | 李老六 | 男 | 19 | NULL | NULL | NULL | NULL | ++------+-----------+------+------+---------+------+-----------+--------+ +2 行于数据集 (0.01 秒) +``` + +查询学生信息表中english不为null学生信息 + +```mysql +mysql> select * from students where english is not null; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 1 | 张三 | 男 | 19 | 98.5 | 88.0 | 2017-09-01 | 他来自四川 | +| 2 | 李四 | 男 | 20 | 80.0 | 88.0 | 2017-09-01 | 他来自重庆 | +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 4 | 张八 | 男 | 18 | 80.0 | 85.0 | 2017-09-01 | 他来自天津 | +| 5 | 李三 | 男 | 19 | 60.0 | 88.0 | 2017-09-01 | 他来自湖北 | +| 6 | 王六 | 女 | 20 | 50.0 | 70.0 | 2017-09-01 | 他来自湖南 | +| 7 | 刘红 | 女 | 18 | 90.0 | 98.0 | 2017-09-01 | 他来自甘肃 | ++------+--------+------+------+---------+------+------------+-----------------+ +7 行于数据集 (0.02 秒) +``` + +### 3.4、逻辑运算符 + +```mysql +格式: +and #与,二边条件同时成立,成立 && +or #或,二边条件有一边成立,成立 || +not #非,一边条件成立,取反;一边条件不成立,取反 ! +``` + +**案例:** + +查询学生信息表中english大于85的男生的学生信息 + +```mysql +mysql> select * from students where english>85 and sex='男'; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 1 | 张三 | 男 | 19 | 98.5 | 88.0 | 2017-09-01 | 他来自四川 | ++------+--------+------+------+---------+------+------------+-----------------+ +1 行于数据集 (0.01 秒) +``` + +查询学生信息表中年龄大于等于20岁或数学成绩大于85的学生信息 + +```mysql +mysql> select * from students where age>=20 or math>85; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 1 | 张三 | 男 | 19 | 98.5 | 88.0 | 2017-09-01 | 他来自四川 | +| 2 | 李四 | 男 | 20 | 80.0 | 88.0 | 2017-09-01 | 他来自重庆 | +| 5 | 李三 | 男 | 19 | 60.0 | 88.0 | 2017-09-01 | 他来自湖北 | +| 6 | 王六 | 女 | 20 | 50.0 | 70.0 | 2017-09-01 | 他来自湖南 | +| 7 | 刘红 | 女 | 18 | 90.0 | 98.0 | 2017-09-01 | 他来自甘肃 | ++------+--------+------+------+---------+------+------------+-----------------+ +5 行于数据集 (0.01 秒) +``` + +查询学生信息表中除了年龄大于等于20岁或数学成绩大于85的学生信息 + +```mysql +mysql> select * from students where not (age>=20 or math>85); ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 4 | 张八 | 男 | 18 | 80.0 | 85.0 | 2017-09-01 | 他来自天津 | ++------+--------+------+------+---------+------+------------+-----------------+ +2 行于数据集 (0.01 秒) +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL\350\257\255\345\217\245\346\216\222\345\272\217\344\270\216\345\210\206\347\273\204.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL\350\257\255\345\217\245\346\216\222\345\272\217\344\270\216\345\210\206\347\273\204.md" new file mode 100644 index 0000000..23a418d --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/DQL\350\257\255\345\217\245\346\216\222\345\272\217\344\270\216\345\210\206\347\273\204.md" @@ -0,0 +1,213 @@ +## 一、DQL-排序 + +排序是计算机内经常进行的一种操作,其目的是将一组“无序”的记录序列调整为“有序”的记录序列。分内部排序和外部排序,若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序。反之,若参加排序的记录数量很大,整个序列的排序过程不可能在内存中完成,则称此类排序问题为外部排序。内部排序的过程是一个逐步扩大记录的有序序列长度的过程。 + +### 1.1、排序概述 + +将数据库表中杂乱无章的数据记录,通过字段的升序或降序的顺序排列的过程叫做排序。 + +### 1.2、排序语法 + +通过order by子句 + +``` +格式: +select */字段列表 from 数据库表名 [where 条件表达式] [order by 字段名 [asc/desc]]; +``` + +**说明:** + +asc:升序,默认值 + +desc:降序 + +### 1.3、单列排序 + +按照一个字段进行排序 + +**案例:** + +查看学生信息表中按照英语成绩升序排列,去掉成绩为null的学生。 + +``` +mysql> select * from students where english is not null order by english; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 6 | 王六 | 女 | 20 | 50.0 | 70.0 | 2017-09-01 | 他来自湖南 | +| 5 | 李三 | 男 | 19 | 60.0 | 88.0 | 2017-09-01 | 他来自湖北 | +| 2 | 李四 | 男 | 20 | 80.0 | 88.0 | 2017-09-01 | 他来自重庆 | +| 4 | 张八 | 男 | 18 | 80.0 | 85.0 | 2017-09-01 | 他来自天津 | +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 7 | 刘红 | 女 | 18 | 90.0 | 98.0 | 2017-09-01 | 他来自甘肃 | +| 1 | 张三 | 男 | 19 | 98.5 | 88.0 | 2017-09-01 | 他来自四川 | ++------+--------+------+------+---------+------+------------+-----------------+ +7 行于数据集 (0.01 秒) +``` + +### 1.4、组合排序 + +按照多个字段进行排序,先按1字段排序,在按2字段排序,在按n字段排序 + +``` +格式: +select */字段列表 from 数据库表名 [where 条件表达式] [order by 字段名1 [asc/desc],字段名2 [asc/desc],...,字段名n [asc/desc]]; +``` + +**案例:** + +查看学生信息表中先按照数学成绩升序排列,在按照英语成绩降序排列,最后去掉成绩为null的学生。 + +``` +mysql> select * from students where english is not null order by math,english desc; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 6 | 王六 | 女 | 20 | 50.0 | 70.0 | 2017-09-01 | 他来自湖南 | +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 4 | 张八 | 男 | 18 | 80.0 | 85.0 | 2017-09-01 | 他来自天津 | +| 1 | 张三 | 男 | 19 | 98.5 | 88.0 | 2017-09-01 | 他来自四川 | +| 2 | 李四 | 男 | 20 | 80.0 | 88.0 | 2017-09-01 | 他来自重庆 | +| 5 | 李三 | 男 | 19 | 60.0 | 88.0 | 2017-09-01 | 他来自湖北 | +| 7 | 刘红 | 女 | 18 | 90.0 | 98.0 | 2017-09-01 | 他来自甘肃 | ++------+--------+------+------+---------+------+------------+-----------------+ +7 行于数据集 (0.02 秒) +``` + +## 二、DQL 分组 + +数据分组是根据统计研究的需要,将原始数据按照某种标准划分成不同的组别,分组后的的数据称为分组数据。 + +数据分组应遵循两个基本原则: + +穷尽性原则 + +这一原则就是要求调查的每一单位都能无一例外地划归到某一组去,不会产生“遗漏”现象。 + +互斥性原则 + +这一原则就是要求将调查单位分组后,各个组的范围应该互不相容、互为排斥。即每个调查单位在特定的分组标志下只能归属某一组,而不能同时或可能同时归属到几个组。 + +### 2.1、分组概述 + +- 什么是分组 + +分组就是将一组行记录按列或表达式的值分组成摘要行记录。通过GROUP BY子句返回每个分组的一个行记录。换句话说,它减少了在结果集中的行数。 + +- 分组语法 + +– 语法 + +```mysql +格式: +select */字段列表 from 数据库表名 [group by 分组字段名 [having 条件表达式]]; +``` + +– 分组方式 + +将学生信息表中男、女同学进行分组 + +![image20200209001000938.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603188686160.png) + +**原始数据** + +![image20200209001300283.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603188795282.png) + +**分组为:男一组,女一组** + +![image20200209001300283.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603188695335.png) + +**返回每组第一条数据** + +![image20200209002544753.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603188705609.png) + +### 2.2、分组应用 + +- 实际分组方式 + +```mysql +mysql> select sex from students group by sex; ++------+ +| sex | ++------+ +| 男 | +| 女 | ++------+ +2 行于数据集 (0.01 秒) +``` + +**注意:** + +当我们使用某个字段分组,在查询的时候也需要将这个字段查询出来,否则看不到数据属于哪组的。 + +单独分组没什么用处,分组的目的就是为了统计,一般分组会跟**聚合函数**一起使用。 + +**案例:** + +查询学生信息表中男、女同学的人数 + +```mysql +mysql> select sex,count(*) from students group by sex; ++------+----------+ +| sex | count(*) | ++------+----------+ +| 男 | 6 | +| 女 | 3 | ++------+----------+ +2 行于数据集 (0.01 秒) +``` + +- where与having + +– where** + +查询学生信息表中数学成绩在80分以上的,男、女同学的人数 + +```mysql +#where后面不能用聚合函数 +mysql> select sex,count(*) from students where math>80 group by sex; ++------+----------+ +| sex | count(*) | ++------+----------+ +| 男 | 4 | +| 女 | 1 | ++------+----------+ +2 行于数据集 (0.01 秒) +``` + +**注意:** + +where是将不符合条件的先去掉,在分组。 + +– having + +查询学生信息表中男、女同学的人数,人数超过3人显示 + +```mysql +#having n>3 可以写成 having count(*)>3 +mysql> select sex,count(*) as n from students group by sex having n>3; ++------+---+ +| sex | n | ++------+---+ +| 男 | 6 | ++------+---+ +1 行于数据集 (0.03 秒) +``` + +**注意:** + +having是先分组,在将分组后不符合条件的去掉。 + +– where与having区别 + +**where** **子句** + +在分组之前过滤数据,即先过滤再分组。 + +where 后面不可以使用聚合函数。 + +**having** **子句** + +在分组之后过滤数据,即先分组再过滤。 + +having 后面可以使用聚合函数。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL AB\345\244\215\345\210\266.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL AB\345\244\215\345\210\266.md" new file mode 100644 index 0000000..d490ed5 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL AB\345\244\215\345\210\266.md" @@ -0,0 +1,398 @@ +# mysql AB复制实战 + +mysqldump解决了mysql数据库的备份,它只是基于某个时间点做备份,无法解决实时备份的问题,为了解决mysql实时备份的问题,mysql官方推出了mysql主从备份机制,可以让用户通过设置mysql主从来实现数据库实时备份。 + +1、MySQL服务器宕机怎么 单点故障 + +2、数据的安全 + +## 一、mysql AB复制 + +通过多台机器实现一主多从的方式来实现数据备份,主服务器负责让用户读写数据,从服务器负责同步主服务器数据,也可以承担用户读的任务。 + +至少两台机器 + +## 二、AB复制原理 + +![mysql_ab_原理.jpg](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603972949435.jpg) + +1、用户or web 对主服务器的所有修改操作都会记录在binary log日志 + +成功的修改操作【增加 修改 删除】 记录的是SQL语句 主上的一个线程 + +2、从 有两个线程 + +IO线程:负责连接主mysql【AB通信 A授权账号】提取binlog中的SQL语句到relay log + +SQL线程:在本地执行relay log中新增的SQL语句 + +注意:AB是异步 + +## 三、master服务器设置 + +**实验拓扑** + +![mysql_ab拓扑图.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603972978082.png) + +- 安装mysql并启动 +- 关闭防火墙,selinux +- 设置时间服务器 +- 修改配置文件 设置server-id=N +- 创建slave连接master的账号,用于取SQL语句 + +### 3.1、安装mysql并启动 + +a、安装mysql + +``` +官网下载mysql yum源,安装 +安装方法:yum -y install mysql-server mysql +``` + +b、启动mysql + +``` +systemctl enable mysqld;systemctl start mysqld +``` + +c、修改root密码 + +``` +mysql> alter user 'root'@'localhost' identified by '98989'; +Query OK, 0 rows affected (0.01 sec) +``` + +### 3.2、关闭防火墙,selinux + +``` +[root@node1 ~]# systemctl disable firewalld +[root@node1 ~]# iptables -F +[root@node1 ~]# iptables -t nat -F +[root@node1 ~]# sed -i -r '/SELINUX=/c\SELINUX=disabled' /etc/selinux/config +[root@node1 ~]# reboot + + +其他机器同理 +``` + +### 3.3、设置时间服务器 + +``` +禁止向centos默认时间服务器同步时间 +[root@node1 ~]# sed -i.bak '/^pool 2.centos.pool.ntp.org iburst$/s//#/' /etc/chrony.conf + +设置时间服务器为阿里云的 +[root@node1 ~]# cat >> /etc/chrony.conf < server ntp1.aliyun.com +> server ntp2.aliyun.com +> server ntp3.aliyun.com +> server ntp4.aliyun.com +> EOF + +重启服务生效 +[root@node1 ~]# systemctl restart chronyd +查看命令,看一下时间服务器IP地址 +[root@node1 ~]# chronyc sources -v +``` + +### 3.4、修改配置文件 设置server-id=N + +server-id的数字越小,优先级越高。 + +``` +[root@node1 ~]# echo "server-id=1" >> /etc/my.cnf.d/mysql-server.cnf +``` + +确认binlog是开启的 + +``` +如果没有开启 log-bin=binlog +``` + +### 3.5、创建slave连接master的账号,用于取SQL语句 + +**登陆进入mysql: mysql -u root -p** + +**password:** + +``` +mysql> create user sko identified by "98989"; +Query OK, 0 rows affected (0.00 sec) + +mysql> grant replication slave on *.* to sko; +Query OK, 0 rows affected (0.00 sec) + +mysql> flush privileges; +Query OK, 0 rows affected (0.00 sec) +``` + +查看主的状态 + +``` +mysql> show master status \G; +*************************** 1. row *************************** + File: binlog.000002 + Position: 155 + Binlog_Do_DB: + Binlog_Ignore_DB: +Executed_Gtid_Set: +1 row in set (0.00 sec) + +ERROR: +No query specified + +mysql> +mysql> create database db1; +Query OK, 1 row affected (0.00 sec) + + +File: binlog.000002 当前主的binlog日志 +Position: 155 当前binlog日志的SQL语句记录点 +``` + +## 四、slave设置 + +**实验步骤** + +- 安装mysql并启动 +- 关闭防火墙、selinux +- 设置时间服务器 +- 修改配置文件 设置server-id=N+x +- 设置master主信息 +- 测试同步 + +``` +- [4.1] 安装mysql并启动 +- [4.2] 关闭防火墙、selinux +- [4.3] 设置时间服务器 + +省略...... +``` + +### 4.3、修改配置文件 设置server-id=N+x + +从服务器的server-id要比主的数字大。 + +``` +[root@node2 ~]# echo "server-id=2" >> /etc/my.cnf.d/mysql-server.cnf +``` + +### 4.4、设置slave同步 + +``` +mysql> stop slave; +Query OK, 0 rows affected, 1 warning (0.00 sec) + +mysql> change master to master_host='192.168.98.201',master_user='sko',master_password='98989',master_log_file='binlog.000002'; +Query OK, 0 rows affected, 3 warnings (0.01 sec) + +mysql> start slave; +Query OK, 0 rows affected (0.00 sec) +``` + +### 4.5、验证slave + +``` +mysql> show slave status \G; +*************************** 1. row *************************** + Slave_IO_State: Waiting for master to send event + Master_Host: 192.168.98.201 + Master_User: sko + Master_Port: 3306 + Connect_Retry: 60 + Master_Log_File: binlog.000002 + Read_Master_Log_Pos: 337 + Relay_Log_File: node2-relay-bin.000002 + Relay_Log_Pos: 545 + Relay_Master_Log_File: binlog.000002 + Slave_IO_Running: Yes + Slave_SQL_Running: Yes + Replicate_Do_DB: + Replicate_Ignore_DB: + Replicate_Do_Table: + Replicate_Ignore_Table: + Replicate_Wild_Do_Table: + Replicate_Wild_Ignore_Table: + Last_Errno: 0 + Last_Error: + Skip_Counter: 0 + Exec_Master_Log_Pos: 337 + Relay_Log_Space: 753 + Until_Condition: None + Until_Log_File: + Until_Log_Pos: 0 + Master_SSL_Allowed: No + Master_SSL_CA_File: + Master_SSL_CA_Path: + Master_SSL_Cert: + Master_SSL_Cipher: + Master_SSL_Key: + Seconds_Behind_Master: 0 +Master_SSL_Verify_Server_Cert: No + Last_IO_Errno: 0 + Last_IO_Error: + Last_SQL_Errno: 0 + Last_SQL_Error: + Replicate_Ignore_Server_Ids: + Master_Server_Id: 1 + Master_UUID: ae106b21-59c3-11ea-aa77-000c29b8d045 + Master_Info_File: mysql.slave_master_info + SQL_Delay: 0 + SQL_Remaining_Delay: NULL + Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates + Master_Retry_Count: 86400 + Master_Bind: + Last_IO_Error_Timestamp: + Last_SQL_Error_Timestamp: + Master_SSL_Crl: + Master_SSL_Crlpath: + Retrieved_Gtid_Set: + Executed_Gtid_Set: + Auto_Position: 0 + Replicate_Rewrite_DB: + Channel_Name: + Master_TLS_Version: + Master_public_key_path: + Get_master_public_key: 0 + Network_Namespace: +1 row in set (0.00 sec) + +ERROR: +No query specified +``` + +### 4.6、干货分享,如何解决AB不同步的问题 + +``` +Slave_IO_Running: Yes +#该线程负责从master上拿binlog日志到relaylog,复制线程 +#该线程如果是NO,如何排除 +#1、查主从网络是否能通信,iptables selinux +#2、查你的repl账号在slave上是否能连接master + +Slave_SQL_Running: Yes +#该线程负责将本机relaylog中的SQL语句执行一次 +#该线程为NO,如何排除 +#该线程为NO说明relaylog中的SQL语句在本地无法执行 +#1、查看mysql> show slave status \G; 找到不能执行的语句 + + +mysql> show slave status \G; +*************************** 1. row *************************** + Slave_IO_State: Waiting for master to send event + Master_Host: 192.168.98.201 + Master_User: sko + Master_Port: 3306 + Connect_Retry: 60 + Master_Log_File: binlog.000002 + Read_Master_Log_Pos: 515 + Relay_Log_File: node2-relay-bin.000002 + Relay_Log_Pos: 545 + Relay_Master_Log_File: binlog.000002 + Slave_IO_Running: Yes + Slave_SQL_Running: No + Replicate_Do_DB: + Replicate_Ignore_DB: + Replicate_Do_Table: + Replicate_Ignore_Table: + Replicate_Wild_Do_Table: + Replicate_Wild_Ignore_Table: + Last_Errno: 1008 + Last_Error: Error 'Can't drop database 'db1'; database doesn't exist' on query. Default database: 'db1'. Query: 'drop database db1' + Skip_Counter: 0 + Exec_Master_Log_Pos: 337 + Relay_Log_Space: 931 + Until_Condition: None + Until_Log_File: + Until_Log_Pos: 0 + Master_SSL_Allowed: No + Master_SSL_CA_File: + Master_SSL_CA_Path: + Master_SSL_Cert: + Master_SSL_Cipher: + Master_SSL_Key: + Seconds_Behind_Master: NULL +Master_SSL_Verify_Server_Cert: No + Last_IO_Errno: 0 + Last_IO_Error: + Last_SQL_Errno: 1008 + Last_SQL_Error: Error 'Can't drop database 'db1'; database doesn't exist' on query. Default database: 'db1'. Query: 'drop database db1' + Replicate_Ignore_Server_Ids: + Master_Server_Id: 1 + Master_UUID: ae106b21-59c3-11ea-aa77-000c29b8d045 + Master_Info_File: mysql.slave_master_info + SQL_Delay: 0 + SQL_Remaining_Delay: NULL + Slave_SQL_Running_State: + Master_Retry_Count: 86400 + Master_Bind: + Last_IO_Error_Timestamp: + Last_SQL_Error_Timestamp: 200227 20:36:57 + Master_SSL_Crl: + Master_SSL_Crlpath: + Retrieved_Gtid_Set: + Executed_Gtid_Set: + Auto_Position: 0 + Replicate_Rewrite_DB: + Channel_Name: + Master_TLS_Version: + Master_public_key_path: + Get_master_public_key: 0 + Network_Namespace: +1 row in set (0.00 sec) + +ERROR: +No query specified + +#这段就能看到为何不能执行,原因是slave上没有db1数据库,所以不能删除。 + Last_SQL_Error: Error 'Can't drop database 'db1'; database doesn't exist' on query. Default database: 'db1'. Query: 'drop database db1' + +#2、最关键的一步,如何定位错误点 +#Read_Master_Log_Pos: 515 找到目前复制的master Binlog日志的pos位置,从这个位置开始,后续在slave上做差异还原同步。 + +#拓展:如何找下一个POS位置,去看你master的当前binlog日志 +#定位错误点SQL语句的位置号 +[root@node1 ~]# mysqlbinlog /var/lib/mysql/binlog.000002|egrep -B 30 "drop database db1" +......... +# at 414 错误点SQL语句的位置号 +#200227 20:36:57 server id 1 end_log_pos 515 CRC32 0x683207a9 Query thread_id=8 exec_time=0 error_code=0 Xid = 17 +SET TIMESTAMP=1582853817/*!*/; +drop database db1 +.......... + +#定位错误点SQL语句之后一条的位置号 +[root@node1 ~]# mysqlbinlog /var/lib/mysql/binlog.000002|egrep -A 30 "drop database db1" +drop database db1 +/*!*/; +# at 515 发现下一条SQL语句是515 +#200227 20:42:37 server id 1 end_log_pos 592 CRC32 0x2677edde Anonymous_GTID last_committed=2 sequence_number=3 rbr_only=no original_committed_timestamp=1582854157245396 immediate_commit_timestamp=1582854157245396 transaction_length=182 +# original_commit_timestamp=1582854157245396 (2020-02-27 20:42:37.245396 EST) +# immediate_commit_timestamp=1582854157245396 (2020-02-27 20:42:37.245396 EST) +/*!80001 SET @@session.original_commit_timestamp=1582854157245396*//*!*/; +/*!80014 SET @@session.original_server_version=80017*//*!*/; +/*!80014 SET @@session.immediate_server_version=80017*//*!*/; +SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/; + +# at 592 +#200227 20:42:37 server id 1 end_log_pos 697 CRC32 0x3624f753 Query thread_id=11 exec_time=0 error_code=0 Xid = 24 +SET TIMESTAMP=1582854157/*!*/; +/*!80016 SET @@session.default_table_encryption=0*//*!*/; +create database db2 +/*!*/; +.................... +#发现下一条SQL语句是515 + + +#通过上述命令可以查看pos 515之后的语句,-A 30 是指往后30行 -B 30是看往前30行,根据自己的需求设置 + + +#3、重新设置同步指令 +mysql> stop slave; +Query OK, 0 rows affected (0.01 sec) + +mysql> change master to master_host='192.168.98.201',master_user='sko',master_password='98989',master_log_file='binlog.000002',master_log_pos=515; +Query OK, 0 rows affected, 2 warnings (0.01 sec) + +mysql> start slave; +Query OK, 0 rows affected (0.00 sec) +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL DCL\350\257\255\345\217\245.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL DCL\350\257\255\345\217\245.md" new file mode 100644 index 0000000..2acd6df --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL DCL\350\257\255\345\217\245.md" @@ -0,0 +1,239 @@ +数据控制语言 (Data Control Language) 在SQL语言中,是一种可对数据访问权进行控制的指令,它可以控制特定用户账户对数据表、查看表、存储程序、用户自定义函数等数据库对象的控制权。由 GRANT 和 REVOKE 两个指令组成。 + +## 一、DCL概述 + +### 1.1、什么是DCL + +DCL 语句主要是DBA 用来管理系统中的对象权限时所使用,一般的开发人员很少使用。 + +DCL中主要包括创建用户、给用户授权、对用户撤销授权、查询用户授权和删除用户等操作。 + +### 1.2、为什么学习DCL + +在一个企业里面的数据库服务器上面可能同时运行着很多个项目的数据库。所以,我们应该可以根据不同的项目建立不同的用户,分配不同的权限来管理和维护数据库。 + +## 二、用户管理 + +mysql数据库的用户都在mysql数据库下面的user表中 + +### 2.1、查看用户 + +```mysql +格式: +select * from user; +``` + +**案例:** + +```mysql +mysql> select * from user; + +mysql> select user,host,plugin,authentication_string from user; +``` + +![image20200218234525100.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603521889167.png) + +### 2.2、创建用户 + +```mysql +格式: +create user '用户名'@'主机名' identified by '密码'; +``` + +**注意:** + +**用户名:** 新用户的名字 + +**主机名:** 指定该用户在哪个主机上可以登陆,如果是本地用户可用localhost,如果想让该用户可以从任意远程主机登陆,可以使用通配符% + +**密码:** 密码可以为空,如果为空则该用户可以不需要密码登陆服务器 + +**案例:** + +创建一个用户root1,只能在本机登录(localhost) + +```mysql +mysql> create user 'root1'@'localhost' identified by '123'; +Query OK, 0 rows affected (0.02 秒) + +mysql> select user,host,plugin,authentication_string from user; +``` + +![image20200219000040373.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603521923781.png) + +创建一个用户root2,可以在任何主机(%)登录 + +```mysql +mysql> create user 'root2'@'%' identified by '123'; +Query OK, 0 rows affected (0.01 秒) + +mysql> select user,host,plugin,authentication_string from user; +``` + +![image20200219000412028.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603521943126.png) + +**注意:** + +指定加密方式,增加用户 + +```mysql +mysql> create user 'root3'@'%' identified with mysql_native_password by '123'; +Query OK, 0 rows affected (0.01 秒) + +mysql> select user,host,plugin,authentication_string from user; +``` + +![image20200219001939522.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603521967385.png) + +### 2.3、删除用户 + +```mysql +drop user '用户名'@'主机名'; +``` + +**案例:** + +删除root1 + +```mysql +mysql> drop user root1@localhost; +Query OK, 0 rows affected (0.01 秒) + +mysql> select user,host,plugin,authentication_string from user; +``` + +## 三、密码管理 + +### 3.1、修改用户密码 + +```mysql +格式: +alter user '用户名'@'主机名' identified by '密码'; +``` + +**案例:** + +修改root2的密码 + +```mysql +mysql> alter user 'root2'@'%' identified by '456'; +Query OK, 0 rows affected (0.02 秒) +``` + +**注意:** + +如果想用该root2用户连接上mysql服务端的话,我们的密码修改时应该是: + +```mysql +mysql> alter user 'root2'@'%' identified with mysql_native_password by '456'; +Query OK, 0 rows affected (0.02 秒) +``` + +### 3.2、设置管理员(root)密码 + +清空密码 + +```mysql +use mysql; + +update user set authentication_string='' where user='root';#设置提root用户的密码为‘’,本地,远程 +``` + +设置密码 + +```mysql +alter user 'root'@'%' identified by 'Root12345'; +alter user 'root'@'localhost' identified by 'Root12345'; +``` + +## 四、权限管理 + +### 4.1、查看用户权限 + +```mysql +格式: +show grants for '用户名'@'主机名'; +``` + +**案例:** + +查看’root2’,'root3’及’root’权限 + +```mysql +mysql> show grants for 'root2'@'%'; ++-----------------------------------+ +| Grants for root2@% | ++-----------------------------------+ +| GRANT USAGE ON *.* TO `root2`@`%` | ++-----------------------------------+ +1 行于数据集 (0.01 秒) + +mysql> show grants for 'root3'@'%'; ++-----------------------------------+ +| Grants for root3@% | ++-----------------------------------+ +| GRANT USAGE ON *.* TO `root3`@`%` | ++-----------------------------------+ +1 行于数据集 (0.02 秒) + +mysql> show grants for 'root'@'%' +``` + +![image20200219002900607.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603521994010.png) + +### 4.2、授权 + +```mysql +格式: +grant 权限 1, 权限 2... on 数据库名.表名 to '用户名'@'主机名'; +``` + +**注意:** + +**grant… on …to :**授权关键字 + +**权限:** 如select\insert\update\delete等,如果是所有用all + +**数据库名.表名:** 该用户可以操作哪个数据库的哪些表。如果要授予该用户对所有数据库和表的相应操作权限则可用*表示,如*.* + +**’用户名’@‘主机名’ :** 注意单引号不能省略 + +**案例:** + +给’root2’分配,增加、删除、修改、查询表的权限 + +```mysql +mysql> grant insert,delete,update,select on zutuanxue.* to 'root2'@'%'; +``` + +给’root3’分配所有权限 + +```mysql +mysql> grant all on *.* to 'root3'@'%'; +``` + +### 4.3、撤销授权 + +```mysql +格式: +revoke 权限 1, 权限 2... on 数据库名.表名 from '用户名'@'主机名'; +``` + +**注意:** + +**revoke… on …from :** 撤消授权关键字 + +**权限:** 如select\insert\update\delete等,如果是所有用all + +**数据库名.表名:** 该用户可以操作哪个数据库的哪些表。如果要撤消授予该用户对所有数据库和表的相应操作权限则可用*表示,如*.* + +**’用户名’@‘主机名’ :** 注意单引号不能省略 + +**案例:** + +撤消’root2’的权限 + +```mysql +mysql> revoke all on zutuanxue.* from 'root2'@'%'; +Query OK, 0 rows affected (0.01 sec) +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL \345\255\230\345\202\250\350\277\207\347\250\213.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL \345\255\230\345\202\250\350\277\207\347\250\213.md" new file mode 100644 index 0000000..95fc278 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL \345\255\230\345\202\250\350\277\207\347\250\213.md" @@ -0,0 +1,1065 @@ +存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,它存储在数据库中,一次编译后永久有效,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象。在数据量特别庞大的情况下利用存储过程能达到倍速的效率提升 + +## 一、存储过程概述 + +### 1.1、什么是存储过程 + +存储过程是数据库中的一个重要对象。 + +存储过程是在数据库系统中,一组为了完成特定功能的SQL 语句集。存储过程是存储在数据库中,一次编译后,到处运行。不需要再次编译,用户通过指定存储过程的名字并传递参数(如果该存储过程带有参数)来执行。 + +### 1.2、存储过程特点 + +用来完成较复杂业务 +比较灵活,易修改,好编写,可编程性强 +编写好的存储过程可重复使用 + +### 1.3、存储过程优缺点 + +**优点** + +存储过程在创建的时候直接编译,sql语句每次使用都要编译,效率高。 + +存储过程可以被重复使用。 + +存储过程只连接一次数据库,sql语句在访问多张表时,连接多次数据库。 + +存储的程序是安全的。存储过程的应用程序授予适当的权限。 +**缺点** +在那里创建的存储过程,就只能在那里使用,可移植性差。 + +开发存储过程时,标准不定好的话,后期维护麻烦。 + +没有具体的编辑器,开发和调试都不方便。 + +太复杂的业务逻辑,存储过程也解决不了。 + +## 二、存储过程创建 + +### 2.1、创建格式 + +```mysql +格式: +create procedure 过程名() +begin +...... +end; +``` + +**案例:** + +查看员工与部门表中的全信息 + +```mysql +create procedure dept_emp() +begin + select * from dept; + select * from emp; +end; + +mysql> call dept_emp(); ++----+-----------+ +| id | name | ++----+-----------+ +| 1 | 研发部 | +| 2 | 渠道部 | +| 3 | 教务部 | +| 4 | 执行部 | ++----+-----------+ +4 行于数据集 (0.02 秒) + ++----+--------+--------+--------+------------+---------+ +| id | name | gender | salary | join_date | dept_id | ++----+--------+--------+--------+------------+---------+ +| 1 | 张三 | 男 | 7200 | 2013-02-24 | 1 | +| 2 | 李四 | 男 | 3600 | 2010-12-02 | 2 | +| 3 | 王五 | 男 | 9000 | 2008-08-08 | 2 | +| 4 | 赵六 | 女 | 5000 | 2015-10-07 | 3 | +| 5 | 吴七 | 女 | 4500 | 2011-03-14 | 1 | +| 6 | 王一 | 男 | 8768 | 2013-12-05 | NULL | +| 7 | 王二 | 女 | NULL | NULL | NULL | ++----+--------+--------+--------+------------+---------+ +7 行于数据集 (0.05 秒) + +Query OK, 0 rows affected (0.05 秒) +``` + +### 2.2、变量 + +```mysql +格式: +declare 变量名 变量类型 default 默认值; #声明变量 +set 变量名=值; #变量赋值 +select 字段名 into 变量名 from 数据库表; #查询表中字段,完成变量赋值 +select 变量名; #显示变量 +``` + +**案例:** + +查看员工表中id=1的员工的姓名 + +```mysql +create procedure emp_name() +begin + declare ename varchar(20) default ''; + select name into ename from emp where id=1; + select ename; +end; + +mysql> call emp_name(); ++--------+ +| ename | ++--------+ +| 张三 | ++--------+ +1 行于数据集 (0.01 秒) + +Query OK, 0 rows affected (0.01 秒) +``` + +### 2.3、变量作用域 + +存储过程中变量是有作用域的,作用范围在begin和end块之间,end结束变量的作用范围即结束。 + +变量可分为: + +**局部变量:** begin和end块之间 + +**全局变量:** 放在所有代码块之前;传参变量是全局的,可以在多个块之间起作用 + +**案例:** + +查看员工的人数与部门表中的部门数,并找出最高和最低工资(局部变量) + +```mysql +create procedure dept_or_emp() +begin + begin + declare e_n int default 0; + declare d_n int default 0; + select count(*) into e_n from emp; + select count(*) into d_n from dept; + select e_n,d_n; + end; + begin + declare max_s double default 0; + declare min_s double default 0; + select max(salary) into max_s from emp; + select min(salary) into min_s from emp; + select max_s,min_s; + end; +end; + +mysql> call dept_or_emp(); ++------+------+ +| e_n | d_n | ++------+------+ +| 7 | 4 | ++------+------+ +1 行于数据集 (0.26 秒) + ++-------+-------+ +| max_s | min_s | ++-------+-------+ +| 9000 | 3600 | ++-------+-------+ +1 行于数据集 (0.26 秒) + +Query OK, 0 rows affected (0.26 秒) +``` + +查看员工的人数与部门表中的部门数,并找出最高和最低工资(全局变量) + +```mysql +create procedure dept_or_emp1() +begin + declare e_n int default 0; + declare d_n int default 0; + declare max_s double default 0; + declare min_s double default 0; + begin + select count(*) into e_n from emp; + select count(*) into d_n from dept; + end; + begin + + select max(salary) into max_s from emp; + select min(salary) into min_s from emp; + end; + select e_n,d_n,max_s,min_s; +end; + +mysql> call dept_or_emp1(); ++------+------+ +| e_n | d_n | ++------+------+ +| 7 | 4 | ++------+------+ +1 行于数据集 (0.22 秒) + ++-------+-------+ +| max_s | min_s | ++-------+-------+ +| 9000 | 3600 | ++-------+-------+ +1 行于数据集 (0.23 秒) + +Query OK, 0 rows affected (0.23 秒) +``` + +## 三、存储过程参数 + +```mysql +格式: +create procedure 过程名([IN|OUT|INOUT] 参数名 参数数据类型 ) +begin +...... +end; +``` + +**注意:** + +in:传入参数 + +out:传出参数 + +inout:可以传入也可以传出 + +### 3.1、in + +表示该参数的值必须在调用存储过程事指定,如果不显示指定为in,那么默认就是in类型。 + +**案例:** + +根据传入的id查看员工的姓名。 + +```mysql +create procedure emp_id(eid int) +begin + declare ename varchar(20) default ''; + select name into ename from emp where id=eid; + select ename; +end; + +mysql> call emp_id(1); ++--------+ +| ename | ++--------+ +| 张三 | ++--------+ +1 行于数据集 (0.01 秒) + +Query OK, 0 rows affected (0.01 秒) + +mysql> call emp_id(2); ++--------+ +| ename | ++--------+ +| 李四 | ++--------+ +1 行于数据集 (0.01 秒) + +Query OK, 0 rows affected (0.02 秒) + +mysql> call emp_id(9); ++-------+ +| ename | ++-------+ +| | ++-------+ +1 行于数据集 (0.01 秒) + +Query OK, 0 rows affected (0.01 秒) +``` + +### 3.2、out + +out参数也需要指定,但必须是变量,不能是常量。 + +**案例:** + +根据传入的id,返回员工的姓名。 + +```mysql +create procedure emp_id1(eid int,out ename varchar(20)) +begin + select name into ename from emp where id=eid; +end; + +mysql> set @ename=''; +Query OK, 0 rows affected (0.02 秒) + +mysql> call emp_id1(3,@ename); +Query OK, 1 rows affected, 1 warnings (0.02 秒) + +mysql> select @ename; ++--------+ +| @ename | ++--------+ +| 王五 | ++--------+ +1 行于数据集 (0.02 秒) +``` + +### 3.3、inout + +如果既需要传入,同时又需要传出,则可以使用INOUT类型参数 + +**案例:** + +根据传入的id,返回员工的id和姓名。 + +```mysql +create procedure emp_id2(inout eid int,out ename varchar(20)) +begin + select id,name into eid,ename from emp where id=eid; +end; + +mysql> set @eid=3; +Query OK, 0 rows affected (0.01 秒) + +mysql> set @ename=''; +Query OK, 0 rows affected (0.01 秒) + +mysql> call emp_id2(@eid,@ename); +Query OK, 1 rows affected (0.01 秒) + +mysql> select @eid,@ename; ++------+--------+ +| @eid | @ename | ++------+--------+ +| 3 | 王五 | ++------+--------+ +1 行于数据集 (0.01 秒) +``` + +## 四、存储过程条件 + +### 4.1、if…else…end if + +```mysql +格式: +if() +then +... +else +... +end if; +``` + +**案例:** + +输入一个id,判断他是否是偶数,偶数打印对应的姓名,奇数打印id + +```mysql +create procedure emp_if_id(eid int) +begin + declare ename varchar(20) default ''; + if(eid%2=0) + then + select name into ename from emp where id=eid; + select ename; + else + select eid; + end if; +end; + +mysql> call emp_if_id(2); ++--------+ +| ename | ++--------+ +| 李四 | ++--------+ +1 行于数据集 (0.02 秒) + +Query OK, 0 rows affected (0.02 秒) + +mysql> call emp_if_id(1); ++------+ +| eid | ++------+ +| 1 | ++------+ +1 行于数据集 (0.01 秒) + +Query OK, 0 rows affected (0.01 秒) +``` + +### 4.2、if…elseif…else…endif + +```mysql +格式: +if() +then +... +elseif() +then +... +else +... +end if; +``` + +**案例:** + +给id为1,2,3的员工加薪1000元,其他员工不变 + +```mysql +create procedure emp_if_salary(eid int) +begin + declare esalary double default 0; + if(eid=1) + then + update emp set salary=salary+1000 where id=eid; + elseif(eid=2) + then + update emp set salary=salary+1000 where id=eid; + elseif(eid=3) + then + update emp set salary=salary+1000 where id=eid; + else + update emp set salary=salary where id=eid; + end if; + select salary into esalary from emp where id=eid; + select esalary; +end; + +mysql> call emp_if_salary(1); ++---------+ +| esalary | ++---------+ +| 8200 | ++---------+ +1 行于数据集 (0.03 秒) + +Query OK, 0 rows affected (0.05 秒) + +mysql> call emp_if_salary(3); ++---------+ +| esalary | ++---------+ +| 10000 | ++---------+ +1 行于数据集 (0.02 秒) + +Query OK, 0 rows affected (0.02 秒) + +mysql> call emp_if_salary(9); ++---------+ +| esalary | ++---------+ +| 0 | ++---------+ +1 行于数据集 (0.02 秒) + +Query OK, 0 rows affected (0.02 秒) +``` + +### 4.3、case + +```mysql +格式: +case() +when... then... +when... then... +else... +end case; +``` + +**案例:** + +给id为1,2,3的员工加薪1000元,其他员工不变 + +```mysql +create procedure emp_case_salary(eid int) +begin + declare esalary double default 0; + case (eid) + when 1 then update emp set salary=salary+1000 where id=eid; + when 2 then update emp set salary=salary+1000 where id=eid; + when 3 then update emp set salary=salary+1000 where id=eid; + else + update emp set salary=salary where id=eid; + end case; + select salary into esalary from emp where id=eid; + select esalary; +end; + +mysql> call emp_case_salary(3); ++---------+ +| esalary | ++---------+ +| 12000 | ++---------+ +1 行于数据集 (0.02 秒) + +Query OK, 0 rows affected (0.02 秒) +``` + +## 五、存储过程循环 + +### 5.1、while + +```mysql +格式: +while(表达式) do +...... +end while; +``` + +**案例:** + +通过id查询出员工表中的前5个员工的姓名 + +```mysql +create procedure emp_view() +begin + declare eid int default 1; + declare ename varchar(20) default ''; + while(eid<=5) do + select name into ename from emp where id=eid; + select ename; + set eid=eid+1; + end while; +end; + +mysql> call emp_view(); ++--------+ +| ename | ++--------+ +| 张三 | ++--------+ +1 行于数据集 (0.01 秒) + ++--------+ +| ename | ++--------+ +| 李四 | ++--------+ +1 行于数据集 (0.01 秒) + ++--------+ +| ename | ++--------+ +| 王五 | ++--------+ +1 行于数据集 (0.02 秒) + ++--------+ +| ename | ++--------+ +| 赵六 | ++--------+ +1 行于数据集 (0.02 秒) + ++--------+ +| ename | ++--------+ +| 吴七 | ++--------+ +1 行于数据集 (0.03 秒) + +Query OK, 0 rows affected (0.03 秒) +``` + +### 5.2、repeat + +```mysql +格式: +repeat +... +until 条件 -- 条件成立,跳出循环 +.... +end repeat; +``` + +**案例:** + +通过id查询出员工表中的前5个员工的姓名 + +```mysql +create procedure emp_view1() +begin + declare eid int default 1; + declare ename varchar(20) default ''; + repeat + select name into ename from emp where id=eid; + select ename; + set eid=eid+1; + until eid>5 + end repeat; +end; + +mysql> call emp_view1(); ++--------+ +| ename | ++--------+ +| 张三 | ++--------+ +1 行于数据集 (0.02 秒) + ++--------+ +| ename | ++--------+ +| 李四 | ++--------+ +1 行于数据集 (0.03 秒) + ++--------+ +| ename | ++--------+ +| 王五 | ++--------+ +1 行于数据集 (0.05 秒) + ++--------+ +| ename | ++--------+ +| 赵六 | ++--------+ +1 行于数据集 (0.06 秒) + ++--------+ +| ename | ++--------+ +| 吴七 | ++--------+ +1 行于数据集 (0.06 秒) + +Query OK, 0 rows affected (0.06 秒) +``` + +## 六、存储过程游标 + +游标是保存查询结果的临时区域 + +```mysql +格式: +declare 游标名 cursor for SQL语句; #声明游标 +open 游标名; #打开游标 +fetch 游标名 into 变量名; #取出游标的值 +close 游标名; #关闭游标 +``` + +**案例:** + +输出员工表中的id和姓名 + +```mysql +create procedure emp_all_view() +begin + declare eid int default 1; + declare ename varchar(20) default ''; + declare c_emp cursor for select id,name from emp; + open c_emp; + fetch c_emp into eid,ename; + select eid,ename; + close c_emp; +end; + +mysql> call emp_all_view(); ++------+--------+ +| eid | ename | ++------+--------+ +| 1 | 张三 | ++------+--------+ +1 行于数据集 (0.03 秒) + +Query OK, 0 rows affected (0.03 秒) +``` + +这样我们只取出了一条信息,这个时候我们需要循环? + +```mysql +create procedure emp_all_view1() +begin + declare eid int default 1; + declare ename varchar(20) default ''; + declare c_emp cursor for select id,name from emp; + + open c_emp; + loop + fetch c_emp into eid,ename; + select eid,ename; + end loop; + close c_emp; +end; + +mysql> call emp_all_view1(); ++------+--------+ +| eid | ename | ++------+--------+ +| 1 | 张三 | ++------+--------+ +1 行于数据集 (0.01 秒) + ++------+--------+ +| eid | ename | ++------+--------+ +| 2 | 李四 | ++------+--------+ +1 行于数据集 (0.02 秒) + ++------+--------+ +| eid | ename | ++------+--------+ +| 3 | 王五 | ++------+--------+ +1 行于数据集 (0.03 秒) + ++------+--------+ +| eid | ename | ++------+--------+ +| 4 | 赵六 | ++------+--------+ +1 行于数据集 (0.03 秒) + ++------+--------+ +| eid | ename | ++------+--------+ +| 5 | 吴七 | ++------+--------+ +1 行于数据集 (0.03 秒) + ++------+--------+ +| eid | ename | ++------+--------+ +| 6 | 王一 | ++------+--------+ +1 行于数据集 (0.04 秒) + ++------+--------+ +| eid | ename | ++------+--------+ +| 7 | 王二 | ++------+--------+ +1 行于数据集 (0.05 秒) + +No data - zero rows fetched, selected, or processed +``` + +## 七、存储过程操作 + +### 7.1、存储过程查看 + +```mysql +格式: +show procedure status [like '%字符串%']; +``` + +案例: + +```mysql +mysql> show procedure status; +mysql>show procedure status like '%emp%'; +``` + +![image20200221144121604.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603520873279.png) + +### 7.2、存储过程删除 + +```mysql +格式: +drop procedure 存储过程名; +``` + +**案例:** + +```mysql +mysql> drop procedure emp_id; +Query OK, 0 rows affected (0.02 秒) +``` + +## 八、自定义函数 + +### 8.1、自定义函数创建 + +函数与存储过程最大的区别是函数必须有返回值,否则会报错 + +```mysql +格式: +create function 函数名(参数) returns 返回类型 +begin +..... +return 返回值; +end; +``` + +**案例:** + +通过输入的id获取员工的姓名 + +```mysql +create function getName(eid int) returns varchar(20) +begin + declare ename varchar(20) default ''; + select name into ename from emp where id=eid; + return ename; +end; +``` + +![image20200221152753864.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603521032491.png) + +**注意:** + +这是我们开启了bin-log, 我们就必须指定我们的函数指定一个参数deterministic 不确定的 +no sql 没有SQL语句,当然也不会修改数据 +reads sql data 只是读取数据,当然也不会修改数据 +modifies sql data 要修改数据 +contains sql 包含了SQL语句 + +```mysql +create function getName(eid int) returns varchar(20) reads sql data +begin + declare ename varchar(20) default ''; + select name into ename from emp where id=eid; + return ename; +end; + +mysql> select getName(1); ++------------+ +| getName(1) | ++------------+ +| 张三 | ++------------+ +1 行于数据集 (0.02 秒) +``` + +### 8.2、自定义函数操作 + +#### 8.2.1、自定义函数查询 + +```mysql +格式: +show function status [like '%字符串%']; +``` + +**案例:** + +```mysql +mysql> show function status; +mysql> show function status like '%getName%'; +``` + +![image20200221154839122.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603521094762.png) + +#### 8.2.2、自定义函数删除 + +```mysql +格式: +drop function 函数名; +``` + +**案例:** + +```mysql +mysql> drop function getName; +Query OK, 0 rows affected (0.03 秒) +``` + +## 九、触发器 + +触发器与函数、存储过程一样,触发器是一种对象,它能根据对表的操作时间,触发一些动作,这些动作可以是insert,update,delete等操作。 + +### 9.1、触发器创建 + +```mysql +create trigger 触发器名字 触发时间 触发事件 on 表 for each row +begin + -- 触发器内容主体,每行用分号结尾 +end +``` + +**注意:** + +**触发时间:** + +当 SQL 指令发生时,会令行中数据发生变化,而每张表中对应的行有两种状态:**数据操作前和操作后** + +before:表中数据发生改变前的状态 + +after:表中数据发生改变后的状态 + +**触发事件:** + +触发器是针对数据发送改变才会被触发,对应的操作只有insert、update、delete + +**案例:** + +向员工表中插入数据时,记录插入的id,动作,时间 + +```mysql +#创建一个操作表 +create table emp_log( + id int primary key auto_increment, + eid int, + eaction varchar(20), + etime datetime +); + +mysql> select * from emp_log; +空的数据集 (0.01 秒) + +#创建触发器 +create trigger emp_insert after insert on emp for each row +begin + insert into emp_log values(null,NEW.id,'insert',now()); +end; + +mysql> insert into emp(id,name,gender)values(8,'王三','男'); +Query OK, 1 rows affected (0.01 秒) + +mysql> select * from emp_log; ++----+------+---------+---------------------+ +| id | eid | eaction | etime | ++----+------+---------+---------------------+ +| 1 | 8 | insert | 2020-02-21 03:12:44 | ++----+------+---------+---------------------+ +1 行于数据集 (0.02 秒) +``` + +### 9.2、触发器操作 + +#### 9.2.1、触发器查看 + +```mysql +格式: +show triggers [like '%字符串%']; +``` + +**案例:** + +```mysql +mysql> show triggers; +mysql> show triggers like '%emp%'; +``` + +![image20200221161653246.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603521169582.png) + +#### 9.2.2、触发器删除 + +```mysql +格式: +drop trigger 触发器名; +``` + +**案例:** + +```mysql +mysql> drop trigger emp_insert; +Query OK, 0 rows affected (0.02 秒) +``` + +## 十、事件 + +事件取代了原先只能由操作系统的计划任务来执行的工作,而且MySQL的事件调度器可以精确到每秒钟执行一个任务,而操作系统的计划任务只能精确到每分钟执行一次。 + +### 10.1、事件创建 + +```mysql +格式: +create event[IF NOT EXISTS] event_name -- 创建事件 +on schedule 时间和频率 -- on schedule 什么时候来执行 +[on completion [NOT] preserve] -- 调度计划执行完成后是否还保留 +[enable | disable] -- 是否开启事件,默认开启 +[comment '事件描述'] -- 事件的注释 +do event_body;-- 需要执行的SQL +``` + +**注意:** + +**单次计划任务示例** +在2019年2月1日4点执行一次 on schedule at ‘2019-02-01 04:00:00’ + +**重复计划执行** +on schedule every 1 second 每秒执行一次 +on schedule every 1 minute 每分钟执行一次 +on schedule every 1 day 没天执行一次 + +**指定时间范围的重复计划任务** +每天在20:00:00执行一次 on schedule every 1 day starts ‘2019-02-01 20:00:00’ + +**案例:** + +每5秒向emp_log,插入当前日期时间记录 + +```mysql +mysql> desc emp_log; +``` + +![image20200221171724196.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603521230682.png) + +```mysql +create event e_insert on schedule every 5 second on completion preserve +enable +comment '每5秒插入一次' +do +begin + insert into emp_log values(null,1,'insert1',now()); +end; +#do call 存储过程 +#do select 函数名 +``` + +### 10.2、事件操作 + +#### 10.2.1、查看事件 + +```mysql +格式: +show events; +``` + +**案例:** + +```mysql +mysql> show events; +``` + +![image20200221174040539.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603521251515.png) + +#### 10.2.2、启用和禁用事件 + +```mysql +格式: +alter event 事件名 disable/enable; +``` + +**禁用事件** + +```mysql +mysql> alter event e_insert disable; +Query OK, 0 rows affected (0.01 秒) + +mysql> select * from emp_log; +``` + +![image20200221174401961.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603521269958.png) + +**启用事件** + +```mysql +mysql> alter event e_insert enable; +Query OK, 0 rows affected (0.02 秒) + +mysql> select * from emp_log; +``` + +![image20200221174452171.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603521286648.png) + +#### 10.2.3、删除事件 + +```mysql +格式: +drop event 事件名; +``` + +**案例:** + +```mysql +mysql> drop event e_insert; +Query OK, 0 rows affected (0.02 秒) + +mysql> show events; +空的数据集 (0.01 秒) +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL \347\264\242\345\274\225.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL \347\264\242\345\274\225.md" new file mode 100644 index 0000000..09458c5 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL \347\264\242\345\274\225.md" @@ -0,0 +1,554 @@ +在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。 + +## 一、索引概述 + +### 1.1、什么是索引 + +索引是用于快速找出在某个列中拥有特定值的行。 + +如果没有索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多。 + +如果拥有索引,MySQL能够快速到达一个位置去搜索数据文件,而不必查看所有数据,那么将会节省很大一部分时间。 + +### 1.2、为什么建立索引 + +如果有一张产品表,记录着4W产品的信息。有一个品牌的字段记录产品的品牌,现在想要查询出这个品牌的产品。 + +如果没有索引,那么将从表中第一条记录一条条往下遍历,直到找到该条信息为止。 + +如果拥有索引,那么会将该品牌字段,通过一定的方法进行存储,好让查询该字段上的信息时,能够快速找到对应的数据,而不必在遍历4W条产品数据。 + +### 1.3、索引存储分类 + +其中MySQL中的索引的存储类型有两种:BTREE、HASH。要想知道在这二种存储类型中是如何查找的,那么就必须学会算法的知识,对于现在的我们只需要了解索引的作用及功能就好了。 + +### 1.4、索引优缺点 + +**优点:** + +所有的字段都可以被索引,也就是可以给任意字段设置索引 + +加快数据的查询速度 + +**缺点:** + +创建索引和维护索引要耗费时间 + +数据量的增加,所耗费的时间也会增加 + +索引也需要占空间,如果我们的索引量越来越大的话,那么索引文件可能达到我们数据的最大线值 + +表中数据发生变化时,索引也需要动态维护,降低数据维护效率 + +### 1.5、索引的使用原则 + +通过上面说的优点和缺点,我们可以看出,索引并不是越多越好,而是需要自己合理的使用。那么那些表应该去使用索引呢? + +**避免使用过多索引:** 经常更新的表、数据量小的表、相同值少的字段上等 + +**使用索引:** 经常查询的表、不同值较多的字段上等 + +一个表中很够创建多个索引,这些索引会被存放到一个索引文件中(专门存放索引的地方) + +## 二、索引类型 + +索引是在存储引擎中实现的,也就是说不同的存储引擎,会使用不同的索引。 + +MyISAM和InnoDB存储引擎:只支持BTREE索引, 也就是说默认使用BTREE + +MEMORY/HEAP存储引擎:支持HASH和BTREE索引 + +MySQL目前主要有以下几种索引类型: + +单列索引(普通索引、唯一索引、主键索引) + +组合索引 + +全文索引 + +空间索引 + +### 2.1、单列索引-普通索引 + +MySQL中普通索引并没有什么限制,纯粹为了查询数据更快一点。 + +可以在定义索引的字段中插入重复值和空值 + +**创建表时创建索引** + +```mysql +格式: +create table 表名( + 字段名1 字段类型1, + 字段名2 字段类型2, + ... + 字段名n 字段类型n, + index/key 索引名(字段名(长度)) +); +``` + +**案例:** + +```mysql +create table book( + bid int primary key auto_increment, + bname varchar(200), + bcbs varchar(200), + index(bname) +); + +create table book1( + bid int primary key auto_increment, + bname varchar(200), + bcbs varchar(200), + key(bname) +); + +mysql> show create table book; ++-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Table | Create Table | ++-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| book | CREATE TABLE `book` ( + `bid` int(11) NOT NULL AUTO_INCREMENT, + `bname` varchar(200) DEFAULT NULL, + `bcbs` varchar(200) DEFAULT NULL, + PRIMARY KEY (`bid`), + KEY `bname` (`bname`) +) ENGINE=InnoDB DEFAULT CHARSET=gbk | ++-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +1 行于数据集 (0.01 秒) + +mysql> show create table book1; ++-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Table | Create Table | ++-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| book1 | CREATE TABLE `book1` ( + `bid` int(11) NOT NULL AUTO_INCREMENT, + `bname` varchar(200) DEFAULT NULL, + `bcbs` varchar(200) DEFAULT NULL, + PRIMARY KEY (`bid`), + KEY `bname` (`bname`) +) ENGINE=InnoDB DEFAULT CHARSET=gbk | ++-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +1 行于数据集 (0.01 秒) +``` + +测试查询: + +```mysql +mysql> explain select * from book where bname='计算机'; +``` + +![image20200217091133154.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603519846736.png) + +**id:** select识别符。这是select的查询序列号,也就是一条语句中,该select是第几次出现。比如:在这条语句中select只出现了1次。 + +**select_type:** select查询类型。 + +simple:表示为简单的select,没有使用union或子查询,就是简单的select。 + +primary:表示最外面的select ,拥有子查询时,就会出现2次select。 + +union:表示第二层。在select 之后使用了 union + +subquery:在子查询中,第二SELECT。 + +**table:** 数据库表的名字。他们按被读取的先后顺序排列 + +**type:** 指定本数据表和其他数据表之间的关联关系。 + +**ref:** 就是连接程序无法根据键值只取得一条记录的情况。 + +**system:** 表只有一行记录(等于系统表)。 + +可能的取值有 const、eq_ref、index和all等 + +**possible_keys:** MySQL在搜索数据记录时可以选用的各个索引,该表中就只有一个索引,bname + +**key:** 实际选用的索引 + +**key_len:** 显示了mysql使用索引的长度(也就是使用的索引个数),当 key 字段的值为 null时,索引的长度就是 null。注意,key_len的值可以告诉你在联合索引中mysql会真正使用了哪些索引。 + +**ref:** 给出关联关系中另一个数据表中数据列的名字。常量(const) + +**rows:** MySQL在执行这个查询时预计会从这个数据表里读出的记录条数。 + +**extra:** 提供了与关联操作有关的信息,没有则什么都不写。 + +### 2.2、单列索引-唯一索引 + +唯一索引是索引列中的值必须是唯一的,允许为空值。在使用唯一索引时要加入记录。 + +**创建表时创建索引** + +```mysql +格式: +create table 表名( + 字段名1 字段类型1, + 字段名2 字段类型2, + ... + 字段名n 字段类型n, + unique index 索引名(字段名(长度)) +); +``` + +**案例:** + +```mysql +create table book2( + bid int, + bname varchar(200), + bcbs varchar(200), + unique index unique_bid(bid) +); + +mysql> show create table book2; ++-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Table | Create Table | ++-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| book2 | CREATE TABLE `book2` ( + `bid` int(11) DEFAULT NULL, + `bname` varchar(200) DEFAULT NULL, + `bcbs` varchar(200) DEFAULT NULL, + UNIQUE KEY `unique_bid` (`bid`) +) ENGINE=InnoDB DEFAULT CHARSET=gbk | ++-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +1 行于数据集 (0.02 秒) +``` + +测试查询 + +```mysql +mysql> explain select * from book2 where bid=1; +``` + +![image20200217092552395.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603519903738.png) + +**注意:** + +要查看其中查询使用的索引,必须先往表中插入数据,然后在查询数据,不然查找一个没有的bid值,是不会使用索引的。 + +```mysql +mysql> insert into book2 values(1,'计算机基础','清华出版社'); +Query OK, 1 rows affected (0.06 秒) +mysql> explain select * from book2 where bid=1; +``` + +![image20200217092825869.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603519921512.png) + +可以看到,通过id查询时,会使用唯一索引。并且还实验了查询一个没有的id值,则不会使用索引。 + +### 2.3、单列索引-主键索引 + +是一种特殊的唯一索引,不允许有空值。 + +**创建表时创建索引** + +```mysql +格式: +create table 表名( + 字段名1 字段类型1, + 字段名2 字段类型2, + ... + 字段名n 字段类型n, + primary key 索引名(字段名(长度)) +); +``` + +**案例:** + +```mysql +create table book3( + bid int, + bname varchar(200), + bcbs varchar(200), + primary key(bid) +); + +mysql> show create table book3; ++-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Table | Create Table | ++-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| book3 | CREATE TABLE `book3` ( + `bid` int(11) NOT NULL, + `bname` varchar(200) DEFAULT NULL, + `bcbs` varchar(200) DEFAULT NULL, + PRIMARY KEY (`bid`) +) ENGINE=InnoDB DEFAULT CHARSET=gbk | ++-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +1 行于数据集 (0.02 秒) +``` + +测试查询 + +```mysql +mysql> insert into book3 values(1,'计算机基础','清华出版社'); +Query OK, 1 rows affected (0.12 秒) + +mysql> explain select * from book3 where bid=1; +``` + +![image20200217093610423.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603519985050.png) + +主键索引就是:我们以前声明的主键约束,就是一个主键索引。 + +### 2.4、组合索引 + +在表中的多个字段组合上创建的索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用,使用组合索引时遵循最左前缀集合。 + +**创建表时创建索引** + +```mysql +格式: +create table 表名( + 字段名1 字段类型1, + 字段名2 字段类型2, + ... + 字段名n 字段类型n, + index 索引名(字段名1(长度),字段名2(长度),...字段名n(长度)) +); +``` + +**案例:** + +```mysql +create table stu1( + sid int, + sname varchar(20), + age int, + sex varchar(2), + index index_sid_sname_age(sid,sname,age) +); + +mysql> show create table stu1; ++-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Table | Create Table | ++-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| stu1 | CREATE TABLE `stu1` ( + `sid` int(11) DEFAULT NULL, + `sname` varchar(20) DEFAULT NULL, + `age` int(11) DEFAULT NULL, + `sex` varchar(2) DEFAULT NULL, + KEY `index_sid_sname_age` (`sid`,`sname`,`age`) +) ENGINE=InnoDB DEFAULT CHARSET=gbk | ++-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +1 行于数据集 (0.01 秒) +``` + +**注意:** + +最左前缀 + +组合索引就是遵从了最左前缀,利用索引中最左边的列集来匹配行,这样的列集称为最左前缀。 + +例如,这里由sid、sname和age 3个字段构成的索引,索引行中就按sid/sname/age的顺序存放,索引可以索引下面字段组合(sid,sname,age)、(sid,age)、(sid,sname)或者(sid)。如果要查询的字段不构成索引最左面的前缀,那么就不会是用索引,比如,age或者(sname,age)组合就不会使用索引查询 + +测试查询 + +```mysql +mysql> explain select * from stu1 where sid=1 and sname="job"; +``` + +![image20200217095020128.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603520015989.png) + +```mysql +mysql> explain select * from stu1 where age=17 and sname="job"; +``` + +![image20200217095150193.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603520032028.png) + +### 2.5、全文索引 + +全文索引,只有在MyISAM引擎上才能使用,只能在CHAR,VARCHAR,TEXT类型字段上使用全文索引。 + +全文索引,就是在一堆文字中,通过其中的某个关键字等,就能找到该字段所属的记录行。 + +比如:有学员的备注信息里有"成绩很好,是一个好学生" 通过“好学生”,可能就可以找到该条记录。这里说的是可能,因为全文索引的使用涉及了很多细节。 + +**创建表时创建索引** + +```mysql +格式: +create table 表名( + 字段名1 字段类型1, + 字段名2 字段类型2, + ... + 字段名n 字段类型n, + fulltext index 索引名(字段名(长度)) +)ENGINE=MyISAM; +``` + +**案例:** + +```mysql +create table stu2( + sid int, + sname varchar(20), + age int, + sex varchar(2), + info text, + fulltext index full_info(info) +)ENGINE=MyISAM; + +mysql> show create table stu2; ++-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Table | Create Table | ++-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| stu2 | CREATE TABLE `stu2` ( + `sid` int(11) DEFAULT NULL, + `sname` varchar(20) DEFAULT NULL, + `age` int(11) DEFAULT NULL, + `sex` varchar(2) DEFAULT NULL, + `info` text, + FULLTEXT KEY `full_info` (`info`) +) ENGINE=MyISAM DEFAULT CHARSET=gbk | ++-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +1 行于数据集 (0.02 秒) +``` + +测试全文索引 + +```mysql +mysql> explain select * from stu2 where match(info) against('好学生'); +``` + +![image20200217100917184.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603520068046.png) + +**注意:** + +在使用全文搜索时,限制较多: + +需要使用MATCH函数 + +只能通过MyISAM引擎 + +只能在CHAR,VARCHAR,TEXT上设置全文索引 + +搜索的关键字默认至少要4个字符,搜索的关键字太短就会被忽略掉 + +### 2.6、空间索引 + +空间索引是对空间数据类型的字段建立的索引。 + +MySQL中的空间数据类型有四种,GEOMETRY(几何类型)、POINT(点)、LINESTRING(线)、POLYGON(面)。在创建空间索引时,也要使用MyISAM引擎,创建空间索引的列也不能为null。 + +**创建表时创建索引** + +```mysql +格式: +create table 表名( + 字段名1 字段类型1, + 字段名2 字段类型2, + ... + 字段名n 字段类型n, + spatial index 索引名(字段名(长度)) +)ENGINE = MyISAM; +``` + +**案例:** + +```mysql +create table t( + g geometry not null, + spatial index s_g(g) +)ENGINE = MyISAM; + +mysql> show create table t; ++-------+------------------------------------------------------------------------------------------------------------+ +| Table | Create Table | ++-------+------------------------------------------------------------------------------------------------------------+ +| t | CREATE TABLE `t` ( + `g` geometry NOT NULL, + SPATIAL KEY `s_g` (`g`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 | ++-------+------------------------------------------------------------------------------------------------------------+ +1 行于数据集 (0.01 秒) +``` + +## 三、索引操作 + +### 3.1、创建索引 + +```mysql +格式: +alter table 数据表名 add [unique|fulltext|spatial] [index|key] [索引名][字段名][asc|desc] +``` + +查看表中索引 + +```mysql +格式: +show index from 数据库表名; +``` + +**案例:** + +```mysql +mysql> show index from book2; +``` + +![image20200217104030561.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603520109258.png) + +Table:创建索引的表 + +Non_unique:表示索引非唯一,1代表 非唯一索引, 0代表 唯一索引,意思就是该索引是不是唯一索引 + +Key_name:索引名称 + +Seq_in_index 表示该字段在索引中的位置,单列索引的话该值为1,组合索引为每个字段在索引定义中的顺序(这个只需要知道单列索引该值就为1,组合索引为别的) + +Column_name:表示定义索引的列字段 + +Sub_part:表示索引的长度 + +Null:表示该字段是否能为空值 + +Index_type:表示索引类型 + +我们继续为book2加一个索引 + +```mysql +mysql> alter table book2 add index i_bname(bname); +Query OK, 0 rows affected (0.07 秒) + +mysql> show index from book2; +``` + +![image20200217104438329.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603520139013.png) + +### 3.2、删除索引 + +```mysql +格式一: +alter table 数据库表名 drop index 索引名; +``` + +**案例:** + +删除book2中的i_bname索引 + +```mysql +mysql> alter table book2 drop index i_bname; +Query OK, 0 rows affected (0.02 秒) + +mysql> show index from book2; +``` + +![image20200217112753060.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603520161317.png) + +```mysql +格式二: +drop index 索引名 on 数据库表名; +``` + +**案例:** + +删除book2中的unique_bid索引 + +```mysql +mysql> drop index unique_bid on book2; +Query OK, 0 rows affected (0.12 秒) + +mysql> show index from book2; +空的数据集 (0.01 秒) +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\344\272\213\345\212\241.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\344\272\213\345\212\241.md" new file mode 100644 index 0000000..abb217e --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\344\272\213\345\212\241.md" @@ -0,0 +1,869 @@ +事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的执行所引起,并用形如begin transaction和end transaction语句(或函数调用)来界定。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。 + +## 一、事务概述 + +### 1.1、什么是事务 + +MySQL 事务主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你既需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务! + +事务是一个事件处理的完整的过程。比如:存款、取款、转帐等操作都可以称之为一个事务。 + +### 1.2、事务的应用场景 + +我们想完成一次转帐业务,那么他会多次去访问我们的数据库。转帐实上就是从一个帐户上扣钱,在往一个帐户上加钱。这样我们执行了二次sql,如果其中一个sql失败,那么整个业务就没有执行成功。所有的sql都需要回滚,整个业务失败。 + +**数据准备** + +```mysql +#创建数据表 +create table yh( +id int primary key auto_increment, +name varchar(20), +money double +); + +-- 添加数据 +insert into yh(name,money)values('张三', 1000),('李四', 1000); +``` + +**案例:** + +模拟张三给李四转500元钱 + +分析: + +先从张三的帐户减出500,在往李四的帐户加入500元 + +```mysql +mysql> update yh set money=money-500 where name='张三'; +Query OK, 1 rows affected (0.02 秒) + +mysql> update yh set money=money+500 where name='李四'; +Query OK, 1 rows affected (0.04 秒) + +mysql> select * from yh; ++----+--------+-------+ +| id | name | money | ++----+--------+-------+ +| 1 | 张三 | 500 | +| 2 | 李四 | 1500 | ++----+--------+-------+ +2 行于数据集 (0.04 秒) +``` + +**如果转帐时出现问题:** + +当张三账号上-500 元,服务器崩溃了。李四的账号并没有+500 元,数据就出现问题了。 + +因为他们是一个整体的业务,所以我们需要保证其中一条 SQL 语句出现问题,整个转账就算失败。只有两条 SQL 都成功了转账才算成功。这个时候就需要用到事务。 + +### 1.3、事务提交方式 + +mysql中有两种事务提交方式: + +手动提交 + +自动提交 + +## 二、事务手动提交 + +### 2.1、手动提交的过程 + +![image20200215230939254.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603518979561.png) + +事务执行成功的过程:开启事务->执行多条件SQL语句->成功->事务提交 + +事务执行失败的过程:开启事务->执行多条件SQL语句->失败->事务回滚 + +### 2.2、语法格式 + +```mysql +格式: +start transaction; #开启事务 +commit; #提交事务 +rollback; #回滚事务 +``` + +**案例:** + +事务的成功提交:模拟张三给李四转 500 元钱(成功) 目前数据库数据如下: + +![image20200215232438482.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603518996760.png) + +```mysql +#开启事务 +mysql> start transaction; +Query OK, 0 rows affected (0.01 秒) +#执行从张三帐户扣出500元 +mysql> update yh set money=money-500 where name='张三'; +Query OK, 1 rows affected (0.01 秒) +#执行往李四帐户加入500元 +mysql> update yh set money=money+500 where name='李四'; +Query OK, 1 rows affected (0.01 秒) +#提交事务 +mysql> commit; +Query OK, 0 rows affected (0.08 秒) +#查看帐户 +mysql> select * from yh; ++----+--------+-------+ +| id | name | money | ++----+--------+-------+ +| 1 | 张三 | 0 | +| 2 | 李四 | 2000 | ++----+--------+-------+ +2 行于数据集 (0.01 秒) +``` + +事务回滚:模拟李四给张三转 500 元钱(失败) 目前数据库数据如下: + +![image20200215232946263.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603519029171.png) + +```mysql +#开启事务 +mysql> start transaction; +Query OK, 0 rows affected (0.02 秒) +#执行从李四帐户扣出500元 +mysql> update yh set money=money-500 where name='李四'; +Query OK, 1 rows affected (0.01 秒) +#执行往张三帐户加入500元,但是加了600 +mysql> update yh set money=money+600 where name='张三'; +Query OK, 1 rows affected (0.01 秒) +#事务回滚 +mysql> rollback; +Query OK, 0 rows affected (0.02 秒) +#查看帐户 +mysql> select * from yh; ++----+--------+-------+ +| id | name | money | ++----+--------+-------+ +| 1 | 张三 | 0 | +| 2 | 李四 | 2000 | ++----+--------+-------+ +2 行于数据集 (0.01 秒) +``` + +## 三、事务自动提交 + +MySQL 默认每一条 DML(增删改)语句都是一个单独的事务,每条语句都会自动开启一个事务,语句执行完毕自动提交事务,MySQL 默认开始自动提交事务。 + +如: + +事务开始->update/delete/insert into->事务提交 + +### 3.1、自动提交事务 + +**案例:** + +自动事务提交:往张三的帐户里存入1000元,目前数据库数据如下: + +![image20200215233931488.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603519053659.png) + +```mysql +mysql> update yh set money=money+1000 where name='张三'; +Query OK, 1 rows affected (0.05 秒) + +mysql> select * from yh; ++----+--------+-------+ +| id | name | money | ++----+--------+-------+ +| 1 | 张三 | 1000 | +| 2 | 李四 | 2000 | ++----+--------+-------+ +2 行于数据集 (0.01 秒) +``` + +### 3.2、取消自动提交 + +查看 MySQL 是否开启自动提交事务 + +```mysql +格式: +select @@autocommit; +``` + +**注意:** + +@@表示全局变量,1 表示开启,0 表示关闭 + +取消自动提交事务 + +```mysql +格式: +set autocommit=0; +``` + +**案例:** + +```mysql +mysql> select @@autocommit; ++--------------+ +| @@autocommit | ++--------------+ +| 1 | ++--------------+ +1 行于数据集 (0.01 秒) + +mysql> set autocommit=0; +Query OK, 0 rows affected (0.01 秒) + +mysql> select @@autocommit; ++--------------+ +| @@autocommit | ++--------------+ +| 0 | ++--------------+ +1 行于数据集 (0.01 秒) +``` + +从李四的帐户取出1000元,目前数据库数据如下: + +![image20200215234548334.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603519068528.png) + +**注意:** + +要在窗口A、窗口B中验证 + +```mysql +#窗口A +mysql> update yh set money=money-1000 where name='李四'; +Query OK, 1 rows affected (0.01 秒) + +mysql> select * from yh; ++----+--------+-------+ +| id | name | money | ++----+--------+-------+ +| 1 | 张三 | 1000 | +| 2 | 李四 | 1000 | ++----+--------+-------+ +2 行于数据集 (0.01 秒) + +#在窗口B中查询银行帐户(第一次验证) + +#提交 +mysql> commit; +Query OK, 0 rows affected (0.10 秒) + +#在窗口B中查询银行帐户(第二次验证) +``` + +在打开一个窗口 + +```mysql +#窗口B +mysql> select * from yh; ++----+--------+-------+ +| id | name | money | ++----+--------+-------+ +| 1 | 张三 | 1000 | +| 2 | 李四 | 2000 | ++----+--------+-------+ +2 行于数据集 (0.01 秒) + +mysql> select * from yh; ++----+--------+-------+ +| id | name | money | ++----+--------+-------+ +| 1 | 张三 | 1000 | +| 2 | 李四 | 1000 | ++----+--------+-------+ +2 行于数据集 (0.02 秒) +``` + +## 4、事务原理 + +一个事务会涉及到大量的cpu计算和IO操作,这些操作被打包成一个执行单元,要么同时都完成,要么同时都不完成。 + +### 4.1、自动提交原理图 + +如果没有显示启动事务,数据库会根据autocommit的值.默认每条sql操作都会自动提交。 + +![image20200218000643813.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603519086079.png) + +### 4.2、手动提交原理图 + +如果开启了事务,其中有任何一条语句因为崩溃或者其它原因无法执行,那么该组中所有的sql语句都不会执行。 + +![image20200218001646389.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603519101214.png) + +### 4.3、事务提交步骤 + +客户端连接上服务器端,创建连接同时创建当前用户的临时事务日志文件。 + +开启事务,改变原有的操作机制(所有的操作都会先写入临时日志文件)。 + +写入SQL,接收并执行SQL,所有的SQL操作都会写入临时文件;返回数据时,从数据库表拿取数据,但要通过临时日志文件加工在返回。 + +事务的提交或回滚,提交:同步临时日志文件中的SQL操作结果到数据库表;回滚:清除临时日志文件 + +## 5、事务回滚 + +我们可以在mysql事务处理过程中定义保存点(SAVEPOINT),然后回滚到指定的保存点前的状态。 + +定义保存点,以及回滚到指定保存点前状态的语法如下: + +```mysql +格式: +savepoint 保存点名; #定义保存点 +rollback to savepoint 保存点名; #回滚到指定保存点 +或 +rollback to 保存点名; +``` + +**数据表准备** + +```mysql +#创建一个管理员表 +create table manager( + id int primary key auto_increment, + uname varchar(20), + pword varchar(20) +); + +#插入数据 +insert into manager(uname,pword) values('zhangsan','zhangsan'),('lisi','lisi'); + +#插入数据 +insert into manager(uname,pword) values('wangwu','wangwu'),('zhaoliu','zhaoliu'); +``` + +**案例:** + +开启事务 + +向表中插入二条件记录 + +设置保存点,保存点的名字为:insert_point + +向表中插入二条件记录 + +回到保存点:insert_point + +```mysql +mysql> start transaction; +Query OK, 0 rows affected (0.01 秒) + +mysql> insert into manager(uname,pword) values('zhangsan','zhangsan'),('lisi','lisi'); +Query OK, 2 rows affected (0.01 秒) + +mysql> select * from manager; ++----+----------+----------+ +| id | uname | pword | ++----+----------+----------+ +| 1 | zhangsan | zhangsan | +| 2 | lisi | lisi | ++----+----------+----------+ +2 行于数据集 (0.01 秒) + +mysql> savepoint insert_point; +Query OK, 0 rows affected (0.01 秒) + +mysql> insert into manager(uname,pword) values('wangwu','wangwu'),('zhaoliu','zhaoliu'); +Query OK, 2 rows affected (0.01 秒) + +mysql> select * from manager; ++----+----------+----------+ +| id | uname | pword | ++----+----------+----------+ +| 1 | zhangsan | zhangsan | +| 2 | lisi | lisi | +| 3 | wangwu | wangwu | +| 4 | zhaoliu | zhaoliu | ++----+----------+----------+ +4 行于数据集 (0.01 秒) + +mysql> rollback to savepoint insert_point; +Query OK, 0 rows affected (0.00 秒) + +mysql> select * from manager; ++----+----------+----------+ +| id | uname | pword | ++----+----------+----------+ +| 1 | zhangsan | zhangsan | +| 2 | lisi | lisi | ++----+----------+----------+ +2 行于数据集 (0.01 秒) +``` + +**注意:** + +设置保存点可以让我们在失败的时候回到保存点,而不是回到事务开启的时候。 + +## 六、事务隔离级别 + +### 6.1、事务特性 + +**原子性(Atomicity):** 事务内的操作要嘛全部完成,要嘛全部回滚。 + +**一致性(Consistency):** 事务执行的前后都是合法的数据状态,不会违反任何的数据完整性。 + +**隔离性(Isolation):** 主要是事务之间的相互的影响,根据隔离有不同的影响效果。 + +**持久性(Durability):** 事务一旦提交,就会体现在数据库上,不能回滚。 + +### 6.2、事务的并发问题 + +**脏读:** 比如事务A执行的过程中,读到了事务B未提交的内容。 + +**不可重复读:** 指一个事务在前后两次查询的结果不一致。 + +**幻读:** 幻读是指前后两次相同条件下的查询,后一次查询读到了前一次查询没有的行数据。 + +### 6.3、事务的隔离级别 + +![image20200218012806058.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603519132024.png) + +注意: + +隔离级别越高,性能越差,安全性越高。 + +### 6.4、事务隔离命令 + +查看隔离级别 + +```mysql +#格式: +select @@transaction_isolation; + +mysql> select @@transaction_isolation; ++-------------------------+ +| @@transaction_isolation | ++-------------------------+ +| REPEATABLE-READ | ++-------------------------+ +1 行于数据集 (0.01 秒) +``` + +设置隔离级别 + +```mysql +#格式: +set global transaction_isolation=级别字符串 + +mysql> set global transaction_isolation='read-committed'; +Query OK, 0 rows affected (0.01 秒) +``` + +重启客户端,查看 + +```mysql +mysql> select @@transaction_isolation; ++-------------------------+ +| @@transaction_isolation | ++-------------------------+ +| READ-COMMITTED | ++-------------------------+ +1 行于数据集 (0.02 秒) +``` + +## 7、脏读 + +### 7.1、设置隔离级别 + +```mysql +mysql> set global transaction_isolation='read-uncommitted'; +Query OK, 0 rows affected (0.00 秒) + +#重启窗口查看隔离级别 +mysql> select @@transaction_isolation; ++-------------------------+ +| @@transaction_isolation | ++-------------------------+ +| READ-UNCOMMITTED | ++-------------------------+ +1 行于数据集 (0.02 秒) +``` + +### 7.2、脏读 + +恢复yh表中的数据为: + +![image20200218104028518.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603519178063.png) + +打开A,B两个窗口,分别开启事务: + +```mysql +mysql> start transaction; +Query OK, 0 rows affected (0.00 秒) +``` + +在A窗口里执行,转帐操作 + +```mysql +mysql> update yh set money=money-500 where id=1; +Query OK, 1 rows affected (0.00 秒) + +mysql> update yh set money=money+500 where id=2; +Query OK, 1 rows affected (0.00 秒) +``` + +在B窗口里执行,查看帐户,钱已经到帐 + +```mysql +mysql> select * from yh; ++----+--------+-------+ +| id | name | money | ++----+--------+-------+ +| 1 | 张三 | 500 | +| 2 | 李四 | 1500 | ++----+--------+-------+ +2 行于数据集 (0.01 秒) +``` + +在A窗口里执行回滚 + +```mysql +mysql> rollback; +Query OK, 0 rows affected (0.05 秒) +``` + +在B窗口里执行,查看帐户,钱不见了 + +```mysql +mysql> select * from yh; ++----+--------+-------+ +| id | name | money | ++----+--------+-------+ +| 1 | 张三 | 1000 | +| 2 | 李四 | 1000 | ++----+--------+-------+ +2 行于数据集 (0.01 秒) +``` + +脏读是比较危险的事情,如果张三在李四那里买了一个汽球花了500元,那么张三转帐给李四后,李四发货给张三,张三收到货物后把事务回滚,这样李四再也没有看到钱。 + +**要解决脏读的问题我们要提高隔离级别?** + +```mysql +mysql> set global transaction_isolation='read-committed'; +Query OK, 0 rows affected (0.00 秒) + +#重启窗口查看隔离级别 +mysql> select @@transaction_isolation; ++-------------------------+ +| @@transaction_isolation | ++-------------------------+ +| READ-COMMITTED | ++-------------------------+ +1 行于数据集 (0.02 秒) +``` + +**案例:** + +恢复yh表中的数据为: + +![image20200218104028518.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603519359501.png) + +打开A,B两个窗口,分别开启事务: + +```mysql +mysql> start transaction; +Query OK, 0 rows affected (0.00 秒) +``` + +在A窗口里执行,转帐操作 + +```mysql +mysql> update yh set money=money-500 where id=1; +Query OK, 1 rows affected (0.00 秒) + +mysql> update yh set money=money+500 where id=2; +Query OK, 1 rows affected (0.00 秒) +``` + +在B窗口里执行,查看帐户,帐户没有变化 + +```mysql +mysql> select * from yh; ++----+--------+-------+ +| id | name | money | ++----+--------+-------+ +| 1 | 张三 | 1000 | +| 2 | 李四 | 1000 | ++----+--------+-------+ +2 行于数据集 (0.01 秒) +``` + +在A窗口里执行,事务提交 + +```mysql +mysql> commit; +Query OK, 0 rows affected (0.05 秒) +``` + +在B窗口里执行,查看帐户,钱到帐了 + +```mysql +mysql> select * from yh; ++----+--------+-------+ +| id | name | money | ++----+--------+-------+ +| 1 | 张三 | 500 | +| 2 | 李四 | 1500 | ++----+--------+-------+ +2 行于数据集 (0.01 秒) +``` + +这样我们就解决了脏读的问题,提高我们的隔离级别。 + +## 八、不可重复读 + +### 8.1、设置隔离级别 + +```mysql +mysql> set global transaction_isolation='read-committed'; +Query OK, 0 rows affected (0.00 秒) + +#重启窗口查看隔离级别 +mysql> select @@transaction_isolation; ++-------------------------+ +| @@transaction_isolation | ++-------------------------+ +| READ-COMMITTED | ++-------------------------+ +1 行于数据集 (0.02 秒) +``` + +### 8.2、不可重复读 + +恢复yh表中的数据为: + +![image20200218104028518.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603519359501.png) + +打开A,B两个窗口,分别开启事务: + +```mysql +mysql> start transaction; +Query OK, 0 rows affected (0.00 秒) +``` + +在B窗口里执行,查看帐户 + +```mysql +mysql> select * from yh; ++----+--------+-------+ +| id | name | money | ++----+--------+-------+ +| 1 | 张三 | 1000 | +| 2 | 李四 | 1000 | ++----+--------+-------+ +2 行于数据集 (0.01 秒) +``` + +在A窗口里更新数据,并提交事务 + +```mysql +mysql> update yh set money=money+500 where id=1; +Query OK, 1 rows affected (0.00 秒) + +mysql> commit; +Query OK, 0 rows affected (0.01 秒) +``` + +在B窗口里在次执行,查看帐户 + +```mysql +mysql> select * from yh; ++----+--------+-------+ +| id | name | money | ++----+--------+-------+ +| 1 | 张三 | 1500 | +| 2 | 李四 | 1000 | ++----+--------+-------+ +2 行于数据集 (0.02 秒) +``` + +看着这二个数据本身觉得没有什么问题,如果这二次的数据分别是显示在银行职员的显示器上和发送给客户,那么银行的工作人员都不知道以什么为准了。 + +**要解决不可重复读的问题我们要提高隔离级别?** + +```mysql +mysql> set global transaction_isolation='repeatable-read'; +Query OK, 0 rows affected (0.00 秒) + +#重启窗口查看隔离级别 +mysql> select @@transaction_isolation; ++-------------------------+ +| @@transaction_isolation | ++-------------------------+ +| REPEATABLE-READ | ++-------------------------+ +1 行于数据集 (0.01 秒) +``` + +**案例:** + +恢复yh表中的数据为: + +![image20200218104028518.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603519359501.png) + +打开A,B两个窗口,分别开启事务: + +```mysql +mysql> start transaction; +Query OK, 0 rows affected (0.00 秒) +``` + +在B窗口里执行,查看帐户 + +```mysql +mysql> select * from yh; ++----+--------+-------+ +| id | name | money | ++----+--------+-------+ +| 1 | 张三 | 1000 | +| 2 | 李四 | 1000 | ++----+--------+-------+ +2 行于数据集 (0.01 秒) +``` + +在A窗口里更新数据,并提交事务 + +```mysql +mysql> update yh set money=money+500 where id=1; +Query OK, 1 rows affected (0.00 秒) + +mysql> commit; +Query OK, 0 rows affected (0.01 秒) +``` + +在B窗口里在次执行,查看帐户 + +```mysql +mysql> select * from yh; ++----+--------+-------+ +| id | name | money | ++----+--------+-------+ +| 1 | 张三 | 1000 | +| 2 | 李四 | 1000 | ++----+--------+-------+ +2 行于数据集 (0.02 秒) +``` + +这样我们就解决了不可重复读的问题,提高我们的隔离级别。 + +## 九、幻读 + +### 9.1、设置隔离级别 + +```mysql +mysql> set global transaction_isolation='repeatable-read'; +Query OK, 0 rows affected (0.00 秒) + +#重启窗口查看隔离级别 +mysql> select @@transaction_isolation; ++-------------------------+ +| @@transaction_isolation | ++-------------------------+ +| REPEATABLE-READ | ++-------------------------+ +1 行于数据集 (0.01 秒) +``` + +### 9.2、幻读 + +恢复yh表中的数据为: + +![image20200218104028518.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603519359501.png) + +打开A,B两个窗口,分别开启事务: + +```mysql +mysql> start transaction; +Query OK, 0 rows affected (0.00 秒) +``` + +在A窗口里执行,查询ID为3的帐户 + +```mysql +mysql> select * from yh where id=3; +空的数据集 (0.00 秒) +``` + +在B窗口里执行,查询ID为3的帐户,没有就添加记录,并提交事务 + +```mysql +mysql> select * from yh where id=3; +空的数据集 (0.00 秒) + +mysql> insert into yh values(3,'王五',1000); +Query OK, 1 rows affected (0.01 秒) + +mysql> select * from yh; ++----+--------+-------+ +| id | name | money | ++----+--------+-------+ +| 1 | 张三 | 1500 | +| 2 | 李四 | 1000 | +| 3 | 王五 | 1000 | ++----+--------+-------+ +3 行于数据集 (0.01 秒) + +mysql> commit; +Query OK, 0 rows affected (0.09 秒) +``` + +在A窗口里执行,添加id为3的帐户 + +```mysql +mysql> insert into yh values(3,'王五',1000); +Duplicate entry '3' for key 'PRIMARY' + +mysql> select * from yh; ++----+--------+-------+ +| id | name | money | ++----+--------+-------+ +| 1 | 张三 | 1500 | +| 2 | 李四 | 1000 | ++----+--------+-------+ +2 行于数据集 (0.01 秒) +``` + +我们在A窗口中看不到新加人员的王五信息,但是我们想自己增加王五的信息也无加入的我们的数据库,这就是幻读。 + +**要解决幻读的问题我们要提高隔离级别?** + +```mysql +mysql> set global transaction_isolation='serializable'; +Query OK, 0 rows affected (0.00 秒) + +#重启窗口查看隔离级别 +mysql> select @@transaction_isolation; ++-------------------------+ +| @@transaction_isolation | ++-------------------------+ +| SERIALIZABLE | ++-------------------------+ +1 行于数据集 (0.01 秒) +``` + +**案例:** + +恢复yh表中的数据为: + +![image20200218104028518.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603519359501.png) + +打开A,B两个窗口,分别开启事务: + +```mysql +mysql> start transaction; +Query OK, 0 rows affected (0.00 秒) +``` + +在A窗口里执行,查询ID为3的帐户 + +```mysql +mysql> select * from yh where id=3; +空的数据集 (0.00 秒) +``` + +在B窗口里执行,查询ID为3的帐户,没有就添加记录,并提交事务 + +```mysql +mysql> select * from yh where id=3; +空的数据集 (0.00 秒) + +mysql> insert into yh values(3,'王五',1000); +| #光标闪烁,不能执行下去 +``` + +这样我们就解决了幻读的问题,提高我们了融离级别。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\345\244\232\344\270\273\346\250\241\345\236\213\345\256\236\346\210\230.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\345\244\232\344\270\273\346\250\241\345\236\213\345\256\236\346\210\230.md" new file mode 100644 index 0000000..11d1343 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\345\244\232\344\270\273\346\250\241\345\236\213\345\256\236\346\210\230.md" @@ -0,0 +1,102 @@ +MySQL AB解决了数据备份的问题,但是当A由于某些原因宕机后,WEB服务器就没有办法在往数据库写或者读写了。线上业务中断了,完了,出事故了。这该怎么办呢? + +本节课主要给大家讲解如果处理因为MySQL主服务器宕机造成的业务中断问题,保障MySQL业务高可用。 + +## 一、实验拓扑图 + +![mysql_aa拓扑图.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603973198714.png) + +## 二、架构原理 + +1、MySQL互为主备,保障多台MySQL的数据强一致性。 + +2、VIP漂移,任何一台宕机都不影响数据读写 + +3、宕机服务器修复,自动同步故障间的缺失数据 + +## 三、实验准备 + +- 机器三台并设置好IP地址 +- 关闭防火墙、selinux +- 时间同步 +- node1、node2安装mysql +- manage01部署lamp +- 上线业务并进行容灾测试 +- 知识储备点:MySQL AB复制 + +## 四、node1、node2互为主备 + +``` +1、确认binlog开启 +2、设置server-id +3、创建同步mysql用户 +4、设置同步 + +#以node2为例 +#创建用户 +mysql> create user sko2 identified by "123456"; +Query OK, 0 rows affected (0.00 sec) + +mysql> grant replication slave on *.* to sko2; +Query OK, 0 rows affected (0.00 sec) + +mysql> flush privileges; +Query OK, 0 rows affected (0.00 sec) + +#开始同步 +#同步前 主服务器生成一个新binlog开始同步,防止之前的binlog中语句无法执行 +mysql> stop slave; +Query OK, 0 rows affected, 1 warning (0.00 sec) + +mysql> change master to +-> master_host='192.168.98.202', +-> master_user='sko', +-> master_password='98989', +-> master_log_file='binlog.000002', +-> master_log_pos=xxx; +Query OK, 0 rows affected, 3 warnings (0.01 sec) + +mysql> start slave; +Query OK, 0 rows affected (0.00 sec) +``` + +## 五、manage01-lamp + +``` +# 部署lamp业务环境 +[root@manage01 ~]# yum -y install httpd php php-mysql +[root@manage01 ~]# systemctl start httpd +[root@manage01 ~]# systemctl start php-fpm +[root@manage01 ~]# vim /var/www/html/phpinfo.php + +#测试 + +``` + +## 六、配置MySQL高可用 + +1、模拟故障,将配有VIP的mysql宕机,手动回收VIP并配给另外一个运行的mysql服务器,查看业务是否正常。 + +2、恢复宕机mysql,查看宕机过程中的产生的数据是否能够从另外一个运行的mysql中恢复回来。 + +``` +参考nginx高可用部署 +https://www.zutuanxue.com/home/4/58_388 +``` + +## 七、上线业务测试 + +a、拷贝站点 + +``` +[root@manage01 ~]# cp -r 测试站点html/* /var/www/html/ +``` + +b、安装站点 +打开浏览器输入 http://IP/install.php + +c、根据站点提示输入数据并查询,查询数据库数据同步情况 + +d、停止主mysql继续测试业务,确保正常工作 + +e、启动宕机mysql,确保停机期间的数据同步 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\345\255\220\346\237\245\350\257\242.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\345\255\220\346\237\245\350\257\242.md" new file mode 100644 index 0000000..1a8bc3b --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\345\255\220\346\237\245\350\257\242.md" @@ -0,0 +1,242 @@ +在SQL语言中,一个SELECT-FROM-WHERE语句称为一个查询块。当获得一个查询的答案需要多个步骤的操作,首先必须创建一个查询来确定用户不知道但包含在数据库中的值,将一个查询块嵌套在另一个查询块的WHERE字句或HAVING短语的条件中查询块称为子查询或内层查询。上层的查询块曾为父查询或外层查询。子查询的结果作为输入传递回“父查询”或“外部查询”。父查询将这个值结合到计算中,以便确定最后的输出。 + +## 一、子查询概述 + +### 1.1、什么是子查询 + +子查询是一种常用计算机语言sql中select语言中嵌套查询下层的程序模块。当一个查询是另一个查询的条件时,称之为子查询。 + +**如:** + +查询渠道部有那些员工 + +```mysql +#第一步,查询出'渠道部'的id +mysql> select id from dept where name='渠道部'; ++----+ +| id | ++----+ +| 2 | ++----+ +1 行于数据集 (0.02 秒) +#第二步,通过查询出的‘渠道部’的id,在查询渠道部的员工信息 +mysql> select * from emp where dept_id=2; ++----+--------+--------+--------+------------+---------+ +| id | name | gender | salary | join_date | dept_id | ++----+--------+--------+--------+------------+---------+ +| 2 | 李四 | 男 | 3600 | 2010-12-02 | 2 | +| 3 | 王五 | 男 | 9000 | 2008-08-08 | 2 | ++----+--------+--------+--------+------------+---------+ +2 行于数据集 (0.01 秒) +``` + +子查询方式 + +```mysql +mysql> select * from emp where dept_id=(select id from dept where name='渠道部'); ++----+--------+--------+--------+------------+---------+ +| id | name | gender | salary | join_date | dept_id | ++----+--------+--------+--------+------------+---------+ +| 2 | 李四 | 男 | 3600 | 2010-12-02 | 2 | +| 3 | 王五 | 男 | 9000 | 2008-08-08 | 2 | ++----+--------+--------+--------+------------+---------+ +2 行于数据集 (0.03 秒) +``` + +### 1.2、子查询特点 + +一个查询的结果做为另一个查询的条件 + +有查询的嵌套,内部的查询称为子查询 + +子查询要使用括号 + +### 1.3、子查询结果的三种情况 + +单行单列 + +![image20200215215222589.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603519226794.png) + +多行单列 + +![image20200215215408848.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603519241295.png) + +多行多列 + +![image20200215215431152.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603519252162.png) + +## 二、单行单列查询 + +子查询结果只要是单行单列,肯定在 WHERE 后面作为条件,父查询使用:比较运算符,如:> 、<、<>、=、>=、<=等 + +```mysql +格式: +select */字段列表 from 数据库表名 where 字段名=(子查询); +``` + +**案例:** + +查询工资最高的员工信息 + +分析: + +先找出最高工资,在查找员工信息 + +```mysql +mysql> select max(salary) from emp; ++-------------+ +| max(salary) | ++-------------+ +| 9000 | ++-------------+ +1 行于数据集 (0.01 秒) + +mysql> select * from emp where salary=(select max(salary) from emp); ++----+--------+--------+--------+------------+---------+ +| id | name | gender | salary | join_date | dept_id | ++----+--------+--------+--------+------------+---------+ +| 3 | 王五 | 男 | 9000 | 2008-08-08 | 2 | ++----+--------+--------+--------+------------+---------+ +1 行于数据集 (0.01 秒) +``` + +查询工资小于平均工资的员工信息 + +分析: + +先算出员工的平均工资,在查看小于平均工资的员工信息 + +```mysql +mysql> select avg(salary) from emp; ++-------------------+ +| avg(salary) | ++-------------------+ +| 5994.333333333333 | ++-------------------+ +1 行于数据集 (0.02 秒) + +mysql> select * from emp where salary<(select avg(salary) from emp); ++----+--------+--------+--------+------------+---------+ +| id | name | gender | salary | join_date | dept_id | ++----+--------+--------+--------+------------+---------+ +| 2 | 李四 | 男 | 3600 | 2010-12-02 | 2 | +| 4 | 赵六 | 女 | 5000 | 2015-10-07 | 3 | +| 5 | 吴七 | 女 | 4500 | 2011-03-14 | 1 | ++----+--------+--------+--------+------------+---------+ +3 行于数据集 (0.03 秒) +``` + +## 三、单行多列查询 + +子查询结果只要是单行多列,结果集类似于一个数组,父查询使用in、not in运算符 + +```mysql +格式: +select */字段列表 from 数据库表名 where 字段名 in (子查询); +``` + +**案例:** + +查询工资大于 5000 的员工,来自于哪些部门的名字 + +分析: + +先找出工资大于5000的员工的部门ID,通过部门ID查找对应的部门名字 + +```mysql +mysql> select dept_id from emp where salary>5000; ++---------+ +| dept_id | ++---------+ +| 1 | +| 2 | ++---------+ +2 行于数据集 (0.01 秒) + +mysql> select * from dept where id in(select dept_id from emp where salary>5000); ++----+-----------+ +| id | name | ++----+-----------+ +| 1 | 研发部 | +| 2 | 渠道部 | ++----+-----------+ +2 行于数据集 (0.01 秒) +``` + +查询研发部与渠道部所有的员工信息 + +分析: + +先查找研发部与渠道部的id,通过id查找到研发部与渠道部的员工信息 + +```mysql +mysql> select id from dept where name='研发部' or name='渠道部'; ++----+ +| id | ++----+ +| 1 | +| 2 | ++----+ + +mysql> select * from emp where dept_id in(select id from dept where name in('研发部','渠道部')); ++----+--------+--------+--------+------------+---------+ +| id | name | gender | salary | join_date | dept_id | ++----+--------+--------+--------+------------+---------+ +| 1 | 张三 | 男 | 7200 | 2013-02-24 | 1 | +| 2 | 李四 | 男 | 3600 | 2010-12-02 | 2 | +| 3 | 王五 | 男 | 9000 | 2008-08-08 | 2 | +| 5 | 吴七 | 女 | 4500 | 2011-03-14 | 1 | ++----+--------+--------+--------+------------+---------+ +4 行于数据集 (0.02 秒) +``` + +## 四、多行多列 + +子查询结果只要是多行多列,肯定在 FROM 后面作为表,子查询作为表需要取别名,否则这张表没有名称则无法访问表中的字段。 + +```mysql +格式: +select */字段列表 from (子查询) [as] 表别名 where 条件表达式; +``` + +**案例:** + +查询出 2011 年以后入职的员工信息,包括部门名称 + +分析: +先找出2011年入职的员工信息组成一个新表,在查询所在的部门信息 + +```mysql +mysql> select * from emp where join_date>='2011-01-01'; ++----+--------+--------+--------+------------+---------+ +| id | name | gender | salary | join_date | dept_id | ++----+--------+--------+--------+------------+---------+ +| 1 | 张三 | 男 | 7200 | 2013-02-24 | 1 | +| 4 | 赵六 | 女 | 5000 | 2015-10-07 | 3 | +| 5 | 吴七 | 女 | 4500 | 2011-03-14 | 1 | ++----+--------+--------+--------+------------+---------+ +3 行于数据集 (0.01 秒) + +mysql> select * from dept d,(select * from emp where join_date>='2011-01-01') e where d.id=e.dept_id; ++----+-----------+-------+---------+--------+--------+------------+---------+ +| id | name | id(2) | name(2) | gender | salary | join_date | dept_id | ++----+-----------+-------+---------+--------+--------+------------+---------+ +| 1 | 研发部 | 1 | 张三 | 男 | 7200 | 2013-02-24 | 1 | +| 3 | 教务部 | 4 | 赵六 | 女 | 5000 | 2015-10-07 | 3 | +| 1 | 研发部 | 5 | 吴七 | 女 | 4500 | 2011-03-14 | 1 | ++----+-----------+-------+---------+--------+--------+------------+---------+ +3 行于数据集 (0.02 秒) +``` + +还可以使用表连接查询 + +```mysql +mysql> select * from emp inner join dept on emp.dept_id = dept.id where join_date >='2011-1-1'; ++----+--------+--------+--------+------------+---------+-------+-----------+ +| id | name | gender | salary | join_date | dept_id | id(2) | name(2) | ++----+--------+--------+--------+------------+---------+-------+-----------+ +| 1 | 张三 | 男 | 7200 | 2013-02-24 | 1 | 1 | 研发部 | +| 4 | 赵六 | 女 | 5000 | 2015-10-07 | 3 | 3 | 教务部 | +| 5 | 吴七 | 女 | 4500 | 2011-03-14 | 1 | 1 | 研发部 | ++----+--------+--------+--------+------------+---------+-------+-----------+ +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\345\270\270\347\224\250\345\207\275\346\225\260.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\345\270\270\347\224\250\345\207\275\346\225\260.md" new file mode 100644 index 0000000..813e643 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\345\270\270\347\224\250\345\207\275\346\225\260.md" @@ -0,0 +1,1411 @@ +MySQL函数,是一种控制流程函数,属于数据库用语言。 + +MySQL数据库中提供了很丰富的函数。MySQL函数包括数学函数、字符串函数、日期和时间函数、条件判断函数、系统信息函数、加密函数、格式化函数等。通过这些函数,可以简化用户的操作。 + +## 一、数学函数 + +### 1.1、函数概述 + +MySQL函数是MySQL数据库提供的内部函数。这些内部函数可以帮助用户更加方便的处理表中的数据。 + +### 1.2、数学函数概述 + +数学函数是MySQL中常用的一类函数。主要用于处理数字,包括整型、浮点数等。 + +### 1.3、常用数学函数 + +#### 1.3.1、abs() + +abs(X):返回X的绝对值 + +``` +mysql> select abs(-32); ++----------+ +| abs(-32) | ++----------+ +| 32 | ++----------+ +1 行于数据集 (0.03 秒) +``` + +#### 1.3.2、mod() + +MOD(N,M)或%:返回N被M除的余数。 + +``` +mysql> select mod(15,7); ++-----------+ +| mod(15,7) | ++-----------+ +| 1 | ++-----------+ +1 行于数据集 (0.02 秒) + +mysql> select 15%7; ++------+ +| 15%7 | ++------+ +| 1 | ++------+ +1 行于数据集 (0.02 秒) +``` + +#### 1.3.3、ceiling() + +CEILING(X):返回不小于X的最小整数值。 + +```mysql +mysql> select ceiling(1.23); ++---------------+ +| ceiling(1.23) | ++---------------+ +| 2 | ++---------------+ +1 行于数据集 (0.02 秒) + +mysql> select ceiling(-1.23); ++----------------+ +| ceiling(-1.23) | ++----------------+ +| -1 | ++----------------+ +1 行于数据集 (0.02 秒) +``` + +#### 1.3.4、round() + +ROUND(X) :返回参数X的四舍五入的一个整数。 + +```mysql +mysql> select round(3.58); ++-------------+ +| round(3.58) | ++-------------+ +| 4 | ++-------------+ +1 行于数据集 (0.02 秒) + +mysql> select round(-3.58); ++--------------+ +| round(-3.58) | ++--------------+ +| -4 | ++--------------+ +1 行于数据集 (0.01 秒) +``` + +#### 1.3.5、pi() + +PI():返回圆周率π,默认显示6位小数 + +``` +mysql> select pi(); ++----------+ +| pi() | ++----------+ +| 3.141593 | ++----------+ +1 行于数据集 (0.03 秒) +``` + +#### 1.2.6、sqrt() + +SQRT(x):返回非负数的x的二次方根 + +``` +mysql> select sqrt(16); ++----------+ +| sqrt(16) | ++----------+ +| 4 | ++----------+ +1 行于数据集 (0.03 秒) +``` + +#### 1.3.7、ceil() + +CEIL(x):返回不小于x的最小整数 + +``` +mysql> select ceil(1.3); ++-----------+ +| ceil(1.3) | ++-----------+ +| 2 | ++-----------+ +1 行于数据集 (0.01 秒) + +mysql> select ceil(-1.3); ++---------------+ +| ceiling(-1.3) | ++---------------+ +| -1 | ++---------------+ +1 行于数据集 (0.01 秒) +``` + +#### 1.3.8、floor() + +FLOOR(x):返回不大于x的最大整数 + +```mysql +mysql> select floor(1.3); ++------------+ +| floor(1.3) | ++------------+ +| 1 | ++------------+ +1 行于数据集 (0.01 秒) + +mysql> select floor(-1.3); ++-------------+ +| floor(-1.3) | ++-------------+ +| -2 | ++-------------+ +1 行于数据集 (0.01 秒) +``` + +#### 1.3.9、round() + +ROUND(x)、ROUND(x,y) + +前者返回最接近于x的整数,即对x进行四舍五入;后者返回最接近x的数,其值保留到小数点后面y位,若y为负值,则将保留到x到小数点左边y位 + +``` +mysql> select round(1.3555); ++---------------+ +| round(1.3555) | ++---------------+ +| 1 | ++---------------+ +1 行于数据集 (0.01 秒) + +mysql> select round(1.3555,2); ++-----------------+ +| round(1.3555,2) | ++-----------------+ +| 1.36 | ++-----------------+ +1 行于数据集 (0.02 秒) +``` + +#### 1.3.10、sign() + +SIGN(x):返回参数x的符号,-1表示负数,0表示0,1表示正数 + +```mysql +mysql> select sign(5); ++---------+ +| sign(5) | ++---------+ +| 1 | ++---------+ +1 行于数据集 (0.02 秒) + +mysql> select sign(-5); ++----------+ +| sign(-5) | ++----------+ +| -1 | ++----------+ +1 行于数据集 (0.02 秒) + +mysql> select sign(0); ++---------+ +| sign(0) | ++---------+ +| 0 | ++---------+ +1 行于数据集 (0.02 秒) +``` + +#### 1.3.11、pow(x,y) + +POW(x,y)和、POWER(x,y):返回x的y次乘方的值 + +``` +mysql> select pow(2,4); ++----------+ +| pow(2,4) | ++----------+ +| 16 | ++----------+ +1 行于数据集 (0.01 秒) + +mysql> select power(3,3); ++------------+ +| power(3,3) | ++------------+ +| 27 | ++------------+ +1 行于数据集 (0.02 秒) +``` + +#### 1.3.12、rand() + +RAND():随机函数,返回0-1内的随机数 + +``` +mysql> select rand(); ++---------------------+ +| rand() | ++---------------------+ +| 0.30107216378773766 | ++---------------------+ +1 行于数据集 (0.03 秒) + +mysql> select rand(); ++---------------------+ +| rand() | ++---------------------+ +| 0.37762552907469266 | ++---------------------+ +1 行于数据集 (0.01 秒) +``` + +#### 1.3.13、truncate() + +TRUNCATE(x,Y):数值截取,返回数值x截取y位小数的结果(不四舍五入) + +``` +mysql> select truncate(3.1415926,2); ++-----------------------+ +| truncate(3.1415926,2) | ++-----------------------+ +| 3.14 | ++-----------------------+ +1 行于数据集 (0.01 秒) + +mysql> select truncate(3.1415926,4); ++-----------------------+ +| truncate(3.1415926,4) | ++-----------------------+ +| 3.1415 | ++-----------------------+ +1 行于数据集 (0.01 秒) +``` + +## 二、字符串函数 + +### 2.1、字符串函数概述 + +字符串函数是MySQL中常用的一类函数。主要用于处理字符串。 + +### 2.2、常用字符串函数 + +#### 2.2.1、ascii() + +ASCII(str):返回字符串str的最左面字符的ASCII代码值。如果str是空字符串,返回0。如果str是NULL,返回NULL。 + +``` +mysql> select ascii('2'); ++------------+ +| ascii('2') | ++------------+ +| 50 | ++------------+ +1 行于数据集 (0.01 秒) + +mysql> select ascii(2); ++----------+ +| ascii(2) | ++----------+ +| 50 | ++----------+ +1 行于数据集 (0.01 秒) + +mysql> select ascii('Ax'); ++-------------+ +| ascii('Ax') | ++-------------+ +| 65 | ++-------------+ +1 行于数据集 (0.02 秒) + +mysql> select ascii('ax'); ++-------------+ +| ascii('ax') | ++-------------+ +| 97 | ++-------------+ +1 行于数据集 (0.02 秒) +``` + +#### 2.2.2、concat() + +CONCAT(str1,str2,…):返回来自于参数连结的字符串。如果任何参数是NULL,返回NULL。可以有超过2个的参数。一个数字参数被变换为等价的字符串形式。 + +``` +mysql> select concat('hello','world','!'); ++-----------------------------+ +| concat('hello','world','!') | ++-----------------------------+ +| helloworld! | ++-----------------------------+ +1 行于数据集 (0.02 秒) + +mysql> select concat('hello',null,'world'); ++------------------------------+ +| concat('hello',null,'world') | ++------------------------------+ +| NULL | ++------------------------------+ +1 行于数据集 (0.04 秒) + +mysql> select concat(12,21); ++---------------+ +| concat(12,21) | ++---------------+ +| 1221 | ++---------------+ +1 行于数据集 (0.02 秒) +``` + +#### 2.2.3、length() + +LENGTH(str):获取字符串字节长度(返回字节数,要注意字符集) + +``` +mysql> select length('hello world'); ++-----------------------+ +| length('hello world') | ++-----------------------+ +| 11 | ++-----------------------+ +1 行于数据集 (0.02 秒) + +mysql> select length('你好'); ++--------------+ +| length('你好') | ++--------------+ +| 6 | ++--------------+ +1 行于数据集 (0.02 秒) +``` + +**注意:** + +一个汉字是算三个字节,一个数字或字母算一个字节 + +#### 2.2.4、locate() + +LOCATE(substr,str):返回子串substr在字符串str第一个出现的位置,如果substr不是在str里面,返回0. + +``` +mysql> select locate('wo','hello world'); ++----------------------------+ +| locate('wo','hello world') | ++----------------------------+ +| 7 | ++----------------------------+ +1 行于数据集 (0.04 秒) + +mysql> select locate('wob','hello world'); ++-----------------------------+ +| locate('wob','hello world') | ++-----------------------------+ +| 0 | ++-----------------------------+ +1 行于数据集 (0.02 秒) +``` + +#### 2.2.5、instr() + +INSTR(str,substr):返回子串substr在字符串str中的第一个出现的位置。 + +``` +mysql> select instr('hello world','o'); ++--------------------------+ +| instr('hello world','o') | ++--------------------------+ +| 5 | ++--------------------------+ +1 行于数据集 (0.01 秒) + +mysql> select instr('hello world','ob'); ++---------------------------+ +| instr('hello world','ob') | ++---------------------------+ +| 0 | ++---------------------------+ +1 行于数据集 (0.01 秒) +``` + +#### 2.2.6、left() + +LEFT(str,len):返回字符串str的最左面len个字符。 + +``` +mysql> select left('hello world',5); ++-----------------------+ +| left('hello world',5) | ++-----------------------+ +| hello | ++-----------------------+ +1 行于数据集 (0.01 秒) +``` + +#### 2.2.7、right() + +RIGHT(str,len):返回字符串str的最右面len个字符。 + +``` +mysql> select right('hello world',5); ++------------------------+ +| right('hello world',5) | ++------------------------+ +| world | ++------------------------+ +1 行于数据集 (0.01 秒) +``` + +#### 2.2.8、substring() + +SUBSTRING(str,pos):从字符串str的起始位置pos返回一个子串。 + +``` +mysql> select substring('hello world',5); ++----------------------------+ +| substring('hello world',5) | ++----------------------------+ +| o world | ++----------------------------+ +1 行于数据集 (0.01 秒) +mysql> select substring('hello world',2,6); ++------------------------------+ +| substring('hello world',2,6) | ++------------------------------+ +| ello w | ++------------------------------+ +1 行于数据集 (0.01 秒) + +mysql> select substring('hello world' from 7); ++---------------------------------+ +| substring('hello world' from 7) | ++---------------------------------+ +| world | ++---------------------------------+ +1 行于数据集 (0.01 秒) + +mysql> select substring('hello world' from 7 for 2); ++---------------------------------------+ +| substring('hello world' from 7 for 2) | ++---------------------------------------+ +| wo | ++---------------------------------------+ + +mysql> select substring('hello world' from -3 for 2); ++----------------------------------------+ +| substring('hello world' from -3 for 2) | ++----------------------------------------+ +| rl | ++----------------------------------------+ +1 行于数据集 (0.01 秒) +``` + +#### 2.2.9、trim() + +TRIM(str):返回字符串str,所有前缀或后缀被删除了。 + +``` +mysql> select trim(' hello world '); ++-------------------------+ +| trim(' hello world ') | ++-------------------------+ +| hello world | ++-------------------------+ +1 行于数据集 (0.01 秒) +``` + +#### 2.2.10、ltrim()/rtrim() + +LTRIM(str):返回删除了其前置空格字符的字符串str。 + +RTRIM(str):返回删除了其拖后空格字符的字符串str。 + +``` +mysql> select ltrim(' hello world '); ++--------------------------+ +| ltrim(' hello world ') | ++--------------------------+ +| hello world | ++--------------------------+ +1 行于数据集 (0.01 秒) + +mysql> select rtrim(' hello world '); ++--------------------------+ +| rtrim(' hello world ') | ++--------------------------+ +| hello world | ++--------------------------+ +1 行于数据集 (0.01 秒) +``` + +#### 2.2.11、replace() + +REPLACE(str,from_str,to_str):返回字符串str,其字符串from_str的所有出现由字符串to_str代替。 + +``` +mysql> select replace('hello world','o','O'); ++--------------------------------+ +| replace('hello world','o','O') | ++--------------------------------+ +| hellO wOrld | ++--------------------------------+ +1 行于数据集 (0.01 秒) +``` + +### 2.3、常用字符串函数 + +#### 2.3.1、repeat() + +REPEAT(str,count):返回由重复count次的字符串str组成的一个字符串。如果count <= 0,返回一个空字符串。如果str或count是NULL,返回NULL。 + +``` +mysql> select repeat('hello',3); ++-------------------+ +| repeat('hello',3) | ++-------------------+ +| hellohellohello | ++-------------------+ +1 行于数据集 (0.01 秒) + +mysql> select repeat('hello',0); ++-------------------+ +| repeat('hello',0) | ++-------------------+ +| | ++-------------------+ +1 行于数据集 (0.01 秒) +``` + +#### 2.3.2、reverse() + +REVERSE(str):返回颠倒字符顺序的字符串str。 + +``` +mysql> select reverse('hello world!'); ++-------------------------+ +| reverse('hello world!') | ++-------------------------+ +| !dlrow olleh | ++-------------------------+ +1 行于数据集 (0.02 秒) +``` + +#### 2.3.3、insert() + +INSERT(str,pos,len,newstr):返回字符串str,在位置pos起始的子串且len个字符长的子串由字符串newstr代替。 + +``` +mysql> select insert('hello world!',5,3,'is'); ++---------------------------------+ +| insert('hello world!',5,3,'is') | ++---------------------------------+ +| hellisorld! | ++---------------------------------+ +1 行于数据集 (0.02 秒) +``` + +#### 2.3.4、elt() + +ETL(index,str1,str2,str3…):返回指定index位置的字符串 + +``` +mysql> select elt(2,'hello','world','!'); ++----------------------------+ +| elt(2,'hello','world','!') | ++----------------------------+ +| world | ++----------------------------+ +1 行于数据集 (0.01 秒) + +mysql> select elt(4,'hello','world','!'); ++----------------------------+ +| elt(4,'hello','world','!') | ++----------------------------+ +| NULL | ++----------------------------+ +1 行于数据集 (0.01 秒) +``` + +#### 2.3.5、upper() + +UPPER(x)或UCASE(x):用于将字母转成大写,x可以是单个字母也可以是字符串; + +``` +mysql> select upper('abcdfe'); ++-----------------+ +| upper('abcdfe') | ++-----------------+ +| ABCDFE | ++-----------------+ +1 行于数据集 (0.01 秒) + +mysql> select ucase('abcdfe'); ++-----------------+ +| ucase('abcdfe') | ++-----------------+ +| ABCDFE | ++-----------------+ +1 行于数据集 (0.01 秒) +``` + +#### 2.3.6、lower() + +LOWER(x)或LCASE(x):用于将字母转成小写,x可以是单个字母也可以是字符串; + +``` +mysql> select lower('ABCDEF'); ++-----------------+ +| lower('ABCDEF') | ++-----------------+ +| abcdef | ++-----------------+ +1 行于数据集 (0.01 秒) + +mysql> select lcase('ABCDEF'); ++-----------------+ +| lcase('ABCDEF') | ++-----------------+ +| abcdef | ++-----------------+ +1 行于数据集 (0.01 秒) +``` + +#### 2.3.7、char_length() + +CHAR_LENGTH():获取字符串字符数,获取字符串长度 + +``` +mysql> select char_length('hello world'); ++----------------------------+ +| char_length('hello world') | ++----------------------------+ +| 11 | ++----------------------------+ +1 行于数据集 (0.01 秒) + +mysql> select char_length('你好'); ++-------------------+ +| char_length('你好') | ++-------------------+ +| 2 | ++-------------------+ +1 行于数据集 (0.01 秒) +``` + +**注意:** + +不管汉字还是数字或者是字母都算是一个字符 + +#### 2.3.8、strcmp() + +STRCMP(str1,str2):比较两个字符串的大小。左边大于右边时返回1,左边等于右边时返回0,,左小于于右时返回-1。 + +``` +mysql> select strcmp('a','b'); ++-----------------+ +| strcmp('a','b') | ++-----------------+ +| -1 | ++-----------------+ +1 行于数据集 (0.01 秒) + +mysql> select strcmp('d','b'); ++-----------------+ +| strcmp('d','b') | ++-----------------+ +| 1 | ++-----------------+ +1 行于数据集 (0.01 秒) + +mysql> select strcmp('b','b'); ++-----------------+ +| strcmp('b','b') | ++-----------------+ +| 0 | ++-----------------+ +1 行于数据集 (0.01 秒) +``` + +#### 2.3.9、field() + +FIELD(str,str1,str2,str3…):与find_in_set类似,返回str在str1,str2,str3…中的位置。 + +``` +mysql> select field('a','b','c','d','a','e'); ++--------------------------------+ +| field('a','b','c','d','a','e') | ++--------------------------------+ +| 4 | ++--------------------------------+ +1 行于数据集 (0.02 秒) + +mysql> select find_in_set('a','b,c,d,a,e'); ++------------------------------+ +| find_in_set('a','b,c,d,a,e') | ++------------------------------+ +| 4 | ++------------------------------+ +1 行于数据集 (0.02 秒) +``` + +#### 2.3.10、position() + +POSITION(str1 IN str2):返回子串str1在字符串str2中的位置 + +``` +mysql> select position('ld' in 'helloworld'); ++--------------------------------+ +| position('ld' in 'helloworld') | ++--------------------------------+ +| 9 | ++--------------------------------+ +1 行于数据集 (0.01 秒) +``` + +#### 2.3.11、locate() + +LOCATE(str1,str,pos):函数返回字符串str1在str中的第pos位置后第一次出现的位置。如果str1在str中不存在,返回0。 + +``` +mysql> select locate('hel','hello world',1); ++-------------------------------+ +| locate('hel','hello world',1) | ++-------------------------------+ +| 1 | ++-------------------------------+ +1 行于数据集 (0.01 秒) + +mysql> select locate('hel','hello world',2); ++-------------------------------+ +| locate('hel','hello world',2) | ++-------------------------------+ +| 0 | ++-------------------------------+ +1 行于数据集 (0.01 秒) +``` + +#### 2.3.12、substring_index() + +SUBSTRING_INDEX(str,delim,count):在定界符delim及count出现前,从字符串str返回自字符串。若count为正值,则返回最终定界符(从左边开始) ,若为-1则是从后往前截取; + +``` +mysql> select substring_index('hello/world/!','/',-1); ++-----------------------------------------+ +| substring_index('hello/world/!','/',-1) | ++-----------------------------------------+ +| ! | ++-----------------------------------------+ +1 行于数据集 (0.01 秒) + +mysql> select substring_index('hello/world/!','/',1); ++----------------------------------------+ +| substring_index('hello/world/!','/',1) | ++----------------------------------------+ +| hello | ++----------------------------------------+ +1 行于数据集 (0.01 秒) +``` + +## 三、日期和时间函数 + +### 3.1、日期和时间函数概述 + +日期和时间函数是MySQL中常用的一类函数。主要用于处理日期时间。 + +### 3.2、常用日期和时间函数 + +#### 3.2.1、curdate() + +CURDATE()或CURRENT_DATE():返回当前日期 + +``` +mysql> select curdate(); ++------------+ +| curdate() | ++------------+ +| 2020-02-17 | ++------------+ +1 行于数据集 (0.01 秒) + +mysql> select current_date(); ++----------------+ +| current_date() | ++----------------+ +| 2020-02-17 | ++----------------+ +1 行于数据集 (0.01 秒) +``` + +#### 3.2.2、curtime() + +CURTIME()或CURRENT_TIME():返回当前时间 + +``` +mysql> select curtime(); ++-----------+ +| curtime() | ++-----------+ +| 03:01:16 | ++-----------+ +1 行于数据集 (0.01 秒) + +mysql> select current_time(); ++----------------+ +| current_time() | ++----------------+ +| 03:01:26 | ++----------------+ +1 行于数据集 (0.01 秒) +``` + +#### 3.2.3、now() + +NOW():返回当前日期时间 + +``` +mysql> select now(); ++---------------------+ +| now() | ++---------------------+ +| 2020-02-17 03:02:09 | ++---------------------+ +1 行于数据集 (0.01 秒) +``` + +#### 3.2.4、month() + +MONTH(date)或MONTHNAME(date):返回date的月份,范围1到12 + +``` +mysql> select month(now()); ++--------------+ +| month(now()) | ++--------------+ +| 2 | ++--------------+ +1 行于数据集 (0.01 秒) + +mysql> select monthname(now()); ++------------------+ +| monthname(now()) | ++------------------+ +| February | ++------------------+ +1 行于数据集 (0.01 秒) +``` + +#### 3.2.5、week() + +WEEK(date):从日期中选择出周数 + +``` +mysql> select week(now()); ++-------------+ +| week(now()) | ++-------------+ +| 7 | ++-------------+ +1 行于数据集 (0.01 秒) +``` + +#### 3.2.6、year() + +YEAR(date):从日期中选择出年份 + +``` +mysql> select year(now()); ++-------------+ +| year(now()) | ++-------------+ +| 2020 | ++-------------+ +1 行于数据集 (0.01 秒) +``` + +#### 3.2.7、hour() + +HOUR(date):从日期中选择出小时数,返回time的小时,范围是0到23。 + +``` +mysql> select hour(now()); ++-------------+ +| hour(now()) | ++-------------+ +| 3 | ++-------------+ +1 行于数据集 (0.02 秒) +``` + +#### 3.2.8、minute() + +MINUTE():从日期中选择出分钟数,范围是0到59。 + +``` +mysql> select minute(now()); ++---------------+ +| minute(now()) | ++---------------+ +| 12 | ++---------------+ +1 行于数据集 (0.01 秒) +``` + +#### 3.2.9、second() + +SECOND(time):回来time的秒数,范围是0到59。 + +``` +mysql> select second(now()); ++---------------+ +| second(now()) | ++---------------+ +| 41 | ++---------------+ +1 行于数据集 (0.01 秒) +``` + +### 3.3、常用日期和时间函数 + +#### 3.3.1、weekday() + +WEEKDAY(date)或DAYNAME(date):返回date的星期索引(0=星期一,1=星期二, ……6= 星期天)。 + +``` +mysql> select weekday(now()); ++----------------+ +| weekday(now()) | ++----------------+ +| 0 | ++----------------+ +1 行于数据集 (0.01 秒) + +mysql> select dayname(now()); ++----------------+ +| dayname(now()) | ++----------------+ +| Monday | ++----------------+ +1 行于数据集 (0.01 秒) +``` + +#### 3.3.2、dayofweek() + +DAYOFWEEK(date):返回日期date的星期索引(1=星期天,2=星期一, …7=星期六)。 + +``` +mysql> select dayofweek(now()); ++------------------+ +| dayofweek(now()) | ++------------------+ +| 2 | ++------------------+ +1 行于数据集 (0.01 秒) +``` + +#### 3.3.3、dayofmonth() + +DAYOFMONTH(date):返回date的月份中的日期,在1到31范围内。 + +``` +mysql> select dayofmonth(now()); ++-------------------+ +| dayofmonth(now()) | ++-------------------+ +| 17 | ++-------------------+ +1 行于数据集 (0.01 秒) +``` + +#### 3.3.4、dayofyear() + +DAYOFYEAR(date):返回date在一年中的日数, 在1到366范围内。 + +```mysql +mysql> select dayofyear(now()); ++------------------+ +| dayofyear(now()) | ++------------------+ +| 48 | ++------------------+ +1 行于数据集 (0.01 秒) +``` + +#### 3.3.5、quarter() + +QUARTER(date):返回date一年中的季度,范围1到4。 + +``` +mysql> select quarter(now()); ++----------------+ +| quarter(now()) | ++----------------+ +| 1 | ++----------------+ +1 行于数据集 (0.02 秒) +``` + +#### 3.3.6、date_add() + +DATE_ADD(date,INTERVAL expr type) ,进行日期增加的操作,可以精确到秒 + +``` +mysql> select '1997-12-31 23:59:59'+interval 1 second; ++-----------------------------------------+ +| '1997-12-31 23:59:59'+interval 1 second | ++-----------------------------------------+ +| 1998-01-01 00:00:00 | ++-----------------------------------------+ +1 行于数据集 (0.01 秒) + +mysql> select '1997-12-31'+interval 1 second; ++--------------------------------+ +| '1997-12-31'+interval 1 second | ++--------------------------------+ +| 1997-12-31 00:00:01 | ++--------------------------------+ +1 行于数据集 (0.02 秒) +mysql> select date_add('1997-12-31 23:59:59',interval 1 second); ++---------------------------------------------------+ +| date_add('1997-12-31 23:59:59',interval 1 second) | ++---------------------------------------------------+ +| 1998-01-01 00:00:00 | ++---------------------------------------------------+ +1 行于数据集 (0.01 秒) + +mysql> select date_add('1997-12-31 23:59:59',interval '1:1' minute_second); ++--------------------------------------------------------------+ +| date_add('1997-12-31 23:59:59',interval '1:1' minute_second) | ++--------------------------------------------------------------+ +| 1998-01-01 00:01:00 | ++--------------------------------------------------------------+ +1 行于数据集 (0.01 秒) +``` + +#### 3.3.7、date_sub() + +DATE_SUB(date,INTERVAL expr type) ,进行日期减少的操作,可以精确到秒 + +``` +mysql> select '1997-12-31'-interval 1 second; ++--------------------------------+ +| '1997-12-31'-interval 1 second | ++--------------------------------+ +| 1997-12-30 23:59:59 | ++--------------------------------+ +1 行于数据集 (0.01 秒) +mysql> select date_sub('1997-12-31 23:59:59',interval '1:1' minute_second); ++--------------------------------------------------------------+ +| date_sub('1997-12-31 23:59:59',interval '1:1' minute_second) | ++--------------------------------------------------------------+ +| 1997-12-31 23:58:58 | ++--------------------------------------------------------------+ +1 行于数据集 (0.01 秒) + +mysql> select date_sub('1997-12-31 23:59:59',interval 30 day); ++-------------------------------------------------+ +| date_sub('1997-12-31 23:59:59',interval 30 day) | ++-------------------------------------------------+ +| 1997-12-01 23:59:59 | ++-------------------------------------------------+ +1 行于数据集 (0.01 秒) +``` + +## 四、系统信息函数 + +### 4.1、系统函数概述 + +系统信息函数用来查询MySQL数据库的系统信息。 + +### 4.2、常用系统函数 + +#### 4.2.1、version() + +VERSION()函数返回数据库的版本号; + +``` +mysql> select version(); ++-----------+ +| version() | ++-----------+ +| 8.0.17 | ++-----------+ +1 行于数据集 (0.01 秒) +``` + +#### 4.2.2、connection_id() + +CONNECTION_ID()函数返回服务器的连接数,也就是到现在为止MySQL服务的连接次数; + +``` +mysql> select connection_id(); ++-----------------+ +| connection_id() | ++-----------------+ +| 78 | ++-----------------+ +1 行于数据集 (0.01 秒) +``` + +#### 4.2.3、database() + +DATABASE()和SCHEMA()返回当前数据库名。 + +``` +mysql> select database(); ++------------+ +| database() | ++------------+ +| zutuanxue | ++------------+ +1 行于数据集 (0.01 秒) + +mysql> select schema(); ++----------+ +| schema() | ++----------+ +| zutuanxue | ++----------+ +1 行于数据集 (0.01 秒) +``` + +#### 4.2.4、用户函数 + +USER()、SYSTEM_USER()、SESSION_USER()、CURRENT_USER()和CURRENT_USER这几个函数可以返回当前用户的名称。 + +``` +mysql> select user(); ++--------------------+ +| user() | ++--------------------+ +| root@192.168.1.104 | ++--------------------+ +1 行于数据集 (0.01 秒) + +mysql> select system_user(); ++--------------------+ +| system_user() | ++--------------------+ +| root@192.168.1.104 | ++--------------------+ +1 行于数据集 (0.01 秒) + +mysql> select session_user(); ++--------------------+ +| session_user() | ++--------------------+ +| root@192.168.1.104 | ++--------------------+ +1 行于数据集 (0.02 秒) + +mysql> select current_user(); ++----------------+ +| current_user() | ++----------------+ +| root@% | ++----------------+ +1 行于数据集 (0.01 秒) + +mysql> select current_user; ++--------------+ +| current_user | ++--------------+ +| root@% | ++--------------+ +1 行于数据集 (0.01 秒) +``` + +#### 4.2.5、字符集函数 + +**charset()** + +CHARSET(str)函数返回字符串str的字符集,一般情况这个字符集就是系统的默认字符集; + +``` +mysql> select charset('ad'); ++---------------+ +| charset('ad') | ++---------------+ +| utf8 | ++---------------+ +1 行于数据集 (0.01 秒) +``` + +**collation()** + +COLLATION(str)函数返回字符串str的字符排列方式。 + +``` +mysql> select collation('ad'); ++-----------------+ +| collation('ad') | ++-----------------+ +| utf8_general_ci | ++-----------------+ +1 行于数据集 (0.01 秒) +``` + +## 五、其他函数 + +### 5.1、md5() + +加密函数是MySQL中用来对数据进行加密的函数。 + +MD5(str)函数可以对字符串str进行加密。MD5(str)函数主要对普通的数据进行加密。下面使用MD5(str)函数为字符串“abcd”加密。 + +``` +mysql> select md5('abcd'); ++----------------------------------+ +| md5('abcd') | ++----------------------------------+ +| e2fc714c4727ee9395f324cd2e7f331f | ++----------------------------------+ +1 行于数据集 (0.04 秒) +``` + +### 5.2、format() + +格式化函数FORMAT(x,n) + +FORMAT(x,n)函数可以将数字x进行格式化,将x保留到小数点后n位。这个过程需要进行四舍五入。例如FORMAT(2.356,2)返回的结果将会是2.36;FORMAT(2.353,2)返回的结果将会是2.35。下面使用FORMAT(x,n)函数来讲235.3456和235.3454进行格式化,都保留到小数点后3位。 + +``` +mysql> select format(235.3456,3),format(235.3456,2); ++--------------------+--------------------+ +| format(235.3456,3) | format(235.3456,2) | ++--------------------+--------------------+ +| 235.346 | 235.35 | ++--------------------+--------------------+ +1 行于数据集 (0.01 秒) +``` + +### 5.3、进制转换函数 + +BIN(x)返回x的二进制编码; + +HEX(x)返回x的十六进制编码; + +OCT(x)返回x的八进制编码; + +CONV(x,f1,f2)将x从f1进制数变成f2进制数。 + +``` +mysql> select bin(10); ++---------+ +| bin(10) | ++---------+ +| 1010 | ++---------+ +1 行于数据集 (0.01 秒) + +mysql> select hex(10); ++---------+ +| hex(10) | ++---------+ +| A | ++---------+ +1 行于数据集 (0.01 秒) + +mysql> select oct(10); ++---------+ +| oct(10) | ++---------+ +| 12 | ++---------+ +1 行于数据集 (0.01 秒) + +mysql> select conv(10,10,2); ++---------------+ +| conv(10,10,2) | ++---------------+ +| 1010 | ++---------------+ +1 行于数据集 (0.01 秒) +``` + +### 5.4、条件判断函数 + +#### 5.4.1、if() + +IF(expr,v1,v2)如果表达式 expr 成立,返回结果 v1;否则,返回结果 v2 + +``` +mysql> select if(1>0,'yes','no'); ++--------------------+ +| if(1>0,'yes','no') | ++--------------------+ +| yes | ++--------------------+ +1 行于数据集 (0.01 秒) + +mysql> select if(strcmp('test','test1'),'yes','no'); ++---------------------------------------+ +| if(strcmp('test','test1'),'yes','no') | ++---------------------------------------+ +| yes | ++---------------------------------------+ +1 行于数据集 (0.01 秒) +``` + +#### 5.4.2、ifnull() + +IFNULL(v1,v2):如果v1不为NULL,则返回v1,否则返回v2 + +``` +mysql> select ifnull('yes','no'); ++--------------------+ +| ifnull('yes','no') | ++--------------------+ +| yes | ++--------------------+ +1 行于数据集 (0.02 秒) + +mysql> select ifnull(null,'no'); ++-------------------+ +| ifnull(null,'no') | ++-------------------+ +| no | ++-------------------+ +1 行于数据集 (0.01 秒) +``` + +#### 5.4.3、case + +CASE expr WHEN v1 THEN r1 [WHEN v2 THEN v2] [ELSE rn] END:如果expr等于某个vn,则返回对应位置THEN后面的结果,如果与所有值都不想等,则返回ELSE后面的rn + +``` +mysql> select case 11 when 1 then 'one' when 2 then 'two' else 'more' end; ++-------------------------------------------------------------+ +| case 11 when 1 then 'one' when 2 then 'two' else 'more' end | ++-------------------------------------------------------------+ +| more | ++-------------------------------------------------------------+ +1 行于数据集 (0.01 秒) + +mysql> select case when 1>0 then 'true' else 'false' end; ++--------------------------------------------+ +| case when 1>0 then 'true' else 'false' end | ++--------------------------------------------+ +| true | ++--------------------------------------------+ +1 行于数据集 (0.01 秒) + +mysql> select case binary 'B' when 'a' then 1 when 'b' then 2 end; ++-----------------------------------------------------+ +| case binary 'B' when 'a' then 1 when 'b' then 2 end | ++-----------------------------------------------------+ +| NULL | ++-----------------------------------------------------+ +1 行于数据集 (0.01 秒) + +mysql> select case binary 'B' when 'a' then 1 when 'B' then 2 end; ++-----------------------------------------------------+ +| case binary 'B' when 'a' then 1 when 'B' then 2 end | ++-----------------------------------------------------+ +| 2 | ++-----------------------------------------------------+ +1 行于数据集 (0.01 秒) +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\346\225\260\346\215\256\345\244\207\344\273\275\344\270\216\350\277\230\345\216\237.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\346\225\260\346\215\256\345\244\207\344\273\275\344\270\216\350\277\230\345\216\237.md" new file mode 100644 index 0000000..866cea6 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\346\225\260\346\215\256\345\244\207\344\273\275\344\270\216\350\277\230\345\216\237.md" @@ -0,0 +1,92 @@ +MySQL 数据库管理系统通常会采用有效的措施来维护数据库的可靠性和完整性。但是在数据库的实际使用过程当中,仍存在着一些不可预估的因素,会造成数据库运行事务的异常中断,从而影响数据的正确性,甚至会破坏数据库,导致数据库中的数据部分或全部丢失。 + +数据库系统提供了备份和恢复策略来保证数据库中数据的可靠性和完整性。 + +## 一、mysqldump备份 + +### 1.1、数据库备份 + +数据库备份是指通过导出数据或者复制表文件的方式来制作数据库的副本。当数据库出现故障或遭到破坏时,将备份的数据库加载到系统,从而使数据库从错误状态恢复到备份时的正确状态。 + +### 1.2、备份/还原格式 + +#### 1.2.1、备份 + +备份整个数据库 + +``` +格式: +mysqldump -u用户名 -p密码 数据库名 > sql文件位置 +[root@localhost mysql]# ./bin/mysqldump -uroot -p zutuanxue > /usr/local/mysql/data/zutuanxue.sql +``` + +备份数据库中的某个表 + +``` +格式: +mysqldump -u用户名 -p密码 数据库名 数据库表名1 数据库表名2> sql文件位置 +[root@localhost mysql]# ./bin/mysqldump -uroot -p zutuanxue t5 t6 > ./data/1.sql +``` + +备份多个数据库 + +``` +格式: +mysqldump -u用户名 -p密码 --databases 数据库名1 数据库名2> sql文件位置 +[root@localhost mysql]# ./bin/mysqldump -uroot -p --databases a zutuanxue > ./data/2.sql +``` + +备份系统中所有数据库 + +``` +格式: +mysqldump -u用户名 -p密码 --all-databases > sql文件位置 +[root@localhost mysql]# ./bin/mysqldump -uroot -p --all-databases > ./data/1.sql +``` + +#### 1.2.2、还原 + +登录mysql数据库后 + +```mysql +格式: +source 导入文件的路径; + +mysql> use zutuanxue; +Database changed +mysql> source /usr/local/mysql/data/zutuanxue.sql +``` + +## 二、图形化的备份与还原 + +### 2.1、备份 + +打开数据库->右击要备份的数据库 + +![image20200216142554960.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603521654232.png) + +选择“结构和数据”或者“结构”,跳出存储路径,存储一个sql文件 + +![image20200216142651361.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603521671030.png) + +点击“保存”,跳出进度窗口 + +![image20200216142820725.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603521684164.png) + +### 2.2、还原 + +打开要还原的数据库,右击“数据库” + +![image20200216143025810.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603521704494.png) + +选择“运行SQL文件” + +![image20200216143109143.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603521717747.png) + +选择sql“文件”所在的位置,点击“开始” + +![image20200216143212105.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603521732225.png) + +运行完成后点击关闭,查看数据库下是否有表 + +![image20200216143324447.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603521748776.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\347\272\246\346\235\237.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\347\272\246\346\235\237.md" new file mode 100644 index 0000000..30e2cf7 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\347\272\246\346\235\237.md" @@ -0,0 +1,1066 @@ +约束是按照约定(特定)条件限制,管束等意思。约束的作用是添加、删除。 + +在数据库中对表中的数据进行限制,保证数据的正确性、有效性和完整性。一个表如果添加了约束,不正确的数据将无法插入到表中。约束在创建表的时候添加比较合适。 + +## 一、约束概述 + +### 1.1、什么是约束 + +约束用于限制加入表的数据的类型。 + +可以在创建表时规定约束(通过 CREATE TABLE 语句),或者在表创建之后也可以(通过 ALTER TABLE 语句)。 + +### 1.2、约束作用 + +对表中的数据进行限制,保证数据的正确性、有效性和完整性。一个表如果添加了约束,不正确的数据将无法插入到表中。约束在创建表的时候添加比较合适。 + +### 1.3、约束分类 + +**主键** primary key + +**唯一** unique + +**非空** not null + +**默认值** default + +**外键** foreign key + +**检查约束** check + +## 二、主键约束 + +### 2.1、主键约束格式 + +```mysql +格式1: +字段名 字段类型 primary key #在create table 语句中设置主键 +格式2: +alter table 数据库表名 add primary key(字段名); #在已经创建好的数据库表中增加主键 +格式3: +alter table 数据库表名 drop primary key; #在已经创建好的数据库表中删除主键 +``` + +**注意:** + +非空 not null + +唯一 + +### 2.2、主键约束作用 + +是每一条记录的唯一标识,不会重复。 + +**如:** + +![image20200210091102251.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/21/1603240514001.png) + +**注意:** + +通常主键,单独给每张表设计一个 id 的字段,把 id 作为主键。 + +主键是给数据库和程序使用的,不是给最终的客户使用的。所以主键有没有含义没有关系,只要不重复,非空就行。 + +### 2.3、主键约束应用 + +创建一个老师表,里面包含了字段名(tid,tname,sex,age),将tid做为主键 + +```mysql +create table teacher( + tid int primary key, -- sid为主键 + tname varchar(20), + sex varchar(2), + age int +); +mysql> create table teacher( + tid int primary key, -- sid为主键 + tname varchar(20), + sex varchar(2), + age int +); +Query OK, 0 rows affected (0.10 秒) + +mysql> desc teacher; ++-------+-------------+------+-----+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++-------+-------------+------+-----+---------+-------+ +| tid | int(11) | NO | PRI | NULL | | +| tname | varchar(20) | YES | | NULL | | +| sex | varchar(2) | YES | | NULL | | +| age | int(11) | YES | | NULL | | ++-------+-------------+------+-----+---------+-------+ +4 行于数据集 (0.01 秒) +``` + +往老师表中插入记录 + +```mysql +#插入记录 +mysql> insert into teacher values(1,'李小四','男',45); +Query OK, 1 rows affected (0.08 秒) +#插入相同记录 +mysql> insert into teacher values(1,'李小四','男',45); +Duplicate entry '1' for key 'PRIMARY' +mysql> select * from teacher; ++-----+-----------+------+------+ +| tid | tname | sex | age | ++-----+-----------+------+------+ +| 1 | 李小四 | 男 | 45 | ++-----+-----------+------+------+ +1 行于数据集 (0.01 秒) +#插入一条null记录 +mysql> insert into teacher values(null,'李小四','男',45); +Column 'tid' cannot be null +``` + +去掉老师表中的主键约束 + +```mysql +mysql> alter table teacher drop primary key; +Query OK, 1 rows affected (0.07 秒) +mysql> desc teacher; ++-------+-------------+------+-----+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++-------+-------------+------+-----+---------+-------+ +| tid | int(11) | NO | | NULL | | +| tname | varchar(20) | YES | | NULL | | +| sex | varchar(2) | YES | | NULL | | +| age | int(11) | YES | | NULL | | ++-------+-------------+------+-----+---------+-------+ +4 行于数据集 (0.01 秒) +``` + +为老师表添加主键约束 + +```mysql +mysql> alter table teacher add primary key(tid); +Query OK, 0 rows affected (0.25 秒) + +mysql> desc teacher; ++-------+-------------+------+-----+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++-------+-------------+------+-----+---------+-------+ +| tid | int(11) | NO | PRI | NULL | | +| tname | varchar(20) | YES | | NULL | | +| sex | varchar(2) | YES | | NULL | | +| age | int(11) | YES | | NULL | | ++-------+-------------+------+-----+---------+-------+ +4 行于数据集 (0.02 秒) +``` + +## 三、主键自增 + +### 3.1、主键自增格式 + +在数据库表中,主键一般情况下,我们是用一个id字段来表示,如果让我们自己添加的话要做到不能重复、不能为空就比较麻烦,所以主键我们都是设置为自动增长。 + +```mysql +格式: +字段名 字段类型 primary key auto_increment +``` + +**案例:** + +创建一个用户表,表里面有用户名和密码 + +```mysql +create table user( + uid int primary key auto_increment, + uname varchar(20), + pword varchar(20) +); +``` + +在用户表中插入二条件数据 + +```mysql +mysql> insert into user(uname,pword)values('zutuanxue01','00001'); +Query OK, 1 rows affected (0.06 秒) + +mysql> insert into user(uname,pword)values('zutuanxue02','00002'); +Query OK, 1 rows affected (0.01 秒) + +mysql> select * from user; ++-----+------------+-------+ +| uid | uname | pword | ++-----+------------+-------+ +| 1 | zutuanxue01 | 00001 | +| 2 | zutuanxue02 | 00002 | ++-----+------------+-------+ +2 行于数据集 (0.01 秒) +``` + +**注意:** + +设置表字段的自增长后,他的默认起始值从1开始 + +```mysql +mysql> insert into user values(null,'zutuanxue03','00003'); +Query OK, 1 rows affected (0.03 秒) + +mysql> select * from user; ++-----+------------+-------+ +| uid | uname | pword | ++-----+------------+-------+ +| 1 | zutuanxue01 | 00001 | +| 2 | zutuanxue02 | 00002 | +| 3 | zutuanxue03 | 00003 | ++-----+------------+-------+ +3 行于数据集 (0.01 秒) +``` + +### 3.2、修改主键自增起始值 + +#### 3.2.1、创建表后修改 + +```mysql +格式: +alter table 数据库表名 auto_increment=起始值; +``` + +**案例:** + +修改用户表中主键自增长的起始值为100 + +```mysql +mysql> alter table user auto_increment=100; +Query OK, 0 rows affected (0.05 秒) + +mysql> insert into user values(null,'zutuanxue04','00004'); +Query OK, 1 rows affected (0.10 秒) + +mysql> select * from user; ++-----+------------+-------+ +| uid | uname | pword | ++-----+------------+-------+ +| 1 | zutuanxue01 | 00001 | +| 2 | zutuanxue02 | 00002 | +| 3 | zutuanxue03 | 00003 | +| 100 | zutuanxue04 | 00004 | ++-----+------------+-------+ +4 行于数据集 (0.01 秒) +``` + +#### 3.2.2、创建表时修改 + +```mysql +格式: +create table 数据库表名( + 字段名1 字段类型 primary key auto_increment, + 字段名2 字段类型, + ... + 字段名n 字段类型, +)auto_increment=超始值; +``` + +创建一个新用户表,表里面有用户名和密码,并设置起始值为100 + +```mysql +create table new_user( + uid int primary key auto_increment, + uname varchar(20), + pword varchar(20) +)auto_increment=100; +``` + +在新用户表中插入一条件数据 + +```mysql +mysql> insert into new_user(uname,pword)values('zutuanxue01','00001'); +Query OK, 1 rows affected (0.10 秒) + +mysql> select * from new_user; ++-----+------------+-------+ +| uid | uname | pword | ++-----+------------+-------+ +| 100 | zutuanxue01 | 00001 | ++-----+------------+-------+ +1 行于数据集 (0.01 秒) +``` + +### 3.3、记录删除后对自增的影响 + +#### 3.3.1、delete + +删除记录后,对自增长字段没有影响 + +**案例:** + +删除用户数据库表中的所有记录,在插入1条记录 + +```mysql +mysql> delete from user; +Query OK, 4 rows affected (0.11 秒) + +mysql> insert into user values(null,'zhangsan','zhangsan'); +Query OK, 1 rows affected (0.05 秒) + +mysql> select * from user; ++-----+----------+----------+ +| uid | uname | pword | ++-----+----------+----------+ +| 101 | zhangsan | zhangsan | ++-----+----------+----------+ +1 行于数据集 (0.01 秒) +``` + +#### 3.3.2、truncate + +删除记录后,自增长字段重新从1开始 + +**案例:** + +删除用户数据库表中的所有记录,在插入1条记录 + +```mysql +mysql> truncate user; +Query OK, 0 rows affected (0.02 秒) + +mysql> insert into user values(null,'zhangsan','zhangsan'); +Query OK, 1 rows affected (0.05 秒) + +mysql> select * from user; ++-----+----------+----------+ +| uid | uname | pword | ++-----+----------+----------+ +| 1 | zhangsan | zhangsan | ++-----+----------+----------+ +1 行于数据集 (0.01 秒) +mysql> truncate new_user; +Query OK, 0 rows affected (0.06 秒) + +mysql> insert into new_user values(null,'zhangsan','zhangsan'); +Query OK, 1 rows affected (0.04 秒) + +mysql> select * from new_user; ++-----+----------+----------+ +| uid | uname | pword | ++-----+----------+----------+ +| 1 | zhangsan | zhangsan | ++-----+----------+----------+ +1 行于数据集 (0.01 秒) +``` + +## 四、唯一约束 + +唯一约束就是:设计表中的某一个字段不能出现重复的记录 + +### 4.1、唯一约束格式 + +```mysql +字段名 字段类型 unique #在create table 语句中设置唯一约束 +``` + +### 4.2、唯一约束应用 + +#### 4.2.1、插入相同记录 + +**案例:** + +创建一个新的表t1,表里包含字段名(id,name) + +```mysql +create table t1( + id int, + name varchar(20) unique -- 姓名唯一,不能出现重复 +); +``` + +往表中插入一条记录 + +```mysql +mysql> insert into t1 values(1,'zhangsan'); +Query OK, 1 rows affected (0.08 秒) +``` + +继续插入同一条件记录 + +```mysql +mysql> insert into t1 values(1,'zhangsan'); +Duplicate entry 'zhangsan' for key 'name' +``` + +#### 4.2.1、插入null记录 + +案例: + +```mysql +mysql> insert into t1 values(1,null); +Query OK, 1 rows affected (0.02 秒) +mysql> insert into t1 values(1,null); +Query OK, 1 rows affected (0.05 秒) +mysql> select * from t1; ++------+----------+ +| id | name | ++------+----------+ +| 1 | zhangsan | +| 1 | NULL | +| 1 | NULL | ++------+----------+ +3 行于数据集 (0.01 秒) +``` + +**注意:** + +null表示的是没有数据,所有不存在重复的问题 + +## 五、非空约束 + +非空约束就是:数据库表中的字段的值,不能为null + +### 5.1、非空约束格式 + +```mysql +字段名 字段类型 not null #在create table 语句中设置字段值不能为null +``` + +### 5.2、非空约束应用 + +**案例:** + +创建一个新的表t2,表里包含字段名(id,name) + +```mysql +create table t2( + id int, + name varchar(20) not null -- 姓名的记录不能为null +); +``` + +往表中插入一条记录 + +```mysql +mysql> insert into t2 values(1,'lisi'); +Query OK, 1 rows affected (0.10 秒) +``` + +往表中插入一条姓名为null的记录 + +```mysql +mysql> insert into t2 values(1, null); +Column 'name' cannot be null +mysql> select * from t2; ++------+------+ +| id | name | ++------+------+ +| 1 | lisi | ++------+------+ +1 行于数据集 (0.01 秒) +``` + +**注意:** + +字段设置了非空与唯一约束与主键区别? + +主键数在一个表中,只能有一个。自增长只能用在主键上 + +非空与唯一约束可以设置在N个字段上 + +## 六、默认值 + +默认值就是:当我们在增加记录的时候如果不去设置值,那么自动的会用默认值补齐,字段默认的默认值是null + +### 6.1、默认值格式 + +```mysql +字段名 字段类型 default 默认值 #在create table 语句中设置字段的默认值,不设置默认值为null +``` + +### 6.2、默认值应用 + +**案例:** + +创建一个新的表t3,表里包含字段名(id,name) + +```mysql +create table t3( + id int, + name varchar(20) default 'lisi' -- 增加时如果不加入姓名,姓名为‘lisi’ +); +``` + +往表中插入一条记录 + +``` +mysql> insert into t3 values(1,'zhangsan'); +Query OK, 1 rows affected (0.03 秒) +``` + +往表中插入一条id为1的记录,其他信息不用增加 + +**方法一:** + +```mysql +mysql> insert into t3(id) values(1); +Query OK, 1 rows affected (0.06 秒) + +mysql> select * from t3; ++------+----------+ +| id | name | ++------+----------+ +| 1 | zhangsan | +| 1 | lisi | ++------+----------+ +2 行于数据集 (0.01 秒) +``` + +**方法二:** + +```mysql +mysql> insert into t3 values(1,default); +Query OK, 1 rows affected (0.09 秒) + +mysql> select * from t3; ++------+----------+ +| id | name | ++------+----------+ +| 1 | zhangsan | +| 1 | lisi | +| 1 | lisi | ++------+----------+ +3 行于数据集 (0.01 秒) +``` + +## 七、外键约束产生 + +### 7.1、数据冗余 + +数据冗余是指数据之间的重复,也可以说是同一数据存储在不同数据文件中的现象。 + +### 7.2、表的数据冗余 + +**员工表** + +![image20200213223102058.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/21/1603240575339.png) + +除了数据冗余的问题外,假如我们的研发部搬到了北京,这这时候,我们就要去修改我们的研发部的地点,这样的修改数据的时候也会很麻烦。 + +**问题解决** + +数据冗余、数据增、删、改? + +![image20200213224403897.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/21/1603240588322.png) + +### 7.3、为什么要使用外键约束 + +**新的问题?** + +假如我们在员工表中增加一条记录 + +![image20200213225528342.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/21/1603240601021.png) + +员工表中的记录dep_id中的3,在部门表中并没有这个id的记录。我们也将这条记录加入了进去。那么我们的员工王六就没有对应的部门了。这种情况在实际的应用中是不允许的。 + +**实际情况:** + +我们员工表中的dep_id的值,只能是部门表中存在的id。 + +**解决方法:** + +使用外键约束 + +### 7.4、什么是外键约束 + +一张表的一个字段受限于另外一张表的一个字段对应的值。这里涉及到两张表:被引用的表叫主表(父表),另外一张叫从表(子表)。 + +**子表:**定义了外键的表,外键的取值要么取父表中字段对应的值,要么取NULL值,严重受限于父表 + +**父表:**被引用的字段要具有唯一性(绝大多数都是用的父表的主键) + +![image20200213230844619.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/21/1603240617595.png) + +### + +## 八、外键约束 + +### 8.1、外键约束格式 + +```mysql +格式一: +[constraint][外键约束名称] foreign key(外键字段名) references 主表名称(主键字段名); #在create table时设置 +``` + +**案例:** + +创建一个班级表: + +```mysql +create table classes( -- 班级表 +cid int primary key auto_increment,-- 班级ID +cname varchar(20),-- 班级名称 +crenshu int(3),-- 班级人数 +cmajor varchar(10),-- 专业 +cmark text -- 备注 +); + +mysql> desc classes; ++---------+-------------+------+-----+---------+----------------+ +| Field | Type | Null | Key | Default | Extra | ++---------+-------------+------+-----+---------+----------------+ +| cid | int(11) | NO | PRI | NULL | auto_increment | +| cname | varchar(20) | YES | | NULL | | +| crenshu | int(3) | YES | | NULL | | +| cmajor | varchar(10) | YES | | NULL | | +| cmark | text | YES | | NULL | | ++---------+-------------+------+-----+---------+----------------+ +5 行于数据集 (0.01 秒) +``` + +插入班级信息: + +```mysql +mysql> insert into classes values(null,'一班',60,'计算机','学校的王牌专业'),(null,'二班',50,'财务会计','学校最好就业专业'); +Query OK, 2 rows affected (0.06 秒) +mysql> select * from classes; ++-----+--------+---------+--------------+--------------------------+ +| cid | cname | crenshu | cmajor | cmark | ++-----+--------+---------+--------------+--------------------------+ +| 3 | 一班 | 60 | 计算机 | 学校的王牌专业 | +| 4 | 二班 | 50 | 财务会计 | 学校最好就业专业 | ++-----+--------+---------+--------------+--------------------------+ +2 行于数据集 (0.01 秒) +``` + +创建一个学生表(与班级表建立主外键关联): + +```mysql +create table stu -- 学生表 +( +sid int primary key auto_increment, -- 学生ID +sname varchar(20),-- 学生姓名 +ssex varchar(2),-- 性别 +stell varchar(11),-- 电话号码 +sdate date ,-- 入学日期 +srmark varchar(30),-- 备注 +sclassid int,-- 外键对应主表中的主建 +-- 创建外键约束 +constraint stu_sclassid_fk foreign key (sclassid) references classes(cid) +); + +mysql> desc stu; ++----------+-------------+------+-----+---------+----------------+ +| Field | Type | Null | Key | Default | Extra | ++----------+-------------+------+-----+---------+----------------+ +| sid | int(11) | NO | PRI | NULL | auto_increment | +| sname | varchar(20) | YES | | NULL | | +| ssex | varchar(2) | YES | | NULL | | +| stell | varchar(11) | YES | | NULL | | +| sdate | date | YES | | NULL | | +| srmark | varchar(30) | YES | | NULL | | +| sclassid | int(11) | YES | MUL | NULL | | ++----------+-------------+------+-----+---------+----------------+ +7 行于数据集 (0.01 秒) +``` + +**注意:** + +PRI主键约束; UNI唯一约束; MUL可以重复。 + +插入学生信息: + +```mysql +mysql> insert into stu values(null,'张三','男','13111111111','2019-09-01','学习成绩不错',3); +Query OK, 1 rows affected (0.03 秒) + +mysql> insert into stu values(null,'李四','男','13112211112','2019-09-01','学习成绩一般',1); +Cannot add or update a child row: a foreign key constraint fails (`zutuanxue`.`stu`, CONSTRAINT `stu_sclassid_fk` FOREIGN KEY (`sclassid`) REFERENCES `classes` (`cid`)) + +mysql> select * from stu; ++-----+--------+------+-------------+------------+--------------------+----------+ +| sid | sname | ssex | stell | sdate | srmark | sclassid | ++-----+--------+------+-------------+------------+--------------------+----------+ +| 1 | 张三 | 男 | 13111111111 | 2019-09-01 | 学习成绩不错 | 3 | ++-----+--------+------+-------------+------------+--------------------+----------+ +1 行于数据集 (0.02 秒) +格式二: +alter table 从表名称 add [constraint][外键约束名称] foreign key(外键字段名) references 主表名称(主键字段名); #建好表后修改 +``` + +案例: + +创建一个学生表: + +```mysql +create table stu1 -- 学生表 +( +sid int primary key auto_increment, -- 学生ID +sname varchar(20),-- 学生姓名 +ssex varchar(2),-- 性别 +stell varchar(11),-- 电话号码 +sdate date ,-- 入学日期 +srmark varchar(30),-- 备注 +sclassid int -- 外键对应主表中的主建 +); + +mysql> desc stu1; ++----------+-------------+------+-----+---------+----------------+ +| Field | Type | Null | Key | Default | Extra | ++----------+-------------+------+-----+---------+----------------+ +| sid | int(11) | NO | PRI | NULL | auto_increment | +| sname | varchar(20) | YES | | NULL | | +| ssex | varchar(2) | YES | | NULL | | +| stell | varchar(11) | YES | | NULL | | +| sdate | date | YES | | NULL | | +| srmark | varchar(30) | YES | | NULL | | +| sclassid | int(11) | YES | | NULL | | ++----------+-------------+------+-----+---------+----------------+ +7 行于数据集 (0.02 秒) +``` + +为我们的学生表stu1加入我们的外键约束 + +```mysql +mysql> alter table stu1 add constraint stu_sclassid_fk1 +foreign key (sclassid) references classes(cid); +Query OK, 0 rows affected (0.05 秒) + +mysql> desc stu1; ++----------+-------------+------+-----+---------+----------------+ +| Field | Type | Null | Key | Default | Extra | ++----------+-------------+------+-----+---------+----------------+ +| sid | int(11) | NO | PRI | NULL | auto_increment | +| sname | varchar(20) | YES | | NULL | | +| ssex | varchar(2) | YES | | NULL | | +| stell | varchar(11) | YES | | NULL | | +| sdate | date | YES | | NULL | | +| srmark | varchar(30) | YES | | NULL | | +| sclassid | int(11) | YES | MUL | NULL | | ++----------+-------------+------+-----+---------+----------------+ +7 行于数据集 (0.02 秒) +``` + +插入学生信息: + +```mysql +mysql> insert into stu1 values(null,'张三','男','13111111111','2019-09-01','学习成绩不错',3); +Query OK, 1 rows affected (0.07 秒) + +mysql> insert into stu1 values(null,'李四','男','13112211112','2019-09-01','学习成绩一般',1); +Cannot add or update a child row: a foreign key constraint fails (`zutuanxue`.`stu1`, CONSTRAINT `stu_sclassid_fk1` FOREIGN KEY (`sclassid`) REFERENCES `classes` (`cid`)) + +mysql> select * from stu1; ++-----+--------+------+-------------+------------+--------------------+----------+ +| sid | sname | ssex | stell | sdate | srmark | sclassid | ++-----+--------+------+-------------+------------+--------------------+----------+ +| 1 | 张三 | 男 | 13111111111 | 2019-09-01 | 学习成绩不错 | 3 | ++-----+--------+------+-------------+------------+--------------------+----------+ +1 行于数据集 (0.01 秒) +``` + +### 8.2、删除外键约束 + +```mysql +格式: +alter table 从表 drop foreign key 外键约束名称; +``` + +**案例:** + +删除stu1中的外表关联 + +```mysql +mysql> alter table stu1 drop foreign key stu_sclassid_fk1; +Query OK, 0 rows affected (0.05 秒) + +mysql> desc stu1; ++----------+-------------+------+-----+---------+----------------+ +| Field | Type | Null | Key | Default | Extra | ++----------+-------------+------+-----+---------+----------------+ +| sid | int(11) | NO | PRI | NULL | auto_increment | +| sname | varchar(20) | YES | | NULL | | +| ssex | varchar(2) | YES | | NULL | | +| stell | varchar(11) | YES | | NULL | | +| sdate | date | YES | | NULL | | +| srmark | varchar(30) | YES | | NULL | | +| sclassid | int(11) | YES | MUL | NULL | | ++----------+-------------+------+-----+---------+----------------+ +7 行于数据集 (0.02 秒) +``` + +插入数据 + +```mysql +mysql> insert into stu1 values(null,'李四','男','13112211112','2019-09-01','学习成绩一般',1); +Query OK, 1 rows affected (0.04 秒) + +mysql> select * from stu1; ++-----+--------+------+-------------+------------+--------------------+----------+ +| sid | sname | ssex | stell | sdate | srmark | sclassid | ++-----+--------+------+-------------+------------+--------------------+----------+ +| 1 | 张三 | 男 | 13111111111 | 2019-09-01 | 学习成绩不错 | 3 | +| 3 | 李四 | 男 | 13112211112 | 2019-09-01 | 学习成绩一般 | 1 | ++-----+--------+------+-------------+------------+--------------------+----------+ +2 行于数据集 (0.01 秒) +``` + +## 九、级联操作 + +### 9.1、为什么要级联 + +当我们的主表班级表中的cid发生变化时,我们应该如何去改变我们的从表学生表中的sclassid?这个时候我们就需要级联。 + +```mysql +mysql> delete from classes; +Cannot delete or update a parent row: a foreign key constraint fails (`zutuanxue`.`stu`, CONSTRAINT `stu_sclassid_fk` FOREIGN KEY (`sclassid`) REFERENCES `classes` (`cid`)) +mysql> delete from classes where cid=3; +Cannot delete or update a parent row: a foreign key constraint fails (`zutuanxue`.`stu`, CONSTRAINT `stu_sclassid_fk` FOREIGN KEY (`sclassid`) REFERENCES `classes` (`cid`)) +mysql> update classes set cid=1 where cid=3; +Cannot delete or update a parent row: a foreign key constraint fails (`zutuanxue`.`stu`, CONSTRAINT `stu_sclassid_fk` FOREIGN KEY (`sclassid`) REFERENCES `classes` (`cid`)) +``` + +### 9.2、级联是什么 + +在修改和删除主表的主键时,同时更新或删除副表的外键值,称为级联操作。 + +级联操作分为二种:级联更新、级联删除 + +### 9.2、级联操作方式 + +```mysql +格式: +on update cascade #级联更新 +on delete cascade #级联操作 +``` + +只能是创建表的时候创建级联关系。更新主表中的主键,从表中的外键列也自动同步更新 + +**案例:** + +创建一个学生表(与班级表建立主外键关联,并加入级联操作) + +```mysql +create table stu -- 学生表 +( +sid int primary key auto_increment, -- 学生ID +sname varchar(20),-- 学生姓名 +ssex varchar(2),-- 性别 +stell varchar(11),-- 电话号码 +sdate date ,-- 入学日期 +srmark varchar(30),-- 备注 +sclassid int,-- 外键对应主表中的主建 +-- 创建外键约束 +constraint stu_sclassid_fk foreign key (sclassid) references classes(cid) on update cascade on delete cascade +); +``` + +在学生表中插入数据 + +```mysql +mysql> insert into stu values(null,'张三','男','13111111111','2019-09-01','学习成绩不错',3); +Query OK, 1 rows affected (0.11 秒) + +mysql> insert into stu values(null,'李四','男','13112211112','2019-09-01','学习成绩一般',4); +Query OK, 1 rows affected (0.08 秒) + +mysql> select * from stu; ++-----+--------+------+-------------+------------+--------------------+----------+ +| sid | sname | ssex | stell | sdate | srmark | sclassid | ++-----+--------+------+-------------+------------+--------------------+----------+ +| 1 | 张三 | 男 | 13111111111 | 2019-09-01 | 学习成绩不错 | 3 | +| 2 | 李四 | 男 | 13112211112 | 2019-09-01 | 学习成绩一般 | 4 | ++-----+--------+------+-------------+------------+--------------------+----------+ +2 行于数据集 (0.01 秒) +``` + +修改我们班级表中的主键 + +```mysql +mysql> select * from classes; ++-----+--------+---------+--------------+--------------------------+ +| cid | cname | crenshu | cmajor | cmark | ++-----+--------+---------+--------------+--------------------------+ +| 3 | 一班 | 60 | 计算机 | 学校的王牌专业 | +| 4 | 二班 | 50 | 财务会计 | 学校最好就业专业 | ++-----+--------+---------+--------------+--------------------------+ +2 行于数据集 (0.01 秒) + +mysql> update classes set cid=1 where cid=3; +Query OK, 1 rows affected (0.06 秒) + +mysql> select * from classes; ++-----+--------+---------+--------------+--------------------------+ +| cid | cname | crenshu | cmajor | cmark | ++-----+--------+---------+--------------+--------------------------+ +| 1 | 一班 | 60 | 计算机 | 学校的王牌专业 | +| 4 | 二班 | 50 | 财务会计 | 学校最好就业专业 | ++-----+--------+---------+--------------+--------------------------+ +2 行于数据集 (0.01 秒) + +mysql> select * from stu; ++-----+--------+------+-------------+------------+--------------------+----------+ +| sid | sname | ssex | stell | sdate | srmark | sclassid | ++-----+--------+------+-------------+------------+--------------------+----------+ +| 1 | 张三 | 男 | 13111111111 | 2019-09-01 | 学习成绩不错 | 1 | +| 2 | 李四 | 男 | 13112211112 | 2019-09-01 | 学习成绩一般 | 4 | ++-----+--------+------+-------------+------------+--------------------+----------+ +2 行于数据集 (0.01 秒) +``` + +删除我们班级表中的主键 + +```mysql +mysql> delete from classes where cid=4; +Query OK, 1 rows affected (0.01 秒) + +mysql> select * from classes; ++-----+--------+---------+-----------+-----------------------+ +| cid | cname | crenshu | cmajor | cmark | ++-----+--------+---------+-----------+-----------------------+ +| 1 | 一班 | 60 | 计算机 | 学校的王牌专业 | ++-----+--------+---------+-----------+-----------------------+ +1 行于数据集 (0.01 秒) + +mysql> select * from stu; ++-----+--------+------+-------------+------------+--------------------+----------+ +| sid | sname | ssex | stell | sdate | srmark | sclassid | ++-----+--------+------+-------------+------------+--------------------+----------+ +| 1 | 张三 | 男 | 13111111111 | 2019-09-01 | 学习成绩不错 | 1 | ++-----+--------+------+-------------+------------+--------------------+----------+ +1 行于数据集 (0.01 秒) +``` + +## 十、检查约束 + +### 10.1、什么是检查约束 + +检查约束指定某列中的值必须满足布尔表达式,根据用户自己的需求来进行限制。 + +### 10.2、检查约束使用 + +#### 10.2.1、行级添加 + +```mysql +格式: +create table 表名 +( + check (字段名1 != 字段名1), + 字段名1 字段类型 check (表达式), + 字段名2 字段类型 constraint 唯一约束名 check (表达式) [not enforced] +); +``` + +**注意:** + +表达式中可以包含该字段名: 字段名 > 0 +表达式注意事项 +1.允许使用文字,内置函数和运算符 +2.不允许在使用了auto_increment的列上使用 +3.不允许存储函数和用户定义的函数 +4.不允许子查询等 +如果省略或指定为enforced,则创建并强制执行约束。 +如果指定为not enforced,则创建约束但不强制执行。 + +**案例:** + +创建一个表t4 + +```mysql +create table t4 +( + id int primary key auto_increment, + username varchar(32), + phone varchar(11) check(length(phone) =11) +); +``` + +插入数据 + +```mysql +mysql> insert into t4 values(null,'zhangsan','13812221222'); +Query OK, 1 rows affected (0.01 秒) + +mysql> insert into t4 values(null,'zhangsan','1381222125'); +Check constraint 't4_chk_1' is violated. +``` + +#### 10.2.2、表级添加 + +```mysql +格式: +create table 表名 +( + 字段名1 字段类型, + 字段名2 字段类型, + [constraint 检查约束名] check(布尔表达式) [ not enforced] +); +``` + +**案例:** + +创建一个表t5 + +```mysql +create table t5 +( + id int primary key auto_increment, + username varchar(32), + phone varchar(11), + constraint t5_check_phone check(length(phone) =11) +); +``` + +插入数据 + +```mysql +mysql> insert into t5 values(null,'zhangsan','13812222222'); +Query OK, 1 rows affected (0.01 秒) + +mysql> insert into t5 values(null,'zhangsan','1381222222'); +Check constraint 't4_check_phone' is violated. +``` + +#### 10.2.3、表后添加 + +```mysql +格式: +alter table 数据库表名 add constraint 检查约束名 check(检查约束); +``` + +案例: + +创建一个表t6 + +```mysql +create table t6 +( + id int primary key auto_increment, + username varchar(32), + phone varchar(11) +); + +mysql> alter table t6 add constraint t6_check_phone check(length(phone)=11); +Query OK, 0 rows affected (0.09 秒) +``` + +插入数据 + +```mysql +mysql> insert into t6 values(null,'zhangsan','13812221222'); +Query OK, 1 rows affected (0.01 秒) + +mysql> insert into t6 values(null,'zhangsan','1381222125'); +Check constraint 't6_check_phone' is violated. +``` + +#### 10.2.4、约束删除 + +```mysql +格式: +alter table 数据库表名 drop check 检查约束名; +``` + +案例: + +删除t6表中的检查约束t6_check_phone + +```mysql +mysql> alter table t6 drop check t6_check_phone; +Query OK, 0 rows affected (0.02 秒) +``` + +插入数据 + +```mysql +mysql> insert into t6 values(null,'zhangsan','1381222125'); +Query OK, 1 rows affected (0.01 秒) +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\350\247\206\345\233\276.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\350\247\206\345\233\276.md" new file mode 100644 index 0000000..64cb5a9 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySQL\350\247\206\345\233\276.md" @@ -0,0 +1,520 @@ +视图是指计算机数据库中的视图,是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。但是,视图并不在数据库中以存储的数据值集形式存在。行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。 + +## 一、视图概述 + +### 1.1、什么是视图 + +在 SQL 中,视图是基于 SQL 语句的结果集的可视化的表。 + +视图包含行和列,就像一个真实的表。视图中的字段就是来自一个或多个数据库中的真实的表中的字段。我们可以向视图添加 SQL 函数、WHERE 以及 JOIN 语句,我们也可以提交数据,就像这些来自于某个单一的表。 + +**注意:** + +数据库的设计和结构不会受到视图中的函数、where 或 join 语句的影响。 + +### 1.2、视图的作用 + +重复利用SQL语句 + +简化SQL查询,快速取数据 + +只用知道表的部分结构 + +保护数据,根据特定授权 + +更改数据格式和表示,视图可返回与底层表的表示和格式不同的数据 + +**注意:** +在视图创建后,可以用与表基本相同的方式使用(查询、过滤、排序数据、与其他视图或连结、(添加、更新))。 + +视图只是用来查看存储在别处的数据的设施,本身不包含数据,返回的数据也是从其他表检索出来的。 + +因为视图本身不包含数据,索引多个表连结或嵌套可能存在性能问题,需测试。 + +### 1.3、视图规则和限制 + +与表一样,命名必须是唯一的(不能出现同名视图或表名)。 + +创建视图数目无限制,但是要考虑复杂查询创建为视图之后的性能影响。 + +视图不能添加索引,也不能有关联的触发器或者默认值。 + +视图可以提高安全性,必须具有足够的访问权限。 + +order by可用在视图中,但是如果从该视图检索数据select中含有order by ,那么该视图中的order by将被覆盖。 + +视图可以和表一起使用。 + +### 1.4、视图的应用 + +**权限控制时使用** + +如某几个列,允许用户查询,其他列不允许查询 + +可以通过视图,开放其中几列查询,起到权限控制作用 + +**简化复杂查询时使用** + +查询每个栏目下商品的平均价格,并按平均价格排序,查询出平均价格前3的栏目 + +**视图能不能更新,删除,添加** + +如果视图的每一行,是与物理表一一对应的则可以 + +视图的行是由物理表多行经过计算得到的结果,视图不可以更新的 + +## 二、视图创建 + +### 2.1、创建格式 + +```mysql +格式: +create view 视图名 as select 字段名 from 表名; +``` + +案例: + +创建一个视图 + +```mysql +mysql> create view s_view as (select sname,sex,age from students); +Query OK, 0 rows affected (0.02 sec) + +mysql> select * from s_view; ++--------+------+------+ +| sname | sex | age | ++--------+------+------+ +| 张三 | 男 | 19 | +| 李四 | 男 | 20 | +| 张红 | 女 | 19 | +| 张八 | 男 | 18 | +| 三李 | 男 | 19 | +| 王六 | 女 | 20 | +| 刘红 | 女 | 18 | ++--------+------+------+ +8 rows in set (0.00 sec) +``` + +### 2.2、视图的运算规则 + +```mysql +格式: +create [algorithm = {undefined | merge | temptable}] view 视图名 as select 字段名 from 表名; +``` + +**注意:** + +ALGORITHM : 视图算法 + +undefined 系统自动选择算法 + +merge 当使用视图时,会把查询视图的语句和创建视图的语句合并起来,形成一条件一句,最后再从基表中查询 + +temptable 当使用视图时,会把创建视图的语句的查询结果当成一张临时表,再从临时表中进行筛选 + +**案例:** + +用temptable创建视图 + +```mysql +mysql> create algorithm=temptable view view_t as select sname,sex,english,math from students order by math,english desc; +Query OK, 0 rows affected (0.03 秒) + +mysql> select * from view_t; ++--------+------+---------+------+ +| sname | sex | english | math | ++--------+------+---------+------+ +| 王六 | 女 | 50.0 | 70.0 | +| 张红 | 女 | 86.0 | 80.0 | +| 张八 | 男 | 80.0 | 85.0 | +| 张三 | 男 | 98.5 | 88.0 | +| 李四 | 男 | 80.0 | 88.0 | +| 三李 | 男 | 60.0 | 88.0 | +| 刘红 | 女 | 90.0 | 98.0 | ++--------+------+---------+------+ +8 行于数据集 (0.01 秒) + +mysql> select * from view_t group by sex; ++--------+------+---------+------+ +| sname | sex | english | math | ++--------+------+---------+------+ +| 王六 | 女 | 50.0 | 70.0 | +| 张八 | 男 | 80.0 | 85.0 | ++--------+------+---------+------+ +2 行于数据集 (0.01 秒) +``` + +用merge创建视图 + +```mysql +mysql> create algorithm=merge view view_m as select sname,sex,english,math from students order by math,english desc; +Query OK, 0 rows affected (0.04 秒) + +mysql> select * from view_m; ++--------+------+---------+------+ +| sname | sex | english | math | ++--------+------+---------+------+ +| 王六 | 女 | 50.0 | 70.0 | +| 张红 | 女 | 86.0 | 80.0 | +| 张八 | 男 | 80.0 | 85.0 | +| 张三 | 男 | 98.5 | 88.0 | +| 李四 | 男 | 80.0 | 88.0 | +| 三李 | 男 | 60.0 | 88.0 | +| 刘红 | 女 | 90.0 | 98.0 | ++--------+------+---------+------+ +8 行于数据集 (0.02 秒) + +mysql> select * from view_m group by sex; ++--------+------+---------+------+ +| sname | sex | english | math | ++--------+------+---------+------+ +| 张三 | 男 | 98.5 | 88.0 | +| 张红 | 女 | 86.0 | 80.0 | ++--------+------+---------+------+ +2 行于数据集 (0.01 秒) +#查询视图的语句和创建视图的语句合并起来,形成一条件一句,最后再从基表中查询 +mysql> select sname,sex,english,math from students group by sex order by math,english desc; ++--------+------+---------+------+ +| sname | sex | english | math | ++--------+------+---------+------+ +| 张红 | 女 | 86.0 | 80.0 | +| 张三 | 男 | 98.5 | 88.0 | ++--------+------+---------+------+ +2 行于数据集 (0.02 秒) +``` + +### 2.3、视图的权限范围 + +```mysql +格式: +[with [cascaded | local ] check option] +``` + +WITH CHECK OPTION 表示对UPDATE、INSERT和DELETE操作时保持更新,插入或删除的行满足视图定义的条件(即子查询中的条件表达式) + +**注意:** + +cascaded 默认值 更新视图时要满足所有相关视图和表的条件。 + +local 表示更新视图时满足该视图本身定义的条件即可。 + +**案例:** + +```mysql +mysql> create view view_1 as select sid,sname,sex,age from students where sid<6; +Query OK, 0 rows affected (0.02 秒) + +mysql> create view view_1_1 as select * from view_1 where sid>2 with cascaded check option; +Query OK, 0 rows affected (0.02 秒) + +mysql> create view view_1_2 as select * from view_1 where sid>2 with local check option; +Query OK, 0 rows affected (0.02 秒) + +mysql> insert into view_1_1 values(6,'lisi','男',20); +CHECK OPTION failed 'zutuanxue.view_1_1' + +mysql> insert into view_1_2 values(6,'lisi','男',20); +Query OK, 1 rows affected (0.01 秒) +``` + +### 2.4、视图记录修改 + +```mysql +格式: +update 数据库表名 set 字段名1=字段值1,字段名2=字段值2,...字段名n=字段值n where 条件表达式; #和表的修改一样 +``` + +案例: + +修改视图中王六的性别为‘男’ + +```mysql +mysql> update s_view set sex='男' where sname='王六'; +Query OK, 1 row affected (0.01 sec) +Rows matched: 1 Changed: 1 Warnings: 0 + +mysql> select * from s_view; ++--------+------+------+ +| sname | sex | age | ++--------+------+------+ +| 张三 | 男 | 19 | +| 李四 | 男 | 20 | +| 张红 | 女 | 19 | +| 张八 | 男 | 18 | +| 三李 | 男 | 19 | +| 王六 | 男 | 20 | +| 刘红 | 女 | 18 | ++--------+------+------+ +8 rows in set (0.00 sec) +``` + +**注意:** + +修改了视图,对基表数据也有影响 + +```mysql +mysql> select * from students; ++------+--------+------+------+---------+------+------------+-----------------+ +| sid | sname | sex | age | english | math | entertime | remark | ++------+--------+------+------+---------+------+------------+-----------------+ +| 1 | 张三 | 男 | 19 | 98.5 | 88.0 | 2017-09-01 | 他来自四川 | +| 2 | 李四 | 男 | 20 | 80.0 | 88.0 | 2017-09-01 | 他来自重庆 | +| 3 | 张红 | 女 | 19 | 86.0 | 80.0 | 2017-09-01 | 他来自北京 | +| 4 | 张八 | 男 | 18 | 80.0 | 85.0 | 2017-09-01 | 他来自天津 | +| 5 | 三李 | 男 | 19 | 60.0 | 88.0 | 2017-09-01 | 他来自湖北 | +| 6 | 王六 | 男 | 20 | 50.0 | 70.0 | 2017-09-01 | 他来自湖南 | +| 7 | 刘红 | 女 | 18 | 90.0 | 98.0 | 2017-09-01 | 他来自甘肃 | ++------+--------+------+------+---------+------+------------+-----------------+ +8 rows in set (0.00 sec) +``` + +修改students表中王六的年龄为21 + +```mysql +mysql> update students set age=21 where sname='王六'; +Query OK, 1 row affected (0.00 sec) +Rows matched: 1 Changed: 1 Warnings: 0 + +mysql> select * from s_view; ++--------+------+------+ +| sname | sex | age | ++--------+------+------+ +| 张三 | 男 | 19 | +| 李四 | 男 | 20 | +| 张红 | 女 | 19 | +| 张八 | 男 | 18 | +| 三李 | 男 | 19 | +| 王六 | 男 | 21 | +| 刘红 | 女 | 18 | ++--------+------+------+ +8 rows in set (0.00 sec) +``` + +## 三、视图修改 + +### 3.1、修改格式 + +```mysql +格式: +alter view 视图名称 as select 语句; +或 +alter view 视图名称 as select 视图; +或 +create or replace view 视图名 as select 字段名 from 表名; +``` + +### 3.2、select 语句 修改 + +**案例:** + +修改我们的s_view视图 + +```mysql +mysql> alter view s_view as select sname,sex,age,remark from students; +Query OK, 0 rows affected (0.01 sec) + +mysql> select * from s_view; ++--------+------+------+-----------------+ +| sname | sex | age | remark | ++--------+------+------+-----------------+ +| 张三 | 男 | 19 | 他来自四川 | +| 李四 | 男 | 20 | 他来自重庆 | +| 张红 | 女 | 19 | 他来自北京 | +| 张八 | 男 | 18 | 他来自天津 | +| 三李 | 男 | 19 | 他来自湖北 | +| 王六 | 女 | 20 | 他来自湖南 | +| 刘红 | 女 | 18 | 他来自甘肃 | ++--------+------+------+-----------------+ +8 rows in set (0.01 sec) +``` + +### 3.3、select 视图 修改 + +**案例:** + +修改我们的s_view视图 + +```mysql +mysql> create view s_view_1 as(select sname,sex,age,remark from students); +Query OK, 0 rows affected (0.01 sec) + +mysql> alter view s_view as select sname,remark from s_view_1; +Query OK, 0 rows affected (0.01 sec) + +mysql> select * from s_view; ++--------+-----------------+ +| sname | remark | ++--------+-----------------+ +| 张三 | 他来自四川 | +| 李四 | 他来自重庆 | +| 张红 | 他来自北京 | +| 张八 | 他来自天津 | +| 三李 | 他来自湖北 | +| 王六 | 他来自湖南 | +| 刘红 | 他来自甘肃 | ++--------+-----------------+ +8 rows in set (0.00 sec) +``` + +### 3.4、create or replace + +**案例:** + +修改我们的s_view视图 + +```mysql +mysql> create or replace view s_view as select sname from students; +Query OK, 0 rows affected (0.01 sec) + +mysql> select * from s_view; ++--------+ +| sname | ++--------+ +| 张三 | +| 李四 | +| 张红 | +| 张八 | +| 三李 | +| 王六 | +| 刘红 | ++--------+ +8 rows in set (0.00 sec) +``` + +## 四、视图查看 + +### 4.1、显示视图创建情况 + +```mysql +格式: +show create view 视图名; +``` + +案例: + +```mysql +mysql> show create view s_view; ++--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+ +| View | Create View | character_set_client | collation_connection | ++--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+ +| s_view | CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `s_view` AS select `s_view_1`.`sname` AS `sname`,`s_view_1`.`remark` AS `remark` from `s_view_1` | utf8mb4 | utf8mb4_0900_ai_ci | ++--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+ +1 row in set (0.00 sec) +``` + +### 4.2、查看视图 + +### 4.2.1、查看视图结构 + +```mysql +格式: +desc 视图名; +``` + +**案例:** + +查看视图s_view结构 + +```mysql +mysql> desc s_view; ++-------+-------------+------+-----+---------+-------+ +| Field | Type | Null | Key | Default | Extra | ++-------+-------------+------+-----+---------+-------+ +| sname | varchar(20) | YES | | NULL | | ++-------+-------------+------+-----+---------+-------+ +1 row in set (0.02 sec) +``` + +#### 4.2.2、查看数据库中的视图 + +```mysql +格式: +show tables [like %字符串%]; +``` + +案例: + +查看数据库中所有视图 + +```mysql +mysql> show tables; ++--------------------+ +| Tables_in_zutuanxue | ++--------------------+ +| classes | +| new_user | +| s_view | +| s_view_1 | +| stu | +| student | +| students | +| t1 | +| t2 | +| t3 | +| t4 | +| t5 | +| t6 | +| teacher | +| user | ++--------------------+ +15 rows in set (0.00 sec) + +mysql> show tables like '%view%'; ++-----------------------------+ +| Tables_in_zutuanxue (%view%) | ++-----------------------------+ +| s_view | +| s_view_1 | ++-----------------------------+ +2 rows in set (0.00 sec) +``` + +## 五、视图删除及重命名 + +### 5.1、视图删除 + +```mysql +格式: +drop view 视图列表; +``` + +案例: + +删除视图s_view_1 + +```mysql +mysql> drop view s_view_1; +Query OK, 0 rows affected (0.00 sec) + +mysql> show tables like '%view%'; ++-----------------------------+ +| Tables_in_zutuanxue (%view%) | ++-----------------------------+ +| s_view | ++-----------------------------+ +1 row in set (0.00 sec) +``` + +### 5.2、视图重命名 + +```mysql +格式: +rename table 视图名 to 新视图名; +``` + +案例: + +修改视图s_view的名字为view_s + +```mysql +mysql> rename table s_view to view_s; +Query OK, 0 rows affected (0.01 sec) + +mysql> show tables like '%view%'; ++-----------------------------+ +| Tables_in_zutuanxue (%view%) | ++-----------------------------+ +| view_s | ++-----------------------------+ +1 row in set (0.01 sec) +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySql\345\256\211\350\243\205\344\270\216\344\275\277\347\224\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySql\345\256\211\350\243\205\344\270\216\344\275\277\347\224\250.md" new file mode 100644 index 0000000..627423b --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySql\345\256\211\350\243\205\344\270\216\344\275\277\347\224\250.md" @@ -0,0 +1,255 @@ +mysql是目前最流行的关系型数据库管理系统,在WEB应用方面MySQL是最好的RDBMS(Relational Database Management System:关系数据库管理系统)应用软件之一。 + +MySQL是非常灵活的一款数据库,虽然它不是绝对完美,但它的灵活足够适应很多高要求的环境。为了发挥MySQL的性能并很好的使用它,我们就得先了解其设计。MySQL的灵活主要体现在我们可以通过不同的配置使他在不同的硬件上都能运行的很好。但是MySQL最重要,与众不同的特性是它的存储引擎架构,这种架构将查询处理及其他系统任务和数据的存储/提取相分离。 + +## 一、mysql概述 + +### 1.1、关系型数据库 + +关系型数据库天然就是二维表格,因此存储在数据表的行和列中。数据表可以彼此关联协作存储,也很容易提取数据。 + +### 1.2、MySQL数据库 + +MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司。 + +MySQL可将数据保存在不同的表中,而不是将所有数据放在一个大的仓库内,从而加快了访问速度并提高了灵活性。 + +MySQL 使用了标准的 SQL 语言形式。支持大型的数据库,可以处理拥有上千万条记录的大型数据库。MySQL 还可用于多种系统中,且支持多种语言。 + +### 1.3、RDBMS术语 + +数据库:数据库是一些关联表的集合。 + +数据表:表是数据的矩阵。在一个数据库中的表看起来像一个简单的电子表格。 + +列:一列(数据元素)包含了相同的数据,例如邮政编码的数据。 + +行:一行(=元组,或者记录)是一组相关的数据,例如一条用户订阅的数据。 + +亢余:存储两倍数据,亢余降低了性能,但是提高了数据的安全性。 + +主键:主键是唯一的,一个数据表中只能够包含一个主键,你可以使用主键来查询数据。 + +外键:外键用于关联两个表。 + +复合键:复合键(组合键)将多个列作为一个索引键,一般用于复合索引。 + +索引:使用索引可快速访问数据库表中的特定信息。索引是对数据库表中一列或者多列的值进行排序的一种结构。类似于书籍的目录。 + +### 1.4、mysql下载 + +https://dev.mysql.com/downloads/mysql/ + +![image20200223135527926.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186097183.png) + +点击“Download”后,我们要先登录Oracle,才能进行下载。 + +## 2、mysql安装 + +### 2.1、指定安装文件位置 + +将mysql安装包放到/usr/local/下面 + +![image20200223011252870.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186112844.png) + +### 2.2、解压 + +``` +[root@zutuanxue local]# xz -d mysql-8.0.17-linux-glibc2.12-x86_64.tar.xz +[root@zutuanxue local]# tar -xvf mysql-8.0.17-linux-glibc2.12-x86_64.tar +``` + +### 2.3、改名 + +``` +[root@zutuanxue local]# mv mysql-8.0.17-linux-glibc2.12-x86_64 mysql +``` + +### 2.4、创建用户组 + +mysql用户组、mysql用户 + +``` +[root@zutuanxue local]# groupadd mysql +[root@zutuanxue local]# useradd -r -g mysql mysql +[root@zutuanxue local]# passwd mysql +#更改密码:Ww1985929wW +``` + +### 2.5、修改MySQL配置文件 + +/etc/my.cnf + +``` +# For advice on how to change settings please see +# http://dev.mysql.com/doc/refman/5.6/en/server-configuration-defaults.html +# *** DO NOT EDIT THIS FILE. It's a template which will be copied to the +# *** default location during install, and will be replaced if you +# *** upgrade to a newer version of MySQL. + +[mysqld] + +# Remove leading # and set to the amount of RAM for the most important data +# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%. +# innodb_buffer_pool_size = 128M + +# Remove leading # to turn on a very important data integrity option: logging +# changes to the binary log between backups. +# log_bin + +# These are commonly set, remove the # and set as required. +basedir = /usr/local/mysql +datadir = /usr/local/mysql/data +port = 3306 +# server_id = ..... +socket = /tmp/mysql.sock +character-set-server = utf8 +skip-name-resolve +log-error = /usr/local/mysql/data/error.log +pid-file = /usr/local/mysql/data/mysql.pid + +# Remove leading # to set options mainly useful for reporting servers. +# The server defaults are faster for transactions and fast SELECTs. +# Adjust sizes as needed, experiment to find the optimal values. +# join_buffer_size = 128M +# sort_buffer_size = 2M +# read_rnd_buffer_size = 2M + +sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES +``` + +### 2.6、创建data文件夹 + +data文件夹是用于存储数据库文件,他的位置是在mysql目录下 + +``` +[root@zutuanxue mysql]# mkdir data +``` + +### 2.7、更改mysql目录权限 + +``` +[root@zutuanxue mysql]# chown -R mysql . +[root@zutuanxue mysql]# chgrp -R mysql . +``` + +![image20200223012815486.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186134688.png) + +### 2.8、初始化数据库 + +``` +[root@zutuanxue mysql]# ./bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data +``` + +执行完后查看初始密码: + +``` +[root@zutuanxue mysql]# vim /usr/local/mysql/data/error.log +``` + +![image20200223013228179.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186163795.png) + +![image20200223182708100.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186172227.png) + +### 2.9、启动mysql服务 + +``` +[root@zutuanxue mysql]# ./support-files/mysql.server start +Starting MySQL... SUCCESS! +``` + +### 2.10、修改root密码 + +``` +[root@zutuanxue mysql]# ./bin/mysql -uroot -prj%-:yqHb98g +``` + +![image20200223014851493.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186189059.png) + +**修改密码:** + +``` +mysql> alter user 'root'@'localhost' identified by 'Root123456'; +Query OK, 0 rows affected (0.05 sec) +``` + +## 3、mysql操作 + +### 3.1、服务器操作 + +启动、停止、重启 + +``` +[root@zutuanxue mysql]# ./support-files/mysql.server restart +Shutting down MySQL. SUCCESS! +Starting MySQL.. SUCCESS! +[root@zutuanxue mysql]# ./support-files/mysql.server stop +Shutting down MySQL.. SUCCESS! +[root@zutuanxue mysql]# ./support-files/mysql.server start +Starting MySQL.. SUCCESS! +``` + +### 3.2、设置远程连接 + +``` +mysql> create user 'root'@'%' identified with mysql_native_password by 'Root123456'; +Query OK, 0 rows affected (0.01 sec) + +mysql> grant all on *.* to 'root'@'%'; +Query OK, 0 rows affected (0.00 sec) + +mysql> flush privileges; +Query OK, 0 rows affected (0.00 sec) +``` + +**遇到问题:** + +Can’t connect to MySQL server on ‘192.168.1.121’ (61) + +``` +[root@zutuanxue mysql]# systemctl stop firewalld.service +[root@zutuanxue mysql]# firewall-cmd --state +``` + +## 4、mysql卸载 + +### 4.1、停止mysql服务 + +``` +[root@zutuanxue mysql]# ./support-files/mysql.server stop +Shutting down MySQL.... SUCCESS! +``` + +### 4.2、查找所有mysql相关文件夹 + +查找 + +``` +[root@zutuanxue mysql]# find / -name mysql +``` + +![image20200223024128126.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186208888.png) + +删除所有查出来的文件夹 + +``` +[root@zutuanxue mysql]# rm -rf /var/lib/selinux/targeted/active/modules/100/mysql +...... +``` + +### 4.3、删除配置文件 + +配置文件一般有/etc/my.cnf 或/etc/init.d/mysql.server, + +``` +[root@zutuanxue mysql]# rm -f /etc/my.cnf +[root@zutuanxue mysql]# rm -rf /etc/init.d/mysql.server +``` + +### 4.4、删除用户组 + +``` +[root@zutuanxue mysql]# userdel mysql +[root@zutuanxue mysql]# id mysql +id: “mysql”:无此用户 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySql\345\256\242\346\210\267\347\253\257.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySql\345\256\242\346\210\267\347\253\257.md" new file mode 100644 index 0000000..9555a47 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/MySql\345\256\242\346\210\267\347\253\257.md" @@ -0,0 +1,141 @@ +Navicat for MySQL是一套管理和开发MySQL或MariaDB的理想解决方案,支持单一程序,可同时连接到MySQL和MariaDB。这个功能齐备的前端软件为数据库管理、开发和维护提供了直观而强大的图形界面,给MySQL或MariaDB新手以及专业人士提供了一组全面的工具。 + +## 1、Navicat for MySQL下载与安装 + +### 1.1、下载 + +``` +http://www.navicat.com.cn/download/navicat-for-mysql +``` + +![image20200222233257400.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186370700.png) + +![image20200222233338007.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186384589.png) + +### 1.2、下载完成 + +![image20200222233455188.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186400724.png) + +### 1.3、安装 + +**右击“navicat150_mysql_cs_x64.exe”,以管理员身份运行,选择“是”** + +![image20200222233702941.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186444899.png) + +**跳出安装程序对话框,选择“下一步”** + +![image20200222233952780.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186460999.png) + +**选择“我同意”,继续“下一步”** + +![image20200222234125462.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186477455.png) + +**选择“安装路径”,继承“下一步”** + +![image20200222234450664.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186494146.png) + +**选择“快捷方式路径”,继续“下一步”** + +![image20200222234354406.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186509787.png) + +**选择在“桌面创建快捷方式”,继续“下一步”** + +![image20200222234708924.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186527639.png) + +**进入“装备安装”界面,点击“安装”** + +![image20200222234904299.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186542299.png) + +**进入“安装”界面,直到跳出“完成”界面** + +![image20200222235023235.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186557642.png) + +**点击“完成”,安装成功** + +![image20200222235103254.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186572803.png) + +### 1.4、Navicat for MySQL连接MySQL数据库 + +#### 1.4.1、打开Navicat for MySQL + +![image20200222235353143.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186588911.png) + +#### 1.4.2、创建新连接 + +**连接->MySQL** + +![image20200222235549717.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186603371.png) + +**文件->新建连接->MySQL** + +![image20200222235719188.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186618860.png) + +**新建连接对话框,输入对应信息,点击“测试连接”** + +![image20200223000045104.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186632233.png) + +**连接成功** + +![image20200223000156896.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186647147.png) + +**确认连接后如下:** + +![image20200223000512002.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186661203.png) + +## 2、Navicat for MySQL操作-上 + +### 2.1、数据库操作 + +#### 2.2.1、创建数据库 + +**右击“MySQL连接”,选择“新建数据库”** + +![image20200223001205072.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186683271.png) + +#### 2.2.2、删除数据库 + +**右击想要删除的数据库,选择“删除数据库”** + +![image20200223001414043.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186700884.png) + +### 2.2、数据库表操作 + +#### 2.2.1、新建表 + +**右击“表”,选择“新建表”** + +![image20200223001746104.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186715524.png) + +![image20200223002004707.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186727307.png) + +## 3、Navicat for MySQL操作-下 + +### 3.1、数据库表操作 + +#### 3.1.1、操作表中结构与记录 + +**表结构(表的修改)** + +![image20200223002415540.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186745243.png) + +**表记录(记录的增加、删除、修改、查看)** + +![image20200223002826369.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186756221.png) + +#### 3.1.2、删除表 + +**右击想删除的表,选择“删除表”** + +![image20200223003000136.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186773023.png) + +### 3.2、命令列窗口的打开 + +**右击连接/数据库,选择“命令列窗口”** + +![image20200223003312998.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186786858.png) + +![image20200223003438588.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186796440.png) + +相当于 + +![image20200223003552091.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603186810087.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/SQL\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/SQL\344\273\213\347\273\215.md" new file mode 100644 index 0000000..6154afe --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/SQL\344\273\213\347\273\215.md" @@ -0,0 +1,51 @@ +结构化查询语言是高级的非过程化编程语言,允许用户在高层数据结构上工作。它不要求用户指定对数据的存放方法,也不需要用户了解具体的数据存放方式,所以具有完全不同底层结构的不同数据库系统, 可以使用相同的结构化查询语言作为数据输入与管理的接口。结构化查询语言语句可以嵌套,这使它具有极大的灵活性和强大的功能。 + +## 一、SQL概述 + +### 1.1、什么是SQL + +结构化查询语言(Structured Query Language)简称SQL,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统;同时也是数据库脚本文件的扩展名。 + +### 1.2、SQL作用 + +是一种所有关系型数据库的查询规范,不同的数据库都支持。 + +通用的数据库操作语言,可以用在不同的数据库中。 + +不同的数据库 SQL 语句有一些区别 + +## 二、SQL分类 + +**数据查询语言(DQL:Data Query Language):** + +其语句,也称为“数据检索语句”,用以从表中获得数据,确定数据怎样在应用程序给出。保留字SELECT是DQL(也是所有SQL)用得最多的动词,其他DQL常用的保留字有WHERE,ORDER BY,GROUP BY和HAVING。这些DQL保留字常与其他类型的SQL语句一起使用。 + +**数据操作语言**(**DML**:**Data Manipulation Language**): + +其语句包括动词INSERT,UPDATE和DELETE。它们分别用于添加,修改和删除表中的行。也称为动作查询语言。 + +**事务处理语言(TPL):** + +它的语句能确保被DML语句影响的表的所有行及时得以更新。TPL语句包括BEGIN TRANSACTION,COMMIT和ROLLBACK。 + +**数据定义语言(\**DDL\**):** + +其语句包括动词CREATE和DROP。在数据库中创建新表或删除表(CREAT TABLE 或 DROP TABLE);为表加入索引等。DDL包括许多与人数据库目录中获得数据有关的保留字。它也是动作查询的一部分。 + +**指针控制语言(CCL):** + +它的语句,像DECLARE CURSOR,FETCH INTO和UPDATE WHERE CURRENT用于对一个或多个表单独立的操作。 + +**数据控制语言**(**DCL**): + +它的语句通过GRANT或REVOKE获得许可,确定单个用户和用户组对数据库对象的访问。某些RDBMS可用GRANT或REVOKE控制对表单个列的访问。 + +## 三、MySql语法 + +每条语句以分号(;)结尾。 + +SQL 中不区分大小写,关键字中认为大写和小写是一样的 + +3种注释方法: + +![image20200128220353753.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603187016784.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/\345\244\232\350\241\250\350\277\236\346\216\245\346\237\245\350\257\242.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/\345\244\232\350\241\250\350\277\236\346\216\245\346\237\245\350\257\242.md" new file mode 100644 index 0000000..cb7869e --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/\345\244\232\350\241\250\350\277\236\346\216\245\346\237\245\350\257\242.md" @@ -0,0 +1,282 @@ +连接查询是关系数据库中最主要的查询,主要包括内连接、外连接和交叉连接等。通过连接运算符可以实现多个表查询。连接是关系数据库模型的主要特点,也是它区别于其它类型数据库管理系统的一个标志。 在关系数据库管理系统中,表建立时各数据之间的关系不必确定,常把一个实体的所有信息存放在一个表中。当检索数据时,通过连接操作查询出存放在多个表中的不同实体的信息。连接操作给用户带来很大的灵活性,他们可以在任何时候增加新的数据类型。为不同实体创建新的表,然后通过连接进行查询。 + +## 一、多表连接查询概述 + +### 1.1、什么是多表查询 + +连接是在多个表之间通过一定的连接条件,使表之间发生关联,进而能从多个表之间获取数据。 + +**比如:** + +有一个部门表,有一个员工表,我想查询某部门中的所有员工的信息。这时我们要先找出部门ID,通过部门ID查询出对应的员工信息。 + +这样我们在查询我们需要的信息的时候就应用了多表。所以这就是我们的多表查询。 + +### 1.2、多表查询的作用 + +**比如:** + +我们想查询员工A的名字和他所在的部门的名字,则需要使用多表查询。 + +那么我们使用一条 SQL 语句查询多张表,因为查询结果在多张不同的表中。而我们的结果要从每张表取 1 列或多列。这就是多表查询的作用。 + +### 1.3、多表查询分类 + +多表查询可以分为二类查询: + +**内连接:**隐匿内连接、显示内连接 + +**外连接:**左外连接、右外连接 + +### 1.4、笛卡尔积现象 + +#### 1.4.1、数据准备 + +创建表和数据 + +```mysql +#部门表 +create table dept( +id int primary key auto_increment, +name varchar(20) +); +insert into dept (name) values ('研发部'),('渠道部'),('教务部'); + +# 创建员工表 +create table emp ( +id int primary key auto_increment, +name varchar(10), +gender char(1), -- 性别 +salary double, -- 工资 +join_date date, -- 入职日期 +dept_id int, +foreign key (dept_id) references dept(id) -- 外键,关联部门表(部门表的主键) +); +insert into emp(name,gender,salary,join_date,dept_id) values('张三','男',7200,'2013-02-24',1); +insert into emp(name,gender,salary,join_date,dept_id) values('李四','男',3600,'2010-12-02',2); +insert into emp(name,gender,salary,join_date,dept_id) values('王五','男',9000,'2008-08-08',2); +insert into emp(name,gender,salary,join_date,dept_id) values('赵六','女',5000,'2015-10-07',3); +insert into emp(name,gender,salary,join_date,dept_id) values('吴七','女',4500,'2011-03-14',1); +``` + +显示表中数据 + +```mysql +mysql> select * from dept; ++----+-----------+ +| id | name | ++----+-----------+ +| 1 | 研发部 | +| 2 | 渠道部 | +| 3 | 教务部 | ++----+-----------+ +3 行于数据集 (0.01 秒) + +mysql> select * from emp; ++----+--------+--------+--------+------------+---------+ +| id | name | gender | salary | join_date | dept_id | ++----+--------+--------+--------+------------+---------+ +| 1 | 张三 | 男 | 7200 | 2013-02-24 | 1 | +| 2 | 李四 | 男 | 3600 | 2010-12-02 | 2 | +| 3 | 王五 | 男 | 9000 | 2008-08-08 | 2 | +| 4 | 赵六 | 女 | 5000 | 2015-10-07 | 3 | +| 5 | 吴七 | 女 | 4500 | 2011-03-14 | 1 | ++----+--------+--------+--------+------------+---------+ +5 行于数据集 (0.01 秒) +``` + +#### 1.4.2、什么是笛卡尔积 + +案例: + +查询所有员工和所有部门 + +```mysql +mysql> select * from emp,dept; +``` + +![image20200215173505470.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/21/1603241592735.png) + +左表的每条数据和右表的每条数据组合,这种效果就是笛卡尔积 + +#### 1.4.3、清除笛卡尔积 + +我们发现笛卡尔积所产生的数据并不是都是有用的,只有员工.dept_id=部门.id的值才是我们想要的。 + +所以我们需要过滤掉没有用的数据。那么如何设置过滤条件呢? + +```mysql +mysql> select * from emp,dept where emp.dept_id=dept.id; ++----+--------+--------+--------+------------+---------+-------+-----------+ +| id | name | gender | salary | join_date | dept_id | id(2) | name(2) | ++----+--------+--------+--------+------------+---------+-------+-----------+ +| 1 | 张三 | 男 | 7200 | 2013-02-24 | 1 | 1 | 研发部 | +| 5 | 吴七 | 女 | 4500 | 2011-03-14 | 1 | 1 | 研发部 | +| 2 | 李四 | 男 | 3600 | 2010-12-02 | 2 | 2 | 渠道部 | +| 3 | 王五 | 男 | 9000 | 2008-08-08 | 2 | 2 | 渠道部 | +| 4 | 赵六 | 女 | 5000 | 2015-10-07 | 3 | 3 | 教务部 | ++----+--------+--------+--------+------------+---------+-------+-----------+ +mysql> select emp.name,dept.name from emp,dept where emp.dept_id=dept.id; ++--------+-----------+ +| name | name(2) | ++--------+-----------+ +| 张三 | 研发部 | +| 吴七 | 研发部 | +| 李四 | 渠道部 | +| 王五 | 渠道部 | +| 赵六 | 教务部 | ++--------+-----------+ +5 行于数据集 (0.01 秒) +``` + +## 二、内连接 + +用左边表的记录去匹配右边表的记录,如果符合条件的则显示。如:从表.外键=主表.主键 + +### 2.1、隐式内连接 + +看不到 join 关键字,条件使用 where 指定 + +```mysql +格式: +select */字段列表 from 左表,右表 where 条件表达式; +``` + +案例: + +查询员工表中所有员工及所在部门 + +```mysql +mysql> select * from emp,dept where emp.dept_id=dept.id; ++----+--------+--------+--------+------------+---------+-------+-----------+ +| id | name | gender | salary | join_date | dept_id | id(2) | name(2) | ++----+--------+--------+--------+------------+---------+-------+-----------+ +| 1 | 张三 | 男 | 7200 | 2013-02-24 | 1 | 1 | 研发部 | +| 5 | 吴七 | 女 | 4500 | 2011-03-14 | 1 | 1 | 研发部 | +| 2 | 李四 | 男 | 3600 | 2010-12-02 | 2 | 2 | 渠道部 | +| 3 | 王五 | 男 | 9000 | 2008-08-08 | 2 | 2 | 渠道部 | +| 4 | 赵六 | 女 | 5000 | 2015-10-07 | 3 | 3 | 教务部 | ++----+--------+--------+--------+------------+---------+-------+-----------+ +``` + +### 2.2、显式内连接 + +使用inner join…on语句,可以省略inner + +```mysql +格式: +select */字段列表 from 左表 [inner] join 右表 on 条件表达式; +``` + +案例: + +查询王五的信息,显示员工 id,姓名,性别,工资和所在的部门名称。 + +```mysql +mysql> select emp.id,emp.name,emp.gender,emp.salary,dept.name from emp join dept on emp.dept_id=dept.id where emp.name='王五'; ++----+--------+--------+--------+-----------+ +| id | name | gender | salary | name(2) | ++----+--------+--------+--------+-----------+ +| 3 | 王五 | 男 | 9000 | 渠道部 | ++----+--------+--------+--------+-----------+ +1 行于数据集 (0.02 秒) +``` + +SQL优化 + +```mysql +select emp.id,emp.name,emp.gender,emp.salary,dept.name from emp join dept on emp.dept_id=dept.id where emp.name='王五'; +或 +select e.id,e.name,e.gender,e.salary,d.name from emp e join dept d on e.dept_id=d.id where e.name='王五'; +或 +select e.id,e.name,gender,salary,d.name from emp e join dept d on dept_id=d.id where e.name='王五'; +``` + +### 2.3、内连接使用步骤 + +- 确认查询的数据库表 +- 确认数据库表连接条件 +- 确认数据库表查询条件 +- 确认数据库表显示字段 + +## 三、左/右连接 + +### 3.1、左连接 + +使用 left outer join…on,outer 可以省略 + +```mysql +格式: +select */字段列表 from 左表 left [outer] join 右表 on 条件表达式; +``` + +用左边表的记录去匹配右边表的记录,如果符合条件的则显示;否则,显示 NULL + +**案例:** + +在部门表中增加一个部门 + +```mysql +mysql> insert into dept(name) values('执行部'); +Query OK, 1 rows affected (0.08 秒) +``` + +用内连接查询信息 + +``` +mysql> select * from dept d inner join emp e on d.id=e.dept_id; +``` + +![image20200215182047845.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/21/1603241661863.png) + +用左连接查询信息 + +``` +mysql> select * from dept d left join emp e on d.id=e.dept_id; +``` + +![image20200215182100590.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/21/1603241674165.png) + +**注意:** + +左连接表示的是在内连接的基础上保证左表的信息全部显示 + +### 3.2、右连接 + +使用 right outer join…on,outer 可以省略 + +```mysql +格式: +select */字段列表 from 左表 right [outer] join 右表 on 条件表达式; +``` + +用右边表的记录去匹配左边表的记录,如果符合条件的则显示;否则,显示 NULL + +**案例:** + +在员工表中加入一个新员工 + +```mysql +mysql> insert into emp values (null, '王一','男',6666,'2013-12-05',null); +Query OK, 1 rows affected (0.02 秒) +``` + +用内连接查询信息 + +```mysql +mysql> select * from dept d inner join emp e on d.id=e.dept_id; +``` + +![image20200215182047845.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/21/1603241693324.png) + +用右连接查询信息 + +```mysql +mysql> select * from dept d right join emp e on d.id=e.dept_id; +``` + +![image20200215183504384.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/21/1603241714996.png) + +**注意:** + +右连接表示的是在内连接的基础上保证右表的信息全部显示 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/\346\225\260\346\215\256\345\272\223\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/\346\225\260\346\215\256\345\272\223\344\273\213\347\273\215.md" new file mode 100644 index 0000000..5a56b70 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/\346\225\260\346\215\256\345\272\223\344\273\213\347\273\215.md" @@ -0,0 +1,65 @@ +数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,它产生于距今六十多年前,随着信息技术和市场的发展,特别是二十世纪九十年代以后,数据管理不再仅仅是存储和管理数据,而转变成用户所需要的各种数据管理的方式。数据库有很多种类型,从最简单的存储有各种数据的表格到能够进行海量数据存储的大型数据库系统都在各个方面得到了广泛的应用。 + +在信息化社会,充分有效地管理和利用各类信息资源,是进行科学研究和决策管理的前提条件。数据库技术是管理信息系统、办公自动化系统、决策支持系统等各类信息系统的核心部分,是进行科学研究和决策管理的重要技术手段。 + +## 一、数据库管理系统 + +### 1.1、数据存储方式 + +计算机数据(Data)的存储一般以硬盘为数据存储空间资源,从而保证计算机内的数据能够持续保存。对于数据的处理,一般会采用数据库相关的技术进行处理,从而保证数据处理的高效性。 + +采用数据库的管理模式不仅提高了数据的存储效率,而且在存储的层面上提高了数据的安全性。通过分类的存储模式让数据管理更加安全便捷,更能实现对数据的调用和对比,并且方便查询等操作的使用。 + +### 1.2、数据库管理系统 + +**常见的数据库管理系统:** + +MySQL:开源免费的数据库,小型的数据库。已经被Oracle收购了,MySQL6.x版本也开始收费。 + +Oracle:收费的大型数据库,Oracle公司的产品。Oracle收购SUN公司,收购MYSQL。 + +DB2:IBM公司的数据库产品,收费的。常应用在银行系统中. + +SQLServer:MicroSoft 公司收费的中型的数据库。C#、.net等语言常使用。 + +SyBase:已经淡出历史舞台。提供了一个非常专业数据建模的工具PowerDesigner。 + +SQLite:嵌入式的小型数据库,应用在手机端。 + +Java常用的数据库:MySQL,Oracle。 + +Python常用的数据库:MySQL。 + +### 1.3、数据库与数据库管理系统关系 + +![image20200128210246764.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603185856048.png) + +## 2、数据库 + +数据库就是存储数据的仓库,由数据库表组成,其本质是一个文件系统,数据库按照特定的格式将数据存储起来,用户可以对数据库中的数据进行增加,修改,删除及查询操作。 + +### 2.1、数据库表 + +数据库中以表为组织单位存储数据。 + +数据库表由:表名、表字段、表记录构成 + +**如:** + +在学生档案中,学生信息(**数据库表**)是由学号、姓名、性别、年龄、籍贯、院系、联系电话(**表中字段**)等特征组成的,那么这些具体的特征值所构成的一条记录就是一个学生的信息数据,例如“2016010102,张三,男,26,山西,计算机学院,18513232232”(**记录**)。 + +### 2.2、数据库表记录 + +根据表字段所规定的数据类型,我们可以向其中填入一条条的数据,而表中的每条数据类似类的实例对象。表中的一行一行的信息我们称之为记录。 + +#### 2.2.1、数据库 + +![image20200128212446704.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603185877802.png) + +#### 2.2.2、数据库表结构 + +![image20200128212610860.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603185890762.png) + +#### 2.2.3、记录 + +![image20200128212711794.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603185901929.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/\346\225\260\346\215\256\345\272\223\350\256\276\350\256\241.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/\346\225\260\346\215\256\345\272\223\350\256\276\350\256\241.md" new file mode 100644 index 0000000..1f5deea --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/\346\225\260\346\215\256\345\272\223\350\256\276\350\256\241.md" @@ -0,0 +1,130 @@ +数据库设计(Database Design)是指对于一个给定的应用环境,构造最优的数据库模式,建立数据库及其应用系统,使之能够有效地存储数据,满足各种用户的应用需求(信息要求和处理要求)。在数据库领域内,常常把使用数据库的各类系统统称为数据库应用系统。 +数据库设计的设计内容包括:需求分析、概念结构设计、逻辑结构设计、物理结构设计、数据库的实施和数据库的运行和维护。 + +## 一、范式概述 + +### 1.1、什么是范式 + +好的数据库设计对数据的存储性能和后期的程序开发,都会产生重要的影响。建立科学的,规范的数据库就需要满足一些规则来优化数据的设计和存储,这些规则就称为范式。 + +### 1.2、范式分类 + +目前关系数据库有六种范式: + +第一范式(1NF) + +第二范式(2NF) + +第三范式(3NF) + +巴斯-科德范式(BCNF)、 + +第四范式(4NF) + +第五范式(5NF,又称完美范式) + +一般说来,数据库只需满足第三范式(3NF)就行了。 + +## 二、第一范式 + +确保每个字段不可再分。确保每列原子性。 + +**案例:** + +班级表中的字段 + +```mysql ++---------+----------+------------------------+ +| 班级id | 班级名称 | 上课时间 | ++---------+----------+------------------------+ +| 1 | 一班 | 1999-09-01~2000-01-04 | ++---------+----------+-------------------------+ +``` + +不合理。不满足第一范式,上课时间可以再分 + +```mysql ++---------+----------+------------------------+ +| 班级id | 班级名称 | 开课时间 | 结课时间 | ++---------+----------+------------------------+ +| 1 | 一班 | 1999-09-01 | 2000-01-04| ++---------+----------+-------------------------+ +``` + +**地址包含省、市、县、地区是否需要拆分?** +如果仅仅起地址的作用,不需要统计,可以不拆分;如果有按地区统计的功能需要拆分。一般情况下拆分 + +## 三、第二范式 + +一个表只能描述一件事。 + +订单表中的字段 + +```mysql ++---------+----------+------------------------+ +| 订单编号 | 产品编号 | 订购日期 | 价格 | ++---------+----------+------------------------+ +| 00001 | A00001 | 1999-09-01 | 35687.0 | ++---------+----------+------------------------+ +``` + +不合理。不满足第二范式,一个表中出现了二种描述,一个是订单,一个是产品 + +```mysql +订单表 ++---------+------------+ +| 订单编号 | 订购日期 | ++---------+------------+ +| 00001 | 1999-09-01 | ++---------+------------+ +产品表 ++----------+------------+ +| 产品编号 | 价格 | ++----------+------------+ +| A00001 | 35687.0 | ++----------+------------+ +``` + +**如下表设计是否合理?** + +``` ++------+--------+--------+---------+----------+ +| 学号 | 姓名 | 年龄 | 最高气温 | 青菜价格 | ++------+--------+--------+---------+----------+ +``` + +## 四、第三范式 + +在所有的非键字段中,不能有传递依赖。消除传递依赖 + +订单表中的字段 + +``` ++---------+----------+------------------------+ +| 订单编号 | 订购日期 | 顾客编号 | 顾客姓名 | ++---------+----------+------------------------+ +| 00001 |1999-09-01| A000001 | Luc | ++---------+----------+------------------------+ +``` + +不合理。不满足第三范式,因为我们已经可以通过顾客编号知道顾客姓名,所以我们不需要定义顾客姓名 + +``` ++---------+----------+------------+ +| 订单编号 | 订购日期 | 顾客编号 | ++---------+----------+------------+ +| 00001 |1999-09-01| A000001 | ++---------+----------+------------+ +``` + +下列设计是否满足第三范式? + +``` ++------+--------+--------+---------+----------+ +| 学号 | 姓名 | 语文 | 数学 | 总分 | ++------+--------+--------+---------+----------+ +``` + +不满足,因为语文和数学确定了,总分就确定了。 +上面的设计不满足第三范式,但是高考分数表就是这样设计的,为什么? +高考分数峰值访问量非常大,这时候就是性能更重要。当性能和规范化冲突的时候,我们首选性能。这就是“反三范式”。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/\350\241\250\344\270\216\350\241\250\344\271\213\351\227\264\345\205\263\347\263\273.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/\350\241\250\344\270\216\350\241\250\344\271\213\351\227\264\345\205\263\347\263\273.md" new file mode 100644 index 0000000..d0b2cdc --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/MySQL\346\225\260\346\215\256\345\272\223\345\256\236\346\210\230/\350\241\250\344\270\216\350\241\250\344\271\213\351\227\264\345\205\263\347\263\273.md" @@ -0,0 +1,315 @@ +可以在数据库图表中的表之间创建关系,以显示一个表中的列与另一个表中的列是如何相链接的。 + +在一个关系型数据库中,利用关系可以避免多余的数据。 + +## 一、表与表之间关系概述 + +### 1.1、什么是表与表之间关系 + +在关系型数据库中,为了避免数据冗余,我们的一些表与表之间肯定是有一定的关系。 + +如:学生表与老师表,部门表与员工表,用户表与权限表等。 + +在表设计的时候,就应该体现出来表与表之间的这种关系。 + +### 1.2、表与表之间关系分类 + +#### 1.2.1、一对多关系 + +一对多关系是最普通的一种关系。在这种关系中,A 表中的一行可以匹配 B 表中的多行,但是 B 表中的一行只能匹配 A 表中的一行。 + +只有当一个相关列是一个主键或具有唯一约束时,才能创建一对多关系。 + +![image20200215112949021.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/21/1603241036981.png) + +**注意:** + +一对多的创建原则: + +主外键关连 + +#### 1.2.2、一对一关系 + +在一对一关系中,A 表中的一行最多只能匹配于 B 表中的一行,反之亦然。如果相关列都是主键或都具有唯一约束,则可以创建一对一关系。 + +![image20200215122050731.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/21/1603241052871.png) + +**注意:** + +一对一的创建原则: + +外键唯一:主表的主键和从表的外键(唯一),形成主外键关系,外键唯一 UNIQUE + +外键是主键:主表的主键和从表的主键,形成主外键关系 + +#### 1.2.3、多对多关系 + +在多对多关系中,A 表中的一行可以匹配 B 表中的多行,反之亦然。要创建这种关系,需要定义第三个表,称为结合表,它的主键由 A 表和 B 表的外部键组成。 + +![image20200215121200999.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/21/1603241065129.png) + +**注意:** + +多对多的创建原则: + +二个表与中间表创建1对多的关系。 + +## 2、一对多应用 + +创建一对多关系:主外键关连 + +![image20200215123556759.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/21/1603241079269.png) + +新华出版社(Python爬虫、Linux) + +海燕出版社(操作系统、数学) + +摆渡出版社(英语、网页设计) + +大众出版社() + +**案例:** + +这是一个书和出版社的一个例子,书要关联出版社(多个书可以是一个出版社,一个出版社也可以有好多书)。 + +表的创建 + +```mysql +#出版社表(被关联表) +create table press( +id int primary key auto_increment, +name char(20)-- 出版社名字 +); + +#书表(关联表) +create table book( +book_id int primary key auto_increment, +book_name varchar(20), +book_price int, +press_id int, +constraint fk_pressid_id foreign key(press_id) references press(id) +on delete cascade +on update cascade +); +``` + +插入数据 + +```mysql +mysql> insert into press(name) values('新华出版社'), ('海燕出版社'), ('摆渡出版社'), ('大众出版社'); +Query OK, 4 rows affected (0.09 秒) + +mysql> insert into book(book_name,book_price,press_id) values('Python爬虫',100,1), ('Linux',80,1), ('操作系统',70,2), ('数学',50,2), ('英语',103,3), ('网页设计',22,3); +Query OK, 6 rows affected (0.07 秒) +``` + +查看数据 + +```mysql +mysql> select * from press; ++----+-----------------+ +| id | name | ++----+-----------------+ +| 1 | 新华出版社 | +| 2 | 海燕出版社 | +| 3 | 摆渡出版社 | +| 4 | 大众出版社 | ++----+-----------------+ +4 行于数据集 (0.01 秒) + +mysql> select * from book; ++---------+--------------+------------+----------+ +| book_id | book_name | book_price | press_id | ++---------+--------------+------------+----------+ +| 1 | Python爬虫 | 100 | 1 | +| 2 | Linux | 80 | 1 | +| 3 | 操作系统 | 70 | 2 | +| 4 | 数学 | 50 | 2 | +| 5 | 英语 | 103 | 3 | +| 6 | 网页设计 | 22 | 3 | ++---------+--------------+------------+----------+ +6 行于数据集 (0.01 秒) +``` + +## 三、一对一应用 + +创建一对一:外键唯一,user_id唯一对应一个uid,user_id必须在uid里出现 + +![image20200215164955805.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/21/1603241161787.png) + +**案例:** + +用户和管理员(只有管理员才可以登录,一个管理员对应一个用户) + +表创建 + +```mysql +#用户表(被关联表) +create table user( +id int primary key auto_increment, #主键自增 +name char(10) +); + +#管理员表(关联表) +create table manager( +id int primary key auto_increment, +user_id int unique, +password varchar(16), +foreign key(user_id) references user(id) +on delete cascade +on update cascade +); +``` + +插入数据 + +```mysql +mysql> insert into user(name)values('susan1'),('susan2'),('susan3'),('susan4'),('susan5'),('susan6'); +Query OK, 6 rows affected (0.02 秒) + +mysql> insert into manager(user_id,password) values(4,'sds156'),(2,'531561'),(6,'f3swe'); +Query OK, 3 rows affected (0.03 秒) +``` + +查看数据 + +```mysql +mysql> select * from user; ++----+--------+ +| id | name | ++----+--------+ +| 1 | susan1 | +| 2 | susan2 | +| 3 | susan3 | +| 4 | susan4 | +| 5 | susan5 | +| 6 | susan6 | ++----+--------+ +6 行于数据集 (0.01 秒) + +mysql> select * from manager; ++----+---------+----------+ +| id | user_id | password | ++----+---------+----------+ +| 1 | 4 | sds156 | +| 2 | 2 | 531561 | +| 3 | 6 | f3swe | ++----+---------+----------+ +3 行于数据集 (0.01 秒) +``` + +## 4、多对多应用 + +创建多对多:要把book_id和author_id设置成联合唯一 + +![image20200215161523092.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/21/1603241222140.png) + +九阳神功(egon、e3) + +葵花宝典(egon、e4) + +辟邪剑谱(e1、e2、e3) + +降龙十巴掌(e4) + +**或者** + +egon(九阳神功、葵花宝典) + +e1(辟邪剑谱) + +e2(辟邪剑谱) + +e3(九阳神功、辟邪剑谱) + +e4(葵花宝典、降龙十巴掌) + +**案例:** + +这是一个书和作者的一个例子,书要关联作者(一个作者可以写多个书,一本书也可以有多个作者,双向的一对多,即多对多)。 + +表创建 + +```mysql +#书表(被关联表) +create table book1( +id int primary key auto_increment, +name varchar(10), +price float(3,2) +); + +#作者表(被关联表) +create table author( +id int primary key auto_increment, +name char(5) +); + +#作者和书表(关联表) +create table author2book( +id int primary key auto_increment, +book_id int not null, +author_id int not null, +unique(book_id,author_id), +foreign key(book_id) references book1(id) +on delete cascade +on update cascade, +foreign key(author_id) references author(id) +on delete cascade +on update cascade +); +``` + +插入数据 + +```mysql +mysql> insert into book1(name,price) values('九阳神功',9.9), ('葵花宝典',9.5), ('辟邪剑谱',5), ('降龙十巴掌',7.3); +Query OK, 4 rows affected (0.09 秒) + +mysql> insert into author(name) values('egon'),('e1'),('e2'),('e3'),('e4'); +Query OK, 5 rows affected (0.07 秒) + +mysql> insert into author2book(book_id,author_id) values(1,1),(1,4),(2,1),(2,5),(3,2),(3,3),(3,4),(4,5); +Query OK, 8 rows affected (0.03 秒) +``` + +查看数据 + +```mysql +mysql> select * from book1; ++----+-----------------+-------+ +| id | name | price | ++----+-----------------+-------+ +| 1 | 九阳神功 | 9.90 | +| 2 | 葵花宝典 | 9.50 | +| 3 | 辟邪剑谱 | 5.00 | +| 4 | 降龙十巴掌 | 7.30 | ++----+-----------------+-------+ +4 行于数据集 (0.02 秒) + +mysql> select * from author; ++----+------+ +| id | name | ++----+------+ +| 1 | egon | +| 2 | e1 | +| 3 | e2 | +| 4 | e3 | +| 5 | e4 | ++----+------+ +5 行于数据集 (0.01 秒) + +mysql> select * from author2book; ++----+---------+-----------+ +| id | book_id | author_id | ++----+---------+-----------+ +| 1 | 1 | 1 | +| 2 | 1 | 4 | +| 3 | 2 | 1 | +| 4 | 2 | 5 | +| 5 | 3 | 2 | +| 6 | 3 | 3 | +| 7 | 3 | 4 | +| 8 | 4 | 5 | ++----+---------+-----------+ +8 行于数据集 (0.01 秒) +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \344\270\273\344\273\216\345\244\215\345\210\266.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \344\270\273\344\273\216\345\244\215\345\210\266.md" new file mode 100644 index 0000000..d3e6bb0 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \344\270\273\344\273\216\345\244\215\345\210\266.md" @@ -0,0 +1,352 @@ +Redis有两种不同的持久化方式,Redis服务器通过持久化,把Redis内存中持久化到硬盘当中,当Redis宕机时,我们重启Redis服务器时,可以由RDB文件或AOF文件恢复内存中的数据。 + +不过持久化后的数据仍然只在一台机器上,因此当硬件发生故障时,比如主板或CPU坏了,这时候无法重启服务器,有什么办法可以保证服务器发生故障时数据的安全性?或者可以快速恢复数据呢?想做到这一点,我们需要再了解Redis另外一种机制:主从复制。 + +## 一、主从复制概述 + +### 1.1、单机问题 + +#### 1.1.1、机器宕机 + +如果发生机器宕机(主板烧坏、硬盘损坏、内存损坏等),短时间内我们也无法修复,我们就会考虑将redis迁移到另外一台机器上,并且还要考虑数据同步问题。 + +#### 1.1.2、容器瓶颈 + +一台机器内存是16G,redis使用12个G内存,除了redis还要使用其他的应用,这个时候,我们可能需要32个G内存才能使用,但是redis的应用对内存的增加也会提交,我们不能一直去提高单机的内存? + +#### 1.1.3、QPS瓶颈 + +redis官方数据显示redis可以处理达到10w的QPS,如果业务需要50w、100w的QPS时我们怎么办? + +关于容量瓶颈、QPS瓶颈和机器宕机,这就是redis分布式和高可用需要解决的问题。 + +### 1.2、什么是主从复制 + +Master可以拥有多个slave;多个slave可以连接同一个Master外,还可以连接到其他的slave;主从复制不会阻塞Master,在主从复制时,Master可以处理client请求。 + +### 1.3、主从复制形式 + +#### 1.3.1、一主一从 + +![image20200304135049546.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603524494515.png) + +左边是Master节点,右边是slave节点,即主节点和从节点。主节点是数据写入,从节点可以通过复制操作将主节点的数据同步过来,并且随着主节点数据不断写入,从节点数据也会做同步的更新。 + +#### 1.3.2、一主多从 + +![image20200304135547579.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603524507422.png) + +一个master可以有多个slave,也就相当于有了多份的数据副本。这样可以做一个更加高可用的选择,例如一个master和一个slave挂掉了,还能有其他的slave数据备份。 + +### 1.4、主从复制作用 + +**数据备份** + +将master的数据,备份到slave + +**读写分离** + +用master来写入数据,用slave完成备份后,来完成只读的功能。 + +**注意:** + +当master宕机后,不会去选择slave作为master。需要手动将一台slave使用slaveof on one提升为master,要想自动实现提升,我们就需要使用哨兵。 + +## 二、单机主从 + +配置一主二从 + +### 2.1、复制redis.conf + +在/usr/local/redis目下,将redis.conf复制成三份分别取名为:redis-8000.conf、redis-8001.conf、redis-8002.conf三个配置文件 + +``` +[root@zutuanxue redis]# cp redis.conf redis-8000.conf +[root@zutuanxue redis]# cp redis.conf redis-8001.conf +[root@zutuanxue redis]# cp redis.conf redis-8002.conf +``` + +### 2.2、配置主机 + +以redis-8000为主机 + +``` +#bind 127.0.0.1 #将bind注释掉 或 bind 0.0.0.0 +port 8000 #改变其服务端口 +daemonize yes #修改服务为后台运行 +pidfile /var/run/redis_8000.pid #指定不同的pid文件,注意三份配置文件不同。 +logfile "/usr/local/redis/log/redis_8000.log" #指定log日志路径,自己配,要求不同。 +dir ./data/redis_8000 #这个指定rdb文件和aof文件的路径配置,要求改成不同。 +masterauth ibethfy #都配上吧,从服务到主服务的认证密码。 +requirepass ibethfy #三份文件都配置,客户端访问需要密码验证。 +``` + +### 2.3、配置从机 + +以redis-8001,redis-8002为从机 + +``` +#bind 127.0.0.1 #将bind注释掉 或 bind 0.0.0.0 +port 8001 #改变其服务端口 +daemonize yes #修改服务为后台运行 +pidfile /var/run/redis_8001.pid #指定不同的pid文件,注意三份配置文件不同。 +logfile "/usr/local/redis/log/redis_8001.log" #指定log日志路径,自己配,要求不同。 +dir ./data/redis_8001 #这个指定rdb文件和aof文件的路径配置,要求改成不同。 +replicaof 127.0.0.1 8000 #主服务这句话注释,从服务配置的两台需要开启。配置主服务的ip的port。 +masterauth ibethfy #都配上吧,从服务到主服务的认证密码。 +requirepass ibethfy #三份文件都配置,客户端访问需要密码验证。 +#bind 127.0.0.1 #将bind注释掉 或 bind 0.0.0.0 +port 8002 #改变其服务端口 +daemonize yes #修改服务为后台运行 +pidfile /var/run/redis_8002.pid #指定不同的pid文件,注意三份配置文件不同。 +logfile "/usr/local/redis/log/redis_8002.log" #指定log日志路径,自己配,要求不同。 +dir ./data/redis_8002 #这个指定rdb文件和aof文件的路径配置,要求改成不同。 +replicaof 127.0.0.1 8000 #主服务这句话注释,从服务配置的两台需要开启。配置主服务的ip的port。 +masterauth ibethfy #从服务到主服务的认证密码。 +requirepass ibethfy #三份文件都配置,客户端访问需要密码验证。 +``` + +**注意:** + +replicaof 127.0.0.1 8000 在以前的版本中用的是slaveof 127.0.0.1 8000,这个配置现在也可以使用 + +### 2.4、启动服务 + +开启服务 + +``` +[root@zutuanxue redis]# ./src/redis-server ./redis-8000.conf +[root@zutuanxue redis]# ./src/redis-server ./redis-8001.conf +[root@zutuanxue redis]# ./src/redis-server ./redis-8002.conf +``` + +查看服务是否启动 + +``` +[root@zutuanxue redis]# ps -ef|grep redis +root 14464 1 0 11:58 ? 00:00:00 ./src/redis-server 0.0.0.0:8000 +root 14477 1 0 11:58 ? 00:00:00 ./src/redis-server 0.0.0.0:8001 +root 14484 1 0 11:58 ? 00:00:00 ./src/redis-server 0.0.0.0:8002 +root 14491 13960 0 11:58 pts/1 00:00:00 grep --color=auto redis +``` + +开启三个客户端 + +``` +[root@zutuanxue redis]# ./src/redis-cli -h 127.0.0.1 -p 8000 +[root@zutuanxue redis]# ./src/redis-cli -h 127.0.0.1 -p 8001 +[root@zutuanxue redis]# ./src/redis-cli -h 127.0.0.1 -p 8002 +``` + +查看主从信息info replication + +``` +127.0.0.1:8000> info replication +# Replication +role:master +connected_slaves:2 +slave0:ip=127.0.0.1,port=8001,state=online,offset=392,lag=1 +slave1:ip=127.0.0.1,port=8002,state=online,offset=392,lag=1 +master_replid:9e9ab9f313fae877e7330507fd7b4ce99bc98124 +master_replid2:0000000000000000000000000000000000000000 +master_repl_offset:392 +second_repl_offset:-1 +repl_backlog_active:1 +repl_backlog_size:1048576 +repl_backlog_first_byte_offset:1 +repl_backlog_histlen:392 +127.0.0.1:8001> info replication +# Replication +role:slave +master_host:127.0.0.1 +master_port:8000 +master_link_status:up +master_last_io_seconds_ago:6 +master_sync_in_progress:0 +slave_repl_offset:434 +slave_priority:100 +slave_read_only:1 +connected_slaves:0 +master_replid:9e9ab9f313fae877e7330507fd7b4ce99bc98124 +master_replid2:0000000000000000000000000000000000000000 +master_repl_offset:434 +second_repl_offset:-1 +repl_backlog_active:1 +repl_backlog_size:1048576 +repl_backlog_first_byte_offset:1 +repl_backlog_histlen:434 +127.0.0.1:8002> info replication +# Replication +role:slave +master_host:127.0.0.1 +master_port:8000 +master_link_status:up +master_last_io_seconds_ago:4 +master_sync_in_progress:0 +slave_repl_offset:420 +slave_priority:100 +slave_read_only:1 +connected_slaves:0 +master_replid:9e9ab9f313fae877e7330507fd7b4ce99bc98124 +master_replid2:0000000000000000000000000000000000000000 +master_repl_offset:420 +second_repl_offset:-1 +repl_backlog_active:1 +repl_backlog_size:1048576 +repl_backlog_first_byte_offset:1 +repl_backlog_histlen:420 +``` + +### 2.5、读写分离 + +主机写入信息 + +``` +[root@zutuanxue redis]# ./src/redis-cli -h 127.0.0.1 -p 8000 +127.0.0.1:8000> set str helloworld +OK +``` + +从机查看信息 + +``` +[root@zutuanxue redis]# ./src/redis-cli -h 127.0.0.1 -p 8001 +127.0.0.1:8001> get str +"helloworld" +127.0.0.1:8001> set h 123 +(error) READONLY You can't write against a read only replica. +[root@zutuanxue redis]# ./src/redis-cli -h 127.0.0.1 -p 8002 +127.0.0.1:8002> get str +"helloworld" +127.0.0.1:8002> set h 123 +(error) READONLY You can't write against a read only replica. +``` + +## 三、多机主从 + +配置一主二从 + +### 3.1、准备工作 + +开启三台虚拟主机123、124、125,分别安装redis + +关闭主机防火墙 + +``` +firewall-cmd --state #查看防火墙状态 +service firewalld stop #关闭防火墙 +``` + +### 3.2、配置主机和从机 + +123为主机,修改配置文件redis.conf + +``` +主机配置 +#bind 127.0.0.1 #将bind注释掉 或 bind 0.0.0.0 +port 6379 #改变其服务端口 +daemonize yes #修改服务为后台运行 +pidfile /var/run/redis_6379.pid #指定不同的pid文件,注意三份配置文件不同。 +logfile "/usr/local/redis/log/redis.log" #指定log日志路径,自己配,要求不同。 +dir ./ #这个指定rdb文件和aof文件的路径配置,要求改成不同。 +masterauth ibethfy #都配上吧,从服务到主服务的认证密码。 +requirepass ibethfy #三份文件都配置,客户端访问需要密码验证。 + +从机配置 +replicaof 192.168.1.123 6379 #主服务这句话注释,从服务配置的两台需要开启。配置主服务的ip的port。 +``` + +### 3.3、启动服务 + +分别启动三台主机的redis服务器端服务 + +``` +[root@zutuanxue redis]# ./src/redis-server ./redis.conf +[root@zutuanxue redis]# ps -ef|grep redis +``` + +分别启动三台主机客户端服务 + +``` +[root@zutuanxue redis]# ./src/redis-cli +``` + +查看主从信息info replication + +``` +127.0.0.1:6379> info replication +``` + +### 3.4、读写分离 + +123为Master,124、125为Slave + +Master为写 + +``` +127.0.0.1:6379> set str helloworld +OK +``` + +Slave为读 + +``` +127.0.0.1:6379> get str +"helloworld" +127.0.0.1:6379> set ss fdfd +(error) READONLY You can't write against a read only replica. +``` + +## 四、手动设置主从 + +当123虚拟机死机后,如何去手动设置我们的主从,124为主,125为从 + +**124执行slaveof no one** + +执行命令 SLAVEOF NO ONE 将使得这个从属服务器关闭复制功能,并从从属服务器转变回主服务器,原来同步所得的数据集不会被丢弃。 + +``` +127.0.0.1:6379> slaveof no one +OK +127.0.0.1:6379> info replication +# Replication +role:master +connected_slaves:0 +master_replid:edb62cdf853a4c9caeab077005a58a3633cb55d0 +master_replid2:4bf0fb1edcb4ed661b919c0d10e6be193c63ccd1 +master_repl_offset:1630 +second_repl_offset:1631 +repl_backlog_active:1 +repl_backlog_size:1048576 +repl_backlog_first_byte_offset:1 +repl_backlog_histlen:1630 +``` + +**125执行slaveof host port** + +执行 SLAVEOF host port 将使当前服务器停止对旧主服务器的同步,丢弃旧数据集,转而开始对新主服务器进行同步。 + +``` +127.0.0.1:6379> slaveof 192.168.1.124 6379 +OK +127.0.0.1:6379> info replication +# Replication +role:slave +master_host:192.168.1.124 +master_port:6379 +master_link_status:up +master_last_io_seconds_ago:3 +master_sync_in_progress:0 +slave_repl_offset:1701 +slave_priority:100 +slave_read_only:1 +connected_slaves:0 +master_replid:edb62cdf853a4c9caeab077005a58a3633cb55d0 +master_replid2:4bf0fb1edcb4ed661b919c0d10e6be193c63ccd1 +master_repl_offset:1701 +second_repl_offset:1631 +repl_backlog_active:1 +repl_backlog_size:1048576 +repl_backlog_first_byte_offset:1 +repl_backlog_histlen:1701 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \345\221\275\344\273\244\346\223\215\344\275\234.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \345\221\275\344\273\244\346\223\215\344\275\234.md" new file mode 100644 index 0000000..54005d6 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \345\221\275\344\273\244\346\223\215\344\275\234.md" @@ -0,0 +1,339 @@ +## 一、连接命令 + +**ping** + +通常用于测试与服务器的连接是否仍然生效,或者用于测量延迟值。 + +如果连接正常就返回一个PONG ,否则返回一个连接错误。 + +``` +127.0.0.1:6379> ping +PONG +``` + +**echo m** + +打印一个特定的信息 m ,测试时使用。 + +``` +127.0.0.1:6379> echo 'hello world' +"hello world" +``` + +**select i** + +切换到指定的数据库,数据库索引号 i 用数字值指定,以 0 作为起始索引值。默认使用 0号数据库。 + +``` +127.0.0.1:6379> select 1 +OK +127.0.0.1:6379[1]> +``` + +**案例:** + +在0号数据库中设置键a为‘hello world’,在1号数据库中调用 + +``` +127.0.0.1:6379> set a 'hello world' +OK +127.0.0.1:6379> select 1 +OK +127.0.0.1:6379[1]> get a +(nil) +``` + +**auth pword** + +开启了密码保护,在每次连接 Redis 服务器之后,就要使用auth命令解锁,解锁之后才能使用其他 Redis 命令。密码匹配时返回 `OK` ,否则返回一个错误。 + +设置密码 + +``` +127.0.0.1:6379> config set requirepass redis123456 +OK #requirepass的值就是密码 +127.0.0.1:6379> quit +``` + +在次登录 + +``` +[root@localhost redis]# ./src/redis-cli +127.0.0.1:6379> ping +(error) NOAUTH Authentication required. +127.0.0.1:6379> auth redis123456 +OK +127.0.0.1:6379> ping +PONG +``` + +清空密码 + +``` +127.0.0.1:6379> config set requirepass “” +OK #requirepass的值就是密码 +127.0.0.1:6379> quit +``` + +**quit** + +请求服务器关闭与当前客户端的连接。总是返回 `OK` (但是不会被打印显示,因为当时 Redis-cli 已经退出)。 + +``` +127.0.0.1:6379[1]> quit +[root@localhost redis]# +``` + +## 二、键命令 + +**set key value** + +将字符串值 value关联到 key 。 + +``` +127.0.0.1:6379> set key1 1 #传入的都是字符串 +OK +``` + +**get key** + +返回 key所关联的字符串值。如果 key 不存在那么返回特殊值 nil 。 + +``` +127.0.0.1:6379> get key1 +"1" +``` + +**del key1 [key2 … keyn]** + +删除给定的一个或多个 key 。没有的key忽略,返回被删除 key 的数量。 + +``` +127.0.0.1:6379> del key1 +(integer) 1 +``` + +**案例:** + +声明key1,key2,key3,删除key1,key2,key4 + +``` +127.0.0.1:6379> set key1 1 +OK +127.0.0.1:6379> set key2 1 +OK +127.0.0.1:6379> set key3 1 +OK +127.0.0.1:6379> del key1 key2 key4 +(integer) 2 +``` + +**exists key** + +检查给定 key 是否存在。若 key 存在,返回 1 ,否则返回 0 。 + +``` +127.0.0.1:6379> exists key3 +(integer) 1 +``` + +**type key** + +返回 key 所储存的值的类型。none (key不存在)、string (字符串)、list (列表)、set (集合)、zset (有序集)、hash (哈希表) + +``` +127.0.0.1:6379> type key1 +string +``` + +**expire key seconds** + +为给定 key 设置生存时间,以秒为单位,当 key 过期时(生存时间为 0 ),它会被自动删除。设置成功返回 1 。其他为0。 + +``` +127.0.0.1:6379> expire key3 30 +(integer) 1 +127.0.0.1:6379> ttl key3 #查看有效时间 +(integer) 24 +127.0.0.1:6379> exists key3 #验证是否存在 +(integer) 0 +``` + +**pexpire key mseconds** + +这个命令和 EXPIRE 命令的作用类似,但是它以毫秒为单位设置 key 的生存时间,而不像 EXPIRE 命令那样,以秒为单位。设置成功,返回 1。key不存在或设置失败,返回0 + +``` +127.0.0.1:6379> set key1 abc +OK +127.0.0.1:6379> pexpire key1 10000 +(integer) 1 +127.0.0.1:6379> ttl key1 +(integer) 5 +127.0.0.1:6379> pttl key1 +(integer) 746 +``` + +**persist key** + +移除给定 key 的生存时间,将这个 key 从易失的转换成持久的。当生存时间移除成功时,返回 1 .如果 key 不存在或 key 没有设置生存时间,返回 0 。 + +``` +127.0.0.1:6379> set zhangwu 1 +OK +127.0.0.1:6379> persist zhangwu +(integer) 0 +127.0.0.1:6379> expire zhangwu 30 +(integer) 1 +127.0.0.1:6379> persist zhangwu +(integer) 1 +127.0.0.1:6379> ttl zhangwu +(integer) -1 +``` + +**ttl key** + +以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。当 key 不存在时,返回 -2 。当 key 存在但没有设置剩余生存时间时,返回 -1 。 + +``` +127.0.0.1:6379> set key1 helloworld +OK +127.0.0.1:6379> ttl key1 +(integer) -1 +127.0.0.1:6379> expire key1 50 +(integer) 1 +127.0.0.1:6379> ttl key1 +(integer) 44 +127.0.0.1:6379> ttl key1 +(integer) -2 +``` + +**pttl key** + +这个命令类似于 TTL 命令,但它以毫秒为单位返回 key 的剩余生存时间,而不是像 TTL 命令那样,以秒为单位。当 key 不存在时,返回 -2 。当 key 存在但没有设置剩余生存时间时,返回 -1 。 + +``` +127.0.0.1:6379> pttl key1 +(integer) -2 +127.0.0.1:6379> set key1 abc +OK +127.0.0.1:6379> pexpire key1 30000 +(integer) 1 +127.0.0.1:6379> pttl key1 +(integer) 27345 +``` + +**keys pattern** + +查找所有符合给定模式 pattern 的 key 。符合给定模式的 key 列表。 + +**通配符** + +``` +* 表示多个字符 +? 表示一个字符 +[] 表示只能是[]里面的字符 +\ 表示指定特殊字符 +127.0.0.1:6379> mset zhangsan 1 zhangsi 2 zhangwu 3 +OK +127.0.0.1:6379> keys * +1) "zhangwu" +2) "zhangsan" +3) "zhangsi" +127.0.0.1:6379> keys ng* +(empty list or set) +127.0.0.1:6379> keys *ng* +1) "zhangwu" +2) "zhangsan" +3) "zhangsi" +127.0.0.1:6379> keys zhang?? +1) "zhangwu" +2) "zhangsi" +127.0.0.1:6379> keys zha[ng]si +(empty list or set) +127.0.0.1:6379> keys zhan[ng]si +1) "zhangsi" +``` + +**move key db** + +将当前数据库的 key 移动到给定的数据库 db 当中。移动成功返回 1 ,失败则返回 0 。 + +``` +127.0.0.1:6379> keys * +1) "zhangwu" +2) "zhangsan" +3) "zhangsi" +127.0.0.1:6379> select 1 +OK +127.0.0.1:6379[1]> keys * +(empty list or set) +127.0.0.1:6379[1]> select 0 +OK +127.0.0.1:6379> move zhangsan 1 +(integer) 1 +127.0.0.1:6379> select 1 +OK +127.0.0.1:6379[1]> keys * +1) "zhangsan" +127.0.0.1:6379[1]> select 0 +OK +127.0.0.1:6379> keys * +1) "zhangwu" +2) "zhangsi" +``` + +**注意:** + +key不存在时,移动失败 + +key移动到1库时,1库中出现同名的key,移动失败 + +**random key** + +从当前数据库中随机返回(不删除)一个 key 。当数据库不为空时,返回一个 key 。当数据库为空时,返回 nil 。 + +``` +127.0.0.1:6379> randomkey +"zhangwu" +127.0.0.1:6379> randomkey +"key" +127.0.0.1:6379> randomkey +"key" +127.0.0.1:6379> randomkey +"zhangwu" +``` + +**rename key newkey** + +将 key 改名为 newkey 。改名成功时提示 OK ,失败时候返回一个错误。 + +``` +127.0.0.1:6379> rename key key1 +OK +127.0.0.1:6379> keys * +1) "key1" +2) "zhangwu" +3) "zhangsi" +``` + +**注意:** + +当 key 和 newkey 相同,或者 key 不存在时,返回一个错误。 + +当 newkey 已经存在时, RENAME 命令将覆盖旧值。 + +**renamenx key newkey** + +当且仅当 newkey 不存在时,将 key 改名为 newkey 。修改成功时,返回 1 。如果 newkey 已经存在,返回 0 。 + +``` +127.0.0.1:6379> renamenx zhangsi zhangwu +(integer) 0 +127.0.0.1:6379> renamenx zhangsi zhangsan +(integer) 1 +127.0.0.1:6379> keys * +1) "zhangsan" +2) "key1" +3) "zhangwu" +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \345\223\250\345\205\265\346\250\241\345\274\217.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \345\223\250\345\205\265\346\250\241\345\274\217.md" new file mode 100644 index 0000000..7238ed7 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \345\223\250\345\205\265\346\250\241\345\274\217.md" @@ -0,0 +1,317 @@ +哨兵是一个分布式系统,你可以在一个架构中运行多个哨兵进程,这些进程使用流言协议来接收关于Master主服务器是否下线的信息,并使用投票协议来决定是否执行自动故障迁移,以及选择哪个Slave作为新的Master。 + +## 一、哨兵模式概述 + +### 1.1、为什么要启动哨兵模式 + +当我们的主服务器宕机后,要手动的去切换主从模式,这样的人工干预,费事费力,还会造成一段时间我们的服务不能使用。所有我们要使用哨兵模式来解决这一问题。 + +### 1.2、什么是哨兵模式 + +哨兵是对Redis的系统的运行情况的监控,它是一个独立进程,功能有二个: + +监控主机Redis和从机Redis是否运行正常; + +主机Redis出现故障后自动将从机转化为主机; + +### 1.3、哨兵工作原理 + +**单个哨兵的工作原理:** + +![image20200308235519661.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603524739859.png) + +单个哨兵,只需要监控主Redis,就可能得到从Redis。 + +**多个哨兵的工作原理:** + +![image20200309015254574.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603524758323.png) + +多个哨兵,不仅同时监控主从Redis,而且哨兵之间互为监控。 + +多个哨兵,防止哨兵单点故障。 + +### 1.4、哨兵功能 + +**集群监控**:负责监控主从集群中的Master和Slave进程是否正常工作。 + +**故障转移(failover)**:如果Master宕机,会自动从Slave中选举出新的Master,进行主从自动切换。 + +**配置中心**:如果发生了故障转移,Sentinel负责通知客户端新的Master的地址。 + +**消息通知**:如果某个redis节点有故障,那么Sentsinel会发送报警消息给系统管理员。 + +### 1.5、配置说明 + +``` +protected-mode no +#关闭保护模式,使外网能访问。 +port 26379 +#修改端口。三份文件分别不同。 +daemonize no +#修改为后台运行。 +pidfile /var/run/redis-sentinel.pid +#指定不同pid文件,注意文件夹不存在自己要新建。 +logfile "" +#配置哨兵日志文件。 +dir "/tmp" +#配置哨兵工作路径。 +sentinel monitor mymaster 192.167.1.123 6379 2 +#配置哨兵需要监控的主节点ip和端口,2表示哨兵数(quorum) +sentinel auth-pass mymaster ibethfy +#配置哨兵连接主节点的认证密码。(主节点配置的requirepass)。 +sentinel down-after-milliseconds mymaster 5000 +#配置多少毫秒后没收到主节点的反馈,则主观认为主节点down了。 +sentinel failover-timeout mymaster 30000 +#表示如果30秒后,mysater仍没活过来,则启动failover,从剩下的slave中选一个升级为master +sentinel parallel-syncs mymaster 1 +#parallel-syncs 指定了在执行故障转移时, 最多可以有多少个slave同时对新的master进行同步, 这个数字越小, 完成故障转移所需的时间就越长 +``` + +**注意:** + +majority表示大多数哨兵 + +quorum表示哨兵数 + +如果quorum < majority,比如5个哨兵,majority就是3,quorum设置为2,那么就3个哨兵授权就可以执行切换。 + +但是如果quorum >= majority,那么必须quorum数量的哨兵都授权,比如5个哨兵,quorum是5,那么必须5个哨兵都同意授权,才能执行切换。 + +## 二、单哨兵模式 + +在一主多从的环境中,125为主机,123、124为从机 + +哨兵主机121 + +### 2.1、设置哨兵 + +修改配置文件/usr/local/redis/sentinel.conf + +``` +[root@zutuanxue redis]# vim sentinel.conf + +#修改配置 +sentinel monitor mymaster 192.168.1.123 6379 1 +``` + +**注意:** + +mymaster:监控主数据的名称,命名时可以使用大小写字母和“.-_”符号 + +192.168.1.123 6379:主机的IP和端口号 + +### 2.2、启动哨兵 + +``` +[root@zutuanxue redis]# ./src/redis-sentinel ./sentinel.conf +或 +[root@zutuanxue redis]# ./src/redis-server ./sentinel.conf --sentinel +``` + +![image20200309004221200.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603524787197.png) + +看出: + +125为主机,123、124为从机 + +### 2.3、从机宕机 + +杀死124从机进程,30秒后观察哨兵日志 + +``` +[root@zutuanxue redis]# ps -ef|grep redis +root 18752 12399 0 06:35 pts/1 00:00:00 ./src/redis-cli +root 22163 1 0 12:18 ? 00:00:02 ./src/redis-server 0.0.0.0:6379 +root 22392 22002 0 12:44 pts/2 00:00:00 grep --color=auto redis +[root@zutuanxue redis]# kill -s 9 22163 +``` + +![image20200309004654315.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603524805745.png) + +启动124从机,观察哨兵日志 + +``` +[root@zutuanxue redis]# ./src/redis-server ./redis.conf +``` + +![image20200309004921484.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603524827043.png) + +### 2.4、主机宕机 + +杀死125主机进程,30秒后观察哨兵日志 + +``` +[root@zutuanxue redis]# ps -ef|grep redis +root 14988 1 0 06:20 ? 00:01:15 ./src/redis-server 0.0.0.0:6379 +root 15144 8874 0 06:35 pts/0 00:00:00 ./src/redis-cli +root 18527 18104 0 12:50 pts/1 00:00:00 grep --color=auto redis +[root@zutuanxue redis]# kill -s 9 14988 +``` + +![image20200309005314573.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603524845851.png) + +日志状态说明: + +``` ++reset-master: +#主服务器已被重置。 ++slave: +#一个新的从服务器已经被 Sentinel 识别并关联。 ++failover-state-reconf-slaves: +#故障转移状态切换到了 reconf-slaves 状态。 ++failover-detected: +#另一个 Sentinel 开始了一次故障转移操作,或者一个从服务器转换成了主服务器。 ++slave-reconf-sent: +#领头(leader)的 Sentinel 向实例发送了 [SLAVEOF](/commands/slaveof.html) 命令,为实例设置新的主服务器。 ++slave-reconf-inprog: +#实例正在将自己设置为指定主服务器的从服务器,但相应的同步过程仍未完成。 ++slave-reconf-done: +#从服务器已经成功完成对新主服务器的同步。 +-dup-sentinel: +#对给定主服务器进行监视的一个或多个 Sentinel 已经因为重复出现而被移除 —— 当 Sentinel 实例重启的时候,就会出现这种情况。 ++sentinel: +#一个监视给定主服务器的新 Sentinel 已经被识别并添加。 ++sdown: +#给定的实例现在处于主观下线状态。 +-sdown: +#给定的实例已经不再处于主观下线状态。 ++odown: +#给定的实例现在处于客观下线状态。 +-odown: +#给定的实例已经不再处于客观下线状态。 ++new-epoch: +#当前的纪元(epoch)已经被更新。 ++try-failover: +#一个新的故障迁移操作正在执行中,等待被大多数 Sentinel 选中(waiting to be elected by the majority)。 ++elected-leader: +#赢得指定纪元的选举,可以进行故障迁移操作了。 ++failover-state-select-slave: +#故障转移操作现在处于 select-slave 状态 —— Sentinel 正在寻找可以升级为主服务器的从服务器。 +no-good-slave: +#Sentinel 操作未能找到适合进行升级的从服务器。Sentinel 会在一段时间之后再次尝试寻找合适的从服务器来进行升级,又或者直接放弃执行故障转移操作。 +selected-slave: +#Sentinel 顺利找到适合进行升级的从服务器。 +failover-state-send-slaveof-noone: +#Sentinel 正在将指定的从服务器升级为主服务器,等待升级功能完成。 +failover-end-for-timeout: +#故障转移因为超时而中止,不过最终所有从服务器都会开始复制新的主服务器(slaves will eventually be configured to replicate with the new master anyway)。 +failover-end: +#故障转移操作顺利完成。所有从服务器都开始复制新的主服务器了。 ++switch-master +#配置变更,主服务器的 IP 和地址已经改变。 这是绝大多数外部用户都关心的信息。 ++tilt: +#进入 tilt 模式。 +-tilt: +#退出 tilt 模式 +``` + +启动125主机,观察哨兵日志 + +``` +[root@zutuanxue redis]# ./src/redis-server ./redis.conf +``` + +![image20200309005527164.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603524868822.png) + +## 三、多哨兵模式 + +在一主多从的环境中,123为主机,124、125为从机 + +121中设置三个哨兵sentinel-1.conf、sentinel-2.conf、sentinel-3.conf + +### 3.1、设置哨兵 + +将哨兵文件sentinel.conf,复制三份sentinel-1.conf、sentinel-2.conf、sentinel-3.conf + +``` +[root@zutuanxue redis]# cp sentinel.conf sentinel-1.conf +[root@zutuanxue redis]# cp sentinel.conf sentinel-2.conf +[root@zutuanxue redis]# cp sentinel.conf sentinel-3.conf +``` + +修改配置文件/usr/local/redis/sentinel-1.conf + +``` +[root@zutuanxue redis]# vim sentine-l.conf + +#修改配置 +protected-mode no +port 27001 +daemonize yes +pidfile "/var/run/redis-sentinel-27001.pid" +logfile "/usr/local/redis/log/27001.log" +sentinel monitor m1 192.168.1.123 6379 1 +#sentinel myid c299ec06a9dde77dcbc086082e9d7e30a29615b7 +``` + +修改配置文件/usr/local/redis/sentinel-2.conf + +``` +[root@zutuanxue redis]# vim sentine-2.conf + +#修改配置 +protected-mode no +port 27002 +daemonize yes +pidfile "/var/run/redis-sentinel-27002.pid" +logfile "/usr/local/redis/log/27002.log" +sentinel monitor m2 192.168.1.123 6379 1 +#sentinel myid c299ec06a9dde77dcbc086082e9d7e30a29615b7 +``` + +修改配置文件/usr/local/redis/sentinel-3.conf + +``` +[root@zutuanxue redis]# vim sentine-3.conf + +#修改配置 +protected-mode no +port 27003 +daemonize yes +pidfile "/var/run/redis-sentinel-27003.pid" +logfile "/usr/local/redis/log/27003.log" +sentinel monitor m3 192.168.1.123 6379 1 +#sentinel myid c299ec06a9dde77dcbc086082e9d7e30a29615b7 +``` + +### 3.2、启动哨兵 + +``` +[root@zutuanxue redis]# ./src/redis-sentinel ./sentinel-1.conf +[root@zutuanxue redis]# ./src/redis-sentinel ./sentinel-2.conf +[root@zutuanxue redis]# ./src/redis-sentinel ./sentinel-3.conf +``` + +### 3.3、从机宕机 + +杀死125从机进程 + +``` +[root@zutuanxue redis]# ps -ef|grep redis +root 20733 1 0 11:55 ? 00:00:00 ./src/redis-server 0.0.0.0:6379 +root 20775 20646 0 11:59 pts/0 00:00:00 grep --color=auto redis +[root@zutuanxue redis]# kill -s 9 20733 +``` + +启动125从机 + +``` +[root@zutuanxue redis]# ./src/redis-server ./redis.conf +``` + +### 3.4、主机宕机 + +杀死123主机进程,30秒后观察哨兵日志 + +``` +[root@zutuanxue redis]# ps -ef|grep redis +root 27555 1 0 11:55 ? 00:00:01 ./src/redis-server 0.0.0.0:6379 +root 27693 27393 0 12:08 pts/0 00:00:00 grep --color=auto redis +[root@zutuanxue redis]# kill -s 9 27555 +``` + +启动123主机 + +``` +[root@zutuanxue redis]# ./src/redis-server ./redis.conf +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \346\225\260\346\215\256\346\214\201\344\271\205\345\214\226.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \346\225\260\346\215\256\346\214\201\344\271\205\345\214\226.md" new file mode 100644 index 0000000..2200685 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \346\225\260\346\215\256\346\214\201\344\271\205\345\214\226.md" @@ -0,0 +1,506 @@ +Redis支持两种数据持久化方式:RDB方式和AOF方式。前者会根据配置的规则定时将内存中的数据持久化到硬盘上,后者则是在每次执行写命令之后将命令记录下来。两种持久化方式可以单独使用,但是通常会将两者结合使用。 + +## 一、持久化 + +### 1.1、什么是持久化 + +持久化功能有效地避免因进程退出造成的数据丢失问题,当下次重启时利用之前持久化的文件即可实现数据恢复。 + +### 1.2、持久化方式 + +Redis支持RDB和AOF两种持久化机制: + +**RDB(快照方式):** RDB方式是一种快照式的持久化方法,将某一时刻的数据持久化到磁盘中。这种方式就是将内存中数据以快照的方式写入到二进制文件中 ,默认的文件名为dump.rdb。 + +**AOF(日志追加):** AOF方式是将执行过的写指令记录下来,在数据恢复时按照从前到后的顺序再将指令执行一遍。这种方式 redis 会将每一个收到的写命令都通过 write 函数追加到文件中(默认appendonly.aof)。 + +### 1.3、RDB优缺点 + +**优点:** + +RDB是一个紧凑的单一文件,方便传送,适用于灾难恢复。 + +与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些。 + +**缺点:** + +Redis意外宕机,可能会丢失几分钟的数据(取决于配置的save时间点)。RDB方式需要保存珍整个数据集,是一个比较繁重的工作,通常需要设置5分钟或者更久做一次完整的保存。 + +针对RDB不适合实时持久化的问题,Redis提供了AOF持久化方式来解决。 + +### 1.4、AOF优缺点 + +**优点:** + +AOF只是追加日志文件,因此对服务器性能影响较小,速度比RDB要快,消耗的内存较少。 + +**缺点:** + +AOF方式生成的日志文件太大,即使通过AOF重写,文件体积仍然很大。 + +恢复数据的速度比RDB慢。 + +## 二、RDB持久化触发机制 + +触发RDB持久化过程分为手动触发和自动触发 + +### 2.1、手动触发 + +手动触发持久化的操作有二个:save和bgsave。它们主要区别体现在:是否阻塞 Redis 主线程的执行。 + +**save命令** + +在客户端中执行 save 命令,就会触发 Redis 的持久化,但同时也是使 Redis 处于阻塞状态,直到 RDB 持久化完成,才会响应其他客户端发来的命令,所以在生产环境一定要慎用。 + +![image20200229001933749.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603523916780.png) + +执行过程: + +查看/usr/local/redis/dump.rdb文件保存时间 + +``` +[root@zutuanxue redis]# ls dump.rdb -l +-rw-r--r--. 1 root root 92 2月 28 03:37 dump.rdb +[root@zutuanxue redis]# ./src/redis-cli +127.0.0.1:6379> save +OK +127.0.0.1:6379> exit +[root@zutuanxue redis]# ls dump.rdb -l +-rw-r--r--. 1 root root 92 2月 28 11:08 dump.rdb +``` + +当执行完 save 命令之后,持久化文件 dump.rdb 的修改时间就变了,这就表示 save 成功的触发了 RDB 持久化。 + +**bgsave命令** + +bgsave(background save)既后台保存的意思, 它和 save 命令最大的区别就是 bgsave 会 fork() 一个子进程来执行持久化,整个过程中只有在 fork() 子进程时有短暂的阻塞,当子进程被创建之后,Redis 的主进程就可以响应其他客户端的请求了,相对于整个流程都阻塞的 save 命令来说,显然 bgsave 命令更适合我们使用。 + +![image20200229003129948.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603523960708.png) + +执行过程 + +``` +127.0.0.1:6379> bgsave +Background saving started +127.0.0.1:6379> exit +[root@zutuanxue redis]# ls dump.rdb -l +-rw-r--r--. 1 root root 92 2月 28 11:29 dump.rdb +``` + +### 2.2、自动触发 + +自动触发持久化,本质是 Redis 通过判断,如果满足设置的触发条件,自动执行一次 bgsave 命令。 + +RDB 自动持久化主要来源于以下几种情况: + +**save m n** + +表示的是在 m 秒内,如果有 n 个键发生改变,则自动触发持久化。 + +如: + +配置文件(/usr/local/redis/redis.conf)中的默认配置 + +![image20200229011458921.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603523982153.png) + +当 900s 内如果有 1次 Redis 键值发生改变,就会触发持久化; + +当 300s 内如果有 10次 Redis 键值发生改变,就会触发持久化; + +当 60s 内如果有 10000次 Redis 键值发生改变,就会触发持久化; + +**注意:** + +当设置多个 save m n 命令时,满足任意一个条件都会触发持久化。 + +**flushall** + +清空 Redis 数据库,在生产环境下一定慎用,当 Redis 执行了 flushall 命令之后,则会触发自动持久化,把 RDB 文件清空。 + +``` +127.0.0.1:6379> flushall +OK +``` + +## 三、RDB持久化配置 + +### 3.1、配置文件 + +vim /usr/local/redis/redis.conf + +``` +#RDB持久化自动触发条件 +save 900 1 +save 300 10 +save 60 10000 +#bgsave持久化失败,是否停止持久化数据到磁盘,yes 表示停止持久化,no 表示忽略错误继续写文件 +stop-writes-on-bgsave-error yes +#rdb文件是否压缩 +rdbcompression yes +#写入文件和读取文件时是否开启rdb文件检查,检查是否有无损坏,如果在启动是检查发现损坏,则停止启动。 +rdbchecksum yes +#rdb持久化后存放的文件名 +dbfilename dump.rdb +#rdb持久化后文件的存放路径 +dir ./ +``` + +**注意:** + +文件压缩要是开启的话:Redis 会采用 LZF 算法进行压缩。如果不想消耗 CPU 性能来进行文件压缩的话,可以设置为关闭此功能,这样的缺点是需要更多的磁盘空间来保存文件。 + +### 3.2、配置查询/设置 + +**config get xxx** + +``` +127.0.0.1:6379> config get dir +1) "dir" +2) "/usr/local/redis" +127.0.0.1:6379> config get dbfilename +1) "dbfilename" +2) "dump.rdb" +127.0.0.1:6379> config get stop-writes-on-bgsave-error +1) "stop-writes-on-bgsave-error" +2) "yes" +``` + +**config set xxx** + +``` +[root@zutuanxue redis]# mkdir data +[root@zutuanxue redis]# ./src/redis-cli +127.0.0.1:6379> config set dir "/usr/local/redis/data" +OK +127.0.0.1:6379> config get dir +1) "dir" +2) "/usr/local/redis/data" +``` + +**注意:** + +使用命令修改的方式,马上生效,在 Redis 重启之后就会丢失。手动修改 Redis 配置文件,想要立即生效需要重启 Redis 服务器,会一直有效。 + +### 3.3、禁用持久化 + +``` +127.0.0.1:6379> config set save "" +OK +``` + +### 3.4、RDB文件恢复 + +当 Redis 服务器启动时,Redis 就会自动加载 RDB 文件恢复持久化数据。 + +**验证加载** + +启动redis时 + +![image20200229014938758.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603524030551.png) + +## 四、RDB持久化案例 + +### 4.1、手动持久化 + +``` +127.0.0.1:6379> config set save "" +OK +127.0.0.1:6379> set s helloworld! +OK +127.0.0.1:6379> get s +"helloworld!" +127.0.0.1:6379> save +OK +127.0.0.1:6379> del s +(integer) 1 +127.0.0.1:6379> get s +(nil) +127.0.0.1:6379> exit +[root@zutuanxue redis]# ./src/redis-cli shutdown +[root@zutuanxue redis]# ./src/redis-server ./redis.conf +#Redis服务端启动成功提示信息 +[root@zutuanxue redis]# ./src/redis-cli +127.0.0.1:6379> get s +"helloworld!" +``` + +### 4.2、自动持久化案例 + +``` +#新建log文件夹 +[root@zutuanxue redis]# mkdir log +#配置日志文件 +[root@zutuanxue redis]# vim redis.conf +#配置:logfile "/usr/local/redis/log/redis.log" +[root@zutuanxue redis]# ./src/redis-server ./redis.conf +[root@zutuanxue redis]# ./src/redis-cli +127.0.0.1:6379> config set save "10 1" +OK +127.0.0.1:6379> config get save +1) "save" +2) "10 1" +127.0.0.1:6379> set a 123 +OK +127.0.0.1:6379> set b 456 +OK +127.0.0.1:6379> set c 789 +OK +127.0.0.1:6379> set d 8910 +OK +127.0.0.1:6379> exit +[root@zutuanxue redis]# cd log +[root@zutuanxue log]# ls +redis.log +[root@zutuanxue log]# vim redis.log +``` + +![image20200229024640021.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603524065211.png) + +## 五、AOF持久化 + +AOF方式在使用Redis存储非临时数据时,一般都需要打开AOF持久化来降低进程终止导致的数据丢失,AOF可以将Redis执行的每一条写命令追加到硬盘文件中,这一过程显然会降低Redis的性能,但是大部分情况下这个影响是可以接受的,另外,使用较快的硬盘能提高AOF的性能。 + +### 5.1、AOF工作流 + +命令写入 (append)、文件同步(sync)、文件重写(rewrite)、重启加载 (load) + +![image20200303224156711.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603524103564.png) + +### 5.2、AOF特点 + +默认文件名是 appendonly.aof。保存的位置由配置中 dir 来配置目录。 + +AOF 每次都会保存写命令,数据实时性更高。 + +AOF 需要使用“重写机制”来优化,每次记录写命令,文件会很大的问题。 + +AOF 根据不同的“缓冲区同步策略”将我们缓冲区中写入的命令,同步到磁盘。 + +**重写机制** + +![image20200303233558568.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603524125650.png) + +**缓冲区同步策略** + +设置appendfsync 控制,一共3种: + +always:客户端的每一个写操作都保存到aof文件当,这种策略很安全,但是每个写都会有IO操作,所以也很慢。 + +everysec:每秒写入一次aof文件,因此,最多可能会丢失1s的数据。 推荐使用这种方式。 + +no: 交由操作系统来处理什么时候写入aof文件。更快,但也是最不安全的选择,不推荐使用。 + +### 5.3、持久化恢复 + +在重启redis服务时,rdb与aof如何执行? + +![image20200303235441014.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603524148069.png) + +## 六、开启AOF持久化 + +### 6.1、修改配置 + +修改配置文件/usr/local/redis/redis.conf + +``` +appendonly yes #表示开启AOF持久化,默认是no表示关闭 +appendfilename "appendonly.aof" #AOF持久化文件名 +appendfsync everysec #缓冲同步策略,默认值 +no-appendfsync-on-rewrite no #是否重写,默认不重写 +``` + +### 6.2、测试aof + +开启之后,Redis每执行一条写命令就会将该命令写入硬盘中的AOF文件。AOF文件保存路径和RDB文件路径是一致的,都是通过dir参数配置 , 默 认文 件 名 是 : appendonly.aof + +``` +[root@zutuanxue redis]# ./src/redis-server ./redis.conf +[root@zutuanxue redis]# ./src/redis-cli +127.0.0.1:6379> set x 123 +OK +127.0.0.1:6379> set y 345 +OK +127.0.0.1:6379> exit +[root@zutuanxue redis]# cat appendonly.aof +*2 #表示有二个参数,注意命令本身也是参数的一部份 +$6 #第一个参数,长度为6(字节数) +SELECT #第一个参数,总是命令本身 +$1 #第二个参数,长度为1 +0 #第二个参数 +*3 +$3 +set +$1 +x +$3 +123 +*3 +$3 +set +$1 +y +$3 +345 +``` + +在次测试 + +``` +[root@zutuanxue redis]# ./src/redis-cli +127.0.0.1:6379> set z 23 +OK +127.0.0.1:6379> get z +"23" +127.0.0.1:6379> exit +[root@zutuanxue redis]# cat appendonly.aof +/*前面有以前的写命令,aof文件只会存储写命令*/ +*2 +$6 +SELECT +$1 +0 +*3 +$3 +set +$1 +z +$2 +23 +``` + +## 七、AOF重写 + +### 7.1、为什么要重写 + +随着aof文件越来越大,需要定期对aof文件进行重写,达到压缩的目的。 + +### 7.2、重写aof改变 + +进程内已经超时的数据不再写入文件。 + +旧的aof有无效命令(如:set k1 hello ex 10000),新的aof文件只保留最终数据的写入命令。 + +多条写命令可以合并为一个(如:lpush list a、lpush list b、lpush list c可以转化为:lpush list a b c)。但也不能将整个lpush生成的元素全部写在一起,所以对于list、set、hash、zset等类型操作,以64个元素为界拆分为多条。来防止客户端缓冲区溢出。 + +AOF重写降低了文件占用空间,更小的aof 文件启动redis时,加载更快。 + +### 7.3、重写方式 + +AOF重写过程可以手动触发和自动触发: + +**手动触发:**直接调用bgrewriteaof命令。 + +**自动触发:**根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发时机 + +![image20200303233558568.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603524191402.png) + +### 7.4、手动触发 + +``` +127.0.0.1:6379> bgrewriteaof +Background append only file rewriting started +``` + +![image20200304005133531.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603524208890.png) + +``` +[root@zutuanxue redis]# ./src/redis-cli +127.0.0.1:6379> keys * +1) "k2" +2) "ff" +3) "h" +4) "k3" +5) "k1" +6) "fds" +7) "hfds" +8) "z" +9) "k" +127.0.0.1:6379> set a 1231 +OK +127.0.0.1:6379> set b 12321 +OK +127.0.0.1:6379> exit +[root@zutuanxue redis]# cat appendonly.aof +``` + +![image20200304012220240.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603524240666.png) + +### 7.5、自动触发 + +#### 7.5.1、配置文件 + +修改配置文件/usr/local/redis/redis.conf + +``` +auto-aof-rewrite-percentage 100 #AOF文件增长率(当前AOF文件大小超过上一次重写的AOF文件大小的百分之多少才会重写) +auto-aof-rewrite-min-size 64mb #表示运行AOF重写时文件最小体积,默认为64MB。 +``` + +**注意:** + +aof_current_size: aof当前尺寸(单位:字节) + +aof_base_size: aof上次启动和重写的尺寸(单位:字节) + +#### 7.5.2、自动触发时机 + +当前 AOF 文件大小超过最小重写尺寸 + +当前 AOF 文件大小超过上次重写完的 AOF 尺寸*的百分之多少(*auto-aof-rewrite-percentage) + +**换算** + +自动触发时机=aof_current_size>auto-aof-rewrite-min-size&&(aof_current_size-aof_base_size)/aof_base_size>=auto-aof-rewrite-percentage + +**查看aof_current_size和aof_base_size的值** + +``` +127.0.0.1:6379> info persistence +# Persistence +loading:0 +rdb_changes_since_last_save:1 +rdb_bgsave_in_progress:0 +rdb_last_save_time:1583254417 +rdb_last_bgsave_status:ok +rdb_last_bgsave_time_sec:0 +rdb_current_bgsave_time_sec:-1 +rdb_last_cow_size:188416 +aof_enabled:1 +aof_rewrite_in_progress:0 +aof_rewrite_scheduled:0 +aof_last_rewrite_time_sec:0 +aof_current_rewrite_time_sec:-1 +aof_last_bgrewrite_status:ok +aof_last_write_status:ok +aof_last_cow_size:2330624 +aof_current_size:295 +aof_base_size:211 +aof_pending_rewrite:0 +aof_buffer_length:0 +aof_rewrite_buffer_length:0 +aof_pending_bio_fsync:0 +aof_delayed_fsync:0 +``` + +**295>64M &&(295-211)/211>=100** + +只有当这二个条件同时成立,我们才会去触发我们的重写AOF + +### 7.6、aof文件恢复 + +在写入aof日志文件时,如果Redis服务器宕机,则aof日志文件文件会出格式错误,在重启Redis服务器时,Redis服务器会拒绝载入这个aof文件,可以通过以下步骤修复aof并恢复数据。 + +备份现在aof文件,以防万一。 + +出现以下提示: + +![image20200310153632470.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603524305793.png) + +使用redis-check-aof命令修复aof文件,该命令格式如下: + +``` +# 修复aof日志文件 +$ redis-check-aof -fix file.aof +``` + +重启Redis服务器,加载已经修复的aof文件,恢复数据。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \346\225\260\346\215\256\347\261\273\345\236\213.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \346\225\260\346\215\256\347\261\273\345\236\213.md" new file mode 100644 index 0000000..de60ccc --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \346\225\260\346\215\256\347\261\273\345\236\213.md" @@ -0,0 +1,1721 @@ +Redis支持五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)及Zset(sorted set:有序集合)。 + +## 一、字符串类型概述 + +### 1.1、数据类型 + +Redis支持五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)及Zset(sorted set:有序集合)。 + +### 1.2、字符串简介 + +字符串类型是redis最基础的数据结构,首先键是字符串类型,而且其他几种结构都是在字符串类型基础上构建的,所以字符串类型为其他四种数据结构尊定了基础。 + +字符串类型实际上可以是简单的字符串、复杂的字符串(xml、json)、数字(整数、浮点数)、二进制(图片、音频、视频)。 + +### 1.3、字符串应用场景 + +**共享session:** + +用户登录后,用户刷新一次可能会重复登录,这个时候我们就将用户session集中管理,在这种模式下每次获取和更新用户信息都可以从redis中获取。 + +**限速:** + +当我们在登录时,用来限制为我手机接到验证码的时间,防止我们的短信接口不被频繁访问,会限制用户每分钟获取验证码的频率。 + +## 二、字符串命令 + +**set key value [EX seconds] [PX milliseconds] [NX|XX]** + +将字符串值 value 关联到 key + +**注意:** + +EX:设置键的过期时间为 second 秒 + +PX:设置键的过期时间为 millisecond 毫秒 + +NX:只在键不存在时,才对键进行设置操作。 + +XX:只在键已经存在时,才对键进行设置操作。 + +``` +# EX 秒 +127.0.0.1:6379> set key1 hello EX 1000 +OK +127.0.0.1:6379> get key1 +"hello" +127.0.0.1:6379> ttl key1 +(integer) 992 + +# PX 毫秒 +127.0.0.1:6379> set key2 hello PX 100000 +OK +127.0.0.1:6379> get key2 +"hello" +127.0.0.1:6379> pttl key2 +(integer) 89973 + +#NX 键不存在设置成功 +127.0.0.1:6379> set key3 hello NX +OK +127.0.0.1:6379> get key3 +"hello" +127.0.0.1:6379> set key3 helloworld NX +(nil) +127.0.0.1:6379> get key3 +"hello" + +#XX 键存在设置成功 +127.0.0.1:6379> set key4 helloworld XX +(nil) +127.0.0.1:6379> set key3 helloworld XX +OK +127.0.0.1:6379> get key3 +"helloworld" +127.0.0.1:6379> get key4 +(nil) +``` + +**注意:** + +因为 SET 命令可以通过参数来实现和 SETNX 、 SETEX 和 PSETEX 三个命令的效果: + +SETNX:若给定的 key 已经存在,则 SETNX 不做任何动作 + +SETEX:如果 key 已经存在, SETEX 命令将覆写旧值。 + +PSETEX:这个命令和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 SETEX 命令那样,以秒为单位。 + +**get key** + +返回 key 所关联的字符串值。 + +当 key 不存在时,返回 nil ,否则,返回 key 的值。如果 key 不是字符串类型,那么返回一个错误。 + +``` +127.0.0.1:6379> set key1 hello +OK +127.0.0.1:6379> get key1 +"hello" +127.0.0.1:6379> get key2 +(nil) +``` + +**mset key value [key value …]** + +同时设置一个或多个 key-value 对。 + +``` +127.0.0.1:6379> mset k1 zhangsan k2 lisi k3 wangwu +OK +127.0.0.1:6379> get k1 +"zhangsan" +127.0.0.1:6379> mget k1 k2 k3 +1) "zhangsan" +2) "lisi" +3) "wangwu" +``` + +**mget key [key …]** + +返回所有(一个或多个)给定 key 的值。 + +如果给定的 key 里面,有某个 key 不存在,那么这个 key 返回特殊值 nil 。因此,该命令永不失败。 + +``` +127.0.0.1:6379> del k1 k2 k3 +(integer) 3 +127.0.0.1:6379> keys * +1) "key1" +2) "key3" +127.0.0.1:6379> set k1 zhangsan +OK +127.0.0.1:6379> set k2 lisi +OK +127.0.0.1:6379> mget k1 k2 k3 +1) "zhangsan" +2) "lisi" +3) (nil) +``` + +**append key value** + +如果 key 已经存在并且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾。 + +如果 key 不存在, APPEND 就简单地将给定 key 设为 value ,就像执行 SET key value 一样。 + +``` +127.0.0.1:6379> append k1 zhang +(integer) 5 +127.0.0.1:6379> get k1 +"zhang" +127.0.0.1:6379> append k1 san +(integer) 8 +127.0.0.1:6379> get k1 +"zhangsan" +``` + +**decr key** + +将 key 中储存的数字值减一。 + +如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 DECR 操作。 + +如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。 + +``` +127.0.0.1:6379> set k2 10 +OK +127.0.0.1:6379> decr k2 +(integer) 9 +127.0.0.1:6379> get k2 +"9" +127.0.0.1:6379> set k3 zhangsan +OK +127.0.0.1:6379> decr k3 +(error) ERR value is not an integer or out of range +127.0.0.1:6379> decr k4 +(integer) -1 +127.0.0.1:6379> get k4 +"-1" +127.0.0.1:6379> keys * +1) "k4" +2) "k2" +3) "k1" +4) "k3" +``` + +**decrby key decrement** + +将 key 所储存的值减去减量 decrement 。 + +如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 DECRBY 操作。 + +如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。 + +``` +127.0.0.1:6379> set k1 100 +OK +127.0.0.1:6379> decrby k1 20 +(integer) 80 +127.0.0.1:6379> get k1 +"80" +127.0.0.1:6379> decrby k2 20 +(integer) -20 +127.0.0.1:6379> get k2 +"-20" +127.0.0.1:6379> set k3 zhangsan +OK +127.0.0.1:6379> decrby k3 10 +(error) ERR value is not an integer or out of range +``` + +**incr key** + +将 key 中储存的数字值增一。 + +如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。 + +如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。 + +``` +127.0.0.1:6379> set n 10 +OK +127.0.0.1:6379> incr n +(integer) 11 +127.0.0.1:6379> get n +"11" +127.0.0.1:6379> incr m +(integer) 1 +127.0.0.1:6379> get m +"1" +127.0.0.1:6379> set s 'zhangsan' +OK +127.0.0.1:6379> incr s +(error) ERR value is not an integer or out of range +``` + +**incrby key increment** + +将 key 所储存的值加上增量 increment 。 + +如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCRBY 命令。 + +如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。 + +``` +127.0.0.1:6379> set n 10 +OK +127.0.0.1:6379> incrby n 10 +(integer) 20 +127.0.0.1:6379> get n +"20" +127.0.0.1:6379> incrby m -20 +(integer) -20 +127.0.0.1:6379> get m +"-20" +127.0.0.1:6379> set s abc +OK +127.0.0.1:6379> incrby s 10 +(error) ERR value is not an integer or out of range +``` + +**incrbyfloat key increment** + +为 key 中所储存的值加上浮点数增量 increment 。 + +如果 key 不存在,那么 INCRBYFLOAT 会先将 key 的值设为 0 ,再执行加法操作。 + +``` +127.0.0.1:6379> set m 10.05 +OK +127.0.0.1:6379> incrbyfloat m 0.1 +"10.15" +``` + +**getrange key start end** + +返回 key 中字符串值的子字符串,字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内)。 + +负数偏移量表示从字符串最后开始计数, -1 表示最后一个字符, -2 表示倒数第二个,以此类推。 + +``` +127.0.0.1:6379> set str 'hello world!' +OK +127.0.0.1:6379> getrange str 0 4 +"hello" +127.0.0.1:6379> getrange str -4 -1 +"rld!" +127.0.0.1:6379> getrange str -1 -5 +"" +127.0.0.1:6379> getrange str 0 -1 +"hello world!" +127.0.0.1:6379> getrange str 0 20 +"hello world!" +``` + +**注意:** + +substr与getrange一样 + +**getset key value** + +将给定 key 的值设为 value ,并返回 key 的旧值(old value)。 + +返回给定 key 的旧值。当 key 没有旧值时,也即是, key 不存在时,返回 nil 。 + +``` +127.0.0.1:6379> getset db mysql +(nil) +127.0.0.1:6379> get db +"mysql" +127.0.0.1:6379> getset db oracle +"mysql" +127.0.0.1:6379> get db +"oracle" +``` + +**strlen key** + +返回 key 所储存的字符串值的长度。 + +当 key 储存的不是字符串值时,返回一个错误。 + +``` +127.0.0.1:6379> set s 'hello world!' +OK +127.0.0.1:6379> strlen s +(integer) 12 +``` + +## 三、哈希类型概述 + +### 3.1、哈希介绍 + +在redis中哈希类型是指键本身又是一种键值对结构: + +value格式:{{key1,value1},…{keyn,valuen}} + +### 3.2、哈希类型应用场景 + +适合存储对象,并且可以像数据库中update一样,去修改其中的一个属性中的一个值。比如:用户(姓名、性别、年龄等),文章(标题、发布时间、作者、内容),那么我们就可以对用户里面的性别,年龄等属性做到一对一的修改、存储、读取。 + +### 3.3、哈希命令 + +**hset key field value** + +将哈希表 key 中的域 field 的值设为 value 。 + +如果 key 不存在,一个新的哈希表被创建并进行 HSET 操作。 + +如果域 field 已经存在于哈希表中,旧值将被覆盖。 + +如果 field 是哈希表中的一个新建域,并且值设置成功,返回 1 。 + +如果哈希表中域 field 已经存在且旧值已被新值覆盖,返回 0 。 + +``` +127.0.0.1:6379> hset k1 xm zhangsan xb '男' +(integer) 2 +127.0.0.1:6379> hget k1 xb +"\xe7\x94\xb7" +127.0.0.1:6379> hget k1 xm +"zhangsan" +127.0.0.1:6379> hset k1 xb nan +(integer) 0 +127.0.0.1:6379> hget k1 xb +"nan" +``` + +**hget key field** + +返回哈希表 key 中给定域 field 的值。 + +给定域的值。 + +当给定域不存在或是给定 key 不存在时,返回 nil 。 + +``` +127.0.0.1:6379> hset k2 xm lisi +(integer) 1 +127.0.0.1:6379> hget k2 xm +"lisi" +127.0.0.1:6379> hget k2 +(error) ERR wrong number of arguments for 'hget' command +``` + +**hdel key field [field …]** + +删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略。 + +``` +127.0.0.1:6379> del k1 +(integer) 1 +127.0.0.1:6379> keys * +1) "s" +2) "k2" +3) "m" +127.0.0.1:6379> hdel k2 +(error) ERR wrong number of arguments for 'hdel' command +127.0.0.1:6379> hdel k2 xm +(integer) 1 +127.0.0.1:6379> keys * +1) "s" +2) "m" +``` + +**注意:** + +HDEL 每次只能删除单个域,如果你需要在一个原子时间内删除多个域,请将命令包含在 MULTI / EXEC 块内(事务)。 + +**hexists key field** + +查看哈希表 key 中,给定域 field 是否存在。 + +如果哈希表含有给定域,返回 1 。 + +如果哈希表不含有给定域,或 key 不存在,返回 0 。 + +``` +127.0.0.1:6379> hset k1 xm zhangsan xb nan +(integer) 2 +127.0.0.1:6379> hexists k1 xm +(integer) 1 +127.0.0.1:6379> hdel k1 xb +(integer) 1 +127.0.0.1:6379> hexists k1 xb +(integer) 0 +``` + +**hgetall key** + +返回哈希表 key 中,所有的域和值。 + +以列表形式返回哈希表的域和域的值。 + +若 key不存在,返回空列表。 + +``` +127.0.0.1:6379> hgetall k1 +1) "xm" +2) "zhangsan" +127.0.0.1:6379> hset k1 xb nan +(integer) 1 +127.0.0.1:6379> hgetall k1 +1) "xm" +2) "zhangsan" +3) "xb" +4) "nan" +``` + +**hincrby key field increment** + +为哈希表 key 中的域 field 的值加上增量 increment 。 + +增量也可以为负数,相当于对给定域进行减法操作。 + +``` +127.0.0.1:6379> hset count h_i 100 +(integer) 1 +127.0.0.1:6379> hincrby count h_i 1 +(integer) 101 +127.0.0.1:6379> hincrby count h_i -10 +(integer) 91 +127.0.0.1:6379> hincrby count n_i -10 +(integer) -10 +127.0.0.1:6379> hgetall count +1) "h_i" +2) "91" +3) "n_i" +4) "-10" +``` + +**hincrbyfloat key field increment** + +为哈希表 key 中的域 field 加上浮点数增量 increment 。 + +``` +127.0.0.1:6379> hset count m_i 11.56 +(integer) 1 +127.0.0.1:6379> hincrbyfloat count m_i 11.2 +"22.76" +``` + +**hkeys key** + +返回哈希表 key 中的所有域。 + +一个包含哈希表中所有域的表。 + +当 key 不存在时,返回一个空表。 + +``` +127.0.0.1:6379> hset stu xm zhangsan xb nan +(integer) 0 +127.0.0.1:6379> hkeys * +(empty list or set) +127.0.0.1:6379> hkeys stu +1) "xm" +2) "xb" +``` + +**hlen key** + +返回哈希表 key 中域的数量。 + +当 key 不存在时,返回 0 。 + +``` +127.0.0.1:6379> hlen stu +(integer) 2 +``` + +**hmset key field value [field value …]** + +同时将多个 field-value (域-值)对设置到哈希表 key 中。 + +此命令会覆盖哈希表中已存在的域。 + +``` +127.0.0.1:6379> hmset www baidu www.baidu.com jd www.jd.com +OK +127.0.0.1:6379> hget www baidu +"www.baidu.com" +127.0.0.1:6379> hget www jd +"www.jd.com" +``` + +**hmget key field [field …]** + +返回哈希表 key 中,一个或多个给定域的值。 + +如果给定的域不存在于哈希表,那么返回一个 nil 值。 + +``` +127.0.0.1:6379> hmget www baidu jd +1) "www.baidu.com" +2) "www.jd.com" +``` + +**hsetnx key field value** + +将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在。 + +若域 field 已经存在,该操作无效。 + +``` +127.0.0.1:6379> hsetnx ww taobao www.taobao.com +(integer) 1 +127.0.0.1:6379> hsetnx ww taobao www.taobao.com +(integer) 0 +``` + +**hvals key** + +返回哈希表 key 中所有域的值。 + +``` +127.0.0.1:6379> hvals www +1) "www.baidu.com" +2) "www.jd.com" +``` + +## 四、列表类型概述 + +### 4.1、列表简介 + +列表类型是用来储存多个有序的字符串,列表类型中字符串称之为元素,一个列表最多可以储存2的32次方-1个元素。我们可以对列表两端插入和弹出操作,还可以通过索引下标获取指定范围的元素列表、获取指定索引下标元素等。 + +优点: + +列表类型中的元素可以重复。 + +列表类型中的元素是有序的。 + +列表类型中的元素可以通过索引下标获取某个或某个范围内的元素列表。 + +### 4.2、使用场景 + +栈:先进后出 + +队列:先进先出 + +消息队列: 主要表现在生产者与消费者之间。比如:小红希望小明多读书,常寻找好书给小明看,之前的方式是这样:小红问小明什么时候有空,把书给小明送去,并亲眼监督小明读完书才走。久而久之,两人都觉得麻烦。 + +后来的方式改成了:小红对小明说:“我放到书架上的书你都要看“,然后小红每次发现不错的书都放到书架上,小明则看到书架上有书就拿下来看。 +书架就是一个消息队列,小红是生产者,小明是消费者。 + +最新列表:例如新闻列表页面最新的新闻列表,如果总数量很大的情况下,尽量不要使用select a from A limit 10这种low货,用 LPUSH命令构建List,一个个顺序都塞进去就可以啦。 + +我们可以通过列表操作来模拟以下情况: +lpush+lpop=Stack(栈) +lpush+rpop=Queue(队列) +lpush+ltrim=Capped Collection(有限集合) +lpush+brpop=Message Queue(消息队列) + +### 4.3、列表命令 + +**lpush key value [value …]** + +将一个或多个值 value 插入到列表 key 的表头 + +如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表头。 + +**如:** + +``` +lpush k a b c #他的值为:c b a +#相当于 +lpush k a +lpush k b +lpush k c +``` + +如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作。 + +当 key 存在但不是列表类型时,返回一个错误。 + +``` +127.0.0.1:6379> lpush k1 a b c +(integer) 3 +127.0.0.1:6379> lpush k1 a +(integer) 4 +127.0.0.1:6379> lrange k1 0 -1 +1) "a" +2) "c" +3) "b" +4) "a" +``` + +**注意:** +lpush可以重复,写在前面的在底部,后进来的在前面 + +**rpush key value [value …]** + +将一个或多个值 value 插入到列表 key 的表尾(最右边)。 + +如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表尾。 + +如: + +``` +rpush k a b c #他的值为:a b c +#相当于 +rpush k a +rpush k b +rpush k c +``` + +如果 key 不存在,一个空列表会被创建并执行 RPUSH 操作。 + +当 key 存在但不是列表类型时,返回一个错误。 + +``` +127.0.0.1:6379> rpush k2 a b c +(integer) 3 +127.0.0.1:6379> rpush k2 a +(integer) 4 +127.0.0.1:6379> lrange k2 0 -1 +1) "a" +2) "b" +3) "c" +4) "a" +``` + +**llen key** + +返回列表 key 的长度。 + +如果 key 不存在,则 key 被解释为一个空列表,返回 0 . + +如果 key 不是列表类型,返回一个错误。 + +``` +127.0.0.1:6379> llen k3 +(integer) 0 +127.0.0.1:6379> lpush k3 "hello world" "what you name" +(integer) 2 +127.0.0.1:6379> llen k3 +(integer) 2 +``` + +**lrange key start stop** + +返回列表 key 中指定区间内的元素,区间以偏移量 start 和 stop 指定。 + +下标(index)参数 start 和 stop 都以 0 为底,也就是说,以 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。 + +你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。 + +``` +127.0.0.1:6379> lrange k3 1 2 +1) "hello world" +127.0.0.1:6379> lrange k3 0 2 +1) "what you name" +2) "hello world" +127.0.0.1:6379> lrange k2 0 2 +1) "a" +2) "b" +3) "c" +127.0.0.1:6379> lrange k2 0 -1 +1) "a" +2) "b" +3) "c" +4) "a" +``` + +**ltrim key start stop** + +让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。 + +如: + +``` +ltrim k1 0 2 #表示只保留列表 list 的前三个元素,其余元素全部删除。 +``` + +下标(index)参数 start 和 stop 都以 0 为底,也就是说,以 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。 + +你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。 + +当 key 不是列表类型时,返回一个错误。 + +``` +127.0.0.1:6379> lpush k4 a b c d e f g +(integer) 7 +127.0.0.1:6379> lrange k4 0 -1 +1) "g" +2) "f" +3) "e" +4) "d" +5) "c" +6) "b" +7) "a" +127.0.0.1:6379> ltrim k4 1 -1 +OK +127.0.0.1:6379> lrange k4 0 -1 +1) "f" +2) "e" +3) "d" +4) "c" +5) "b" +6) "a" +127.0.0.1:6379> ltrim k4 1000 2000 +OK +127.0.0.1:6379> lrange k4 0 -1 +(empty list or set) +127.0.0.1:6379> rpush k5 a b c d e f g +(integer) 7 +127.0.0.1:6379> ltrim k5 1000 2000 +OK +127.0.0.1:6379> lrange k5 0 -1 +(empty list or set) +``` + +**lset key index value** + +将列表 key 下标为 index 的元素的值设置为 value 。 + +当 index 参数超出范围,或对一个空列表( key 不存在)进行 LSET 时,返回一个错误。 + +``` +127.0.0.1:6379> exists k1 +(integer) 0 +127.0.0.1:6379> lset k1 0 item1 +(error) ERR no such key +127.0.0.1:6379> lpush k1 item1 item2 +(integer) 2 +127.0.0.1:6379> lset k1 0 item0 +OK +127.0.0.1:6379> lrange k1 0 -1 +1) "item0" +2) "item1" +127.0.0.1:6379> rpush k2 item1 item2 +(integer) 2 +127.0.0.1:6379> lset k2 0 item0 +OK +127.0.0.1:6379> lrange k2 0 -1 +1) "item0" +2) "item2" +127.0.0.1:6379> lset k1 5 item5 +(error) ERR index out of range +127.0.0.1:6379> lset k2 5 item5 +(error) ERR index out of range +``` + +**lrem key count value** + +根据参数 count 的值,移除列表中与参数 value 相等的元素。 + +count 的值可以是以下几种: + +count > 0: 从表头开始向表尾搜索,移除与value相等的元素,数量为count 。 + +count < 0: 从表尾开始向表头搜索,移除与value相等的元素,数量为count的绝对值。 + +count = 0 : 移除表中所有与 value 相等的值。 + +``` +127.0.0.1:6379> lpush k3 a b d f a d f b e c +(integer) 10 +127.0.0.1:6379> lrange k3 0 -1 + 1) "c" + 2) "e" + 3) "b" + 4) "f" + 5) "d" + 6) "a" + 7) "f" + 8) "d" + 9) "b" +10) "a" +127.0.0.1:6379> lrem k3 1 a +(integer) 1 +127.0.0.1:6379> lrange k3 0 -1 +1) "c" +2) "e" +3) "b" +4) "f" +5) "d" +6) "f" +7) "d" +8) "b" +9) "a" +127.0.0.1:6379> lrem k3 1 f +(integer) 1 +127.0.0.1:6379> lrange k3 0 -1 +1) "c" +2) "e" +3) "b" +4) "d" +5) "f" +6) "d" +7) "b" +8) "a" +127.0.0.1:6379> lrem k3 2 d +(integer) 2 +127.0.0.1:6379> lrange k3 0 -1 +1) "c" +2) "e" +3) "b" +4) "f" +5) "b" +6) "a" +127.0.0.1:6379> lrem k3 -1 a +(integer) 1 +127.0.0.1:6379> lrange k3 0 -1 +1) "c" +2) "e" +3) "b" +4) "f" +5) "b" +127.0.0.1:6379> lrem k3 0 b +(integer) 2 +127.0.0.1:6379> lrange k3 0 -1 +1) "c" +2) "e" +3) "f" +``` + +**lpop key** + +移除并返回列表 key 的头元素。 + +``` +127.0.0.1:6379> lpush a 212 fdsf fds fd fsd fds +(integer) 6 +127.0.0.1:6379> lrange a 0 -1 +1) "fds" +2) "fsd" +3) "fd" +4) "fds" +5) "fdsf" +6) "212" +127.0.0.1:6379> lpop a +"fds" +127.0.0.1:6379> lrange a 0 -1 +1) "fsd" +2) "fd" +3) "fds" +4) "fdsf" +5) "212" +127.0.0.1:6379> rpush b fdsf fds fd s fd f d +(integer) 7 +127.0.0.1:6379> lrange b 0 -1 +1) "fdsf" +2) "fds" +3) "fd" +4) "s" +5) "fd" +6) "f" +7) "d" +127.0.0.1:6379> lpop b +"fdsf" +127.0.0.1:6379> lrange b 0 -1 +1) "fds" +2) "fd" +3) "s" +4) "fd" +5) "f" +6) "d" +``` + +**rpop key** + +移除并返回列表 key 的尾元素。 + +``` +127.0.0.1:6379> lrange a 0 -1 +1) "fsd" +2) "fd" +3) "fds" +4) "fdsf" +5) "212" +127.0.0.1:6379> rpop a +"212" +127.0.0.1:6379> lrange a 0 -1 +1) "fsd" +2) "fd" +3) "fds" +4) "fdsf" +127.0.0.1:6379> lrange b 0 -1 +1) "fds" +2) "fd" +3) "s" +4) "fd" +5) "f" +6) "d" +127.0.0.1:6379> rpop b +"d" +127.0.0.1:6379> lrange b 0 -1 +1) "fds" +2) "fd" +3) "s" +4) "fd" +5) "f" +127.0.0.1:6379> +``` + +**blpop key [key …] timeout** + +当给定多个 key 参数时,按参数 key 的先后顺序依次检查各个列表,弹出第一个非空列表的头元素。 + +当key元素存在,非阻塞行为 + +``` +127.0.0.1:6379> lpush a hello +(integer) 1 +127.0.0.1:6379> lpush b world +(integer) 1 +127.0.0.1:6379> blpop a b 0 +1) "a" +2) "hello" +127.0.0.1:6379> blpop c a b 0 +1) "b" +2) "world" +``` + +当key元素不存在,阻塞行为 + +``` +127.0.0.1:6379> blpop a b c 0 +``` + +**brpop key [key …] timeout** + +当给定多个 key 参数时,按参数 key 的先后顺序依次检查各个列表,弹出第一个非空列表的尾部元素。 + +``` +127.0.0.1:6379> llen a +(integer) 0 +127.0.0.1:6379> rpush a java +(integer) 1 +127.0.0.1:6379> rpush a python +(integer) 2 +127.0.0.1:6379> brpop a 30 +1) "a" +2) "python" +``` + +## 五、集合概述 + +### 5.1、集合简介 + +集合类型也是用来保存多个字符串的元素,集合类型中不允许有重复的元素,集合类型中元素是无序的,不能通过索引下标获取元素。在redis除了学习集合的增删改查,同时还可以对集合类型进行取交集、并集、差集。 + +### 5.2、使用场景 + +兴趣标签(tag):兴趣标签可以用来标记一个用户对什么样的活动感兴趣,如:唱歌、跳舞、爬山等都是我们的兴趣标签。如果我们有很多用户都 有这些兴趣标签的话,有了这些数据就可以得到同一标签的人,以及用户的共同爱好的标签,这些数据对于用户体验以及曾强用户粘度比较重要。 + +我们可以通过集合操作来模拟以下情况: + +sadd=tagging(标签) + +spop/srandmember=random item(生成随机数,比如抽奖) + +sadd+sinter=social Graph(社交需求) + +### 5.3、集合命令 + +**sadd key member [member …]** + +将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略。 + +假如 key 不存在,则创建一个只包含 member 元素作成员的集合。 + +当 key 不是集合类型时,返回一个错误。 + +``` +127.0.0.1:6379> sadd s_a 123 234 345 +(integer) 3 +127.0.0.1:6379> smembers s_a +1) "123" +2) "234" +3) "345" +127.0.0.1:6379> sadd s_a 123 987 +(integer) 1 +127.0.0.1:6379> smembers s_a +1) "123" +2) "234" +3) "345" +4) "987" +``` + +**smembers key** + +返回集合 key 中的所有成员。 + +不存在的 key 被视为空集合。 + +``` +127.0.0.1:6379> sadd s_d dfs fds fds +(integer) 2 +127.0.0.1:6379> smembers s_d +1) "dfs" +2) "fds" +``` + +**srem key member [member …]** + +移除集合 key 中的一个或多个 member 元素,不存在的 member 元素会被忽略。 + +当 key 不是集合类型,返回一个错误。 + +``` +127.0.0.1:6379> smembers s_a +1) "123" +2) "234" +3) "345" +4) "987" +127.0.0.1:6379> srem s_a 234 +(integer) 1 +127.0.0.1:6379> smembers s_a +1) "123" +2) "345" +3) "987" +127.0.0.1:6379> srem s_a 134 +(integer) 0 +127.0.0.1:6379> srem s_a 123 987 +(integer) 2 +127.0.0.1:6379> smembers s_a +1) "345" +``` + +**spop key** + +移除并返回集合中的一个随机元素。 + +``` +127.0.0.1:6379> sadd s_b abc bcd fd sfds fdfd +(integer) 5 +127.0.0.1:6379> smembers s_b +1) "sfds" +2) "bcd" +3) "abc" +4) "fd" +5) "fdfd" +127.0.0.1:6379> spop s_b +"fd" +127.0.0.1:6379> smembers s_b +1) "sfds" +2) "abc" +3) "bcd" +4) "fdfd" +127.0.0.1:6379> spop s_b +"sfds" +127.0.0.1:6379> smembers s_b +1) "abc" +2) "bcd" +3) "fdfd" +``` + +**srandmember key [count]** + +如果命令执行时,只提供了 key 参数,那么返回集合中的一个随机元素,不删除。 + +如果 count 为正数,且小于集合基数,那么命令返回一个包含 count 个元素的数组,数组中的元素各不相同。如果 count 大于等于集合基数,那么返回整个集合。 + +如果 count 为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为 count 的绝对值。 + +``` +127.0.0.1:6379> sadd s_c afd fds fd s fds dfs dfs fd sfds +(integer) 6 +127.0.0.1:6379> srandmember s_c +"s" +127.0.0.1:6379> srandmember s_c +"sfds" +127.0.0.1:6379> smembers s_c +1) "sfds" +2) "s" +3) "fd" +4) "dfs" +5) "afd" +6) "fds" +127.0.0.1:6379> srandmember s_c 3 +1) "sfds" +2) "s" +3) "afd" +127.0.0.1:6379> srandmember s_c 3 +1) "sfds" +2) "s" +3) "fd" +127.0.0.1:6379> srandmember s_c -3 +1) "dfs" +2) "s" +3) "s" +127.0.0.1:6379> srandmember s_c -3 +1) "fd" +2) "afd" +3) "s" +127.0.0.1:6379> srandmember s_c 10 +1) "fd" +2) "sfds" +3) "s" +4) "dfs" +5) "afd" +6) "fds" +127.0.0.1:6379> srandmember s_c -10 + 1) "fd" + 2) "dfs" + 3) "s" + 4) "s" + 5) "fds" + 6) "s" + 7) "fds" + 8) "sfds" + 9) "fds" +10) "fd" +127.0.0.1:6379> smembers s_c +1) "sfds" +2) "s" +3) "fd" +4) "dfs" +5) "afd" +6) "fds" +``` + +**smove source destination member** + +将 member 元素从 source 集合移动到 destination 集合。 + +``` +127.0.0.1:6379> smembers s_a +1) "345" +127.0.0.1:6379> smembers s_b +1) "abc" +2) "bcd" +3) "fdfd" +127.0.0.1:6379> smove s_b s_a abc +(integer) 1 +127.0.0.1:6379> smembers s_a +1) "abc" +2) "345" +127.0.0.1:6379> smembers s_b +1) "bcd" +2) "fdfd" +``` + +**scard key** + +返回集合 key 的基数(集合中元素的数量)。 + +``` +127.0.0.1:6379> smembers s_c +1) "sfds" +2) "s" +3) "fd" +4) "dfs" +5) "afd" +6) "fds" +127.0.0.1:6379> scard s_c +(integer) 6 +127.0.0.1:6379> del s_c +(integer) 1 +127.0.0.1:6379> scard s_c +(integer) 0 +``` + +**sismember key member** + +判断 member 元素是否集合 key 的成员。 + +``` +127.0.0.1:6379> smembers s_b +1) "bcd" +2) "fdfd" +127.0.0.1:6379> sismember s_b bcd +(integer) 1 +127.0.0.1:6379> sismember s_b bcf +(integer) 0 +``` + +**sinter key [key …]** + +返回一个集合的全部成员,该集合是所有给定集合的交集。 + +不存在的 key 被视为空集。 + +当给定集合当中有一个空集时,结果也为空集(根据集合运算定律)。 + +``` +127.0.0.1:6379> smembers s_a +1) "abc" +2) "345" +127.0.0.1:6379> smembers s_b +1) "bcd" +2) "fdfd" +127.0.0.1:6379> sinter s_a s_b +(empty list or set) +127.0.0.1:6379> sadd s_a bcd +(integer) 1 +127.0.0.1:6379> sinter s_a s_b +1) "bcd" +``` + +**sinterstore destination key [key …]** + +这个命令类似于 [SINTER key key …] 命令,但它将结果保存到 destination 集合,而不是简单地返回结果集。 + +如果 destination 集合已经存在,则将其覆盖。 + +destination 可以是 key 本身。 + +``` +127.0.0.1:6379> smembers s_a +1) "bcd" +2) "abc" +3) "345" +127.0.0.1:6379> smembers s_b +1) "bcd" +2) "fdfd" +127.0.0.1:6379> sinterstore s_c s_a s_b +(integer) 1 +127.0.0.1:6379> smembers s_c +1) "bcd" +127.0.0.1:6379> sinterstore s_a s_a s_b +(integer) 1 +127.0.0.1:6379> smembers s_a +1) "bcd" +``` + +**sunion key [key …]** + +返回一个集合的全部成员,该集合是所有给定集合的并集。 + +不存在的 key被视为空集。 + +``` +127.0.0.1:6379> smembers s_a +1) "bcd" +2) "fd" +127.0.0.1:6379> smembers s_b +1) "bcd" +2) "fdfd" +127.0.0.1:6379> sunion s_a s_b +1) "bcd" +2) "fdfd" +3) "fd" +``` + +**sunionstore destination key [key …]** + +这个命令类似于 [SUNION key key …] 命令,但它将结果保存到 destination 集合,而不是简单地返回结果集。 + +如果 destination 已经存在,则将其覆盖。 + +destination 可以是 key 本身。 + +``` +127.0.0.1:6379> smembers s_a +1) "bcd" +2) "fd" +127.0.0.1:6379> smembers s_b +1) "bcd" +2) "fdfd" +127.0.0.1:6379> sunionstore s_c s_a s_b +(integer) 3 +127.0.0.1:6379> smembers s_c +1) "bcd" +2) "fdfd" +3) "fd" +127.0.0.1:6379> sunionstore s_a s_a s_b +(integer) 3 +127.0.0.1:6379> smembers s_a +1) "bcd" +2) "fdfd" +3) "fd" +``` + +**sdiff key [key …]** + +返回一个集合的全部成员,该集合是所有给定集合之间的差集。 + +不存在的 key 被视为空集。 + +``` +127.0.0.1:6379> smembers s_a +1) "bcd" +2) "fdfd" +3) "fd" +127.0.0.1:6379> smembers s_b +1) "bcd" +2) "fdfd" +127.0.0.1:6379> sdiff s_a s_b +1) "fd" +``` + +**sdiffstore destination key [key …]** + +这个命令的作用和 [SDIFF key key …] 类似,但它将结果保存到 destination 集合,而不是简单地返回结果集。 + +如果 destination 集合已经存在,则将其覆盖。 + +destination 可以是 key 本身。 + +``` +127.0.0.1:6379> smembers s_a +1) "bcd" +2) "fdfd" +3) "fd" +127.0.0.1:6379> smembers s_b +1) "bcd" +2) "fdfd" +127.0.0.1:6379> sdiffstore s_c s_a s_b +(integer) 1 +127.0.0.1:6379> smembers s_c +1) "fd" +127.0.0.1:6379> sdiffstore s_a s_a s_b +(integer) 1 +127.0.0.1:6379> smembers s_a +1) "fd" +``` + +## 六、有序集合概述 + +### 6.1、有序集合简介 + +有序集合保留了集合中不能有重复成员的特性,与集合不同的是有序集合中的元素是可以进行排序,他的排序方式是给每个元素设置一个分数,作为排序的依据。 + +有序集合中的元素不可以重复,但是score可以重复,就和一个人的身份证号不能重复一样,但姓名是可以重复的。 + +### 6.2、使用场景 + +排行榜:有序集合经典使用场景。比如说朋友圈集赞排行榜,我们以用户的点赞数作为score,在按照点赞数来进行排序,这样我们就可以按照点赞数获取排行榜了。 + +### 6.3、有序集合命令 + +**zadd key score member [[score member] …]** + +将一个或多个 member 元素及其 score 值加入到有序集 key 当中。 + +如果某个 member 已经是有序集的成员,那么更新这个 member 的 score 值,并通过重新插入这个 member 元素,来保证该 member 在正确的位置上。 + +score 值可以是整数值或双精度浮点数。 + +如果 key 不存在,则创建一个空的有序集并执行 ZADD 操作。 + +当 key 存在但不是有序集类型时,返回一个错误。 + +``` +127.0.0.1:6379> zadd z_a 9 abc 10 def +(integer) 2 +127.0.0.1:6379> zadd z_a 8 fdfd +(integer) 1 +127.0.0.1:6379> zrange z_a 0 -1 +1) "fdfd" +2) "abc" +3) "def" +127.0.0.1:6379> zrange z_a 0 -1 withscores +1) "fdfd" +2) "8" +3) "abc" +4) "9" +5) "def" +6) "10" +127.0.0.1:6379> zadd z_a 7 abc +(integer) 0 +127.0.0.1:6379> zrange z_a 0 -1 withscores +1) "abc" +2) "7" +3) "fdfd" +4) "8" +5) "def" +6) "10" +127.0.0.1:6379> zadd z_a 4 afdsc +(integer) 1 +127.0.0.1:6379> zrange z_a 0 -1 withscores +1) "afdsc" +2) "4" +3) "abc" +4) "7" +5) "fdfd" +6) "8" +7) "def" +8) "10" +127.0.0.1:6379> zadd z_a 9 afddsc +(integer) 1 +127.0.0.1:6379> zrange z_a 0 -1 withscores + 1) "afdsc" + 2) "4" + 3) "abc" + 4) "7" + 5) "fdfd" + 6) "8" + 7) "afddsc" + 8) "9" + 9) "def" +10) "10" +``` + +**zrange key start stop [withscores]** + +返回有序集 key 中,指定区间内的成员。 + +其中成员的位置按 score 值递增(从小到大)来排序。 + +具有相同 score 值的成员按字典序(lexicographical order )来排列。 + +如果你需要成员按 score 值递减(从大到小)来排列,请使用 [ZREVRANGE key start stop WITHSCORES] 命令。 + +下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员,以此类推。 你也可以使用负数下标,以 -1 表示最后一个成员, -2 表示倒数第二个成员,以此类推。 + +超出范围的下标并不会引起错误。 比如说,当 start 的值比有序集的最大下标还要大,或是 start > stop 时, ZRANGE 命令只是简单地返回一个空列表。 另一方面,假如 stop 参数的值比有序集的最大下标还要大,那么 Redis 将 stop 当作最大下标来处理。 + +可以通过使用 WITHSCORES 选项,来让成员和它的 score 值一并返回,返回列表以 value1,score1, …, valueN,scoreN 的格式表示。 客户端库可能会返回一些更复杂的数据类型,比如数组、元组等。 + +``` +127.0.0.1:6379> zrange z_a 0 -1 withscores +1) "afdsc" +2) "4" +3) "fdfd" +4) "8" +5) "afddsc" +6) "9" +127.0.0.1:6379> zrange z_a 1 2 withscores +1) "fdfd" +2) "8" +3) "afddsc" +4) "9" +127.0.0.1:6379> zrange z_a 0 200 withscores +1) "afdsc" +2) "4" +3) "fdfd" +4) "8" +5) "afddsc" +6) "9" +127.0.0.1:6379> zrange z_a 200 300 withscores +(empty list or set) +``` + +**zrevrange key start stop [withscores]** + +返回有序集 key 中,指定区间内的成员。 + +其中成员的位置按 score 值递减(从大到小)来排列。 具有相同 score 值的成员按字典序的逆序(reverse lexicographical order)排列。 + +``` +127.0.0.1:6379> zrange z_a 0 -1 withscores +1) "aaa" +2) "2" +3) "afdsc" +4) "4" +5) "fdfd" +6) "4" +7) "afddsc" +8) "9" +127.0.0.1:6379> zrevrange z_a 0 -1 withscores +1) "afddsc" +2) "9" +3) "fdfd" +4) "4" +5) "afdsc" +6) "4" +7) "aaa" +8) "2" +``` + +**zscore key member** + +返回有序集 key 中,成员 member 的 score 值。 + +如果 member 元素不是有序集 key 的成员,或 key 不存在,返回 nil 。 + +``` +127.0.0.1:6379> zrange z_a 0 -1 withscores +1) "afdsc" +2) "4" +3) "fdfd" +4) "8" +5) "afddsc" +6) "9" +127.0.0.1:6379> zscore z_a fdfd +"8" +``` + +**zrem key member [member …]** + +移除有序集 key 中的一个或多个成员,不存在的成员将被忽略。 + +当 key 存在但不是有序集类型时,返回一个错误。 + +``` +127.0.0.1:6379> zrange z_a 0 -1 withscores + 1) "afdsc" + 2) "4" + 3) "abc" + 4) "7" + 5) "fdfd" + 6) "8" + 7) "afddsc" + 8) "9" + 9) "def" +10) "10" +127.0.0.1:6379> zrem z_a 4 +(integer) 0 +127.0.0.1:6379> zrem z_a abc def +(integer) 2 +127.0.0.1:6379> zrange z_a 0 -1 withscores +1) "afdsc" +2) "4" +3) "fdfd" +4) "8" +5) "afddsc" +6) "9" +``` + +**zincrby key increment member** + +为有序集 key 的成员 member 的 score 值加上增量 increment 。 + +可以通过传递一个负数值 increment ,让 score 减去相应的值,比如 ZINCRBY key -5 member ,就是让 member 的 score 值减去 5 。 + +当 key 不存在,或 member 不是 key 的成员时, ZINCRBY key increment member 等同于 ZADD key increment member 。 + +当 key 不是有序集类型时,返回一个错误。 + +score 值可以是整数值或双精度浮点数。 + +``` +127.0.0.1:6379> zrange z_a 0 -1 withscores +1) "afdsc" +2) "4" +3) "fdfd" +4) "8" +5) "afddsc" +6) "9" +127.0.0.1:6379> zscore afdsc +(error) ERR wrong number of arguments for 'zscore' command +127.0.0.1:6379> zscore z_a fdfd +"8" +127.0.0.1:6379> zincrby z_a 2 fdfd +"10" +127.0.0.1:6379> zrange z_a 0 -1 withscores +1) "afdsc" +2) "4" +3) "afddsc" +4) "9" +5) "fdfd" +6) "10" +127.0.0.1:6379> zincrby z_a -6 fdfd +"4" +127.0.0.1:6379> zrange z_a 0 -1 withscores +1) "afdsc" +2) "4" +3) "fdfd" +4) "4" +5) "afddsc" +6) "9" +``` + +**zrank key member** + +返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递增(从小到大)顺序排列。 + +排名以 0 为底,也就是说, score 值最小的成员排名为 0 。 + +``` +127.0.0.1:6379> zrange z_a 0 -1 withscores +1) "afdsc" +2) "4" +3) "fdfd" +4) "4" +5) "afddsc" +6) "9" +127.0.0.1:6379> zrank z_a fdfd +(integer) 1 +127.0.0.1:6379> zrank z_a afdsc +(integer) 0 +127.0.0.1:6379> zrank z_a afddsc +(integer) 2 +127.0.0.1:6379> zadd z_a 2 aaa +(integer) 1 +127.0.0.1:6379> zrange z_a 0 -1 withscores +1) "aaa" +2) "2" +3) "afdsc" +4) "4" +5) "fdfd" +6) "4" +7) "afddsc" +8) "9" +127.0.0.1:6379> zrank z_a fdfd +(integer) 2 +``` + +**zrevrank key member** + +返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递减(从大到小)排序。 + +排名以 0 为底,也就是说, score 值最大的成员排名为 0 。 + +``` +127.0.0.1:6379> zrange z_a 0 -1 withscores +1) "aaa" +2) "2" +3) "afdsc" +4) "4" +5) "fdfd" +6) "4" +7) "afddsc" +8) "9" +127.0.0.1:6379> zrevrank z_a fdfd +(integer) 1 +127.0.0.1:6379> zrevrank z_a afddsc +(integer) 0 +127.0.0.1:6379> zrevrank z_a aaa +(integer) 3 +``` + +**zrangebyscore key min max [withscores] [limit offset count]** + +返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。 + +具有相同 score 值的成员按字典序(lexicographical order)来排列(该属性是有序集提供的,不需要额外的计算)。 + +可选的 LIMIT 参数指定返回结果的数量及区间(就像SQL中的 SELECT LIMIT offset, count ),注意当 offset 很大时,定位 offset 的操作可能需要遍历整个有序集,此过程最坏复杂度为 O(N) 时间。 + +可选的 WITHSCORES 参数决定结果集是单单返回有序集的成员,还是将有序集成员及其 score 值一起返回。 + +``` +127.0.0.1:6379> zadd salary 5000 zhangsan 2500 lisi 12000 wangwu +(integer) 3 +127.0.0.1:6379> zrangebyscore salary -inf +inf +1) "lisi" +2) "zhangsan" +3) "wangwu" +127.0.0.1:6379> zrangebyscore salary -inf +inf withscores +1) "lisi" +2) "2500" +3) "zhangsan" +4) "5000" +5) "wangwu" +6) "12000" +127.0.0.1:6379> zrangebyscore salary -inf +inf withscores limit 0 2 +1) "lisi" +2) "2500" +3) "zhangsan" +4) "5000" +127.0.0.1:6379> zrangebyscore salary -inf +inf withscores limit 2 2 +1) "wangwu" +2) "12000" +127.0.0.1:6379> zrangebyscore salary -inf +inf withscores limit 1 2 +1) "zhangsan" +2) "5000" +3) "wangwu" +4) "12000" +127.0.0.1:6379> zrangebyscore salary 2500 6000 +1) "lisi" +2) "zhangsan" +127.0.0.1:6379> zrangebyscore salary (2500 6000 +1) "zhangsan" +127.0.0.1:6379> zrangebyscore salary (2500 (5000 +(empty list or set) +127.0.0.1:6379> zrangebyscore salary (2500 5000 +1) "zhangsan" +``` + +**zcount key min max** + +返回有序集 key 中, score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员的数量。 + +``` +127.0.0.1:6379> zadd salary 5000 zhangsan 2500 lisi 12000 wangwu +(integer) 3 +127.0.0.1:6379> zcount salary -inf +inf +(integer) 3 +127.0.0.1:6379> zcount salary 2500 5000 +(integer) 2 +127.0.0.1:6379> zcount salary 2500 (5000 +(integer) 1 +``` + +**zcard key** + +返回有序集 key的基数。 + +``` +127.0.0.1:6379> zcard z_a +(integer) 4 +127.0.0.1:6379> zcard salary +(integer) 3 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \351\233\206\347\276\244.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \351\233\206\347\276\244.md" new file mode 100644 index 0000000..ca877da --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis \351\233\206\347\276\244.md" @@ -0,0 +1,391 @@ +sentinel模式基本可以满足一般生产的需求,具备高可用性。但是当数据量过大到一台服务器存放不下的情况时,主从模式或sentinel模式就不能满足需求了,这个时候需要对存储的数据进行分片,将数据存储到多个Redis实例中。cluster模式的出现就是为了解决单机Redis容量有限的问题,将Redis的数据根据一定的规则分配到多台机器。 + +## 一、集群模式概述 + +### 1.1、什么是集群模式 + +Redis 的哨兵和主从模式基本已经可以实现高可用和读写分离 ,但是在这种模式下每台 Redis 服务器都存储相同的数据,浪费内存空间,所以在redis上加入了 Cluster 集群模式,实现了 Redis 的分布式存储,也就是说Redis 节点上存储不同的内容。 + +![image20200311161653767.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603525043995.png) + +### 1.2、集群模式特点 + +多个redis节点网络互联,数据共享 + +所有的节点都是一主一从(也可以是一主多从),其中从节点不提供服务,仅作为备用 + +不支持同时处理多个key(如MSET/MGET),因为redis需要把key均匀分布在各个节点上,并发量很高的情况下同时创建key-value会降低性能并导致不可预测的行为 + +支持在线增加、删除节点 + +客户端可以连接任何一个主节点进行读写 + +### 1.3、集群工作方式 + +**数据存取工作方式** + +在 Redis 的每一个节点上,都有这么两个东西,一个是插槽(slot),一个是cluster。 + +插槽的取值范围是:0-16383。cluster,可以理解为是一个集群管理的插件。 + +当我们的存取 Key的时候,Redis 会根据算法得出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。 + +**集群工作方式** + +为了保证高可用,redis集群模式引入了主从模式,一个主节点对应一个或者多个从节点,当主节点宕机的时候,就会启用从节点。 + +那么如何发现主节点宕机?当其它主节点ping一个主节点C时,如果半数以上的主节点与C通信超时,那么认为主节点C宕机了。如果主节点C和它的从节点C1都宕机了,那么该集群就无法再提供服务了。 + +## 二、集群模式的搭建 + +### 2.1、搭建前的准备 + +集群搭建:至少要三个master + +第一步:创建一个文件夹redis-cluster,然后在其下面分别创建6个文件夹如下: + +``` +[root@zutuanxue redis]# mkdir redis-cluster +[root@zutuanxue redis]# cd redis-cluster/ +[root@zutuanxue redis-cluster]# mkdir 7001 +[root@zutuanxue redis-cluster]# mkdir 7002 +[root@zutuanxue redis-cluster]# mkdir 7003 +[root@zutuanxue redis-cluster]# mkdir 7004 +[root@zutuanxue redis-cluster]# mkdir 7005 +[root@zutuanxue redis-cluster]# mkdir 7006 +``` + +第二步:把之前的redis.conf配置文件分别copy到700*下 + +``` +[root@zutuanxue redis]# cp redis.conf ./redis-cluster/7001/redis.conf +[root@zutuanxue redis]# cp redis.conf ./redis-cluster/7002/redis.conf +[root@zutuanxue redis]# cp redis.conf ./redis-cluster/7003/redis.conf +[root@zutuanxue redis]# cp redis.conf ./redis-cluster/7004/redis.conf +[root@zutuanxue redis]# cp redis.conf ./redis-cluster/7005/redis.conf +[root@zutuanxue redis]# cp redis.conf ./redis-cluster/7006/redis.conf +``` + +第三步:由于redis集群需要使用ruby命令,所以我们需要安装ruby + +``` +yum install ruby +yum install rubygems +gem install redis #(安装redis和ruby的接口) +``` + +### 2.2、修改集群配置 + +``` +[root@zutuanxue redis]# vim ./redis-cluster/7001/redis.conf +#需要修改的配置 +daemonize yes +port 700* #(分别对每个机器的端口号进行设置) +bind 192.168.1.171 #(必须要绑定当前机器的ip,不然会无限悲剧下去哇..深坑勿入!!!) +dir /usr/local/redis-cluster/700*/ #(指定数据文件存放位置,必须要指定不同的目录位置,不然会丢失数据,深坑勿入!!!) +appendonly yes +cluster-enabled yes #(启动集群模式,开始玩耍) +cluster-config-file nodes700*.conf#(这里700x最好和port对应上) +cluster-node-timeout 5000 #redis节点宕机被发现的时间 +``` + +**注意:** + +每个文件要修改端口号,bind的ip,数据存放的dir,并且nodes文件都需要进行修改! + +### 2.3、启动redis服务 + +``` +[root@zutuanxue redis]# ./src/redis-server ./redis-cluster/7001/redis.conf +[root@zutuanxue redis]# ./src/redis-server ./redis-cluster/7002/redis.conf +[root@zutuanxue redis]# ./src/redis-server ./redis-cluster/7003/redis.conf +[root@zutuanxue redis]# ./src/redis-server ./redis-cluster/7004/redis.conf +[root@zutuanxue redis]# ./src/redis-server ./redis-cluster/7005/redis.conf +[root@zutuanxue redis]# ./src/redis-server ./redis-cluster/7006/redis.conf +``` + +### 2.4、创建集群 + +执行redis-cli --cluster create命令 + +``` +[root@zutuanxue redis]# ./src/redis-cli --cluster create 192.168.1.121:7001 192.168.1.121:7002 192.168.1.121:7003 192.168.1.121:7004 192.168.1.121:7005 192.168.1.121:7006 --cluster-replicas 1 +``` + +**说明:** + +create + +表示创建一个redis集群。 + +–cluster-replicas 1 + +表示为集群中的每一个主节点指定一个从节点,即一比一的复制。 + +![image20200311021844778.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603525088763.png) + +### 2.5、查看redis服务状态 + +``` +[root@zutuanxue redis]# ps -ef|grep redis +``` + +![image20200311022733954.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603525120529.png) + +### 2.6、进入一个节点 + +``` +[root@zutuanxue redis]# ./src/redis-cli -c -h 192.168.1.121 -p 7001 +192.168.1.121:7001> info cluster +# Cluster +cluster_enabled:1 #节点是否为cluster模式 。1是0否 +``` + +### 2.7、测试操作 + +``` +[root@zutuanxue redis]# ./src/redis-cli -c -h 192.168.1.121 -p 7005 +192.168.1.121:7005> set b fdfsfsd +-> Redirected to slot [3300] located at 192.168.1.121:7001 +OK +192.168.1.121:7001> get b +"fdfsfsd" +192.168.1.121:7001> set c fdsfdfdsfds +-> Redirected to slot [7365] located at 192.168.1.121:7002 +OK +192.168.1.121:7002> get c +"fdsfdfdsfds" +192.168.1.121:7002> set x fdsfdsfsdf +-> Redirected to slot [16287] located at 192.168.1.121:7003 +OK +192.168.1.121:7003> keys * +1) "x" +2) "a" +192.168.1.121:7003> get b +-> Redirected to slot [3300] located at 192.168.1.121:7001 +"fdfsfsd" +192.168.1.121:7001> keys * +1) "b" +192.168.1.121:7001> set d fdsfdsfsd +-> Redirected to slot [11298] located at 192.168.1.121:7003 +OK +192.168.1.121:7003> get d +"fdsfdsfsd" +192.168.1.121:7003> set x zhangsan +OK +192.168.1.121:7003> get x +"zhangsan" +``` + +## 三、集群操作 + +### 3.1、主从切换 + +查看节点信息 + +``` +[root@zutuanxue redis]# ./src/redis-cli -c -h 192.168.1.121 -p 7001 +192.168.1.121:7001> cluster nodes #查看集群中的节点 +``` + +![image20200311022119169.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603525167260.png) + +停掉7003,在查看节点信息 + +``` +[root@zutuanxue redis]# ps -ef|grep redis +root 31370 1 0 21:04 ? 00:00:05 ./src/redis-server 192.168.1.121:7001 [cluster] +root 31375 1 0 21:04 ? 00:00:05 ./src/redis-server 192.168.1.121:7002 [cluster] +root 31380 1 0 21:04 ? 00:00:05 ./src/redis-server 192.168.1.121:7003 [cluster] +root 31385 1 0 21:05 ? 00:00:05 ./src/redis-server 192.168.1.121:7004 [cluster] +root 31394 1 0 21:05 ? 00:00:05 ./src/redis-server 192.168.1.121:7005 [cluster] +root 31399 1 0 21:05 ? 00:00:05 ./src/redis-server 192.168.1.121:7006 [cluster] +root 32361 2769 0 22:39 pts/0 00:00:00 grep --color=auto redis +[root@zutuanxue redis]# kill -s 9 31380 +[root@zutuanxue redis]# ./src/redis-cli -c -h 192.168.1.121 -p 7005 +192.168.1.121:7005> cluster nodes +``` + +![image20200311104105384.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603525193743.png) + +启动7003,查看节点信息 + +``` +[root@zutuanxue redis]# ./src/redis-server ./redis-cluster/7003/redis.conf +[root@zutuanxue redis]# ./src/redis-cli -c -h 192.168.1.121 -p 7005 +192.168.1.121:7005> cluster nodes +``` + +![image20200311104532681.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603525212892.png) + +### 3.2、从节点操作 + +#### 3.2.1、前期准备 + +准备一个新的Redis,7007 + +``` +[root@zutuanxue redis]# cd redis-cluster/ +[root@zutuanxue redis-cluster]# ls +7001 7002 7003 7004 7005 7006 +[root@zutuanxue redis-cluster]# mkdir 7007 +[root@zutuanxue redis-cluster]# cp ./7006/redis.conf ./7007/redis.conf +[root@zutuanxue redis-cluster]# cd .. +[root@zutuanxue redis]# vim ./redis-cluster/7007/redis.conf +[root@zutuanxue redis]# ./src/redis-server ./redis-cluster/7007/redis.conf +``` + +#### 3.2.2、增加从节点 + +``` +[root@zutuanxue redis]# ./src/redis-cli --cluster add-node 192.168.1.121:7007 192.168.1.121:7004 --cluster-slave +``` + +![image20200311110027423.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603525250988.png) + +查看节点信息 + +``` +[root@zutuanxue redis]# ./src/redis-cli -c -h 192.168.1.121 -p 7005 +192.168.1.121:7005> cluster nodes +``` + +![image20200311110122577.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603525267045.png) + +#### 3.2.3、删除从节点 + +删除7007节点 + +``` +[root@zutuanxue redis]# ./src/redis-cli --cluster del-node 192.168.1.121:7007 99d2ceb080ef0d701546dea0901d4784a201fc06 +>>> Removing node 99d2ceb080ef0d701546dea0901d4784a201fc06 from cluster 192.168.1.121:7007 +>>> Sending CLUSTER FORGET messages to the cluster... +>>> SHUTDOWN the node. +``` + +查看节点信息 + +``` +[root@zutuanxue redis]# ./src/redis-cli -c -h 192.168.1.121 -p 7005 +192.168.1.121:7005> cluster nodes +``` + +![image20200311111604404.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603525295327.png) + +### 3.3、主节点操作 + +#### 3.3.1、添加主节点 + +将7007设置为7006的主节点 + +保证7007服务是启动的 + +``` +[root@zutuanxue redis]# ./src/redis-cli --cluster add-node 192.168.1.121:7007 192.168.1.121:7006 +``` + +![image20200311113529372.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603525349151.png) + +查看节点信息,未分配槽位不能存储数据 + +``` +[root@zutuanxue redis]# ./src/redis-cli -c -h 192.168.1.121 -p 7005 +192.168.1.121:7005> cluster nodes +``` + +![image20200311113509393.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603525366728.png) + +重新分配槽位 + +``` +[root@zutuanxue redis]# ./src/redis-cli --cluster reshard 192.168.1.121:7007 +``` + +![image20200311114438978.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603525385352.png) + +查看节点信息 + +``` +[root@zutuanxue redis]# ./src/redis-cli -c -h 192.168.1.121 -p 7005 +192.168.1.121:7005> cluster nodes +``` + +![image20200311114537492.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603525403580.png) + +#### 3.3.2、给主节点加从节点 + +准备一个新的Redis,7008 + +``` +[root@zutuanxue redis]# cd redis-cluster/ +[root@zutuanxue redis-cluster]# ls +7001 7002 7003 7004 7005 7006 7007 +[root@zutuanxue redis-cluster]# mkdir 7008 +[root@zutuanxue redis-cluster]# cp ./7007/redis.conf ./7008/redis.conf +[root@zutuanxue redis-cluster]# vim ./7008/redis.conf +[root@zutuanxue redis-cluster]# cd .. +[root@zutuanxue redis]# ./src/redis-server ./redis-cluster/7008/redis.conf +``` + +为7007添加从节点7008 + +``` +[root@zutuanxue redis]# ./src/redis-cli --cluster add-node 192.168.1.121:7008 192.168.1.121:7007 --cluster-slave +``` + +查看节点信息 + +``` +[root@zutuanxue redis]# ./src/redis-cli -c -h 192.168.1.121 -p 7005 +192.168.1.121:7005> cluster nodes +``` + +![image20200311115414289.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603525436695.png) + +### 3.4、主节点操作 + +#### 3.4.1、删除主节点 + +删除从节点 + +``` +[root@zutuanxue redis]# ./src/redis-cli --cluster del-node 192.168.1.121:7008 8e52c94dafa72df26b1eddf94363a4780bed9339 +>>> Removing node 8e52c94dafa72df26b1eddf94363a4780bed9339 from cluster 192.168.1.121:7008 +>>> Sending CLUSTER FORGET messages to the cluster... +>>> SHUTDOWN the node. +``` + +移动数据将7007移动到7001节点 + +``` +[root@zutuanxue redis]# ./src/redis-cli --cluster reshard 192.168.1.121:7007 +``` + +![image20200311120414164.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603525488124.png) + +查看节点信息 + +``` +[root@zutuanxue redis]# ./src/redis-cli -c -h 192.168.1.121 -p 7005 +192.168.1.121:7005> cluster nodes +``` + +![image20200311120554074.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603525509641.png) + +删除主节点 + +``` +[root@zutuanxue redis]# ./src/redis-cli --cluster del-node 192.168.1.121:7007 d7a3e48cd142dce6566023fce21e31669e9fa3d5 +>>> Removing node d7a3e48cd142dce6566023fce21e31669e9fa3d5 from cluster 192.168.1.121:7007 +>>> Sending CLUSTER FORGET messages to the cluster... +>>> SHUTDOWN the node. +``` + +查看节点信息 + +``` +[root@zutuanxue redis]# ./src/redis-cli -c -h 192.168.1.121 -p 7005 +192.168.1.121:7005> cluster nodes +``` + +![image20200311120839746.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603525527888.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262.md" new file mode 100644 index 0000000..6191af2 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Redis\346\225\260\346\215\256\345\272\223/Redis\346\234\215\345\212\241\345\231\250\351\203\250\347\275\262.md" @@ -0,0 +1,223 @@ +Redis(全称:Remote Dictionary Server 远程字典服务)是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。 + +Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets)和有序集合(sorted sets)等类型。 + +## 一、Redis概述 + +### 1.1、NoSQL + +NoSQL,泛指非关系型的数据库,是不同于传统的关系型数据库的数据库管理系统的统称。 + +NoSQL用于超大规模数据的存储,收集万亿比特的数据。这些类型的数据存储没有固定的形式,没有多余操作就可以横向扩展。 + +### 1.2、什么是Redis + +Redis是NoSQL中的一种存储工具,他是一个key-value存储系统。默认有16个数据库从0到15来进行表示。Redis的存储类型:包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。在此基础上,Redis支持各种不同方式的排序。 + +Redis 被广泛应用在缓存方向,与传统数据库不同的是 Redis 的数据是存在内存中的,因此读写速度非常快。 + +Redis为分布式缓存,在多客户端的情况下,共用一份缓存数据,缓存具有一致性。 + +Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步,为了可靠性。 + +### 1.3、Redis特点 + +**性能极高** – Redis读的速度是11W次/s,写的速度是81K次/s + +**支持数据的持久化**,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。 + +**丰富的数据类型**,Redis不仅仅支持简单的key-value类型的数据,同时还提供Strings, Lists, Hashes, Sets 及 Ordered Sets 等数据结构的存储。 + +**支持数据的备份**,即master-slave模式的数据备份。 + +### 1.4、Redis优缺点 + +**优点:** + +- 对数据高并发读写 +- 对海量数据的高效率存储和访问 +- 对数据具有的可扩展性和高可用性 + +**缺点:** + +- redis(ACID)处理非常简单 +- 无法做到太复杂的关系数据库模型 + +## 二、Redis下载与安装 + +### 2.1、Redis下载 + +**下载地址:** http://www.redis.cn/download.html + +![image20200223232710202.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603522538421.png) + +### 2.2、Redis安装 + +#### 2.2.1、指定redis存放位置 + +/usr/local/目录下 + +![image20200223233057457.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603522573612.png) + +#### 2.2.2、解压 + +``` +[root@localhost local]# tar xzf redis-5.0.5.tar.gz +``` + +#### 2.2.3、改名 + +``` +[root@localhost local]# mv redis-5.0.5 redis +``` + +#### 2.2.3、安装 + +进入redis目录,输入make + +``` +[root@localhost /]# cd /usr/local/redis +[root@localhost redis]# make +``` + +#### 2.2.4、启动服务 + +进入src目录,输入./redis-server + +``` +[root@localhost redis]# cd src +[root@localhost src]# ./redis-server +``` + +![image20200223235132859.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603522620683.png) + +#### 2.2.5、使用客户端程序 + +进入src目录,输入./redis-cli + +``` +[root@localhost ~]# cd /usr/local/redis/src +[root@localhost src]# ./redis-cli +``` + +![image20200223235513766.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603522636085.png) + +## 三、服务器操作 + +### 3.1、服务器端 + +#### 3.1.1、查看是否启动 + +``` +[root@localhost redis]# ps -ef|grep redis +``` + +或 + +``` +[root@localhost redis]# ./src/redis-cli ping +``` + +#### 3.1.2、启动 + +**前台启动** + +``` +[root@localhost redis]# ./src/redis-server +``` + +**后台启动** + +修改/usr/local/redis/redis.conf文件 + +``` +daemonize yes #前台启动,改后台启动 +``` + +指定配置文件,启动 + +``` +[root@localhost redis]# ./src/redis-server ./redis.conf +``` + +#### 3.1.3、关闭 + +``` +[root@localhost redis]# ./src/redis-cli shutdown +``` + +### 3.2、客户端 + +#### 3.2.1、启动 + +``` +[root@localhost redis]# ./src/redis-cli +127.0.0.1:6379> +``` + +#### 3.2.2、关闭 + +方式一:指令ctrl+c + +方式二:执行指令quit + +方式三:执行指令exit + +### 3.3、设置远程访问 + +修改/usr/local/redis/redis.conf文件 + +``` +#bind 127.0.0.1 #注释掉允许本地连接 +protected-mode no #允许远程访问 +``` + +## 四、Redis客户端 + +### 4.1、Redis客户端下载 + +**下载地址:** https://redisdesktop.com/pricing + +![image20200224004947866.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603522698044.png) + +### 4.2、安装 + +双击打开程序,选择“下一步” + +![image20200224005136221.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603522739448.png) + +继续选择“我同意” + +![image20200224005207896.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603522754703.png) + +选择安装路径,点击“安装” + +![image20200224005249413.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603522775709.png) + +安装中。。。。。。。 + +![image20200224005325342.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603522788655.png) + +安装完成,点击“下一步” + +![image20200224005411045.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603522805312.png) + +选择“桌面快捷”,点击“完成” + +![image20200224005451664.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603522822832.png) + +## 五、Redis客户端应用 + +### 5.1、连接Redis服务端 + +打开客户端 + +![image20200225125542277.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603522842260.png) + +点击“Connect to Redis Server”,创建连接 + +![image20200225125723427.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603522858849.png) + +### 5.2、客户端操作 + +![image20200225130032651.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603522873998.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/Nginx\345\210\206\345\217\221\347\256\227\346\263\225.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/Nginx\345\210\206\345\217\221\347\256\227\346\263\225.md" new file mode 100644 index 0000000..753786e --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/Nginx\345\210\206\345\217\221\347\256\227\346\263\225.md" @@ -0,0 +1,269 @@ +## 一、分发算法介绍 + +如何将用户请求按照一定的规律分发给业务服务器。主要分为Nginx集群默认算法和基于请求头分发算法。 + +## 二、nginx集群默认算法 + +nginx的upstream 目前支持4种方式的分配 + +- 轮询(默认) +   每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。用于处理静态页面 +- weight +   指定权重,数值大的服务器,获得的请求的数量越多,用于后端服务器性能不均的情况。用于处理静态页面 +- ip_hash +   每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务,好处是可以解决session的问题。可以处理动态网站。 +- url_hash(第三方) +   按访问url的hash结果来分配请求,使每个url定向到同一个后端服务 ,后端服务器为缓存时比较有效。 + +**nginx有很多第三方模块,各位可以去下载使用** + +``` +https://www.nginx.com/resources/wiki/modules/ +``` + +## 三、nginx业务服务器状态 + +每个设备的状态设置参数: + +- down + 表示当前的server暂时不参与负载; +- weight + 默认为1,weight越大,负载的权重就越大; +- max_fails + 允许请求失败的次数默认为1,当超过最大次数时,返回proxy_next_upstream模块定义的错误; +- fail_timeout + 失败超时时间,在连接Server时,如果在超时时间之内超过max_fails指定的失败次数,会认为在fail_timeout时间内Server不可用,默认为10s +- backup + 其他所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。 + +## 四、nginx集群默认算法测试 + +### 实验环境 + +实验机 :四台虚拟机,一台测试机,一台分发器,两台web服务器。 + +网卡:vmnet4 + +系统:CentOS8.0 + +SELinux&防火墙:关闭 + +网段:192.168.0.0/24 + +![image20200221112806031.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603972051599.png) + +### 实验拓扑 + +![image20200220115749617.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603972068286.png) + +### 4.1、轮询算法 + +``` +upstream web { + server 192.168.0.42; + server 192.168.0.43; +} +server { + listen 80; + server_name localhost; + location / { + proxy_pass http://web; + } +} +``` + +前面已经测试验证了轮询算法分发。 + +**配置backup参数** + +``` +upstream web { + server 192.168.0.42; + server 192.168.0.43 backup; +} +server { + listen 80; + server_name localhost; + location / { + proxy_pass http://web; + } +} +``` + +先正常访问测试 + +``` +[root@client ~]# curl 192.168.0.40 +web1 +[root@client ~]# curl 192.168.0.40 +web1 +[root@client ~]# curl 192.168.0.40 +web1 +``` + +关停第一个节点情况,访问尝试: + +``` +[root@web1 ~]# systemctl stop httpd +[root@client ~]# curl 192.168.0.40 +web2 +[root@client ~]# curl 192.168.0.40 +web2 +[root@client ~]# curl 192.168.0.40 +web2 +``` + +启动第一个节点测试 + +``` +[root@web1 ~]# systemctl start httpd +[root@client ~]# curl 192.168.0.40 +web1 +[root@client ~]# curl 192.168.0.40 +web1 +[root@client ~]# curl 192.168.0.40 +web1 +``` + +### 4.2、基于权重 + +通过配置权重,可以让性能好的服务器承担更多的负载 + +``` +upstream web { + # 设置权重比例1:2 + server 192.168.0.42 weight=1; + server 192.168.0.43 weight=2; +} +server { + listen 80; + server_name localhost; + location / { + proxy_pass http://web; + } +} +``` + +测试 + +``` +[root@client ~]# curl 192.168.0.40 + web1 +[root@client ~]# curl 192.168.0.40 + web2 +[root@client ~]# curl 192.168.0.40 + web2 +[root@client ~]# curl 192.168.0.40 + web1 +[root@client ~]# curl 192.168.0.40 + web2 +[root@client ~]# curl 192.168.0.40 + web2 +``` + +### 4.3、基于ip_hash分发 + +ip_hash算法能够保证来自**同样源地址的请求**都分发到同一台主机。 +  需要注意:ip_hash算法不支持backup、weight设置。默认权重为1。 + +``` +upstream web { + ip_hash; # 指定ip_hash即可,默认weight权重比例1: 1 + server 192.168.0.42; + server 192.168.0.43; +} +server { + listen 80; + server_name localhost; + location / { + proxy_pass http://web; + } +} +``` + +测试 + +``` +[root@client ~]# curl 192.168.0.40 +web2 +[root@client ~]# curl 192.168.0.40 +web2 +[root@client ~]# curl 192.168.0.40 +web2 +切换到另外一台不同网段的主机 +MacBook-Pro:~ hello$ ifconfig +vmnet8: flags=8863 mtu 1500 + ether 00:50:56:c0:00:08 + inet 172.16.121.1 netmask 0xffffff00 broadcast 172.16.121.255 + +MacBook-Pro:~ hello$ curl 172.16.121.134 +web1 +MacBook-Pro:~ hello$ curl 172.16.121.134 +web1 +MacBook-Pro:~ hello$ curl 172.16.121.134 +web1 +``` + +### 4.4、基于url的hash + +不同的URL我去找不同的机器访问,就是把url计算出一个值然后除以机器的数量取余 ,需要安装第三方插件 + +``` +nginx分发器上,将nginx主程序包和下载好的第三方软件包放在同一个目录下解压 +[root@master ~]# cd nginx-1.15.12/ +[root@master ~]# ./configure --prefix=/usr/local/nginx --add-module=/root/ngx_http_consistent_hash-master +第三方模块的安装方法 + +[root@master ~]# make & make install +[root@master ~]# vim /usr/local/nginx/conf/nginx.conf + + +worker_processes 1; +events { + worker_connections 1024; +} +http { + include mime.types; + default_type application/octet-stream; + sendfile on; + keepalive_timeout 65; + upstream web { + consistent_hash $request_uri; + server 192.168.0.42 ; + server 192.168.0.43 ; + } + server { + listen 80; + server_name localhost; + location / { + proxy_pass http://web; + } + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root html; + } + } +} +[root@master ~]# /usr/local/nginx/sbin/nginx + +在web主机上生成测试页面 +[root@web1 ~]# for i in `seq 1 10`; do echo "web1_$i" > /var/www/html/$i.html; done + +[root@web2 ~]# for i in `seq 1 10`; do echo "web2_$i" > /var/www/html/$i.html; done +这样我们就知道测试的时候访问的是哪台机器的页面文件了 + +测试访问 +[root@client ~]# for i in `seq 1 10`; do curl http://192.168.0.40/$i.html; done +web1_1 +web1_2 +web1_3 +web2_4 +web2_5 +web1_6 +web2_7 +web1_8 +web2_9 +web2_10 +``` + +这个方式一般用在我们的缓存上,目的是为了命中率,什么是命中率,也就是说同样是下数据,你要是从源下就是没有命中,从缓存下就是命中 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/Nginx\345\237\272\344\272\216\350\257\267\346\261\202\345\244\264\347\232\204\345\210\206\345\217\221.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/Nginx\345\237\272\344\272\216\350\257\267\346\261\202\345\244\264\347\232\204\345\210\206\345\217\221.md" new file mode 100644 index 0000000..8a75147 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/Nginx\345\237\272\344\272\216\350\257\267\346\261\202\345\244\264\347\232\204\345\210\206\345\217\221.md" @@ -0,0 +1,237 @@ +前面的分发方式都是基于一个集群分发的,nginx是一个基于7层的分发也就是可以实现基于主机头的分发,这种分发一般都是用于多集群环境中。 + +## 一、HTTP请求头和响应头 + +客户端浏览器开发者工具network工具下,获取请求的请求头信息如下所示: + +``` +Request URL: http://192.168.0.40 #请求的URL +Request method:GET #请求的方法,GET是获取数据 +Remote address:192.168.0.40:80#远程主机的地址 +Status code: 200 OK #请求代码,200表示正常,如果页面无法打开会显示404,403等 +Version: HTTP/1.1#HTTP协议的版本 + + +Response headers (235 B) #响应头 +Accept-Ranges:bytes#接受范围,如果出现此字段表示,这是一个续传的下载(断点续传),bytes表示服务器可接受范围请求的单位是bytes,none表示不支持 +Connection:keep-alive #是否支持长连接,从HTTP1.1开始默认 +Content-Length:5 #返回的数据长度,单位为字节 +Content-Type:text/html#页面类型,文本、图片、视频、音频 +Date:Fri, 21 Feb 2020 01:37:17 GMT#返回的时间 +ETag:"5e4e2e62-5"#验证标签,用来帮助控制缓存验证,当浏览器请求服务器的某项资源(A)时, 服务器根据A算出一个哈希值,并通过 ETag 返回给浏览器,浏览器把对应的哈希值和A同时缓存在本地,当下次再次向服务器请求A时,会把这个哈希值发送给服务器,服务器再次计算A的哈希值并和刚刚接收到的哈希值做比较,如果发现A发生了变化就把A返回给浏览器(200),如果发现A没有变化就给浏览器返回一个304未修改。这样通过控制浏览器端的缓存,可以节省服务器的带宽,因为服务器不需要每次都把全量数据返回给客户端 +Last-Modified:Thu, 20 Feb 2020 06:59:46 GMT#服务器认定的资源做出修改的日期及时间。 它通常被用作判断接收到的或者存储的资源是否一致。由于精确度比ETag要低,所以这是一个备用机制。 +Server:nginx/1.15.12 #服务器的软件类型和版本 + + +Request headers (355 B) #请求头 +Accept:text/html,application/xhtml+xm… #接受的数据类型 +Accept-Encoding:gzip, deflate #是否支持压缩,及类型 +Accept-Language:en-US,en;q=0.5 #语言环境 +Cache-Control:no-cache#缓存实现的机制。 +Connection:keep-alive +Host:192.168.0.40#访问的名称(主机名还是IP地址),虚拟主机就是依靠这个字段来判断返回哪个页面内容 +Pragma:no-cache#http1.0使用的字段,如果是no-cache与cache-control功能一致 +Upgrade-Insecure-Requests:1 #客户端优先选择加密及带有身份验证的响应 +User-Agent:Mozilla/5.0 (X11; Linux x86_64…) Firefox/60.0 #客户端浏览器类型和版本 +``` + +以上只是对在发者工具中看到的内容进行的说明,有需要的同学,或者是如果以后看到了其它额外字段的内容可以参看https://developer.mozilla.org/zh-CN/docs/Web/HTTP,里面有详细的说明 + +## 二、基于请求头的分发 + +### 2.1、基于host分发 + +基于host分发这种分发方式适用于多集群分发。例如:一个公司有多个网站,每个网站就是一个集群。 + +``` +#nginx分发器设置 +http { + upstream web1 { # 名为web1的反向代理群组 + server 192.168.0.42; + } + upstream web2 { # 名为web2的反向代理群组 + server 192.168.0.43; + } + server { # web1虚拟主机 + listen 80; + server_name www.web1.com; # 基于域名分发必须有域名 + location / { + proxy_pass http://web1; + } + } + server { # web2虚拟主机 + listen 80; + server_name www.web2.com; # 基于域名分发必须有域名 + location / { + proxy_pass http://web2; + } + } +} +``` + +### 2.2、基于域名的分发测试: + +``` +#客户端测试机设置 +[root@client ~]# vim /etc/hosts +168.0.40 www.web1.com +192.168.0.40 www.web2.com +[root@client ~]# curl www.web1.com +web1 +[root@client ~]# curl www.web2.com +web2 +``` + +### 2.3、基于开发语言分发 + +这种分发方式适用于混合开发的网站,某些大型网站既有php也有jsp,就可以基于开发语言分发。 + +``` +# 192.168.0.40分发器上nginx配置 +http { + upstream php { + server 192.168.0.42; + } + upstream html { + server 192.168.0.43; + } + server { + location ~* \.php$ { # 以php结尾的 + proxy_pass http://php; + } + location ~* \.html$ { # 以html结尾的 + proxy_pass http://html; + } + } +} +``` + +测试验证: + +``` +# 在web1这台主机上安装php环境 +[root@web1 ~]# dnf -y install php# 安装php +# 启动apache,自带php +[root@web1 ~]# systemctl restart httpd + +# 编写php文件 +[root@web1 ~]# echo "" > /var/www/html/index.php + +# 访问192.168.0.40/index.php 可以看到php-info信息页面 +# 访问192.168.0.40/index.html 可以看到web2 +``` + +### 2.4、基于浏览器分发 + +这种基于浏览器的分发,常应用于PC端和移动端区分或浏览器适配。 + +**部署第三台业务主机** + +``` +[root@web3 ~]# dnf install httpd -y +[root@web3 ~]# echo web3 > /var/www/html/index.html +[root@web3 ~]# systemctl restart httpd +[root@web3 ~]# curl localhost +``` + +**配置基于浏览器的分发** + +``` +upstream curl { server 192.168.0.42; } +upstream firefox { server 192.168.0.43; } +upstream other { server 192.168.0.44; } +server { + listen 80; + server_name www.web1.com; + location / { + proxy_pass http://other; + if ( $http_user_agent ~* curl ) { + proxy_pass http://curl; + } + if ( $http_user_agent ~* firefox ) { + proxy_pass http://firefox; + } + } +} +``` + +**测试** + +使用不同的浏览器访问分发器会得到不同的页面 + +### 2.5、基于源IP分发 + +像腾讯新闻,网易,58同城,真爱,百合,赶集,智联等等很多网站,这种网站都有一个特性,你一访问,就知道你的位置,然后根据你的位置,给你推荐或者展示相关内容。很多APP也是这样的,只不过,网站是通过你的源IP来确定你的位置,APP的则更为直接一些,通过定位数据获取位置。比如说,你去新闻类的网站,这些网站的本地新版板块显示的都是你所在地的相关信息。也就是说我们可以让服务器对源IP进行判断,根据判断的结果不同,再返回不同的数据给客户端;如果判断不出来,就按照默认去处理。如果想实现基于源IP的分发我们需要一个叫geo的参数,这个参数可以要根据客户端ip访问到不同的server,它是通过一个叫ngx_http_geo_module模块提供的。默认情况下,nginx安装时是会自动加载这个模块,除非安装时人为的手动添加–without-http_geo_module。 + +**配置** + +``` +upstream bj.server { + server 192.168.0.42; # web01 +} +upstream sh.server { + server 192.168.0.43; # web02 +} +upstream default.server { + server 192.168.0.44; # web03 +} +geo $geo { # IP库 + default default; + 192.168.0.10/32 bj; # 北京 + 192.168.0.20/32 sh; # 上海 +} +server { + listen 80; + server_name www.web1.com; + + location / { + proxy_pass http://$geo.server$request_uri; + } +} +``` + +如果客户端地址是0.10 就访问北京,如果是0.20就访问上海,如果不是0.10也不是0.20就按照default处理,线上环境这里面就是个IP库 我现在没有ip库只能写两个IP来代表看下后面的掩码是32表示这一个网段只有这一个IP吧,当然你也可以换成网段。 + +http后面加上$request_uri的原因就是避免客户 找你拿数据的时候一指定URI你就无法正常代理了,目的就是保证客户在访问类似http://www.a.com/a/b/c/d.jpg这样的网址的时候可以正常访问 也就是说当用户请求的URL当中的URI跟着变化的时候你的代理服务器一样可以正常工作 + +重启nginx服务器,切换到客户端测试 + +``` +[root@client ~]# ifconfig +ens33: flags=4163 mtu 1500 + inet 192.168.0.10 netmask 255.255.255.0 broadcast 192.168.0.255 + inet6 fe80::2386:3dbd:531c:7bc1 prefixlen 64 scopeid 0x20 + ether 00:0c:29:a6:ad:95 txqueuelen 1000 (Ethernet) + RX packets 1177 bytes 280850 (274.2 KiB) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 1115 bytes 111602 (108.9 KiB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +lo: flags=73 mtu 65536 + inet 127.0.0.1 netmask 255.0.0.0 + inet6 ::1 prefixlen 128 scopeid 0x10 + loop txqueuelen 1000 (Local Loopback) + RX packets 7080 bytes 601912 (587.8 KiB) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 7080 bytes 601912 (587.8 KiB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +[root@client ~]# curl 192.168.0.40 +web1 +[root@client ~]# nmcli connection modify ens33 ipv4.addresses 192.168.0.20/24 ipv4.method manual autoconnect yes +[root@client ~]# nmcli connection down ens33 +成功停用连接 "ens33"(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/16) + +[root@client ~]# nmcli connection up ens33 +连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/17) +[root@client ~]# curl 192.168.0.40 +web2 +[root@client ~]# nmcli connection modify ens33 ipv4.addresses 192.168.0.30/24 ipv4.method manual autoconnect yes +[root@client ~]# nmcli connection down ens33 +成功停用连接 "ens33"(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/17) + +[root@client ~]# nmcli connection up ens33 +连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/18) +[root@client ~]# curl 192.168.0.40 +web3 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/Nginx\351\233\206\347\276\244\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/Nginx\351\233\206\347\276\244\344\273\213\347\273\215.md" new file mode 100644 index 0000000..03a5160 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/Nginx\351\233\206\347\276\244\344\273\213\347\273\215.md" @@ -0,0 +1,44 @@ +## 一、Nginx集群组成 + +**组成要素:** +  1)VIP: 给分发器的一个虚IP +  2)分发器:nginx +  3)数据服务器:web服务器 + +## 二、nginx集群原理 + +在Nginx集群中Nginx扮演的角色是:分发器。 +任务:接受请求、分发请求、响应请求。 +功能模块: +    1)ngx_http_upstream_module:基于应用层(七层)分发模块 +    2)ngx_stream_core_module:基于传输层(四层)分发模块(1.9开始提供该功能) + +**nginx集群的实质** + +nginx 默认支持分发 他有一个自带模块 叫upstream 这就是nginx的分发模块,也就是说nginx分发是一个组合体 将什么组合在一起呢 + +虚拟主机+反向代理+upstream,在这个组合中 + +- 虚拟主机:负责接受和响应请求。 +- 反向代理:带领用户去数据服务器拿数据。 +- upstream:告诉nginx去哪个数据服务器拿数据。 + +**数据包走向** + + 1)用户发起请求 + + 2)虚拟主机接受用户请求 + + 3)虚拟主机去找反向代理(问反向代理去哪拿数据) + + 4)反向代理让去找upstream + + 5)upstream告诉一个数据服务器IP + + 6)Nginx去找数据服务器,并发起用户的请求 + + 7)数据服务器接受请求并处理请求 + + 8)数据服务器响应请求给Nginx + + 9)Nginx响应请求给用户 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\350\256\244\350\257\206LVS\351\233\206\347\276\244.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\350\256\244\350\257\206LVS\351\233\206\347\276\244.md" new file mode 100644 index 0000000..d21b219 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\350\256\244\350\257\206LVS\351\233\206\347\276\244.md" @@ -0,0 +1,141 @@ +## 一、LVS集群介绍 + +LVS(linux virtual server)即linux虚拟服务器,由章文嵩博士主导开发的开源负载均衡项目,从2.6内核开始已经被集成到linux内核模块中了,该项目在linux内核中实现了基于IP的数据请求负载均衡调度方案,终端互联网用户从外部访问公司的外部负载均衡服务器,终端用户的web请求会发送给LVS调度器,调度器根据自己预设的算法决定将该请求发送给后端的某台web服务器,如果后端的所有web服务器存储的内容时相同的,那么用户不管访问哪台真实的web服务器得到的内容也都是相同的,所以整个集群对于用户而言是透明的。最后根据工作模式不同,真实服务器会选择不同的方式将用户需要的数据发送给终端用户。 + +![image20200204132829832.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603964223443.png) + +### 1.1、LVS的三种模式 + +- NAT模式 +- DR直连路由 +- TUN隧道模式 + +### 1.2、LVS负载均衡调度算法 + +**分发算法介绍** +分发算法其实就是分发器如何将用户请求分发给数据服务器,让数据服务器来处理。比如: + +**幼儿园里老师分苹果** + +- 老师就是分发器:他来决定给小朋友们如何发苹果 +- 苹果就是用户请求 +- 小朋友就是数据服务器,负责来处理苹果 + +根据前面的介绍,我们了解了LVS的三种模式,但是不管使用哪种模式,调度器进行调度的策略与算法都是LVS的核心技术,LVS在内核中主要实现了八种调度算法 + +**1.2.1、轮询 rr** +调度器通过“轮叫”调度算法将外部请求按顺序轮流分配到集群中的真实服务器上,它均等地对待每一台服务器,而不管服务器上实际的连接数和系统负载。 + +**1.2.2、加权轮询 wrr** +调度器通过“加权轮叫”调度算法根据真实服务器的不同处理能力来调度访问请求。这样可以保证处理能力强的服务器能处理更多的访问流量。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。 + +**1.2.3、最小连接 lc** +调度器通过“最少连接”调度算法动态地将网络请求调度到已建立的链接数最少的服务器上。如果集群系统的真实服务器具有相近的系统性能,采用“最小连接”调度算法可以较好地均衡负载。 + +**1.2.4、加权最小连接 wlc** +在集群系统中的服务器性能差异较大的情况下,调度器采用“加权最少链接”调度算法优化负载均衡性能,具有较高权值的服务器将承受较大比例的活动连接负载。调度器可以自动问询真实服务器的负载情况,并动态地调整其权值。 + +**1.2.5、基于局部的最小连接 lblc** +基于局部性的最少链接”调度算法是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。该算法根据请求的目标IP地址找出该目标IP地址最近使用的服务器,若该服务器是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于一半的工作负载,则用“最少链接” 的原则选出一个可用的服务器,将请求发送到该服务器。 + +**1.2.6、带复制的基于局部性最少链接 lblcr** +带复制的基于局部性最少链接”调度算法也是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。它与LBLC算法的不同之处是它要维护从一个目标 IP地址到一组服务器的映射,而LBLC算法维护从一个目标IP地址到一台服务器的映射。该算法根据请求的目标IP地址找出该目标IP地址对应的服务器组,按“最小连接”原则从服务器组中选出一台服务器,若服务器没有超载,将请求发送到该服务器;若服务器超载,则按“最小连接”原则从这个集群中选出一台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的程度。 + +**1.2.7、目标地址散列 dh** +目标地址散列”调度算法根据请求的目标IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。 + +**1.2.8、源地址散列 sh** +源地址散列”调度算法根据请求的源IP地址,作为散列键(Hash Key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。 + +**一般情况 rr wrr lc wlc适用于静态网站,lblc sh dh适用于动态网站** + +## 二、集群部署工具-ipvsadm介绍 + +LVS已经集成在linux内核模块中,但整个LVS环境又分为内核层与用户层,内核层负责核心算法的实现,用户层需要安装ipvsadm工作,通过命令将管理员需要的工作模式与实现算法传递给内核来实现,在CentOS8的光盘镜像中已经包含了相关的软件包,我们可以使用dnf安装 + +``` +[root@zutuanxue ~]# dnf install ipvsadm -y +``` + +安装完成之后会生成一个同名的命令工具,我们需要使用该命令来配置LVS和算法 + +``` +用法 +ipvsadm 选项 服务器地址 -s 算法 +ipvsadm 选项 服务器地址 -r 真是服务器地址 [工作模式] [权重] + +选项 + A 添加一个虚拟服务器 + E 编辑一个虚拟服务器 + D 删除一个虚拟服务器 + C 清空虚拟服务器列表 + R 从标准输入中还原虚拟服务器规则 + S 将虚拟服务器规则保存至标准输出 + a 添加一个真实服务器 + e 编辑一个真实服务器 + d 删除一个真实服务器 + l/L 查看分发列表 + t 使用tcp协议 + u 使用udp协议 + s 指定算法 + r 设置真实服务器的IP地址和端口信息 + g DR模式 + i tun模式 + m nat模式 + w 设置真实服务器的权重 + c 查看连接状态,需要配合L使用 + n 以数字形式输出 + + +比如,添加一个虚拟服务器,算法为rr,所有使用tcp协议访问192.168.1.100:80的请求,最终都被NAT模式转发给了192.168.2.210和2.220的80端口 +[root@zutuanxue ~]# ipvsadm -A -t 192.168.1.100:80 -s rr +[root@zutuanxue ~]# ipvsadm -a -t 192.168.1.100:80 -r 192.168.2.210:80 -m +[root@zutuanxue ~]# ipvsadm -a -t 192.168.1.100:80 -r 192.168.2.220:80 -m + +查看规则 +[root@zutuanxue ~]# ipvsadm -l +IP Virtual Server version 1.2.1 (size=4096) +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP localhost.localdomain:http rr + -> 192.168.2.210:http Masq 1 0 0 + -> 192.168.2.220:http Masq 1 0 0 +[root@zutuanxue ~]# ipvsadm -ln +IP Virtual Server version 1.2.1 (size=4096) +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP 192.168.1.100:80 rr + -> 192.168.2.210:80 Masq 1 0 0 + -> 192.168.2.220:80 Masq 1 0 0 + + +查看调度状态 +[root@zutuanxue ~]# ipvsadm -lnc +IPVS connection entries +pro expire state source virtual destination +TCP 00:20 TIME_WAIT 192.168.1.100:36916 192.168.1.100:80 192.168.2.220:80 +TCP 01:09 TIME_WAIT 192.168.1.100:36922 192.168.1.100:80 192.168.2.210:80 +TCP 00:20 TIME_WAIT 192.168.1.100:36918 192.168.1.100:80 192.168.2.210:80 +TCP 00:25 TIME_WAIT 192.168.1.100:36920 192.168.1.100:80 192.168.2.220:80 +TCP 01:40 TIME_WAIT 192.168.1.100:36924 192.168.1.100:80 192.168.2.220:80 +TCP 14:57 ESTABLISHED 192.168.1.100:36926 192.168.1.100:80 192.168.2.210:80 + + +删除真实服务器 +[root@zutuanxue ~]# ipvsadm -d -t 192.168.1.100:80 -r 192.168.2.220 +[root@zutuanxue ~]# ipvsadm -ln +IP Virtual Server version 1.2.1 (size=4096) +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP 192.168.1.100:80 rr + -> 192.168.2.210:80 Masq 1 0 2 + +备份规则 +[root@zutuanxue ~]# ipvsadm -S > /tmp/ipvs.bak +清空规则 +[root@zutuanxue ~]# ipvsadm -C +还原规则 +[root@zutuanxue ~]# ipvsadm -R < /tmp/ipvs.bak +修改算法 +[root@zutuanxue ~]# ipvsadm -E -t 192.168.1.100:80 -s wrr +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\203\250\347\275\262LVS DR\351\233\206\347\276\244.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\203\250\347\275\262LVS DR\351\233\206\347\276\244.md" new file mode 100644 index 0000000..c5efb5e --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\203\250\347\275\262LVS DR\351\233\206\347\276\244.md" @@ -0,0 +1,163 @@ +## 一、DR模式集群 + +在TUN模式下,由于需要在LVS与真实服务器之间创建隧道连接,这样会增加服务器的负担。与TUN模式类似,在DR模式中LVS依然只承担数据的入站请求,并且根据算法选择出合适的真实服务器,最终有后端真实服务器负责将响应数据包发送给客户端。但是与隧道模式不同的是,DR模式中要求调度器与后端服务器必须在同一个局域网内,VIP地址也需要在调度器与后端所有的服务器间共享,因为最终的真实服务器给客户端回应数据包时需要设置源地址为VIP的地址,目标地址为为客户端的IP地址,这样客户端访问的是LVS调度器的VIP地址,回应的源地址也依然是VIP地址,客户端是感觉不到后端服务器的存在的,由于多台计算机都设置了同样一个VIP地址,所以在DR模式中要求调度器的VIP地址对外是可见的,客户端需要讲请求数据包发送到调度器主机,也就是LVS,而所有的真实服务器的VIP地址必须配置在Non-ARP的网络设备上,也就是该网络设备并不会向外广播自己的MAC及对应的IP地址,真实服务器的VIP对外是不可见的,但是真实服务器却可以接受目标地址为VIP的网络请求,并在回应数据包时将源地址设置为该VIP地址,LVS根据算法选出真实服务器后,在不修改数据报文的情况下,将数据帧的MAC地址修改为选择出的真实服务器的MAC地址,通过交换机将该数据帧发给真实服务器。整个过程中,真实服务器的VIP不需要对外可见 + +![image20200204140723491.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603967556922.png) + +### 工作原理 + +基于直接路由来实现。当用户请求到达director之后,director将请求报文的目标地址(即VIP)改成选定的realserver地址,还要改写请求报文的mac地址,将请求发送到指定mac的realserver,而realserver将响应直接返回给客户端,不经过director。这个方式是三种调度中性能最好的,也是我们生产环境中使用最多的。 + +### 特点: + +1、集群节点和director必须在一个物理网络内 +2、RIP可以使用公网地址或私有地址 +3、director仅处理入站请求 +4、集群节点网关不指向director,故出站不经过director +5、不支持端口映射 +6、大多数操作系统可以作为realserver,要支持隔离arp广播 +7、director服务器的压力比较小 + +**优点:** VS/DR跟 VS/TUN 方法相同,负载调度器中只负责调度请求,而服务器直接将响应返回给客户,可以极大地提高整个集群系统的吞吐量。 + +**缺点:** 要求负载均衡器的网卡必须与RS物理网卡在一个物理段上 + +## 二、实战案例 + +### 案例需求 + +部署基于LVS DR模式的web集群 + +### 实验环境 + +五台安装CentOS8的虚拟机一台测试机,一台LVS分发器,一台路由器,两台web服务器 + +### 注意事项 + +- 关闭selinux +- 关闭防火墙 +- 停止libvirtd.service服务 + +### 实验拓扑图 + +![image20200215202839308.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603967852346.png) + +### 实验机器 + +| 角色 | 接口和IP | +| ------- | ----------------------------------------------- | +| client | ens33=192.168.1.200 | +| route | ens33=192.168.1.1;ens160=192.168.2.1 | +| LVS | ens33=192.168.2.200;ens37=192.168.2.100(VIP) | +| RS1&RS2 | ens33=192.168.2.210&220;lo:0=192.168.2.100(VIP) | + +### 实验步骤 + +a、配置路由,开启转发 + +``` +ens33=192.168.1.1 +ens160=192.168.2.1 + +[root@route ~]# echo 1 > /proc/sys/net/ipv4/ip_forward +``` + +c、配置客户端 + +``` +ens33=192.168.1.200 +[root@client ~]# route add default gw 192.168.1.1 +``` + +c、LVS负载均衡器设置 + +``` +ens33=192.168.2.200 +ens37=192.168.2.100(VIP) +[root@lvs ~]# route add default gw 192.168.2.1 +[root@lvs ~]# ipvsadm -A -t 192.168.2.100:80 -s rr +[root@lvs ~]# ipvsadm -a -t 192.168.2.100:80 -r 192.168.2.220:80 -g +[root@lvs ~]# ipvsadm -a -t 192.168.2.100:80 -r 192.168.2.210:80 -g +``` + +d、RS1&RS2设置 + +``` +RS1=192.168.2.220 +RS2=192.168.2.210 + +添加VIP并设置网关,调整内核参数 + +RS1 +[root@rs1 ~]# route add default gw 192.168.2.1 +[root@rs1 ~]# ifconfig lo:0 192.168.2.100 netmask 255.255.255.255 up +[root@rs1 ~]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore +[root@rs1 ~]# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce + +RS2 +[root@rs2 ~]# route add default gw 192.168.2.1 +[root@rs2 ~]# ifconfig lo:0 192.168.2.100 netmask 255.255.255.255 up +[root@rs2 ~]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore +[root@rs2 ~]# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce + +安装web服务,生成测试页面 +RS1 +[root@rs1 ~]# dnf install httpd -y +[root@rs1 ~]# echo "rs1" > /var/www/html/index.html +[root@rs1 ~]# systemctl start httpd.service +RS2 +[root@rs2 ~]# dnf install httpd -y +[root@rs2 ~]# echo "rs2" > /var/www/html/index.html +[root@rs2 ~]# systemctl start httpd.service +``` + +e、客户端测试 + +``` +[root@client ~]# elinks http://192.168.2.100 --dump + rs2 +[root@client ~]# elinks http://192.168.2.100 --dump + rs1 +[root@client ~]# elinks http://192.168.2.100 --dump + rs2 +[root@client ~]# elinks http://192.168.2.100 --dump + rs1 +``` + +## 三、部署中的问题 + +我们知道,每台主机都有一个arp表,这个arp表记录了已知主机的IP地址和对应的mac地址,计算机在进行数据包封装的时候,会读取这个表当中的内容,做为封装数据包的依据,比如说我要给192.168.1.100这台主机发送一个数据包,现在我知道这台主机的IP地址了,但是它的mac地址是多少呢?这就需要查看arp表当中的记录,如果查看到了就直接使用192.168.1.100以及对应的mac地址做为数据包的目的地,但是如果查看不到,计算机就会发送arp广播,在网络上去询问“192.168.1.100你的mac地址是多少?我是xxx,这是我的mac地址”,一旦对方主机给予回应了,双方就会将对应的信息记录到自己的arp表中,以便于下次使用,而我们知道不管是在DR模式还是在tun模式当中所有的主机都配置了一个叫VIP的东西,那么以我们下面的这个架构图为例 + +![image20200213113629470.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603967999086.png) + +当路由器(192.168.2.1)发送arp广播询问谁是192.168.2.100的时候就会出现一个问题,我们期望的是RIP=192.168.2.2的这台分发器去响应这个arp广播,这样路由器才能把客户端的请求包正确的发送给分发器,分发器再去根据自己的算法将请求分配给RS,也就是RIP为2.3和2.4的主机,但是如果是RS去响应这个arp的话,那么数据包就不能按照我们预想的去传递,所以在DR模式和TUN模式中我们要抑制RS主机针对于VIP的arp响应,同时我们还要告诉RS主机在发送arp广播时,不允许使用VIP去声明自己,这就需要我们通过调整内核参数来实现 + +**arp_ignore** 控制系统在收到外部的arp请求时,如何响应。常用的取值主要有0,1,2,3~8较少用到: + +0:响应任意网卡上接收到的对本机IP地址的arp请求(包括环回网卡上的地址),而不管该目的IP是否在接收网卡上。 + +1:只响应目的IP地址为接收网卡上的本地地址的arp请求。 + +2:只响应目的IP地址为接收网卡上的本地地址的arp请求,并且arp请求的源IP必须和接收网卡同网段。 + +由于在DR$TUN模式中我们RS的VIP都不是绑定在实体网卡上,所以我们要使用1这个值来抑制RS主机的arp响应 + +**arp_announce** 控制系统在对外发送arp请求时,如何选择arp请求数据包的源IP地址。常用的取值有0,1,2。 + +0:允许使用任意网卡上的IP地址作为arp请求的源IP + +1:尽量避免使用不属于该发送网卡子网的本地地址作为发送arp请求的源IP地址。也就是说,比如我的主机有两个IP地址,一个是1.100,一个是2.100,但是我发现我需要给2.200这台主机发送一个数据包,那此时如果需要发送arp请求的话呢我就要尽量使用2.100去声明我自己,而尽量去避免使用1.100去声明自己;但是如果我需要给3.200这台主机发送数据包呢?那就会使用2这个级别 + +2:忽略IP数据包的源IP地址,选择该发送网卡上最合适的本地地址作为arp请求的源IP地址。同样使用上面的例子如果给3.200发送数据包的话,你的主机发现自己用哪个IP地址去声明自己都不合适,你的主机就会查看一下路由记录,如果路由记录告诉你的主机发往3网段的数据包都要交给1.1这个网关,那你的主机就会使用1.100去声明自己,如果是交给2.1这个网关的话,你的主机就会使用2.100去声明自己。这就是所谓的最合适的 + +由于在DR$TUN模式中我们RS的VIP都不是绑定在实体网卡上,而实体网卡以及响应的设置信息,才是最合适的,我们就要使用2这个值来控制RS主机如何发送arp请求 + +同样由于CentOS8默认开启了反向路由校验功能,会影响TUN模式的运行,所以我们还要关闭这个功能,所谓反向路由校验,就是在一个网卡收到数据包后,把源地址和目标地址对调后查找路由出口,从而得到反转后路由出口。然后根据反向路由出口进行过滤,简单来说就是开了这个功能数据包就只能从进入的接口出去。而这个功能我们需要调整另外一个内核参数来实现 + +**rp_filter** + +0:关闭反向路由校验 + +1:开启严格的反向路由校验。对每个进来的数据包,校验其反向路由是否是最佳路由。如果反向路由不是最佳路由,则直接丢弃该数据包。 + +2:开启松散的反向路由校验。对每个进来的数据包,校验其源地址是否可达,即反向路由是否能通(通过任意网口),如果反向路径不通,则直接丢弃该数据包。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\203\250\347\275\262LVS NAT\351\233\206\347\276\244.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\203\250\347\275\262LVS NAT\351\233\206\347\276\244.md" new file mode 100644 index 0000000..b0f6947 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\203\250\347\275\262LVS NAT\351\233\206\347\276\244.md" @@ -0,0 +1,131 @@ +## 一、NAT模式集群 + +NAT也就是网络地址转换,其作用是通过数据报头的修改,使位于企业内部的私有IP可以访问外网,以及外部用户可以访问位于公司内部的私有IP主机,在nat模式中LVS负载均衡器需要使用两块网卡配置不同的IP地址,第一块网卡与内部的web服务器连接,第二块网卡与公网用户连接 + +![image20200204131325307.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603966584168.png) + +### 工作原理 + +基于NAT机制实现。当用户请求到达director之后,director将请求报文的目标地址(即VIP)改成选定的realserver地址,同时将报文的目标端口也改成选定的realserver的相应端口,最后将报文请求发送到指定的realserver。在服务器端得到数据后,realserver将数据返给director,而director将报文的源地址和源端口改成VIP和相应端口,然后把数据发送给用户,完成整个负载调度过程。 + +### 特点 + +1,所有的realserver和director要在同一个网段内 +2,RIP是私有地址,仅用于集群节点之间进行通信 +3,director同时处理请求和应答数据包 +4,realserver的网关要指向DIP +5,可以实现端口映射 +6,readlserver可以是任意操作系统 +7,director很可能成为系统性能瓶颈 + +**优点:** 集群中的物理服务器可以使用任何支持TCP/IP操作系统它只需要一个公网 IP 地址配置在调度器上,服务器组可以用私有的 IP 地址。 + +**缺点:** 扩展性有限。当服务器节点(普通PC服务器)增长过多时,负载均衡器将成为整个系统的瓶颈,因为所有的请求包和应答包的流向都经过负载均衡器。当服务器节点过多时,大量的数据包都交汇在负载均衡器那,速度就会变慢。 + +## 二、实战案例 + +### 案例需求 + +配置一个基于LVS NAT的web集群 + +### 实验环境 + +四台安装CentOS8的虚拟机一台测试机,一台LVS分发器,两台web服务器 + +### 注意事项 + +- 在做实验的时候在CLIENT上抓包的时候会发现LVS给CLIENT回复了请求页面,也看到了RS给了CLIENT页面,但是现实环境中是不会让RS给CLIENT页面的,因为RS在私网,他的数据包不会出现在公网,所以CLIENT自然就收不到RS给的包了,实验中能收到是因为没有公私网的概念,自然就没有合法不合法数据包,当然就能收到。 +- 在做这个实验的时候,LVS要用两个独立网卡,不要将VIP当成逻辑网卡绑定到一块物理网卡,TCP半链接太多了。无法测试 +- 关闭selinux关闭防火墙,停止libvirtd.service服务 + +### 实验架构 + +![image20200215194949204.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603966889055.png) + +| 角色名称 | 接口和IP | +| -------- | --------------------------------------- | +| client | ens33=192.168.1.200 | +| LVS | ens33=192.168.1.100;ens37=192.168.2.200 | +| RS1 | ens33=192.168.2.210 | +| RS2 | ens33=192.168.2.220 | + +### 实验步骤 + +a、设置LVS主机 + +``` +LVS配置IP地址 +ens33=192.168.2.200 +ens37=192.168.1.100 + +安装ipvsadm软件包 +[root@lvs ~]# dnf install ipvsadm -y + +开启转发 +[root@lvs ~]# echo 1 > /proc/sys/net/ipv4/ip_forward +``` + +b、真实服务器设置 + +``` +配置IP地址 +ens33=192.168.2.210&192.168.2.220 + +添加网关 网关指向LVS主机 +[root@rs1 ~]# route add default gw 192.168.2.200 +[root@rs2 ~]# route add default gw 192.168.2.200 + +安装web服务,生成测试页面 +RS1 +[root@rs1 ~]# dnf install httpd -y +[root@rs1 ~]# echo "rs1" > /var/www/html/index.html +[root@rs1 ~]# systemctl start httpd.service +RS2 +[root@rs2 ~]# dnf install httpd -y +[root@rs2 ~]# echo "rs2" > /var/www/html/index.html +[root@rs2 ~]# systemctl start httpd.service +``` + +c、客户端设置 + +``` +ens33=192.168.1.200 + +设置网关 +[root@client ~]# route add default gw 192.168.1.100 + + +安装elinks软件包(这里面选择使用没有缓存的elinks浏览器进行测试) +[root@client ~]# wget http://www.elinks.or.cz/download/elinks-current-unstable.tar.gz +[root@client ~]# tar fx elinks-current-unstable.tar.gz +[root@client elinks-0.12-20200204]# ./configure +[root@client elinks-0.12-20200204]# make && make install + +访问web服务器测试 +[root@client ~]# elinks http://192.168.2.210 --dump + rs2 +[root@client ~]# elinks http://192.168.2.220 --dump + rs1 +注意:也可以使用curl进行访问测试 +``` + +d、lvs服务器上添加分发规则 + +``` +[root@lvs ~]# ipvsadm -A -t 192.168.1.100:80 -s rr +[root@lvs ~]# ipvsadm -a -t 192.168.1.100:80 -r 192.168.2.210:80 -m +[root@lvs ~]# ipvsadm -a -t 192.168.1.100:80 -r 192.168.2.220:80 -m +``` + +e、测试结果 + +``` +[root@client elinks-0.12-20200204]# elinks http://192.168.1.100 --dump + rs1 +[root@client elinks-0.12-20200204]# elinks http://192.168.1.100 --dump + rs2 +[root@client elinks-0.12-20200204]# elinks http://192.168.1.100 --dump + rs1 +[root@client elinks-0.12-20200204]# elinks http://192.168.1.100 --dump + rs2 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\203\250\347\275\262LVS TUN\351\233\206\347\276\244.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\203\250\347\275\262LVS TUN\351\233\206\347\276\244.md" new file mode 100644 index 0000000..ff67054 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\203\250\347\275\262LVS TUN\351\233\206\347\276\244.md" @@ -0,0 +1,117 @@ +## 一、TUN模式集群 + +在NAT模式中,由于所有的请求及响应的数据包都需要经过LVS调度器,如果后端的服务器数量较大,则调度器就会成为整个集群环境的瓶颈。而请求包的大小往往小于响应包,因为响应数据包中包含有客户需要的具体数据,所以TUN模式的思路就是将请求与响应分离,让调度器仅处理请求,让真实服务器将响应数据包直接返回给客户端。在TUN模式中有一个IP隧道,这个IP隧道是一种数据包封装技术,可以将原始数据包封装并添加新的包头(包头内容包括新的源地址和端口,新的目标地址和端口),从而实现将一个目标为调度器VIP地址的数据包封装,通过隧道转发给后端的真实服务器,通过将客户端发往调度器的原始数据封装,并在其基础上添加新的包头(修改目标地址为调度器选择出来的真实服务器的地址及端口),TUN模式要求真实服务器可以直接与外部网络连接,真实服务器在收到请求数据包后直接给客户端主机响应数据 + +![image20200204135136495.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603968291812.png) + +### 工作原理 + +基于NAT机制实现。当用户请求到达director之后,director将请求报文的目标地址(即VIP)改成选定的realserver地址,同时将报文的目标端口也改成选定的realserver的相应端口,最后将报文请求发送到指定的realserver。在服务器端得到数据后,realserver将数据返给director,而director将报文的源地址和源端口改成VIP和相应端口,然后把数据发送给用户,完成整个负载调度过程。 + +### 特点 + +1、所有的realserver和director要在同一个网段内 +2、RIP是私有地址,仅用于集群节点之间进行通信 +3、director同时处理请求和应答数据包 +4、realserver的网关要指向DIP +5、可以实现端口映射 +6、readlserver可以是任意操作系统 +7、director很可能成为系统性能瓶颈 + +**优点:** 负载均衡器只负责将请求包分发给后端节点服务器,而RS将应答包直接发给用户。所以,减少了负载均衡器的大量数据流动,负载均衡器不再是系统的瓶颈,就能处理很巨大的请求量,这种方式,一台负载均衡器能够为很多RS进行分发。而且跑在公网上就能进行不同地域的分发。 + +**缺点:** 隧道模式的RS节点需要合法IP,这种方式需要所有的服务器支持”IP Tunneling”(IP Encapsulation)协议,服务器可能只局限在部分Linux系统上。 + +## 二、实战案例 + +### 案例需求 + +部署基于LVS TUN模式的Web集群 + +### 实验环境 + +五台安装CentOS8的虚拟机一台测试机,一台LVS分发器,一台路由器,两台web服务器 +![image20200215203423650.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603968541949.png) + +### 注意事项 + +- 关闭selinux +- 关闭防火墙 +- 停止libvirtd.service服务 + +### 实验拓扑图 + +![image20200215203218254.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603968531606.png) + +### 实验步骤 + +a、配置路由,开启转发 + +``` +ens33=192.168.1.1 +ens160=192.168.2.1 + +[root@route ~]# echo 1 > /proc/sys/net/ipv4/ip_forward +``` + +b、配置客户端 + +``` +ens33=192.168.1.200 +[root@client ~]# route add default gw 192.168.1.1 +``` + +c、LVS负载均衡器设置 + +``` +ens33=192.168.2.200 +ens37=192.168.2.100(VIP) +[root@lvs ~]# route add default gw 192.168.2.1 +[root@lvs ~]# ipvsadm -A -t 192.168.2.100:80 -s rr +[root@lvs ~]# ipvsadm -a -t 192.168.2.100:80 -r 192.168.2.220:80 -i +[root@lvs ~]# ipvsadm -a -t 192.168.2.100:80 -r 192.168.2.210:80 -i +``` + +d、RS1&RS2设置 + +``` +RS1=192.168.2.220 +RS2=192.168.2.210 + +添加VIP并设置网关,调整内核参数 + +RS1 +[root@rs1 ~]# route add default gw 192.168.2.1 +[root@rs1 ~]# ifconfig tunl0 192.168.2.100 netmask 255.255.255.255 up +[root@rs1 ~]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore +[root@rs1 ~]# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce +[root@rs1 ~]# echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter +RS2 +[root@rs2 ~]# route add default gw 192.168.2.1 +[root@rs2 ~]# ifconfig tunl0 192.168.2.100 netmask 255.255.255.255 up +[root@rs2 ~]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore +[root@rs2 ~]# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce +[root@rs2 ~]# echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter +安装web服务,生成测试页面 +RS1 +[root@rs1 ~]# dnf install httpd -y +[root@rs1 ~]# echo "rs1" > /var/www/html/index.html +[root@rs1 ~]# systemctl start httpd.service +RS2 +[root@rs2 ~]# dnf install httpd -y +[root@rs2 ~]# echo "rs2" > /var/www/html/index.html +[root@rs2 ~]# systemctl start httpd.service +``` + +e、客户端测试 + +``` +[root@client ~]# elinks http://192.168.2.100 --dump + rs2 +[root@client ~]# elinks http://192.168.2.100 --dump + rs1 +[root@client ~]# elinks http://192.168.2.100 --dump + rs2 +[root@client ~]# elinks http://192.168.2.100 --dump + rs1 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\203\250\347\275\262nginx web\351\233\206\347\276\244.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\203\250\347\275\262nginx web\351\233\206\347\276\244.md" new file mode 100644 index 0000000..ab76fc3 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\203\250\347\275\262nginx web\351\233\206\347\276\244.md" @@ -0,0 +1,207 @@ +## 一、案例需求 + +使用nginx分发器构建一个web集群 + +## 二、环境准备 + +实验机 :四台虚拟机,一台测试机,一台分发器,两台web服务器。 + +网卡:vmnet4 + +系统:CentOS8.0 + +SELinux&防火墙:关闭 + +网段:192.168.0.0/24 + +| 角色&主机名 | IP | +| -------------- | --------------- | +| 客户端 client | 192.168.0.10/24 | +| 分发器 nginx1 | 192.168.0.40/24 | +| web服务器 web1 | 192.168.0.42/24 | +| web服务器 web2 | 192.168.0.43/24 | + +## 三、架构图 + +![image20200220115749617.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603971518929.png) + +## 四、实验步骤 + +### 4.1、 配置web业务机 + +**a、部署nginx** + +``` +nginx安装脚本 +#!/bin/bash + +nginx_pkg='nginx-1.19.3.tar.gz' +nginx_prefix=/usr/local/nginx +html=/var/nginx +log=/var/log/nginx + +check13 () { + [ $UID -ne 0 ] && echo "need to be root to that" && exit 1 + [ ! -f $nginx_pkg ] && echo "not found source packager" && exit 1 + [ ! -d $html ] && mkdir -p $html + [ ! -d $log ] && mkdir -p $log +} + +nginx_install () { + source_pkg=`echo $nginx_pkg|awk -F ".tar" '{print $1}'` + [ -d /usr/src/$source_pkg ]&&rm -rf /usr/src/$source_pkg + tar xf $nginx_pkg -C /usr/src + cp nginxd /usr/src/$source_pkg + if [ $? -eq 0 ];then + cd /usr/src/$source_pkg + if [ $? -eq 0 ];then + dnf -y install gcc-* pcre pcre-devel zlib zlib-devel openssl-* make*&> /dev/null + [ $? -ne 0 ]&&"YUM set error" && exit 1 + ./configure --prefix=$nginx_prefix + if [ $? -eq 0 ];then + make + if [ $? -eq 0 ];then + make install + if [ $? -eq 0 ];then + ln -s -f $nginx_prefix/conf/nginx.conf /etc/ + ln -s -f $nginx_prefix/logs/ $log/logs + ln -s -f $nginx_prefix/html $html/html + ln -s -f $nginx_prefix/sbin/ /usr/sbin/ + cp nginxd /etc/init.d/nginx;chmod 755 /etc/init.d/nginx + else + exit 1 + fi + else + exit 1 + fi + else + exit 1 + fi + else + exit 1 + fi + else + exit 1 +fi + [ $? -eq 0 ]&&clear||exit + echo -e "\n\033[32m Nginx Install Success: \033[0m" + echo -e "\n" + echo -e "\tNginx_conf: /etc/nginx.conf" + echo -e "\tNginx_html: $html/html" + echo -e "\tNginx_access_log: $log/logs/access.log" + echo -e "\tNginx_error_log: $log/logs/error.log\n\n\n\n" + read -n1 -p "press any key and exit...." + echo +} + +check13 +nginx_install +``` + +我们在学习web服务时,涉及过nginx的安装,这个脚本只是将我们之前需要手动执行的工作变成了自动执行脚本完成的工作 + +- 安装nginx需要用到的软件包 +- 将nginx安装到/usr/local/nginx目录下 +- 页面文件可直接放在/var/nginx目录下 +- 日志文件可直接查看/var/log/nginx目录下 +- 配置文件可直接编辑/etc/nginx.conf + +**b、配置web** + +``` +web1 +[root@web1 ~]# dnf -y install httpd +[root@web1 ~]# echo web1 > /var/www/html/index.html +[root@web1 ~]# systemctl restart httpd +[root@web1 ~]# curl localhost +web1 +[root@web2 ~]# dnf -y install httpd +[root@web2 ~]# echo web2 > /var/www/html/index.html +[root@web2 ~]# systemctl restart httpd +[root@web2 ~]# curl localhost +``` + +### 4.2、配置分发器 + +**a、部署nginx分发器** + +``` +[root@nginx ~]# sh nginx_install.sh +``` + +**b、配置nginx** + +``` +[root@nginx ~]# cd /usr/local/nginx/conf/ +[root@nginx conf]# sed -i '/#/d' nginx.conf +[root@nginx conf]# sed -i '/^$/d' nginx.conf +[root@nginx ~]# vim /etc/nginx.conf +worker_processes 1; +events { + worker_connections 1024; +} +http { + include mime.types; + default_type application/octet-stream; + sendfile on; + keepalive_timeout 65; + upstream web { # 名为web的反向代理群组 + server 192.168.0.42; + server 192.168.0.43; + } + server { + listen 80; + server_name localhost; + location / { + proxy_pass http://web; # 去找反向代理 + } + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root html; + } + } +} +``` + +### 4.3、集群分发测试 + +``` +[root@client ~]# curl 192.168.0.40 +web1 +[root@client ~]# curl 192.168.0.40 +web2 +[root@client ~]# curl 192.168.0.40 +web1 +[root@client ~]# curl 192.168.0.40 +web2 + +停止一台主机的web服务 +[root@web2 ~]# systemctl stop httpd +继续测试 +[root@client ~]# curl 192.168.0.40 +web1 +[root@client ~]# curl 192.168.0.40 +web1 +[root@client ~]# curl 192.168.0.40 +web1 + +由此可见nginx有自动检测后端真实服务器的功能,继续 + +启动web2这台主机的nginx服务,并停掉网卡 +[root@web2 ~]# systemctl start httpd +[root@web2 ~]# nmcli connection down ens33 +成功停用连接 "ens33"(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/1) + + +继续测试 +[root@client ~]# curl 192.168.0.40 +web1 +[root@client ~]# curl 192.168.0.40 +web1 +[root@client ~]# curl 192.168.0.40 +web1 +``` + +如果我把网卡down了,你会发现访问速度变慢 然后才能正常访问 因为down网卡相当于防火墙的DROP 知道等到超时为止 + +也就是说当nginx找upstream要数据的时候,upstream给nginx一个RS地址,nginx去联系这个地址发现联系不上,回去找upstream说你给我那玩意不好使,然后upstream说那我再给你一个吧,那这样的话用户永远都访问不到down掉的RS了,如果都不好使呢?你的网站就挂了。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\233\206\347\276\244\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\233\206\347\276\244\344\273\213\347\273\215.md" new file mode 100644 index 0000000..4b088bb --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\345\244\247\345\271\266\345\217\221\351\233\206\347\276\244\351\203\250\347\275\262/\351\233\206\347\276\244\344\273\213\347\273\215.md" @@ -0,0 +1,74 @@ +## 一、传统web访问模型 + +![image20200219200605577.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603970681446.png) + +### 传统web访问模型完成一次请求的步骤 + +1)用户发起请求 +2)服务器接受请求 +3)服务器处理请求(压力最大) +4)服务器响应请求 + +### 传统模型缺点 + +单点故障; +单台服务器资源有限(客户端则是无限的); +单台服务器处理耗时长(客户等待时间过长); + +### 传统模型优化——单点故障解决方案 + +部署一台备份服务器,宕机直接切换该方案可以有效解决服务器故障导致的单点故障,但且服务器利用率低、成本高,切换不及时,且无法解决服务器业务压力问题。 + +## 二、并行处理解决方案 + +![image20200220095348113.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603970728242.png) + +### 2.1、DNS轮询解析方案 + +通过dns服务器中添加多条A记录,将同一个域名分别解析为不同的IP地址,这样就实现了一个简单的负载均衡 + +**优点:** 成本较低,如果你有多个公网IP的话,只需要在DNS上多添加几条A记录就可以了,公网IP需要收费,这个功能是不收费的;部署方便,只需要增加web服务即可,原架构不需要更改。每台主机的负载都是均衡的。 + +**缺点:** 无法进行健康检查,如果有web服务器宕机,DNS服务器是无法知晓的,会影响业务,而且会暴露太多的公网IP,实效性不佳,修改DNS记录需要一个生效周期,有的是3-4个小时,有的会更久;分配不均,如果几台Web服务器之间的配置不同,能够承受的压力也就不同,但是DNS解析分配的访问却是均匀分配的。其实DNS也是有分配算法的,可以根据当前连接较少的分配、可以设置Rate权重分配等等,只是目前绝大多数的DNS服务器都不支持;会话保持,如果是需要身份验证的网站,在不修改软件构架的情况下,这点是比较致命的,因为DNS解析无法将验证用户的访问持久分配到同一服务器。虽然有一定的本地DNS缓存,但是很难保证在用户访问期间,本地DNS缓存不过期 + +### 2.2、多机阵列——集群模式 + +两台负载均衡主机一个为主服务器,另外一个为备用服务器,他们,正常情况下,主服务器会绑定一个虚拟IP(Virtual IP),DNS将域名解析为虚拟IP,客户端的请求到达负载均衡器后,由负载均衡将请求交给后端的web服务器,如果主服务器宕机,则备用服务器会自动绑定这个虚拟IP,继续进行分发工作,这一切对于用户而言是透明的 + +**优点:** 不需要调整dns服务器,因为是用过相应的软件来实现负载均衡的,并且只需要一个公网IP地址做为虚拟IP就可以了,还能做到随时扩容,如果后端的web服务器宕机,负载均衡器会将其从分发列表里剔除,真正的实现的网站的高度可用,因为负载均衡器有备用服务机,web服务器也有备用机 + +**缺点:** 软件上和硬件上都可以实现负载均衡,选择的时候要慎重,硬件上的设备需要资金投入,软件上的要根据自己的需求决定,如LVS不能实现动静分离;NGINX适用范围小,只能支持http,https等少数的协议;HAProxy不支持POT/SMTP协议,多进程模式不够好等。 + +## 三、集群介绍 + +就像冗余部件可以使你免于硬件故障一样,群集技术则可以使你免于整个系统的瘫痪以及操作系统和应用层次的故障。一台服务器集群包含多台拥有共享数据存储空间的服务器,各服务器之间通过内部局域网进行互相连接;当其中一台服务器发生故障时,它所运行的应用程序将与之相连的服务器自动接管;在大多数情况下,集群中所有的计算机都拥有一个共同的名称,集群系统内任意一台服务器都可被所有的网络用户所使用。 + +- 计算机集群简称集群,是一种计算机系统, 它通过一组松散集成的计算机软件或硬件连接起来高度紧密地协作完成计算工作。在某种意义上,他们可以被看作是一台计算机。 (百度解释) +- 将多个物理机器组成一个逻辑计算机,实现负载均衡和容错。 + +**群集组成** + +``` +VIP [virtual IP] +数据服务器 [data server] +分发器以及故障切换 [Directory and fail over] +``` + +**集群分类** + +- 按分发器类型分 + – LVS集群 + – Nginx集群 + – haproxy集群 + – F5集群 +- 按业务类型分 + – web集群 + – 数据库集群 + – 缓存集群 + – … + +**思考:** + +``` + 什么是单点故障 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apacha\345\216\213\345\212\233\346\265\213\350\257\225.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apacha\345\216\213\345\212\233\346\265\213\350\257\225.md" new file mode 100644 index 0000000..e25c305 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apacha\345\216\213\345\212\233\346\265\213\350\257\225.md" @@ -0,0 +1,111 @@ +## 一、ab命令 + +ab工具 + +Apache服务器的性能测试工具,它可以测试安装Web服务器每秒处理的HTTP请求. + +语法 + +ab {选项} {参数} + +选项 + +-A:指定连接服务器的基本的认证凭据; + +-c:指定一次向服务器发出请求数; + +-C:添加cookie; + +-g:将测试结果输出为“gnuolot”文件; + +-h:显示帮助信息; + +-H:为请求追加一个额外的头; + +-i:使用“head”请求方式; + +-k:激活HTTP中的“keepAlive”特性; + +-n:指定测试会话使用的请求数; + +-p:指定包含数据的文件; + +-q:不显示进度百分比; + +-T:使用POST数据时,设置内容类型头; + +-v:设置详细模式等级; + +-w:以HTML表格方式打印结果; + +-x:以表格方式输出时,设置表格的属性; + +-X:使用指定的代理服务器发送请求; + +-y:以表格方式输出时,设置表格属性。 + +参数 + +主机:被测试主机。 + +## 二、ab压力测试 + +[root@zutuanxue apache]# ./bin/ab -n 10000 -c 200 http://192.168.11.251/index.php + +``` +[root@apache_251 apache]# ./bin/ab -n 10000 -c 200 http://192.168.11.251/index.php +This is ApacheBench, Version 2.3 <$Revision: 1843412 $> +Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ +Licensed to The Apache Software Foundation, http://www.apache.org/ + +Benchmarking 192.168.11.251 (be patient) +Completed 1000 requests +Completed 2000 requests +Completed 3000 requests +Completed 4000 requests +Completed 5000 requests +Completed 6000 requests +Completed 7000 requests +Completed 8000 requests +Completed 9000 requests +Completed 10000 requests +Finished 10000 requests + + +Server Software: Apache/2.4.39 web服务器软件版本 +Server Hostname: 192.168.11.251 web服务器地址 +Server Port: 80 web服务器端口 + +Document Path: /index.php URI +Document Length: 0 bytes + +Concurrency Level: 200 +Time taken for tests: 238.891 seconds 完成请求总共用的时间 +Complete requests: 10000 完成10000个请求 +Failed requests: 0 失败0个请求 +Non-2xx responses: 10000 非2xx返回码请求 +Total transferred: 3300000 bytes 总共传输字节数 +HTML transferred: 0 bytes +Requests per second: 41.86 [#/sec] (mean) 并发数,反应服务器的性能,并发数=Complete requests/Time taken for tests +Time per request: 4777.821 [ms] (mean) 用户平均请求等待时间 +Time per request: 23.889 [ms] (mean, across all concurrent requests) 服务器平均请求等待时间 +Transfer rate: 13.49 [Kbytes/sec] received 传输速率 + +Connection Times (ms) + min mean[+/-sd] median max +Connect: 0 0 0.3 0 3 +Processing: 91 4729 1932.0 4717 21860 +Waiting: 89 4729 1932.0 4717 21860 +Total: 92 4729 1931.9 4717 21860 + +Percentage of the requests served within a certain time (ms) + 50% 4717 + 66% 4784 + 75% 4977 + 80% 6294 + 90% 7809 + 95% 8018 + 98% 9788 + 99% 11148 + 100% 21860 (longest request) +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache URL\351\207\215\345\256\232\345\220\221.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache URL\351\207\215\345\256\232\345\220\221.md" new file mode 100644 index 0000000..22fae87 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache URL\351\207\215\345\256\232\345\220\221.md" @@ -0,0 +1,170 @@ +## 一、URL重写介绍 + +Apached的重写功能,即是mod_rewrite模块功能,它是apache的一个模块。它的功能非常强大,可以操作URL中的所有部分。通过改写url,给用户提供一个简介大方的url,当用户访问时可以通过mod_rewrite模块功能转换为真正的资源路径。通过mod_rewrite能实现的功能还有很多,例如隐藏真实地址、实现URL跳转、域名跳转、防盗链、限制访问资源类型等等。 + +URL重写在生产环境中被广大运维大牛们运用的淋漓尽致,那么什么是URL重写呢?**URL重写其实就是改写用户浏览器中的URL地址**。 + +比如说京东,google、亚马逊都在使用: + +| 域名 | 重写后域名 | +| :------------: | :---------------: | +| www.z.cn | www.amazon.cn | +| www.g.cn | www.google.com.cn | +| www.360buy.com | www.jd.com | + +当用户在浏览器中输入:www.360buy.com域名回车以后,你会发现浏览器中的域名变成了:www.jd.com。这是怎么回事呢? + +那是因为运维在web服务器上设置了URL重写,在你访问服务器的一瞬间改写了你地址栏中的域名。 + +#### URL重写应用场景 + +域名变更:比如京东 + +伪静态:便于CDN缓存页面 + +域名伪装:隐藏URI真实路径 + +## 二、URL重写 + +#### 1)重写指令介绍 + +RewriteEngine on #开启mod_rewrite模块功能 + +RewriteBase 路径 #基准URL(使用alias设置别名则需使用这个) + +RewriteCond TestString CondPattern [flags] #重写条件(可以多个) + +RewriteRule Pattern Substitution [flags] #重写规则 + +``` +RewriteCond及RewriteRule行可以可以多个 +按顺序一个一个执行RewriteRule([flags不终止情况下]) +``` + +#### 2)指令标志位 + +**RewriteRule [flags]** + +[flags],标志符,多个则用逗号隔开。 + +标志符(摘抄于网上): + +redirect|R [=code] (强制重定向 redirect) + +以 [http://thishost[:thisport]/(使新的URL成为一个URI](http://thishost[:thisport]/%28使新的URL成为一个URI%29%29 为前缀的Substitution可以强制性执行一个外部重定向。 如果code没有指定,则产生一个HTTP响应代码302%28临时性移动%29。如果需要使用在300-400范围内的其他响应代码,只需在此指定这个数值即可, 另外,还可以使用下列符号名称之一: temp %28默认的), permanent, seeother. 用它可以把规范化的URL反馈给客户端,如, 重写“/~”为 “/u/”,或对/u/user加上斜杠,等等。 + +注意: 在使用这个标记时,必须确保该替换字段是一个有效的URL! 否则,它会指向一个无效的位置! 并且要记住,此标记本身只是对URL加上 http://thishost[:thisport]/的前缀,重写操作仍然会继续。通常,你会希望停止重写操作而立即重定向,则还需要使用’L’标记. + +forbidden|F (强制URL为被禁止的 forbidden) + +强制当前URL为被禁止的,即,立即反馈一个HTTP响应代码403(被禁止的)。使用这个标记,可以链接若干RewriteConds以有条件地阻塞某些URL。 + +gone|G(强制URL为已废弃的 gone) + +强制当前URL为已废弃的,即,立即反馈一个HTTP响应代码410(已废弃的)。使用这个标记,可以标明页面已经被废弃而不存在了. + +proxy|P (强制为代理 proxy) + +此标记使替换成分被内部地强制为代理请求,并立即(即, 重写规则处理立即中断)把处理移交给代理模块。你必须确保此替换串是一个有效的(比如常见的以 [http://hostname开头的)能够为Apache代理模块所处理的URI。使用这个标记,可以把某些远程成分映射到本地服务器名称空间,](http://xn--hostname-p30ox77bb66d)能够为apache代理模块所处理的uri。使用这个标记,可以把某些远程成分映射到本地服务器名称空间,/) 从而增强了ProxyPass指令的功能。 + +注意: 要使用这个功能,代理模块必须编译在Apache服务器中。 如果你不能确定,可以检查“httpd -l”的输出中是否有mod_proxy.c。 如果有,则mod_rewrite可以使用这个功能;如果没有,则必须启用mod_proxy并重新编译“httpd”程序。 + +last|L (最后一个规则 last) + +立即停止重写操作,并不再应用其他重写规则。 它对应于Perl中的last命令或C语言中的break命令。这个标记可以阻止当前已被重写的URL为其后继的规则所重写。 举例,使用它可以重写根路径的URL(’/’)为实际存在的URL, 比如, ‘/e/www/’. + +next|N (重新执行 next round) + +重新执行重写操作(从第一个规则重新开始). 这时再次进行处理的URL已经不是原始的URL了,而是经最后一个重写规则处理的URL。它对应于Perl中的next命令或C语言中的continue命令。 此标记可以重新开始重写操作,即, 立即回到循环的头部。 + +但是要小心,不要制造死循环! + +chain|C (与下一个规则相链接 chained) + +此标记使当前规则与下一个(其本身又可以与其后继规则相链接的, 并可以如此反复的)规则相链接。 它产生这样一个效果: 如果一个规则被匹配,通常会继续处理其后继规则, 即,这个标记不起作用;如果规则不能被匹配,则其后继的链接的规则会被忽略。比如,在执行一个外部重定向时, 对一个目录级规则集,你可能需要删除“.www” (此处不应该出现“.www”的)。 + +type|T=MIME-type(强制MIME类型 type) + +强制目标文件的MIME类型为MIME-type。 比如,它可以用于模拟mod_alias中的ScriptAlias指令,以内部地强制被映射目录中的所有文件的MIME类型为“application/x-httpd-cgi”。 + +nosubreq|NS (仅用于不对内部子请求进行处理 no internal sub-request) + +在当前请求是一个内部子请求时,此标记强制重写引擎跳过该重写规则。比如,在mod_include试图搜索可能的目录默认文件(index.xxx)时, Apache会内部地产生子请求。对子请求,它不一定有用的,而且如果整个规则集都起作用,它甚至可能会引发错误。所以,可以用这个标记来排除某些规则。 + +根据你的需要遵循以下原则: 如果你使用了有CGI脚本的URL前缀,以强制它们由CGI脚本处理,而对子请求处理的出错率(或者开销)很高,在这种情况下,可以使用这个标记。 + +nocase|NC (忽略大小写 no case) + +它使Pattern忽略大小写,即, 在Pattern与当前URL匹配时,’A-Z’ 和’a-z’没有区别。 + +qsappend|QSA (追加请求串 query string append) + +此标记强制重写引擎在已有的替换串中追加一个请求串,而不是简单的替换。如果需要通过重写规则在请求串中增加信息,就可以使用这个标记。 + +noescape|NE (在输出中不对URI作转义 no URI escaping) + +此标记阻止mod_rewrite对重写结果应用常规的URI转义规则。 一般情况下,特殊字符(如’%’, ‘$’, ‘;’等)会被转义为等值的十六进制编码。 此标记可以阻止这样的转义,以允许百分号等符号出现在输出中,如: + +RewriteRule /foo/(.*) /bar?arg=P1=$1 [R,NE] 可以使’/foo/zed’转向到一个安全的请求’/bar?arg=P1=zed’. + +passthrough|PT (移交给下一个处理器 pass through) + +此标记强制重写引擎将内部结构request_rec中的uri字段设置为 filename字段的值,它只是一个小修改,使之能对来自其他URI到文件名翻译器的 Alias,ScriptAlias, Redirect 等指令的输出进行后续处理。举一个能说明其含义的例子:如果要通过mod_rewrite的重写引擎重写/abc为/def,然后通过mod_alias使/def转变为/ghi,可以这样: + +RewriteRule ^/abc(.*) /def$1 [PT] + +Alias /def /ghi + +如果省略了PT标记,虽然mod_rewrite运作正常, 即, 作为一个使用API的URI到文件名翻译器,它可以重写uri=/abc/…为filename=/def/…,但是,后续的mod_alias在试图作URI到文件名的翻译时,则会失效。 + +注意: 如果需要混合使用不同的包含URI到文件名翻译器的模块时, 就必须使用这个标记。。混合使用mod_alias和mod_rewrite就是个典型的例子。 + +For Apache hackers + +如果当前Apache API除了URI到文件名hook之外,还有一个文件名到文件名的hook, 就不需要这个标记了! 但是,如果没有这样一个hook,则此标记是唯一的解决方案。 Apache Group讨论过这个问题,并在Apache 2.0 版本中会增加这样一个hook。 + +skip|S=num (跳过后继的规则 skip) + +此标记强制重写引擎跳过当前匹配规则后继的num个规则。 它可以实现一个伪if-then-else的构造: 最后一个规则是then从句,而被跳过的skip=N个规则是else从句. (它和’chain|C’标记是不同的!) + +env|E=VAR:VAL (设置环境变量 environment variable) + +此标记使环境变量VAR的值为VAL, VAL可以包含可扩展的反向引用的正则表达式$N和%N。 此标记可以多次使用以设置多个变量。这些变量可以在其后许多情况下被间接引用,但通常是在XSSI (via ) or CGI (如 $ENV{’VAR’})中, 也可以在后继的RewriteCond指令的pattern中通过%{ENV:VAR}作引用。使用它可以从URL中剥离并记住一些信息。 + +cookie|CO=NAME:VAL:domain[:lifetime[:path]] (设置cookie) + +它在客户端浏览器上设置一个cookie。 cookie的名称是NAME,其值是VAL。 domain字段是该cookie的域,比如’.apache.org’, 可选的lifetime是cookie生命期的分钟数,可选的path是cookie的路径。 + +**RewriteCond [flags]** + +’nocase|NC’ (不区分大小写)   在扩展后的TestString和CondPattern中,比较时不区分文本的大小写。注意,这个标志对文件系统和subrequest检查没有影响. + +’ornext|OR’ (建立与下一个条件的或的关系)   默认的情况下,二个条件之间是AND的关系,用这个标志将关系改为OR。 + +## 二、URL重写案例 + +LoadModule rewrite_module modules/mod_rewrite.so + +RewriteEngine on + +**1)将域名重写为**[**http://www.baidu.com**](http://www.baidu.com/)** R 强制重定向 L匹配到此截止** + +\#RewriteRule “^/$” “[http://www.baidu.com](http://www.baidu.com/)” [R] + +**2)浏览器匹配,chrome 和 elinks浏览器** + +\#RewriteCond “%{HTTP_USER_AGENT}” “chrome” [NC,OR] + +\#RewriteCond %{HTTP_USER_AGENT} “^elinks” [NC] + +**#强制重写为403禁止 -不重写 F 403标记** + +\#RewriteRule “^/$” - [F] + +**3)PC端 移动端分流** + +RewriteCond “%{HTTP_USER_AGENT}” “(iPhone|Blackberry|Android|ipad)” [NC] + +RewriteRule “^/$” “[http://m.ayitula.com](http://m.ayitula.com/)” [L] + +RewriteRule “^/$” “[http://book.ayitula.com](http://book.ayitula.com/)” [L] \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \344\273\213\347\273\215.md" new file mode 100644 index 0000000..a97e684 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \344\273\213\347\273\215.md" @@ -0,0 +1,71 @@ +## 一、Apache介绍 + +Apache HTTP Server(简称Apache)是Apache软件基金会的一个开放源码的网页服务器,是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一。它快速、可靠并且可通过简单的API扩充,将Perl/Python等解释器编译到服务器中。 + +Apache HTTP服务器是一个模块化的服务器,源于NCSAhttpd服务器,经过多次修改,成为世界使用排名第一的Web服务器软件。 + +apache当前版本:2.4.X + +- 官方网站:www.apache.org +- 学习手册:http://httpd.apache.org/docs/2.4/ + +## 二、Apache特点 + +**Apacheweb服务器软件拥有以下特性:** + +1.支持最新的HTTP/2通信协议(2.4.17及以后版本) + +2.拥有简单而强有力的基于文件的配置过程 + +3.支持通用网关接口 + +4.支持基于IP和基于域名的虚拟主机 + +5.支持多种方式的HTTP认证 + +6.集成Perl处理模块 + +7.集成代理服务器模块 + +8.支持实时监视服务器状态和定制服务器日志 + +9.支持服务器端包含指令(SSI) + +10.支持安全Socket层(SSL) + +11.提供用户会话过程的跟踪 + +12.支持FastCGI + +13.通过第三方模块可以支持JavaServlets + +14.跨平台 + +**平行软件** + +- IIS +- Nginx +- tengine +- Lighttpd +- Tomcat +- Resin + +## 三、部分Apache2.4新特性 + +**新增模块** + +- Mod_proxy_fcgi:提供fcgi代理 +- Mod_ratelimit:限制用户带宽 +- Mod_request:过滤客户机请求 +- Mod_remoteip:匹配客户端的IP + +**新特性** + +- Mpm(工作模式):支持工作模式在apache运行时更改 +- 但是要开启这种特性,在编译安装要启用这三种功能:–enable-mpms-shared=all --with-mpm=event +- 完善了event模式 +- 支持使用自定义变量 +- 基于FQDN的虚拟主机不再需要NameVirtualHost指令 +- 增强版的表达式分析器 +- 支持异步读写 +- 毫秒级别的keepalivetimeout \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \347\253\231\347\202\271\344\274\230\345\214\226-\345\256\242\346\210\267\347\253\257\347\274\223\345\255\230.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \347\253\231\347\202\271\344\274\230\345\214\226-\345\256\242\346\210\267\347\253\257\347\274\223\345\255\230.md" new file mode 100644 index 0000000..996a35e --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \347\253\231\347\202\271\344\274\230\345\214\226-\345\256\242\346\210\267\347\253\257\347\274\223\345\255\230.md" @@ -0,0 +1,60 @@ +## 一、静态缓存介绍 + +用户每次访问网站都会将页面中的所有元素都请求一遍,全部下载后通过浏览器渲染,展示到浏览器中。但是,网站中的某些元素我们一般都是固定不变的,比如logo,框架文件等元。,用户每次访问都需要加载这些元素。这样做好处是保证了数据的新鲜,可是这些数据不是常变化的,很久才变化一次。每次都请求、下载浪费了用户时间和公司带宽。 + +所以我们通过静态缓存的方式,将这些不常变化的数据缓存到用户本地磁盘,用户以后再访问这些请求,直接从本地磁盘打开加载,这样的好处是加载速度快,且节约公司带宽及成本。 + +#### **应用场景:数据缓存** + +#### **优化目的:提升用户访问页面加载速度,节约带宽** + +## 二、静态缓存实现 + +1)修改apache主配置文件,加载缓存模块 + +LoadModule expires_module modules/mod_expires.so + +2)针对虚拟主机或者目录设置缓存策略 + +``` + + #开启缓存 + ExpiresActive on + #针对不同类型元素设置缓存时间 + ExpiresByType image/gif "access plus 1 days" + ExpiresByType image/jpeg "access plus 24 hours" + ExpiresByType image/png "access plus 24 hours" + ExpiresByType text/css "now plus 2 hour" + ExpiresByType application/x-javascript "now plus 2 hours" + ExpiresByType application/x-shockwave-flash "now plus 2 hours” + #其他数据不缓存 + ExpiresDefault "now plus 0 min" + + + + +缓存起始点 +access 从当前访问时间开始 +now (equivalent to 'access') 相当于access +modification 从修改时间算起 + +缓存时间单位 +years +months +weeks +days +hours +minutes +seconds +``` + +## 三、验证测试 + +**缓存没有生效前* +![no_expires.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1603015493018.png) + +**缓存生效后测试** +![apache_expires.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1603015511691.png) +响应头中加载了缓存字段 + +Cache-control 和 Expires,并且缓存的时间和我们预设的一致,成功啦。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \347\253\231\347\202\271\344\274\230\345\214\226-\351\225\277\350\277\236\346\216\245.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \347\253\231\347\202\271\344\274\230\345\214\226-\351\225\277\350\277\236\346\216\245.md" new file mode 100644 index 0000000..b99b34a --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \347\253\231\347\202\271\344\274\230\345\214\226-\351\225\277\350\277\236\346\216\245.md" @@ -0,0 +1,69 @@ +## 一、长连接介绍 + +#### **面临问题:** + +http是一个面向连接的协议,用户完成一次请求需要以下步骤 + +三次握手 + +发起请求 + +响应请求 + +四次断开 + +N个请求就重复N次,如果希望用户能够更快的拿到数据,服务器的压力降到最低,让你去优化这个请求过程。 + +#### **解决方案:** + +答案很明确,那就是建设每次执行的三次握手和四次断开,最好是一次三次握手建立成功后,在这个数据通道完成所有的请求后,然后在四次断开,这就是优化思路–理想中应该是这样。 + +三次握手 + +发起请求 + +响应请求 + +发起请求 + +响应请求 + +。。。。。 + +请求全部完成后,四次断开 + +#### **优化目的:** + +减少了三次握手和四次断开的次数。 + +#### 注意事项: + +长连接需要服务器和客户端浏览器都支持 + +#### 长连接特点: + +提升用户访问速度 + +降低服务器压力 + +大量空闲长连接可能造成服务器压力过大 + +## 二、长连接实现 + +apache2.4默认开启了长连接,长连接时间为5s,修改子配置文件httpd-default.conf可以定义该选项 + +\#开启长连接功能 On为开启 Off为关闭 + +KeepAlive On + +\#当keepalive打开时,maxkeepaliverequests指令限制每个连接允许的请求数。如果设置为0,则允许无限请求。我们建议将此设置保持为高值以获得最大服务器性能。不建议大家将这个数值设置为0,防止内存溢出。 + +MaxKeepAliveRequests 100 + +长连接时间,默认单位是秒,也可以使用ms 只需在数值后面添加单位就行了。这个值如果你服务器速度快,网络稳定,建议设置小一点,比如3s,因为目前单个请求都是毫秒级的。避免大量空闲长连接消耗你的系统资源。 + +KeepAliveTimeout 5 + +#### 实验总结: + +一次用户访问的长连接数根据用户浏览器的不同建立的数量不同,比如chrome,每次会同时建立5个长连接,也就是五个数据通道,然后完成数据请求,所以大家都反应chrome浏览器好用,其他浏览器要看情况,不同浏览器的连接数不同。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \350\231\232\346\213\237\344\270\273\346\234\272.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \350\231\232\346\213\237\344\270\273\346\234\272.md" new file mode 100644 index 0000000..5fb9c8c --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \350\231\232\346\213\237\344\270\273\346\234\272.md" @@ -0,0 +1,238 @@ +## 一、虚拟主机介绍 + +默认情况下,一个web服务器软件只能定义一个默认网站,也就是说只能发布一个WEB站点,对于大网站还可以,有海量用户来消耗服务器的资源,但是小网站呢?一个服务器上只跑一个小网站,服务器资源使用约等于0,那就尴尬了。为了充分利用服务器资源,现实生产环境中一般都是采用一个WEB服务器软件发布多个站点。如何解决这个问题呢?那就是配置虚拟主机! + +虚拟主机和默认网站在apache中不能同时存在,只能存在一种,当虚拟主机出现后,apache默认网站就失效了,如果你还需要默认网站,就拿虚拟主机在发布一次默认网站对应的站点即可解决。 + +#### 虚拟主机应用场景:一个WEB服务器同时发布多个WEB站点 + +一个站点出现在网络中需要三个条件:监听IP、监听port、域名。 + +so + +虚拟主机有三种实现方式 + +基于IP地址 + +基于监听端口 + +基于域名(host) + +接下来我们就可以使用虚拟主机发布多个网站吧,大家在学习的同时要总结每种实现方式的特点及应用场景 + +## 二、基于IP的虚拟主机 + +step 1 修改主配置文件,打开虚拟主机子配置文件 + +``` +[root@zutuanxue apache]# egrep "Include" conf/httpd.conf +#Include conf/extra/httpd-mpm.conf +#Include conf/extra/httpd-multilang-errordoc.conf +#Include conf/extra/httpd-autoindex.conf +#Include conf/extra/httpd-languages.conf +#Include conf/extra/httpd-userdir.conf +#Include conf/extra/httpd-info.conf +# +#把本行的#去掉 +Include conf/extra/httpd-vhosts.conf +# +# +#Include conf/extra/httpd-manual.conf +#Include conf/extra/httpd-dav.conf +#Include conf/extra/httpd-default.conf +Include conf/extra/proxy-html.conf +#Include conf/extra/httpd-ssl.conf +``` + +step 2 设置基于IP的虚拟主机 + +1)给服务器配置多个IP,有几个虚拟主机及配置几个IP地址,我们实验用了两个虚拟主机,所以我有两个IP即可 192.168.11.251 192.168.11.252 + +[root@zutuanxue ~]# ifconfig ens33:1 192.168.11.252 + +2)创建两个WEB站点 WEB1 WEB2 + +[root@zutuanxue extra]# mkdir /usr/local/apache/htdocs/web{1…2} + +\#生成两个测试页面 + +[root@zutuanxue extra]# echo web1 > /usr/local/apache/htdocs/web1/index.html + +[root@zutuanxue extra]# echo web2 > /usr/local/apache/htdocs/web2/index.html + +3)设置子配置文件 + +``` +[root@zutuanxue extra]# cat httpd-vhosts.conf + + DocumentRoot "/usr/local/apache/htdocs/web1" + #ServerName dummy-host.example.com + #ErrorLog "logs/dummy-host.example.com-error_log" + #CustomLog "logs/dummy-host.example.com-access_log" common + + + + DocumentRoot "/usr/local/apache/htdocs/web2" + #ServerName dummy-host2.example.com + #ErrorLog "logs/dummy-host2.example.com-error_log" + #CustomLog "logs/dummy-host2.example.com-access_log" common + +``` + +4)重启apache + +[root@zutuanxue extra]# /usr/local/apache/bin/apachectl -t + +Syntax OK + +[root@zutuanxue extra]# killall httpd + +[root@zutuanxue extra]# /usr/local/apache/bin/apachectl + +5)测试 + +[root@zutuanxue ~]# elinks [http://192.168.11.251](http://192.168.11.251/) -dump + +web1 + +[root@zutuanxue ~]# elinks [http://192.168.11.252](http://192.168.11.252/) -dump + +web2 + +#### 基于IP的虚拟主机特点 + +不同IP对应不同网站 + +访问方便,用户直接使用默认端口即可访问 + +服务器需要有多个IP地址(一个公网IP大概一年的费用是600左右) + +适合IP充足环境 + +## 三、基于prot的虚拟主机 + +环境还原,清除上个实验中的252IP + +[root@zutuanxue ~]# ifconfig ens33:1 down + +1)修改子配置文件 + +``` +[root@zutuanxue extra]# cat httpd-vhosts.conf + + DocumentRoot "/usr/local/apache/htdocs/web1" + #ServerName dummy-host.example.com + #ErrorLog "logs/dummy-host.example.com-error_log" + #CustomLog "logs/dummy-host.example.com-access_log" common + + +#切莫忘了开端口 +Listen 81 + + DocumentRoot "/usr/local/apache/htdocs/web2" + #ServerName dummy-host2.example.com + #ErrorLog "logs/dummy-host2.example.com-error_log" + #CustomLog "logs/dummy-host2.example.com-access_log" common + +``` + +2)重启服务 + +[root@zutuanxue extra]# /usr/local/apache/bin/apachectl -t + +Syntax OK + +[root@zutuanxue extra]# killall httpd + +[root@zutuanxue extra]# /usr/local/apache/bin/apachectl + +3)测试 + +[root@zutuanxue extra]# elinks [http://192.168.11.251:80](http://192.168.11.251/) -dump + +web1 + +[root@zutuanxue extra]# elinks [http://192.168.11.251:81](http://192.168.11.251:81/) -dump + +web2 + +#### 基于端口的虚拟主机特点 + +不同端口对应不同网站 + +访问需要加端口 + +节省IP地址 + +适合私网运行 + +## 四、基于域名的虚拟主机 + +1)设置多个域名,生产环境中如果我们可以直接在dns解析域名到主机IP,但是实验中我们没有域名和DNS,我就自己使用hosts文件做了个解析。 + +修改客户端hosts文件,解析域名 web1.zutuanxue.com 192.168.11.251 web2.zutuanxue.com 192.168.11.252 + +我就用本机做服务端和客户端,所以我修改本机251的hosts文件 + +[root@zutuanxue extra]# cat /etc/hosts + +127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 + +::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 + +192.168.11.251 web1.zutuanxue.com + +192.168.11.251 web2.zutuanxue.com + +2)修改虚拟主机配置文件 + +``` +[root@zutuanxue extra]# cat httpd-vhosts.conf + + DocumentRoot "/usr/local/apache/htdocs/web1" + ServerName web1.ayitula.com + #ErrorLog "logs/dummy-host.example.com-error_log" + #CustomLog "logs/dummy-host.example.com-access_log" common + + + + DocumentRoot "/usr/local/apache/htdocs/web2" + ServerName web2.ayitula.com + #ErrorLog "logs/dummy-host2.example.com-error_log" + #CustomLog "logs/dummy-host2.example.com-access_log" common + +``` + +\3) 重启服务 + +[root@zutuanxue extra]# /usr/local/apache/bin/apachectl -t + +Syntax OK + +[root@zutuanxue extra]# killall httpd + +[root@zutuanxue extra]# /usr/local/apache/bin/apachectl + +4)测试 + + + +[root@zutuanxue extra]# elinks [http://web1.zutuanxue.com](http://web1.zutuanxue.com/) -dump + +web1 + +[root@zutuanxue extra]# elinks [http://web2.zutuanxue.com](http://web2.zutuanxue.com/) -dump + +web2 + +#### 基于域名的虚拟主机特点 + +不同域名对应不同网站 + +需要多个域名 可以是二级或三级域名 + +每个站点使用默认端口,方便用户访问 + +只需要一个IP地址,节约成本 + +适合公网环境 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \351\273\230\350\256\244\347\275\221\347\253\231.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \351\273\230\350\256\244\347\275\221\347\253\231.md" new file mode 100644 index 0000000..f9c18f7 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache \351\273\230\350\256\244\347\275\221\347\253\231.md" @@ -0,0 +1,1047 @@ +## 一、默认网站 + +每一个web服务器软件一般默认都会提供一个用于测试的网站,apache也为用户提供了一个默认网站。默认网站的配置写在默认配置文件中。 + +## 二、配置文件 + +[root@zutuanxue conf]# cat httpd.conf + +``` +# + +# This is the main Apache HTTP server configuration file. It contains the + +# configuration directives that give the server its instructions. + +# See (URL:http://httpd.apache.org/docs/2.4/); for detailed information. + +# In particular, see + +# URL:http://httpd.apache.org/docs/2.4/mod/directives.html; + +# for a discussion of each configuration directive. + +# + +# Do NOT simply read the instructions in here without understanding + +# what they do. They're here only as hints or reminders. If you are unsure + +# consult the online docs. You have been warned. + +# + +# Configuration and logfile names: If the filenames you specify for many + +# of the server's control files begin with "/" (or "drive:/" for Win32), the + +# server will use that explicit path. If the filenames do *not* begin + +# with "/", the value of ServerRoot is prepended -- so "logs/access_log" + +# with ServerRoot set to "/usr/local/apache2" will be interpreted by the + +# server as "/usr/local/apache2/logs/access_log", whereas "/logs/access_log" + +# will be interpreted as '/logs/access_log'. + +# + +# ServerRoot: The top of the directory tree under which the server's + +# configuration, error, and log files are kept. + +# + +# Do not add a slash at the end of the directory path. If you point + +# ServerRoot at a non-local disk, be sure to specify a local disk on the + +# Mutex directive, if file-based mutexes are used. If you wish to share the + +# same ServerRoot for multiple httpd daemons, you will need to change at + +# least PidFile. + +# + +#apache软件根目录,apache安装路径。 + +ServerRoot "/usr/local/apache" + +# + +# Mutex: Allows you to set the mutex mechanism and mutex file directory + +# for individual mutexes, or change the global defaults + +# + +# Uncomment and change the directory if mutexes are file-based and the default + +# mutex file directory is not on a local disk or is not appropriate for some + +# other reason. + +# + +# Mutex default:logs + +# + +# Listen: Allows you to bind Apache to specific IP addresses and/or + +# ports, instead of the default. See also the <VirtualHost> + +# directive. + +# + +# Change this to Listen on specific IP addresses as shown below to + +# prevent Apache from glomming onto all bound IP addresses. + +# + +#设置apache监听端口及监听IP地址 + +#Listen 12.34.56.78:80 + +Listen 80 + +# + +# Dynamic Shared Object (DSO) Support + +# + +# To be able to use the functionality of a module which was built as a DSO you + +# have to place corresponding `LoadModule' lines at this location so the + +# directives contained in it are actually available _before_ they are used. + +# Statically compiled modules (those listed by `httpd -l') do not need + +# to be loaded here. + +# + +# 动态共享对象支持,使用LoadModule指令为apaceh添加功能模块 --enable-so + +# Example: + +# LoadModule foo_module modules/mod_foo.so + +# + +# 可载入模块,参考(http://httpd.apache.org/docs/2.4/mod/) + +LoadModule mpm_event_module modules/mod_mpm_event.so + +#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so + +#LoadModule mpm_worker_module modules/mod_mpm_worker.so + +LoadModule authn_file_module modules/mod_authn_file.so + +#LoadModule authn_dbm_module modules/mod_authn_dbm.so + +#LoadModule authn_anon_module modules/mod_authn_anon.so + +#LoadModule authn_dbd_module modules/mod_authn_dbd.so + +#LoadModule authn_socache_module modules/mod_authn_socache.so + +LoadModule authn_core_module modules/mod_authn_core.so + +LoadModule authz_host_module modules/mod_authz_host.so + +LoadModule authz_groupfile_module modules/mod_authz_groupfile.so + +LoadModule authz_user_module modules/mod_authz_user.so + +#LoadModule authz_dbm_module modules/mod_authz_dbm.so + +#LoadModule authz_owner_module modules/mod_authz_owner.so + +#LoadModule authz_dbd_module modules/mod_authz_dbd.so + +LoadModule authz_core_module modules/mod_authz_core.so + +LoadModule access_compat_module modules/mod_access_compat.so + +LoadModule auth_basic_module modules/mod_auth_basic.so + +#LoadModule auth_form_module modules/mod_auth_form.so + +#LoadModule auth_digest_module modules/mod_auth_digest.so + +#LoadModule allowmethods_module modules/mod_allowmethods.so + +#LoadModule file_cache_module modules/mod_file_cache.so + +#LoadModule cache_module modules/mod_cache.so + +#LoadModule cache_disk_module modules/mod_cache_disk.so + +#LoadModule cache_socache_module modules/mod_cache_socache.so + +#LoadModule socache_shmcb_module modules/mod_socache_shmcb.so + +#LoadModule socache_dbm_module modules/mod_socache_dbm.so + +#LoadModule socache_memcache_module modules/mod_socache_memcache.so + +#LoadModule socache_redis_module modules/mod_socache_redis.so + +#LoadModule watchdog_module modules/mod_watchdog.so + +#LoadModule macro_module modules/mod_macro.so + +#LoadModule dbd_module modules/mod_dbd.so + +#LoadModule dumpio_module modules/mod_dumpio.so + +#LoadModule buffer_module modules/mod_buffer.so + +#LoadModule ratelimit_module modules/mod_ratelimit.so + +LoadModule reqtimeout_module modules/mod_reqtimeout.so + +#LoadModule ext_filter_module modules/mod_ext_filter.so + +#LoadModule request_module modules/mod_request.so + +#LoadModule include_module modules/mod_include.so + +LoadModule filter_module modules/mod_filter.so + +#LoadModule substitute_module modules/mod_substitute.so + +#LoadModule sed_module modules/mod_sed.so + +#LoadModule deflate_module modules/mod_deflate.so + +LoadModule mime_module modules/mod_mime.so + +LoadModule log_config_module modules/mod_log_config.so + +#LoadModule log_debug_module modules/mod_log_debug.so + +#LoadModule logio_module modules/mod_logio.so + +LoadModule env_module modules/mod_env.so + +#LoadModule expires_module modules/mod_expires.so + +LoadModule headers_module modules/mod_headers.so + +#LoadModule unique_id_module modules/mod_unique_id.so + +LoadModule setenvif_module modules/mod_setenvif.so + +LoadModule version_module modules/mod_version.so + +#LoadModule remoteip_module modules/mod_remoteip.so + +#LoadModule proxy_module modules/mod_proxy.so + +#LoadModule proxy_connect_module modules/mod_proxy_connect.so + +#LoadModule proxy_ftp_module modules/mod_proxy_ftp.so + +#LoadModule proxy\_http_module modules/mod_proxy_http.so + +#LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so + +#LoadModule proxy_scgi_module modules/mod_proxy_scgi.so + +#LoadModule proxy_uwsgi_module modules/mod_proxy_uwsgi.so + +#LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so + +#LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so + +#LoadModule proxy_ajp_module modules/mod_proxy_ajp.so + +#LoadModule proxy_balancer_module modules/mod_proxy_balancer.so + +#LoadModule proxy_express_module modules/mod_proxy_express.so + +#LoadModule proxy_hcheck_module modules/mod_proxy_hcheck.so + +#LoadModule session_module modules/mod_session.so + +#LoadModule session_cookie_module modules/mod_session_cookie.so + +#LoadModule session_dbd_module modules/mod_session_dbd.so + +#LoadModule slotmem_shm_module modules/mod_slotmem_shm.so + +#LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so + +#LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so + +#LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so + +#LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so + +LoadModule unixd_module modules/mod_unixd.so + +#LoadModule dav_module modules/mod_dav.so + +LoadModule status_module modules/mod_status.so + +LoadModule autoindex_module modules/mod_autoindex.so + +#LoadModule info_module modules/mod_info.so + +#LoadModule cgid_module modules/mod_cgid.so + +#LoadModule dav_fs_module modules/mod_dav_fs.so + +#LoadModule vhost_alias_module modules/mod_vhost_alias.so + +#LoadModule negotiation_module modules/mod_negotiation.so + +LoadModule dir_module modules/mod_dir.so + +#LoadModule actions_module modules/mod_actions.so + +#LoadModule speling_module modules/mod_speling.so + +LoadModule alias_module modules/mod_alias.so + +#LoadModule rewrite_module modules/mod_rewrite.so + +#启用模块 unixd_module 设置apache守护进程httpd的管理用户和组 + +#启用模块注意格式 + +#结束 + +#启用的前提是已经使用LoadModule指令载入了该模块 + + + +# + +# If you wish httpd to run as a different user or group, you must run + +# httpd as root initially and it will switch. + +# + +# User/Group: The name (or #number) of the user/group to run httpd as. + +# It is usually good practice to create a dedicated user and group for + +# running httpd, as with most system services. + +# + +#指定守护进程httpd的管理用户 + +User daemon + +#指定守护进程httpd的管理组 + +Group daemon + + + +# 'Main' server configuration + +# + +# The directives in this section set up the values used by the 'main' + +# server, which responds to any requests that aren't handled by a + +# <VirtualHost> definition. These values also provide defaults for + +# any <VirtualHost> containers you may define later in the file. + +# + +# All of these directives may appear inside <VirtualHost> containers, + +# in which case these default settings will be overridden for the + +# virtual host being defined. + +# + +# + +# ServerAdmin: Your address, where problems with the server should be + +# e-mailed. This address appears on some server-generated pages, such + +# as error documents. e.g. admin@your-domain.com + +# + +#指定管理员email地址 + +ServerAdmin you@example.com + +# + +# ServerName gives the name and port that the server uses to identify itself. + +# This can often be determined automatically, but we recommend you specify + +# it explicitly to prevent problems during startup. + +# + +# If your host doesn't have a registered DNS name, enter its IP address here. + +# + +#指定服务器在DNS上注册的名称 FQDN + +#ServerName www.example.com:80 + +ServerName 127.0.0.1 + +# + +# Deny access to the entirety of your server's filesystem. You must + +# explicitly permit access to web content directories in other + +# <Directory> blocks below. + +# + +#apache 目录访问权限 + +#使用 指定目录路径 + +#拒绝用户通过apache访问你的文件系统/及以下的所有内容 + + + +#是否允许.htaccess实现权限复写 + +AllowOverride none + +#设置所有人的访问权限 denied 拒绝 granted允许 + +Require all denied + +#设置结束用指令结束 + + + +# + +# Note that from this point forward you must specifically allow + +# particular features to be enabled - so if something's not working as + +# you might expect, make sure that you have specifically enabled it + +# below. + +# + +# + +# DocumentRoot: The directory out of which you will serve your + +# documents. By default, all requests are taken from this directory, but + +# symbolic links and aliases may be used to point to other locations. + +# + +#使用DocumentRoot指定WEB站点的根目录 + +DocumentRoot "/usr/local/apache/htdocs" + +#对默认网站根目录设置访问权限 + + + +# + +# Possible values for the Options directive are "None", "All", + +# or any combination of: + +# Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews + +# + +# Note that "MultiViews" must be named *explicitly* --- "Options All" + +# doesn't give it to you. + +# + +# The Options directive is both complicated and important. Please see + +# (http://httpd.apache.org/docs/2.4/mod/core.html#options) + +# for more information. + +# + +Options Indexes FollowSymLinks + +#Indexes 站点中有index页面优先加载 + +#FollowSymLinks 在WEB站点根目录允许使用链接文件 + +# + +# AllowOverride controls what directives may be placed in .htaccess files. + +# It can be "All", "None", or any combination of the keywords: + +# AllowOverride FileInfo AuthConfig Limit + +# + +#不许使用权限复写 + +AllowOverride None + +# + +# Controls who can get stuff from this server. + +# + +#允许所有人访问网站根目录 + +Require all granted + + + +# + +# DirectoryIndex: sets the file that Apache will serve if a directory + +# is requested. + +#指定站点的默认索引文件 + + + +DirectoryIndex index.html + + + +# + +# The following lines prevent .htaccess and .htpasswd files from being + +# viewed by Web clients. + +# + +#是否允许在目录下使用.htaccess 和 .htpassswd文件设置客户端对网站目录访问权限 + +#.htaccess 访问控制 + +#.htpasswd 用户登陆验证 + +#拒绝在目录下使用.ht开头的文件 + + + +Require all denied + + + +# + +# ErrorLog: The location of the error log file. + +# If you do not specify an ErrorLog directive within a + +# container, error messages relating to that virtual host will be + +# logged here. If you *do* define an error logfile for a + +# container, that host's errors will be logged there and not here. + +# + +#错误日志 + +ErrorLog "logs/error_log" + +# + +# LogLevel: Control the number of messages logged to the error\_log. + +# Possible values include: debug, info, notice, warn, error, crit, + +# alert, emerg. + +# + +#错误日志记录级别:debug, info, notice, warn, error, crit,alert, emerg. + +LogLevel warn + +#启用日志模块 + + + +# + +# The following directives define some format nicknames for use with + +# a CustomLog directive (see below). + +# + +#定义日志格式 LogFormat "日志格式" 日志格式名称 + +LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined + +LogFormat "%h %l %u %t \"%r\" %>s %b" common + + + +# 在访问日志中记录每个请求的输入输出字节 %I input %O output + +# You need to enable mod\_logio.c to use %I and %O + +LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio + + + +# + +# The location and format of the access logfile (Common Logfile Format). + +# If you do not define any access logfiles within a <VirtualHost> + +# container, they will be logged here. Contrariwise, if you *do* + +# define per- access logfiles, transactions will be + +# logged therein and \*not\* in this file. + +# + +#定义访问日志路径及日志格式 + +CustomLog "logs/access_log" common + +# + +# If you prefer a logfile with access, agent, and referer information + +# (Combined Logfile Format) you can use the following directive. + +# + +#CustomLog "logs/access_log" combined + + + +#使用目录映射 + + + +# + +# URL重定向 + +# Redirect: Allows you to tell clients about documents that used to + +# exist in your server's namespace, but do not anymore. The client + +# will make a new request for the document at its new location. + +# Example: + +# Redirect permanent /foo http://www.example.com/bar + +#URL重定向 Redirect 方法 选项 + +#不同机器重定向将访问http://IP/abc 的用户 重定向访问 http:/www.baidu.com + +Redirect permanent /abc http://www.baidu.com + +#本机内部URL重定向 http://IP/123 http://IP/7878 ==注意==:被重定向的目录必须存在 比如7878必须有 + +Redirect permanent /123 /7878 + +#seeother 表示改资源被替换过 + +Redirect seeother /123 /7878 + +#gone 表示改资源被移除了 + +Redirect gone /123 + +#permanent 永久重定向 301 + +#temp 临时重定向 + +#seeother 返回一个seeother状态码(303)提示这个资源被替代 + +#gone 返回一个gone状态码(410)提示这个资源被永久删除了 + +# + +# Alias: Maps web paths into filesystem paths and is used to + +# access content that does not live under the DocumentRoot. + +# Example: + +# Alias /webpath /full/filesystem/path + +# + +# If you include a trailing / on /webpath then the server will + +# require it to be present in the URL. You will also likely + +# need to provide a section to allow access to + +# the filesystem path. + +#Alias 将URI中的没用了映射到文件系统目录(绝对路径) + +#比如将网站URL http://ip/abc 访问的/abc目录映射到文件系统/usr/local/apache/htdocs/7878 + +Alias /abc /usr/local/apache/htdocs/7878 + +#需要注意是文件系统路径 + +# + +# ScriptAlias: This controls which directories contain server scripts. + +# ScriptAliases are essentially the same as Aliases, except that + +# documents in the target directory are treated as applications and + +# run by the server when requested rather than as documents sent to the + +# client. The same rules about trailing "/" apply to ScriptAlias + +# directives as to Alias. + +# + +ScriptAlias /cgi-bin/ "/usr/local/apache/cgi-bin/" + +#脚本目录别名 + + + +#使用外部CGI守护进程执行CGI脚本 + + + +# + +# ScriptSock: On threaded servers, designate the path to the UNIX + +# socket used to communicate with the CGI daemon of mod\_cgid. + +# + +#Scriptsock cgisock + + + +# + +# "/usr/local/apache/cgi-bin" should be changed to whatever your ScriptAliased + +# CGI directory exists, if you have that configured. + +# + +#CGI目录的访问权限 + + + +AllowOverride None + +Options None + +Require all granted + + + +#自定义http的请求头和响应头 + +#RequestHeader 设置请求头 http://httpd.apache.org/docs/2.4/mod/mod_headers.html + +#Header 设置响应头 http://httpd.apache.org/docs/2.4/mod/mod_headers.html + + + +# + +# Avoid passing HTTP\_PROXY environment to CGI's on this or any proxied + +# backend servers which have lingering "httpoxy" defects. + +# 'Proxy' request header is undefined by the IETF, not listed by IANA + +# + +RequestHeader unset Proxy early + + + +#将请求的文件扩展名与文件的行为(处理程序和筛选器)和内容(mime类型、语言、字符集和编码)相关联。 + +#明确告诉apache 可以接受什么类型的文件 + + + +# + +# TypesConfig points to the file containing the list of mappings from + +# filename extension to MIME-type. + +# + +TypesConfig conf/mime.types + +# + +# AddType allows you to add to or override the MIME configuration + +# file specified in TypesConfig for specific file types. + +# + +#AddType application/x-gzip .tgz + +# + +# AddEncoding allows you to have certain browsers uncompress + +# information on the fly. Note: Not all browsers support this. + +# + +#AddEncoding x-compress .Z + +#AddEncoding x-gzip .gz .tgz + +# + +# If the AddEncoding directives above are commented-out, then you + +# probably should define those extensions to indicate media types: + +# + +AddType application/x-compress .Z + +AddType application/x-gzip .gz .tgz + +# + +# AddHandler allows you to map certain file extensions to "handlers": + +# actions unrelated to filetype. These can be either built into the server + +# or added with the Action directive (see below) + +# + +# To use CGI scripts outside of ScriptAliased directories: + +# (You will also need to add "ExecCGI" to the "Options" directive.) + +# + +#AddHandler cgi-script .cgi + +# For type maps \(negotiated resources\): + +#AddHandler type-map var + +# + +# Filters allow you to process content before it is sent to the client. + +# + +# To parse .shtml files for server-side includes (SSI): + +# (You will also need to add "Includes" to the "Options" directive.) + +# + +#AddType text/html .shtml + +#AddOutputFilter INCLUDES .shtml + + + +# + +# The mod_mime_magic module allows the server to use various hints from the + +# contents of the file itself to determine its type. The MIMEMagicFile + +# directive tells the module where the hint definitions are located. + +# + +#MIMEMagicFile conf/magic + +# + +# Customizable error responses come in three flavors: + +# 1) plain text 2) local redirects 3) external redirects + +# + +# Some examples: + +#ErrorDocument 500 "The server made a boo boo." + +#ErrorDocument 404 /missing.html + +#ErrorDocument 404 "/cgi-bin/missing\_handler.pl" + +#ErrorDocument 402 [http://www.example.com/subscription\_info.html](http://www.example.com/subscription_info.html) + +# + +# + +# MaxRanges: Maximum number of Ranges in a request before + +# returning the entire resource, or one of the special + +# values 'default', 'none' or 'unlimited'. + +# Default setting is to accept 200 Ranges. + +#MaxRanges unlimited + +# + +# EnableMMAP and EnableSendfile: On systems that support it, + +# memory-mapping or the sendfile syscall may be used to deliver + +# files. This usually improves server performance, but must + +# be turned off when serving from networked-mounted + +# filesystems or if support for these functions is otherwise + +# broken on your system. + +# Defaults: EnableMMAP On, EnableSendfile Off + +# + +#EnableMMAP off + +#EnableSendfile on + +# Supplemental configuration + +# + +# The configuration files in the conf/extra/ directory can be + +# included to add extra features or to modify the default configuration of + +# the server, or you may simply copy their contents here and change as + +# necessary. + +#Include 包含子配置文件 + +# Server-pool management \(MPM specific\) + +#Include conf/extra/httpd-mpm.conf + +# Multi-language error messages + +#Include conf/extra/httpd-multilang-errordoc.conf + +# Fancy directory listings + +#Include conf/extra/httpd-autoindex.conf + +# Language settings + +#Include conf/extra/httpd-languages.conf + +# User home directories + +#Include conf/extra/httpd-userdir.conf + +# Real-time info on requests and configuration + +#Include conf/extra/httpd-info.conf + +# Virtual hosts + +#Include conf/extra/httpd-vhosts.conf + +# Local access to the Apache HTTP Server Manual + +#Include conf/extra/httpd-manual.conf + +# Distributed authoring and versioning (WebDAV) + +#Include conf/extra/httpd-dav.conf + +# Various default settings + +#Include conf/extra/httpd-default.conf + +# Configure mod_proxy_html to understand HTML4/XHTML1 + +#启动代理模块 + + + +Include conf/extra/proxy-html.conf + +; + +# Secure (SSL/TLS) connections + +#Include conf/extra/httpd-ssl.conf + +# + +# Note: The following must must be present to support + +# starting without SSL on platforms with no /dev/random equivalent + +# but a statically compiled-in mod\_ssl. + +# + +#启用ssl模块 + + + +SSLRandomSeed startup builtin + +SSLRandomSeed connect builtin + +; +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\345\256\211\345\205\250-\347\224\250\346\210\267\347\231\273\345\275\225\351\252\214\350\257\201.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\345\256\211\345\205\250-\347\224\250\346\210\267\347\231\273\345\275\225\351\252\214\350\257\201.md" new file mode 100644 index 0000000..bbbe935 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\345\256\211\345\205\250-\347\224\250\346\210\267\347\231\273\345\275\225\351\252\214\350\257\201.md" @@ -0,0 +1,72 @@ +## 一、登录验证 + +当用户访问网站或者网站某个目录时,如果希望用户提供授权才能登录,那么就需要针对该站或者该目录设置登录验证了。apache提供了该功能,可以让我们针对站点或目录设置登录验证。这样用户访问网站时需要提交账号密码才能登录。 + +## 二、登录验证实现 + +#### 1)修改apache配置文件 + +``` + + +AuthName "Private" + +AuthType Basic + +AuthUserFile "/usr/local/apache/user.dbm" + +#访问控制 + + +Require valid-user + +Require not ip 192.168.11.251 + + + + + + +#访问控制 +#Order deny,allow + +#Deny from all + +#Allow from 192.168.11.23 + + + + +# 1) AuthName:定义提示信息,用户访问时提示信息会出现在认证的对话框中 +# 2) AuthType:定义认证类型,在HTTP1.0中,只有一种认证类型:basic。在HTTP1.1中有几种认证类型,如:MD5 +# 3) AuthUserFile:定义包含用户名和密码的文本文件,每行一对 +# 4) AuthGroupFile:定义包含用户组和组成员的文本文件。组成员之间用空格分开,如:group1:user1 user2 +# 5) require命令:定义哪些用户或组才能被授权访问。如: +#  require user user1 user2 (只有用户user1和user2可以访问) +#  requires groups group1 (只有group1中的成员可以访问) +#  require valid-user (在AuthUserFile指定的文件中的所有用户都可以访问) +``` + +#### 2)生成用户验证文件 + +[root@apache_251 extra]# /usr/local/apache/bin/htpasswd -cm /usr/local/apache/user.dbm baism + +New password: + +Re-type new password: + +Adding password for user baism + +#### 3)查看文件内容 用户名:秘钥 + +[root@apache_251 extra]# cat /usr/local/apache/user.dbm + +baism:apr1apr1.XawVas2$8Bn7rJFJjGLDZ.63fSiYV1 + +#### 4)设置站点验证目录 + +[root@apache_251 extra]# mkdir /usr/local/apache/htdocs/web1/a + +[root@apache_251 extra]# touch /usr/local/apache/htdocs/web1/a/file{a…z} + +#### 5)重启apache并测试 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\345\256\211\350\243\205-\347\224\250\346\210\267\350\256\277\351\227\256\346\216\247\345\210\266.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\345\256\211\350\243\205-\347\224\250\346\210\267\350\256\277\351\227\256\346\216\247\345\210\266.md" new file mode 100644 index 0000000..5026aeb --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\345\256\211\350\243\205-\347\224\250\346\210\267\350\256\277\351\227\256\346\216\247\345\210\266.md" @@ -0,0 +1,52 @@ +## 一、访问控制介绍 + +生产环境中,我们的网站分为公站和私站,公站我们巴不得所有人都能来访问,所以不会做任何访问限制。但是私站只是内部人访问,越安全越好,比如网站后台、比如公司数据站等等。所以我们需要通过设置访问控制来允许自己公司电脑或者IP登陆访问,其他人不能访问。 + +其实这个功能类似于防火墙,可以但是使用起来更加灵活。只针对本站做限制,不影响其他业务。 + +## 二、访问控制实现 + +#### 指令介绍 + +**Require 指令** + +\#Require all denied 拒绝所有 + +\#Require all granted 允许所有 + +\#Require host address 允许主机域名 多个空格空开 + +\#Require ip ip.address 允许ip或网段 多个空格空开 + +**容器 ** + +只要一个成功即可就通过 + +用于包含一组授权指令,其中一个指令必须成功才能使指令成功。 + +所有指令都生效才通过 + +用于包含一组授权指令,其中无一个指令必须失败,并且至少有一个指令必须成功才能使指令成功。 + +所有指令都不生效才通过 + +用于包含一组授权指令,其中无一个指令必须成功才能使指令不失败。 + +#### 实现代码 + +``` + + AllowOverride None + #apache2.4新方法 + Require all denied + Require ip 192.168.11.24 192.168.11.251 + Require host www.ayitula.com + + #apache2.2老方法 + ##The Allow, Deny, and Order directives, provided by mod_access_compat + #Order deny,allow + #Deny from all + #Allow from 192.168.11.23 + + +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\347\253\231\347\202\271\344\274\230\345\214\226-\344\270\213\350\275\275\351\231\220\351\200\237.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\347\253\231\347\202\271\344\274\230\345\214\226-\344\270\213\350\275\275\351\231\220\351\200\237.md" new file mode 100644 index 0000000..4e7afef --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\347\253\231\347\202\271\344\274\230\345\214\226-\344\270\213\350\275\275\351\231\220\351\200\237.md" @@ -0,0 +1,97 @@ +## 一、限速介绍 + +网站除了能共享页面给用户外,还能作为下载服务器存在。但是作为下载服务器时,我们应该考虑服务器的带宽和IO的性能,防止部分邪恶分子会通过大量下载的方式来攻击你的带宽和服务器IO性能。 + +假如你的服务器被邪恶分子通过下载的方式把带宽占满了,那么你或其他用户在访问的时候就会造成访问慢或者根本无法访问。 + +假如你的服务器被邪恶分子通过下载的方式把服务器IO占满了,那么你的服务器将会无法处理用户请求或宕机。 + +以上的两个问题在我们生产环境下是很可能也是很容易被攻击的,为了保护我们的带宽资源,我们可以通过限制下载速度来解决,防止某个用户下载占用大量带宽。同时,也可以通过限制连接数的上限来控制一个用户同一时间内同时发起的连接数做限制。 + +#### 使用场景:资源下载服务器 + +#### 优化目的:保护带宽及服务器IO资源合理使用 + +## 二、限速方法 + +apache自带了基于带宽限速的模块 + +ratelimit_module 该模块只能对连接下载速度做限制,且是单线程的下载,迅雷等下载工具使用的是多线程下载。 + +mod_limitipconn :限制每 IP 的连接数 。需要额外安装该模块 + +## 三、限速实现 + +1)mod_limitipconn模块下载 + +wget https://dominia.org/djao/limit/mod_limitipconn-0.24.tar.bz2 + +2)模块安装 + +1. tar -zxvf mod_limitipconn-0.24.tar.gz +2. cd mod_limitipconn-0.24 +3. vim Makefile +4. 修改如下行 + +``` + 修改:apxs = “/usr/local/apache/bin/apxs” + 指定apache命令apxs的路径 +``` + +1. make +2. make install + +3)查看apache主配置文件,是否有了该模块 + +LoadModule limitipconn_module modules/mod_limitipconn.so + +有说明模块安装成功 + +4)实现限速 + +限速针对目录或者数据类型 + +针对目录 …… ; + +针对数据类型…… + +``` +LoadModule ratelimit_module modules/mod_ratelimit.so +LoadModule limitipconn_module modules/mod_limitipconn.so + + + SetOutputFilter RATE_LIMIT + SetEnv rate-limit 100 #限速100k +MaxConnPerIP 3 #限制的线程数 +NoIPLimit index.htm #对此文件不做限制 + +``` + +## 四、测试 + +1)生成下载数据 + +dd if=/dev/zero of=/usr/local/apache/htdocs/web1/baism/bigfile bs=1M count=300 + +2)使用wget下载数据 + +wget http://192.168.11.251/baism/bigfile + +测试方法: +并发下载3个以上看是否有限制 +查看下载速率是否在100K左右 + +测试图片 + +未限制限速前下载速度展示 + +![下载限速1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1603016107738.png) + +) +开启下载速度限速,限制下载速度100KB + +![限速2.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1603015916218.png) + +基于IP的并发下载限制,同一客户端下载并发为3 + +![限速3.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1603015930532.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\347\253\231\347\202\271\344\274\230\345\214\226-\346\225\260\346\215\256\345\216\213\347\274\251.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\347\253\231\347\202\271\344\274\230\345\214\226-\346\225\260\346\215\256\345\216\213\347\274\251.md" new file mode 100644 index 0000000..ce05689 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\347\253\231\347\202\271\344\274\230\345\214\226-\346\225\260\346\215\256\345\216\213\347\274\251.md" @@ -0,0 +1,77 @@ +## 一、数据压缩介绍 + +数据从服务器传输到客户端,需要传输时间,文件越大传输时间就越长,为了减少传输时间,我们一般把数据压缩后在传给客户端。 + +apache支持两种压缩:deflate、gzip + +#### mod_gzip 和mod_deflate比较 + +首先一个区别是安装它们的Apache Web服务器版本的差异。Apache 1.x系列没有内建网页压缩技术,所以才去用额外的第三方mod_gzip 模块来执行压缩。而Apache 2.x官方在开发的时候,就把网页压缩考虑进去,内建了mod_deflate 这个模块,用以取代mod_gzip。虽然两者都是使用的Gzip压缩算法,它们的运作原理是类似的。 + +第二个区别是压缩质量。mod_deflate 压缩速度略快而mod_gzip 的压缩比略高。一般默认情况下,mod_gzip 会比mod_deflate 多出4%~6%的压缩量。 + +那么,为什么使用mod_deflate?第三个区别是对服务器资源的占用。 一般来说mod_gzip 对服务器CPU的占用要高一些。mod_deflate 是专门为确保服务器的性能而使用的一个压缩模块,mod_deflate 需要较少的资源来压缩文件。这意味着在高流量的服务器,使用mod_deflate 可能会比mod_gzip 加载速度更快。 + +#### **应用场景:数据压缩传输** + +#### **优化目的:提升用户访问页面加载速度,节约带宽** + +## 二、数据压缩实现 + +1)开启模块 + +LoadModule deflate_module modules/mod_deflate.so + +2)调用模块 + + + +DeflateCompressionLevel 4 + +AddOutputFilterByType DEFLATE text/html text/plain text/xml application/x-javascript application/x-httpd-php + +AddOutputFilter DEFLATE js css + +BrowserMatch \bMSIE\s[1-6] dont-vary + +SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png)$ no-gzip dont-vary + +SetEnvIfNoCase Request_URI .(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary + +SetEnvIfNoCase Request_URI .(?:pdf|doc)$ no-gzip dont-vary + +``` + +# 压缩等级 4 1-9,数字越大压缩的越好,也越占用CPU时间 +DeflateCompressionLevel 4 +# 压缩类型 html、xml、php、css、js +AddOutputFilterByType DEFLATE text/html text/plain text/xml application/x-javascript application/x-httpd-php +AddOutputFilter DEFLATE js css +#浏览器匹配 IE1-6的不压缩 +BrowserMatch \bMSIE\s[1-6] dont-vary +#设置不压缩的文件,注意图片本身就是压缩过的,所以不需要再压缩 +SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png)$ no-gzip dont-vary +SetEnvIfNoCase Request_URI .(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary +SetEnvIfNoCase Request_URI .(?:pdf|doc)$ no-gzip dont-vary + +``` + +## 三、测试 + +1)生成HTML数据页面 + +``` +for i in `seq 1 20`;do + cat /etc/passwd >> /usr/local/apache/htdocs/test_deflate.html +done +``` + +2)未启用压缩前通过浏览器访问该页面,通过开发者工具查看页面大小 + +![deflate_01.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1603015649123.png) + +3)启用压缩再次通过浏览器访问该页面,通过开发者工具查看页面大小,如果明显变小了则说明压缩成功。也可以从响应头中看出多了压缩字段。 + +![deflate_02.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1603015669906.png) + +![deflate_response_headers03.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1603015686310.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\347\253\231\347\202\271\344\274\230\345\214\226-\346\250\241\345\235\227\344\274\230\345\214\226.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\347\253\231\347\202\271\344\274\230\345\214\226-\346\250\241\345\235\227\344\274\230\345\214\226.md" new file mode 100644 index 0000000..4ec2b6d --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/Apache\347\253\231\347\202\271\344\274\230\345\214\226-\346\250\241\345\235\227\344\274\230\345\214\226.md" @@ -0,0 +1,331 @@ +## 一、模块介绍 + +apache是一个补丁服务器,在安装apache的时候就为用户提供了很多常用模块供用户使用。但是,在生产环境中,很多模块是没有用的,如果apache开启的时候加载了这些模块,就会造成资源的浪费,所以我要告诉大家的是:找到你业务中需要的模块,将不需要的模块全部注释掉,不要让apache在加载这些模块,节省运行apache服务器资源。 + +那么如何找到你哪些是你需要的模块呢?请参考apache在线手册,对服务器中你使用的功能做分解,然后在对模块进行区分,筛选后做出模块使用列表,不用的就注释掉。 + +## 二、部分模块介绍 + +**core** + +Apache HTTP服务器核心提供的功能,始终有效。 + +**mpm_common** + +收集了被多个多路处理模块(MPM)实现的公共指令。 + +**beos** + +专门针对BeOS优化过的多路处理模块(MPM) + +**event** + +一个标准workerMPM的实验性变种。 + +**mpm_netware** + +Novell NetWare优化过的线程化的多路处理模块(MPM) + +**mpmt_os2** + +专门针对OS/2优化过的混合多进程多线程多路处理模块(MPM) + +**prefork** + +一个非线程型的、预派生的MPM + +**mpm_winnt** + +用于Windows NT/2000/XP/2003 系列的MPM + +**worker** + +线程型的MPM,实现了一个混合的多线程多处理MPM,允许一个子进程中包含多个线程。 + +**mod_actions** + +基于媒体类型或请求方法,为执行CGI脚本而提供 + +**mod_alias** + +提供从文件系统的不同部分到文档树的映射和URL重定向 + +**mod_asis** + +发送自己包含HTTP头内容的文件 + +**mod_auth_basic** + +使用基本认证 + +**mod_auth_digest** + +使用MD5摘要认证(更安全,但是只有最新的浏览器才支持) + +**mod_authn_alias** + +基于实际认证支持者创建扩展的认证支持者,并为它起一个别名以便于引用 + +**mod_authn_anon** + +提供匿名用户认证支持 + +**mod_authn_dbd** + +使用SQL数据库为认证提供支持 + +**mod_authn_dbm** + +使用DBM数据库为认证提供支持 + +**mod_authn_default** + +在未正确配置认证模块的情况下简单拒绝一切认证信息 + +**mod_authn_file** + +使用纯文本文件为认证提供支持 + +**mod_authnz_ldap** + +允许使用一个LDAP目录存储用户名和密码数据库来执行基本认证和授权 + +**mod_authz_dbm** + +使用DBM数据库文件为组提供授权支持 + +**mod_authz_default** + +在未正确配置授权支持模块的情况下简单拒绝一切授权请求 + +**mod_authz_groupfile** + +使用纯文本文件为组提供授权支持 + +**mod_authz_host** + +供基于主机名、IP地址、请求特征的访问控制 + +**mod_authz_owner** + +基于文件的所有者进行授权 + +**mod_authz_user** + +基于每个用户提供授权支持 + +**mod_autoindex** + +自动对目录中的内容生成列表,类似于"ls"或"dir"命令 + +**mod_cache** + +基于URI键的内容动态缓冲(内存或磁盘) + +**mod_cern_meta** + +允许Apache使用CERN httpd元文件,从而可以在发送文件时对头进行修改 + +**mod_cgi** + +在非线程型MPM(prefork)上提供对CGI脚本执行的支持 + +**mod_cgid** + +在线程型MPM(worker)上用一个外部CGI守护进程执行CGI脚本 + +**mod_charset_lite** + +允许对页面进行字符集转换 + +**mod_dav** + +允许Apache提供DAV协议支持 + +**mod_dav_fs** + +为mod_dav访问服务器上的文件系统提供支持 + +**mod_dav_lock** + +为mod_dav锁定服务器上的文件提供支持 + +**mod_dbd** + +管理SQL数据库连接,为需要数据库功能的模块提供支持 + +**mod_deflate** + +压缩发送给客户端的内容 + +**mod_dir** + +指定目录索引文件以及为目录提供"尾斜杠"重定向 + +**mod_disk_cache** + +基于磁盘的缓冲管理器 + +**mod_dumpio** + +将所有I/O操作转储到错误日志中 + +**mod_echo** + +一个很简单的协议演示模块 + +**mod_env** + +允许Apache修改或清除传送到CGI脚本和SSI页面的环境变量 + +**mod_example** + +一个很简单的Apache模块API演示模块 + +**mod_expires** + +允许通过配置文件控制HTTP的"Expires:"和"Cache-Control:"头内容 + +**mod_ext_filter** + +使用外部程序作为过滤器 + +**mod_file_cache** + +提供文件描述符缓存支持,从而提高Apache性能 + +**mod_filter** + +根据上下文实际情况对输出过滤器进行动态配置 + +**mod_headers** + +允许通过配置文件控制任意的HTTP请求和应答头信息 + +**mod_ident** + +实现RFC1413规定的ident查找 + +**mod_imagemap** + +处理服务器端图像映射 + +**mod_include** + +实现服务端包含文档(SSI)处理 + +**mod_info** + +生成Apache配置情况的Web页面 + +**mod_isapi** + +仅限于在Windows平台上实现ISAPI扩展 + +**mod_ldap** + +为其它LDAP模块提供LDAP连接池和结果缓冲服务 + +**mod_log_config** + +允许记录日志和定制日志文件格式 + +**mod_log_forensic** + +实现"对比日志",即在请求被处理之前和处理完成之后进行两次记录 + +**mod_logio** + +对每个请求的输入/输出字节数以及HTTP头进行日志记录 + +**mod_mem_cache** + +基于内存的缓冲管理器 + +**mod_mime** + +根据文件扩展名决定应答的行为(处理器/过滤器)和内容(MIME类型/语言/字符集/编码) + +**mod_mime_magic** + +通过读取部分文件内容自动猜测文件的MIME类型 + +**mod_negotiation** + +提供内容协商支持 + +**mod_nw_ssl** + +仅限于在NetWare平台上实现SSL加密支持 + +**mod_proxy** + +提供HTTP/1.1的代理/网关功能支持 + +**mod_proxy_ajp** + +mod_proxy的扩展,提供Apache JServ Protocol支持 + +**mod_proxy_balancer** + +mod_proxy的扩展,提供负载平衡支持 + +**mod_proxy_connect** + +mod_proxy的扩展,提供对处理HTTP CONNECT方法的支持 + +**mod_proxy_ftp** + +mod_proxy的FTP支持模块 + +**mod_proxy_http** + +mod_proxy的HTTP支持模块 + +**mod_rewrite** + +一个基于一定规则的实时重写URL请求的引擎 + +**mod_setenvif** + +根据客户端请求头字段设置环境变量 + +**mod_so** + +允许运行时加载DSO模块 + +**mod_speling** + +自动纠正URL中的拼写错误 + +**mod_ssl** + +使用安全套接字层(SSL)和传输层安全(TLS)协议实现高强度加密传输 + +**mod_status** + +生成描述服务器状态的Web页面 + +**mod_suexec** + +使用与调用web服务器的用户不同的用户身份来运行CGI和SSI程序 + +**mod_unique_id** + +为每个请求生成唯一的标识以便跟踪 + +**mod_userdir** + +允许用户从自己的主目录中提供页面(使用"/~username") + +**mod_usertrack** + +使用Session跟踪用户(会发送很多Cookie),以记录用户的点击流 + +**mod_version** + +提供基于版本的配置段支持 + +**mod_vhost_alias** + +提供大批量虚拟主机的动态配置支持 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/lamp\351\203\250\347\275\262-WordPress\347\253\231\347\202\271\344\270\212\347\272\277.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/lamp\351\203\250\347\275\262-WordPress\347\253\231\347\202\271\344\270\212\347\272\277.md" new file mode 100644 index 0000000..8266c27 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/lamp\351\203\250\347\275\262-WordPress\347\253\231\347\202\271\344\270\212\347\272\277.md" @@ -0,0 +1,100 @@ +## 一、配置虚拟主机 + +#### 1)获得网站代码 + +[root@zutuanxue ~]# wget https://wordpress.org/latest.tar.gz + +#### 2)将源文件拷贝到APACHE的htdocs目录 + +[root@zutuanxue ~]# mkdir /usr/local/apache/htdocs/wordpress/ + +[root@zutuanxue ~]# tar xf latest.tar.gz -C /opt + +[root@zutuanxue ~]# mv /opt/wordpress/* /usr/local/apache/htdocs/wordpress/ + +[root@zutuanxue ~]# chown www.www /usr/local/apache/htdocs/wordpress -R + +#### 3)配置虚拟主机 + +[root@zutuanxue htdocs]# cat /usr/local/apache/conf/extra/httpd-vhosts.conf + +``` + + DocumentRoot "/usr/local/apache/htdocs/wordpress" + + + + + Options Indexes FollowSymLinks + AllowOverride None + Require all granted + + + + + DirectoryIndex phpinfo.php index.php index.html + + + + + # Unix sockets require 2.4.7 or later + SetHandler "proxy:unix:/usr/local/php/etc/php-fpm.socket|fcgi://localhost/" + +``` + +#### 4)重启生效 + +[root@zutuanxue ~]# killall httpd + +[root@zutuanxue ~]# /usr/local/apache/bin/apachectl + +## 二、安装wordpress + +#### 1)登陆数据库 + +[root@zutuanxue ~]# mysql -u root -p123 + +#### 2)新建数据库 wordpress + +mysql> create database wordpress; + +Query OK, 1 row affected (0.01 sec) + +#### 3)wordpress安装 + +打开浏览器输入[http://IP。我的IP地址是192.168.11.251 ,所以在地址栏中输入的是http://192.168.11.251![](/assets/wordpress_install_01.png)选择网站语言,我选择的简体中文,然后点继续](http://IP,我的IP地址是192.168.11.251,所以在地址栏中输入的是http://192.168.11.251! +![wordpress_install_01.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1603014837850.png) +选择网站语言,我选择的简体中文,然后点继续) + +![wordpress_install_02.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1603014857570.png) + +欢迎信息,同时告诉你准备连接数据库的相关信息和它的安装操作,直接点现在就开始,继续吧。 + +![wordpress_install_03.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1603014869861.png) + +输入数据库的相关信息,点提交。如果这个过不去,说明你数据库连接有问题。请检查你使用上述信息是否手动能连接到数据库 + +``` +检查方法 +mysql -u root -p123 -h 127.0.0.1 +``` + +![wordpress_install_05.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1603014893231.png) +数据库信息验证正确后,就要开始安装了。 + +![wordpress_install_06.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1603014905185.png) +安装前要求你设置wordpress的后台管理账户和密码,注意,这可是网站后台管理员啊,密码一定不能像我这么随意。输入完毕后点安装就开始安装了。 + +![wordpress_install_07.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1603014921496.png) +看到这个图片,恭喜你安装成功了。点登陆,去登陆后台设置网站吧。 + +![wordpress_install_08.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1603014933461.png) +登陆窗口,输入你的网站后台的管理员账号密码。 + +![wordpress_install_09.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1603014950019.png) +登陆成功,我们写一篇文章纪念一下吧。 + +根据步骤发布一篇文章吧! + +![wordpress_install_11.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1603014975124.png) +再一次在浏览器中输入HTTP://IP 你就能看到我们的文章了。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/\351\203\250\347\275\262Apache\346\234\215\345\212\241\345\231\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/\351\203\250\347\275\262Apache\346\234\215\345\212\241\345\231\250.md" new file mode 100644 index 0000000..f1aa1ab --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/\351\203\250\347\275\262Apache\346\234\215\345\212\241\345\231\250.md" @@ -0,0 +1,200 @@ +## 安装步骤 + +- 安装apr +- 安装apr-util +- 安装apr-iconv +- 安装apache +- 启动apache +- 测试apache +- MPM + +## 一、安装依赖 + +安装依赖 + +[root@zutuanxue ~]# yum install -y pcre-devel libxml2 expat-devel + +## 二、 apr介绍及安装 + +APR(Apache portable Run-time libraries,Apache可移植运行库)的目的如其名称一样,主要为上层的应用程序提供一个可以跨越多操作系统平台使用的底层支持接口库。在早期 的Apache版本中,应用程序本身必须能够处理各种具体操作系统平台的细节,并针对不同的平台调用不同的处理函数。 + +[root@zutuanxue ~]# wget https://www.apache.org/dist/apr/apr-1.7.0.tar.bz2 + +[root@zutuanxue ~]# tar xf apr-1.7.0.tar.bz2 + +[root@zutuanxue ~]# cd apr-1.7.0 + +[root@zutuanxue apr-1.7.0]# ./configure --prefix=/usr/local/apr + +[root@zutuanxue apr-1.7.0]# make + +[root@zutuanxue apr-1.7.0]# make install + +## 三、APR-util介绍及安装 + +apr-util该目录中也是包含了一些常用的开发组件。这些组件与apr目录下的相比,它们与apache的关系更加密切一些。比如存储段和存储段组,加密等等。 + +[root@zutuanxue ~]# wget https://www.apache.org/dist/apr/apr-util-1.6.1.tar.bz2 + +[root@zutuanxue ~]# tar xf apr-util-1.6.1.tar.bz2 + +[root@zutuanxue ~]# cd apr-util-1.6.1 + +[root@zutuanxue apr-util-1.6.1]# yum install -y expat-devel + +[root@zutuanxue apr-util-1.6.1]# ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr/ + +[root@zutuanxue apr-util-1.6.1]# make + +[root@zutuanxue apr-util-1.6.1]# make install + +## 四、apr-iconv介绍及安装 + +apr-iconv包中的文件主要用于实现iconv编码。目前的大部分编码转换过程都是与本地编码相关的。在进行转换之前必须能够正确地设置本地编码。因此假如两个非本地编码A和B需要转换,则转换过程大致为A->Local以及Local->B或者B->Local以及Local->A。 + +[root@zutuanxue ~]# wget https://www.apache.org/dist/apr/apr-iconv-1.2.2.tar.bz2 + +[root@zutuanxue ~]# tar xf apr-iconv-1.2.2.tar.bz2 + +[root@zutuanxue ~]# cd apr-iconv-1.2.2 + +[root@zutuanxue apr-iconv-1.2.2]# ./configure --prefix=/usr/local/apr-iconv --with-apr=/usr/local/apr + +[root@zutuanxue apr-iconv-1.2.2]# make + +[root@zutuanxue apr-iconv-1.2.2]# make install + +## 五、apache安装 + +[root@zutuanxue ~]# wget https://www.apache.org/dist/httpd/httpd-2.4.39.tar.gz + +[root@zutuanxue ~]# tar xf httpd-2.4.39.tar.gz + +[root@zutuanxue ~]# cd httpd-2.4.39 + +[root@zutuanxue httpd-2.4.39]# ./configure --prefix=/usr/local/apache --enable-mpms-shared=all --with-mpm=event --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr-util --enable-so --enable-remoteip --enable-proxy --enable-proxy-fcgi --enable-proxy-uwsgi --enable-deflate=shared --enable-expires=shared --enable-rewrite=shared --enable-cache --enable-file-cache --enable-mem-cache --enable-disk-cache --enable-static-support --enable-static-ab --disable-userdir --enable-nonportable-atomics --disable-ipv6 --with-sendfile + +``` +--prefix=/usr/local/apache 指定安装目录 +--enable-mpms-shared=all --with-mpm=event 开启动态MPM切换 +--with-apr=/usr/local/apr --with-apr-util=/usr/local/apr-util 指定依赖包apr apr-util安装路径 +--enable-so 打开 so 模块,so 模块是用来提 dso 支持的 apache 核心模块 +--enable-remoteip 支持基于客户端IP做访问控制 +--enable-proxy --enable-proxy-fcgi --enable-proxy-uwsgi 启用代理支持PHP Python网站 +--enable-deflate=shared 开启压缩 +--enable-expires=shared 开启客户端缓存 +--enable-rewrite=shared 开启URL重写 +--enable-cache --enable-file-cache --enable-mem-cache --enable-disk-cache 开启服务器缓存 +--enable-static-support 支持静态连接 +--enable-static-ab 使用静态连接编译 ab - apache http 服务器性能测试工具 +--disable-userdir 禁用用户主目录提供页面访问 +--enable-nonportable-atomics 对新式CPU支持,支持原子的比较交换(compare-and -swap, CAS)操作指令 +--disable-ipv6 禁用IPV6 +--with-sendfile 开启sendfile 0复制机制 +``` + +[root@zutuanxue httpd-2.4.39]# make + +[root@zutuanxue httpd-2.4.39]# make install + +\##相关目录 + +[root@zutuanxue apache]# tree -L 1 + +. + +├── bin 二进制命令 + +├── build + +├── cgi-bin cgi脚本目录 + +├── conf 配置文件目录 + +├── error 错误记录 + +├── htdocs 默认网站根目录 + +├── icons 小图标 + +├── include 一些C语言文件 + +├── logs 日志目录 + +├── man 帮助手册 + +├── manual 在线手册 + +└── modules 存放apache运行需要的模块 + +## 六、apache启动 + +[root@zutuanxue ~]# /usr/local/apache/bin/httpd + +## 七、apache状态测试 + +[root@zutuanxue ~]# elinks [http://192.168.11.251](http://192.168.11.251/) -dump + +``` + It works! +``` + +## 八、MPM多处理模块 + +Apache HTTP 服务器被设计为一个功能强大,并且灵活的 web 服务器, 可以在很多平台与环境中工作。不同平台和不同的环境往往需要不同 的特性,或可能以不同的方式实现相同的特性最有效率。Apache httpd 通过模块化的设计来适应各种环境。这种设计允许网站管理员通过在 编译时或运行时,选择哪些模块将会加载在服务器中,来选择服务器特性。 + +Apache HTTP 服务器 2.0 扩展此模块化设计到最基本的 web 服务器功能。 它提供了可以选择的多处理模块(MPM),用来绑定到网络端口上,接受请求, 以及调度子进程处理请求。 + +扩展到这一级别的服务器模块化设计,带来两个重要的好处: + +Apache httpd 能更优雅,更高效率的支持不同的平台。尤其是 Apache httpd 的 Windows 版本现在更有效率了,因为 mpm_winnt 能使用原生网络特性取代在 Apache httpd 1.3 中使用的 POSIX 层。它也可以扩展到其它平台 来使用专用的 MPM。 + +Apache httpd 能更好的为有特殊要求的站点定制。例如,要求 更高伸缩性的站点可以选择使用线程的 MPM,即 worker 或 event; 需要可靠性或者与旧软件兼容的站点可以使用 prefork。 + +在用户看来,MPM 很像其它 Apache httpd 模块。主要是区别是,在任何时间, 必须有一个,而且只有一个 MPM 加载到服务器中。可用的 MPM 列表位于 模块索引页面。 + +**默认MPM** + +下表列出了不同系统的默认 MPM。如果你不在编译时选择,那么它就是你将要使用的 MPM。 + +Netware mpm_netware + +OS/2 mpmt_os2 + +Unix prefork,worker 或 event,取决于平台特性 + +Windows mpm_winnt + +**构建 MPM 为静态模块** + +在全部平台中,MPM 都可以构建为静态模块。在构建时选择一种 MPM,链接到服务器中。如果要改变 MPM,必须重新构建。 + +为了使用指定的 MPM,请在执行 configure 脚本 时,使用参数 --with-mpm=NAME。NAME 是指定的 MPM 名称。 + +编译完成后,可以使用 ./httpd -l 来确定选择的 MPM。 此命令会列出编译到服务器程序中的所有模块,包括 MPM。 + +**构建 MPM 为动态模块** + +在 Unix 或类似平台中,MPM 可以构建为动态模块,与其它动态模块一样在运行时加载。 构建 MPM 为动态模块允许通过修改 LoadModule 指令内容来改变 MPM,而不用重新构建服务器程序。 + +在执行 configure 脚本时,使用 --enable-mpms-shared 选项可以启用此特性。 当给出的参数为 all 时,所有此平台支持的 MPM 模块都会被安装。还可以在参数中给出模块列表。 + +默认 MPM,可以自动选择或者在执行 configure 脚本时通过 --with-mpm 选项来指定,然后出现在生成的服务器配置文件中。 编辑 LoadModule 指令内容可以选择不同的 MPM。 + +**–enable-mpms-shared=all --with-mpm=event** + +**Apache三种MPM介绍** + +**Prefork MPM **: 这个多路处理模块(MPM)实现了一个非线程型的、预派生的web服务器,它的工作方式类似于Apache 1.3。它适合于没有线程安全库,需要避免线程兼容性问题的系统。它是要求将每个请求相互独立的情况下最好的MPM,这样若一个请求出现问题就不会影响到其他请求。 + +这个MPM具有很强的自我调节能力,只需要很少的配置指令调整。最重要的是将MaxClients设置为一个足够大的数值以处理潜在的请求高峰,同时又不能太大,以致需要使用的内存超出物理内存的大小。 + +**Worker MPM** : 此多路处理模块(MPM)使网络服务器支持混合的多线程多进程。由于使用线程来处理请求,所以可以处理海量请求,而系统资源的开销小于基于进程的MPM。但是,它也使用了多进程,每个进程又有多个线程,以获得基于进程的MPM的稳定性。 + +每个进程可以拥有的线程数量是固定的。服务器会根据负载情况增加或减少进程数量。一个单独的控制进程(父进程)负责子进程的建立。每个子进程可以建立ThreadsPerChild数量的服务线程和一个监听线程,该监听线程监听接入请求并将其传递给服务线程处理和应答。 + +不管是Worker模式或是Prefork 模式,Apache总是试图保持一些备用的(spare)或者是空闲的子进程(空闲的服务线程池)用于迎接即将到来的请求。这样客户端就不需要在得到服务前等候子进程的产生。 + +**Event MPM**:以上两种稳定的MPM方式在非常繁忙的服务器应用下都有些不足。尽管HTTP的Keepalive方式能减少TCP连接数量和网络负载,但是 Keepalive需要和服务进程或者线程绑定,这就导致一个繁忙的服务器会耗光所有的线程。 Event MPM是解决这个问题的一种新模型,它把服务进程从连接中分离出来。在服务器处理速度很快,同时具有非常高的点击率时,可用的线程数量就是关键的资源限制,此时Event MPM方式是最有效的。一个以Worker MPM方式工作的繁忙服务器能够承受每秒好几万次的访问量(例如在大型新闻服务站点的高峰时),而Event MPM可以用来处理更高负载。在event工作模式中,会有一些专门的线程用来管理这些keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务器的线程,执行完毕后,又允许它释放。这增强了在高并发场景下的请求处理 + +![apachempm.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1603010761940.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/\351\203\250\347\275\262lamp-MySQL\345\256\211\350\243\205.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/\351\203\250\347\275\262lamp-MySQL\345\256\211\350\243\205.md" new file mode 100644 index 0000000..3d03773 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/\351\203\250\347\275\262lamp-MySQL\345\256\211\350\243\205.md" @@ -0,0 +1,138 @@ +## 一、MySQL介绍 + +瑞典AB公司开发,后来卖给了oracle + +一个关系型数据库 + +中小型数据库,表过大会出现IO性能瓶颈,树明建议单表600万条记录或2G以上就分表 + +分为企业版和社区版,目前两大版本mysql5.7 和mysql 8.0 + +## 二、MySQL安装 + +a、安装前依赖解决 + +1)cmake命令 2.8以上 + +https://cmake.org/download/ + +boost Boost库是一个可移植、提供源代码的C库,作为标准库的后备,是C标准化进程的开发引擎之一 + +https://www.boost.org/ + +mysql获得 + +https://dev.mysql.com/downloads/mysql/ + +b、MySQL 安装 + +[root@zutuanxue ~]# yum -y install ncurses-devel gcc-* bzip2-* bison + +1)cmake 安装 + +``` +[root@zutuanxue ~]# tar xf cmake-3.6.0-rc1.tar +[root@zutuanxue cmake-3.6.0-rc1]# cd cmake-3.6.0-rc1 +[root@zutuanxue cmake-3.6.0-rc1]# ./configure +[root@zutuanxue cmake-3.6.0-rc1]# make +[root@zutuanxue cmake-3.6.0-rc1]# make install +``` + +2)boost 安装 + +``` +[root@zutuanxue ~]# tar xf boost\_1\_59\_0.tar.bz2 +[root@zutuanxue ~]# mv boost\_1\_59\_0 /usr/local/boost +``` + +3)mysql安装 + +``` +[root@zutuanxue ~]# useradd -s /sbin/nologin -r mysql +[root@zutuanxue ~]# mkdir -pv /usr/local/mysql/data +[root@zutuanxue ~]# tar xf mysql...tar.xx + +[root@zutuanxue mysql]# cmake . -DCMAKE\_INSTALL\_PREFIX=/usr/local/mysql -DMYSQL\_DATADIR=/usr/local/mysql/data/ -DMYSQL\_UNIX\_ADDR=/usr/local/mysql/mysql.sock -DWITH\_INNOBASE\_STORAGE\_ENGINE=1 -DWITH\_MYISAM\_STORAGE\_ENGINE=1 -DENABLED\_LOCAL\_INFILE=1 -DEXTRA\_CHARSETS=all -DDEFAULT\_CHARSET=utf8 -DDEFAULT\_COLLATION=utf8\_general\_ci -DMYSQL\_USER=mysql -DWITH\_DEBUG=0 -DWITH\_EMBEDDED\_SERVER=1 -DDOWNLOAD\_BOOST=1 -DENABLE\_DOWNLOADS=1 -DWITH\_BOOST=/usr/local/boost + + +[root@zutuanxue mysql]# cmake . \ +-DCMAKE_INSTALL_PREFIX=/usr/local/mysql 指定安装路径 +-DMYSQL_DATADIR=/usr/local/mysql/data/ 指定数据目录 +-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock 指定sock文件路径 +-DWITH_INNOBASE_STORAGE_ENGINE=1 安装Innodb存储引擎 +-DWITH_MYISAM_STORAGE_ENGINE=1 安装myisam存储引擎 +-DENABLED_LOCAL_INFILE=1 允许使用Load data命令从本地导入数据 +-DEXTRA_CHARSETS=all -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci 安装所有字符集、默认字符集utf-8 、校验字符 +-DMYSQL_USER=mysql mysql用户名 +-DWITH_DEBUG=0 关闭debug +-DWITH_EMBEDDED_SERVER=1 生成一个libmysqld.a(.so)的库,这个库同时集成了mysql服务与客户端API +-DDOWNLOAD_BOOST=1 -DENABLE_DOWNLOADS=1 -DWITH_BOOST=/usr/local/boost 允许boost 允许下载boost库文件。 + + +[root@zutuanxue mysql]# make + +[root@zutuanxue mysql]# make install +``` + +4)安装后操作 + +``` +[root@zutuanxue ~]# cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysql +[root@zutuanxue ~]# chmod 755 /etc/init.d/mysql +[root@zutuanxue ~]# chown mysql.mysql /usr/local/mysql/ -R +[root@zutuanxue ~]# ln -sf /usr/local/mysql/bin/\* /usr/bin/ +[root@zutuanxue ~]# ln -sf /usr/local/mysql/lib/\* /usr/lib/ +[root@zutuanxue ~]# ln -sf /usr/local/mysql/libexec/\* /usr/local/libexec +[root@zutuanxue ~]# ln -sf /usr/local/mysql/share/man/man1/\* /usr/share/man/man1 +[root@zutuanxue ~]# ln -sf /usr/local/mysql/share/man/man8/\* /usr/share/man/man8 +``` + +修改配置文件 确保路径正确 + +``` +egrep -v "^#|^$" /etc/my.cnf + +[mysqld] + +datadir=/usr/local/mysql/data + +socket=/usr/local/mysql/mysql.sock + +symbolic-links=0 + +[mysqld\_safe] + +log-error=/var/log/mysql.log + +pid-file=/var/run/mysql.pid + +!includedir /etc/my.cnf.d +``` + +5)初始化数据库 + +``` +[root@zutuanxue ~]# /usr/local/mysql/bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql/ --datadir=/usr/local/mysql/data/ +``` + +临时密码 + +root@localhost: T6upu>pr+8,Z + +## 三、启动mysql + +``` +[root@zutuanxue ~]# /etc/init.d/mysql start +``` + +1. 密码修改 + +``` +[root@zutuanxue ~]# mysql_secure_installation +``` + +## 四、MySQL测试 + +mysql -u root -p’password’ + +mysql> \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/\351\203\250\347\275\262lamp-php\345\256\211\350\243\205\346\214\207\345\215\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/\351\203\250\347\275\262lamp-php\345\256\211\350\243\205\346\214\207\345\215\227.md" new file mode 100644 index 0000000..41547b9 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/\351\203\250\347\275\262lamp-php\345\256\211\350\243\205\346\214\207\345\215\227.md" @@ -0,0 +1,391 @@ + + +## 一、PHP介绍 + +PHP(外文名:PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域。PHP 独特的语法混合了C、Java、Perl以及PHP自创的语法。它可以比CGI或者Perl更快速地执行动态网页。用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML(标准通用标记语言下的一个应用)文档中去执行,执行效率比完全生成HTML标记的CGI要高许多;PHP还可以执行编译后代码,编译可以达到加密和优化代码运行,使代码运行更快。 + +优点:灵活,上手快,易修改,发布快捷,环境好部署 + +PHP主要用在服务器端上用于Web开发,约占网站总数的80%。 Facebook最初使用的就是PHP,PHP在WordPress内容管理系统中扮演的角色让它很受欢迎。 + +官网 + +[https://www.php.net](https://www.php.net/) + +\#软件包获取 + +https://www.php.net/distributions/php-7.3.4.tar.bz2 + +## 二、PHP安装 + +1)依赖包安装 + +[root@zutuanxue ~]# yum install gcc-c++ libxml2 libxml2-devel openssl openssl-devel bzip2 bzip2-devel libcurl libcurl-devel libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel gmp gmp-devel libmcrypt libmcrypt-devel readline readline-devel libxslt libxslt-devel gd net-snmp-* + +libzip版本低问题处理 + +libzip要求1.1及以上,系统提供1.0需要升级 + +官方网站: https://libzip.org/ + +[root@zutuanxue ~]# wget https://libzip.org/download/libzip-1.5.2.tar.gz + +[root@zutuanxue ~]# tar xf [libzip-1.5.2.tar.gz](https://libzip.org/download/libzip-1.5.2.tar.gz) + +[root@zutuanxue ~]# cd [libzip-1.5.2](https://libzip.org/download/libzip-1.5.2.tar.gz) + +[root@zutuanxue libzip-1.5.2]# mkdir build + +[root@zutuanxue build]# cd build + +[root@zutuanxue build]#cmake … + +[root@zutuanxue build]#make + +[root@zutuanxue build]#make install + +2)配置 + +[root@zutuanxue ~]# tar xf php-7.3.4.tar.bz2 + +[root@zutuanxue php-7.3.4]# ./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc --with-mysqli=mysqlnd --enable-pdo --with-pdo-mysql=mysqlnd --with-iconv-dir=/usr/local/ --enable-fpm --with-fpm-user=www --with-fpm-group=www --with-pcre-regex --with-zlib --with-bz2 --enable-calendar --disable-phar --with-curl --enable-dba --with-libxml-dir --enable-ftp --with-gd --with-jpeg-dir --with-png-dir --with-zlib-dir --with-freetype-dir --enable-gd-jis-conv --with-mhash --enable-mbstring --enable-opcache=yes --enable-pcntl --enable-xml --disable-rpath --enable-shmop --enable-sockets --enable-zip --enable-bcmath --with-snmp --disable-ipv6 --with-gettext --disable-rpath --disable-debug --enable-embedded-mysqli --with-mysql-sock=/usr/local/mysql/ + +``` +配置参数说明 +---prefix=/usr/local/php 安装路径 +--with-config-file-path=/usr/local/php/etc 配置文件路径 +--with-mysqli=mysqlnd --enable-embedded-mysqli --with-mysql-sock=/usr/local/mysql/ mysql支持及客户端设置 +--enable-pdo --with-pdo-mysql=mysqlnd 开启php pdo,PDO一是PHP数据对象(PHP Data Object)的缩写 +--with-iconv-dir=/usr/local/ 指定转码工具,各种字符集间的转换 +--enable-fpm --with-fpm-user=www --with-fpm-group=www 支持php-fpm,允许以服务的方式启动PHP +--with-pcre-regex 支持pcre正则表达式 +--with-zlib --with-bz2 --with-zlib-dir --enable-zip 支持压缩 +--enable-calendar 支持日历 +--disable-phar PHAR (“Php ARchive”) 是PHP里类似于JAR的一种打包文件。如果你使用的是 PHP 5.3 或更高版本,那么Phar后缀文件是默认开启支持的. +--with-curl 支持curl +--enable-dba 开启dba函数支持 +--with-libxml-dir 支持xml文件库 对xml读取和查询 +--enable-ftp 支持ftp +--with-gd --with-jpeg-dir --with-png-dir 支持图片 +--with-freetype-dir 支持字库 +--enable-gd-jis-conv 支持gd库 +--with-mhash --enable-mbstring 支持加密 +--enable-opcache=yes 开启opcache +--enable-pcntl 开启PHP进程控制支持 默认是关闭的 +--enable-xml 允许xml文件 +--disable-rpath 关闭额外的运行库文件 +--enable-shmop 开启Shmop 是一个易用的允许PHP读取、写入、创建和删除Unix共享内存段的函数集 +--enable-sockets 打开 sockets 支持 +--enable-bcmath 增加bcmath扩展的支持,这是一个支持大整数计算的扩展。 +--with-snmp 支持snmp +--disable-ipv6 关闭IPV6支持 +--with-gettext 打开gnu 的gettext 支持,编码库用到 +--disable-debug 关闭调试模式 +``` + +3)编译 + +[root@zutuanxue php-7.3.4]# make + +4)安装 + +[root@zutuanxue php-7.3.4]# make install + +5)拷贝一个配置文件 + +[root@zutuanxue php-7.3.4]# cp /usr/src/php-7.3.4/php.ini-production /usr/local/php/etc/php.ini + +### + +## 三、PHP配置 + +#### **关于PHP工作方式** + +- #### 作为模块运行 + +- #### 独立服务运行 + +1)作为apache模块运行 + +\#if bind to apache + +–with-apxs2=/usr/local/apache2/bin/apxs + +AddType application/x-httpd-php .php + +\#if no mysql + +./configure --with-mysql=mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd + +2)作为服务运行 + +思考问题 apache如何将PHP请求交给PHP呢 PHP是一门语言 + +``` + 思路 CGI fastcgi +``` + +CGI 公共网关接口 (COMMON GATEWAY INTERFACE),是一个协议 + +``` + 它的作用就是帮助服务器与语言通信. 就是apache和php进行通信,因为apache和php的语言不通,因此需要一个沟通转换的过程,而CGI就是这个 + 沟通的协议。 +``` + +FastCGI 快速通用网关接口(FastCommonGatewayInterface),是CGI的升级版,一种语言无关的协议,FastCGI是用来提高CGI程序性能的 + +缺点:传统的cgi协议在每次连接请求时,会开启一个进程进行处理,处理完毕会关闭该进程,因此下次连接,又要再次开启一个进程进行处理,因此有多少个连接就有多少个cgi进程,这也就是为什么传统的cgi会显得缓慢的原因,因此过多的进程会消耗资源和内存。而fast-cgi则是一个进程可以处理多个请求,和上面的cgi协议完全不一样,cgi是一个进程只能处理一个请求,这样就会导致大量的cgi程序,因此会给服务器带来负担。 + +php-fpm:是一个实现了FastCGI(协议)的程序 + +是php提供给http前端服务器(web serve)的fastcgi协议接口程序,允许一个进程对多个连接进行处理,而不会立即关闭这个进程,而是会接着处理下一个连接。 + +PHP-CGI:PHP-CGI是php自带的Fast-CGI管理器。 + +PHP-CGI的不足: + +php-cgi变更php.ini配置后需重启php-cgi才能让新的php-ini生效,不可以平滑重启。 + +直接杀死php-cgi进程,php就不能运行了。(PHP-FPM和Spawn-FCGI就没有这个问题,守护进程会平滑从新生成新的子进程。) + +PHP-FPM(FastCGI Process Manager:FastCGI进程管理器)是一个PHPFastCGI管理器,对于PHP 5.3.3之前的php来说,是一个补丁包 ,旨在将FastCGI进程管理整合进PHP包中。如果你使用的是PHP5.3.3之前的PHP的话,就必须将它patch到你的PHP源代码中,在编译安装PHP后才可以使用。从PHP 5.4 RC2开始,php-fpm已经转正了 + +**PHP-FPM特点** + +1. listen:The address on which to accept FastCGI requests.它支持TCP Socket和unix socket两种通讯协议。可设置listen = [::]:9000。 +2. listen.allowed_clients:List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect. 该配置项为逗号分隔的列表,如listen.allowed_clients = 127.0.0.1,172.17.0.5。 +3. pm:Choose how the process manager will control the number of child processes. 该配置项设置FPM管理进程池的方式,包括static、dynamic、ondemand三种。 +4. pm.max_requests:The number of requests each child process should execute before respawning. This can be useful to work around memory leaks in 3rd party libraries.设置每个子进程处理请求数的上限,对于处理第三方库中的内存泄漏很有用。 +5. pm.status_path:The URI to view the FPM status page. 支持状态页面监控php-fpm + +**PHP-FPM工作原理:** + +1、Web Server启动时载入FastCGI进程管理器(IIS ISAPI或Apache Module) + +2、FastCGI进程管理器自身初始化,启动多个CGI解释器进程(可见多个php-cgi)并等待来自Web Server的连接。 + +3、当客户端请求到达Web Server时,FastCGI进程管理器选择并连接到一个CGI解释器。Web server将CGI环境变量和标准输入发送到FastCGI子进程php-cgi。 + +4、FastCGI子进程完成处理后将标准输出和错误信息从同一连接返回Web Server。当FastCGI子进程关闭连接时,请求便告处理完成。FastCGI子进程接着等待并处理来自FastCGI进程管理器(运行在Web Server中)的下一个连接。 在CGI模式中,php-cgi在此便退出了。 + +在上述情况中,你可以想象CGI通常有多慢。每一个Web请求PHP都必须重新解析php.ini、重新载入全部扩展并重初始化全部数据结构。使用FastCGI,所有这些都只在进程启动时发生一次。一个额外的好处是,持续数据库连接(Persistent database connection)可以工作。 + +\#php-fpm服务设置 pool + +每个pool可以监听不同的sock、tcp/ip,pool池是支持定义多个pool的。所有的网站使用同一个池,那其中一个网站发生一些故障,比如程序员写的一些程序有问题,就会把php资源耗尽,这样的结果就是其他站点的php也会502。所以有必要把每一个站点隔离开。每个pool的名字要唯一。 + +#### PHP服务配置 + +\#主配置文件 + +``` +[root@zutuanxue var]# egrep -v "^;|^$" /usr/local/php/etc/php-fpm.conf + +[global] + +pid = run/php-fpm.pid + +error_log = log/php-fpm.log + +daemonize = yes + +include = /usr/local/php/etc/php-fpm.d/\*.conf +``` + +\#子配置文件 + +``` +[root@zutuanxue var]# cp /usr/local/php/etc/php-fpm.d/www.conf.default /usr/local/php/etc/php-fpm.d/www.conf + +[root@zutuanxue var]# egrep -v "^;|^$" /usr/local/php/etc/php-fpm.d/www.conf + +[www] + +user = www + +group = www + +listen = 127.0.0.1:9000 + +listen.owner = www + +listen.group = www + +listen.mode = 0660 + +pm = dynamic + +pm.max_children = 5 + +pm.start_servers = 2 + +pm.min_spare_servers = 1 + +pm.max_spare_servers = 3 +``` + +\# 全局配置文件 + +``` +注释 +# 全局配置 +[global] +# PID、可以不填 +pid = /usr/local/php/var/run/php-fpm.pid +# 错误日志路径、可以不填 +error_log = /usr/local/php/var/log/php-fpm.log + + +# www虚拟主机配置、可写多个 +# pool命名:www +[www] +# 监听socket方式 +# 可以写成listen = 127.0.0.1:9000 +listen = /tmp/php-fcgi.sock +# 开启php-fpm的执行用户 +user = www +# 开启php-fpm的所属组 +group = www +# 监听socket listen的用户,和web服务器软件的一致 +listen.owner = nobody +# 监听socket listen的组,和web服务器软件的一致 +listen.group = nobody +# 怎样的形式启用进程 +pm = dynamic +# 最大开启子进程数 +pm.max_children = 50 +# 一开始启动多少子进程 +pm.start_servers = 20 +# 空闲时保留多少个子进程 +pm.min_spare_servers = 5 +# 最多空闲子进程 +pm.max_spare_servers = 35 +# 进程处理多少个请求之后销毁重建 +pm.max_requests = 500 +# 限定打开最大的文件数 +rlimit_files = 1024 +``` + +## 四、PHP启动 + +[root@zutuanxue ~]# cp /usr/src/php-7.3.4/sapi/fpm/php-fpm.service /etc/systemd/system/ + +[root@zutuanxue ~]# systemctl daemon-reload + +[root@zutuanxue ~]# systemctl enable php-fpm + +[root@zutuanxue ~]# systemctl start php-fpm + +## 五、相关知识补充 + +**#mysqli 说明** + +MYSQL 也叫 Original MySQL,PHP4版本的MYSQL扩展,从PHP5起已经被废弃,并别从PHP7开始已经被移除。 + +MYSQLI 叫做 “MySQL增强扩展”。 + +MYSQLND MYSQL NATIVE DIRVER 叫做MYSQL “官方驱动”或者更加直接点的叫做“原生驱动” + +PDO PHP Data Objects PHP数据对象,是PHP应用中的一个数据库抽象层规范。 + +**#opcache** + +**原理:** + +其实非常简单,opcache只是把把PHP执行后的数据(opcode)缓存到内存中从而避免重复的编译过程,能够直接使用缓冲区已编译的opcode代码从而提高速度,降低服务器负载 + +**效果: **在实际应用当中能使QPS数大致增加3倍以上 + +**注意:** + +启用opcache后,典型的问题就是由于opcache的缓存加速机制导致的代码变更后无法立即看到效果。php代码被转换成可立即执行的“机器码”后会有一定的缓存时间后才会去检查原始的PHP文件是否变动过,具体视配置项opcache.revalidate_freq设置的秒数情况而定;这样就会导致某些情况下明明更新了PHP文件中的代码,但执行后却看不到改变后的效果,这就是因为opcache检查php文件变动的间隔时间尚未结束所导致。 这个问题并不是bug,而要视具体生产环境来设定opcache.revalidate_freq值,倘若php代码很少变动,建议该值设置的大一些,可减少opcahce由于检查php文件变动而带来的额外开销,比如7200 那么在变动php文件后如何才能快速降低opcache缓存带来的这种问题呢?最简单的方法就是更新代码后重启下php-fpm(nginx fast-cgi模式)或apache(apache-handler模式)。当然还可以自己书写一个php脚本,调用opcache_reset()函数重置所有opcache缓存字节码,或者使用opcache_invalidate(PHPfileDir,true)重置指定php文件的缓存字节码。 + +opcache配置指令详解 + +``` +[Zend Opcache] + +zend_extension = /usr/local/php/lib/php/extensions/no-debug-non-zts-20090626/opcache.so + +opcache.enable=1 ;启用操作码缓存 + +opcache.enable_cli=1 ;仅针对CLI环境启用操作码缓存 + +opcache.memory_consumption=128 ;共享内存大小,单位MB + +opcache.interned_strings_buffer=8 ;存储临时字符串的内存大小,单位MB + +opcache.max_accelerated_files=4000 ;哈希表中可存储的脚本文件数量上限 + +;opcache.max_wasted_percentage=5 ;浪费内存的上限,以百分比计 + +;opcache.use_cwd=1;附加改脚本的工作目录,避免同名脚本冲突 + +opcache.validate_timestamps=1 ;每隔revalidate_freq 设定的秒数 检查脚本是否更新 + +opcache.revalidate_freq=60 ; + +;opcache.revalidate_path=0 ;如果禁用此选项,在同一个 include_path 已存在的缓存文件会被重用 + +;opcache.save_comments=1 ;禁用后将也不会加载注释内容 + +opcache.fast_shutdown=1 ;一次释放全部请求变量的内存 + +opcache.enable_file_override=0 ; 如果启用,则在调用函数file_exists(), is_file() 以及 is_readable() 的时候, 都会检查操作码缓存 + +;opcache.optimization_level=0xffffffff ;控制优化级别的二进制位掩码。 + +;opcache.inherited_hack=1 ;PHP 5.3之前做的优化 + +;opcache.dups_fix=0 ;仅作为针对 “不可重定义类”错误的一种解决方案。 + +;opcache.blacklist_filename="" ;黑名单文件为文本文件,包含了不进行预编译优化的文件名 + +;opcache.max_file_size=0 ;以字节为单位的缓存的文件大小上限 + +;opcache.consistency_checks=0 ;如果是非 0 值,OPcache 将会每隔 N 次请求检查缓存校验和 + +opcache.force_restart_timeout=180 ; 如果缓存处于非激活状态,等待多少秒之后计划重启。 + +;opcache.error_log="" ;OPcache模块的错误日志文件 + +;opcache.log_verbosity_level=1 ;OPcache模块的日志级别。致命(0)错误(1) 警告(2)信息(3)调试(4) + +;opcache.preferred_memory_model="" ;OPcache 首选的内存模块。可选值包括: mmap,shm, posix 以及 win32。 + +;opcache.protect_memory=0 ;保护共享内存,以避免执行脚本时发生非预期的写入。 仅用于内部调试。 + +;opcache.mmap_base=null ;在Windows 平台上共享内存段的基地址 +``` + +## 六、FAQ + +**问题一** + +``` +可能遇到的问题 +centos7 编译libiconv ./stdio.h:1010:1: 错误: ‘gets’未声明(不在函数内) +make报错: +./stdio.h:1010:1: 错误: ‘gets’未声明(不在函数内) +make[2]: *** [progname.o] 错误 1 +make[2]:正在离开目录 `/home/lmos/libiconv-1.14/srclib' +make[1]: *** [all] 错误 2make[1]:正在离开目录 `/home/lmos/libiconv-1.14/srclib' +make: *** [all] 错误 2 +cd srclib 目录 +sed -i -e '/gets is a security/d' ./stdio.in.h +``` + +**问题二** + +``` +checking size of off_t... 0 +configure: error: off_t undefined; check your library configuration + +# 添加搜索路径到配置文件 +echo '/usr/local/lib64 +/usr/local/lib +/usr/lib +/usr/lib64'>>/etc/ld.so.conf +# 更新配置 +ldconfig -v +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/\351\203\250\347\275\262lamp-\345\271\263\345\217\260\351\233\206\346\210\220.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/\351\203\250\347\275\262lamp-\345\271\263\345\217\260\351\233\206\346\210\220.md" new file mode 100644 index 0000000..a4db3f3 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Apache/\351\203\250\347\275\262lamp-\345\271\263\345\217\260\351\233\206\346\210\220.md" @@ -0,0 +1,141 @@ +## 一、平台集成 + +单个软件是无法直接完成我们发布PHP站点的既定任务的,需要我们通过多个软件的通力合作才可以完成,所以我们需要将多个软件关联起来,让彼此各司其职,各干其活。一起完成我们的工作。 + +linux:系统软件,应用软件平台 + +apache:接受用户请求,处理静态数据,响应用户请求 + +php:处理用户的PHP请求 + +mysql:存储数据 + +## 二、平台集成方法 + +- PHP作为模块 +- PHP作为服务 + +#### 1.PHP作为模块 + +这种方式是历史最悠久的关联方法,PHP模块默认出于休眠状态,和apache是上下级关系。apache接受了用户PHP请求后去唤醒PHP模块,PHP模块再去处理请求。 + +#### 2.PHP作为服务 + +这种是apache2.4新增功能,PHP是一个服务,常驻内存。和apache是平级关系,apache接受了用户请求直接通过socket或tcp/ip的方式发送给PHP服务,PHP服务直接处理。如果是在同一台机器安装了apache和php建议使用socket方式关联,系统开销最小,并发更大。 + +## 三、PHP作为模块 + +[root@zutuanxue php-7.3.4]# ./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc --with-mysqli=mysqlnd --enable-pdo --with-pdo-mysql=mysqlnd --with-iconv-dir=/usr/local/ --enable-fpm --with-fpm-user=www --with-fpm-group=www --with-pcre-regex --with-zlib --with-bz2 --enable-calendar --disable-phar --with-curl --enable-dba --with-libxml-dir --enable-ftp --with-gd --with-jpeg-dir --with-png-dir --with-zlib-dir --with-freetype-dir --enable-gd-jis-conv --with-mhash --enable-mbstring --enable-opcache=yes --enable-pcntl --enable-xml --disable-rpath --enable-shmop --enable-sockets --enable-zip --enable-bcmath --with-snmp --disable-ipv6 --with-gettext --disable-rpath --disable-debug --enable-embedded-mysqli --with-mysql-sock=/usr/local/mysql/** --with-apxs2=/usr/local/apache2/bin/apxs** + +在PHP编译的时候需要加上–with-apxs2=/usr/local/apache2/bin/apxs语句,意思是通过apache的apxs命令将PHP生成为一个apache模块。 + +配置方法 + +``` +apache修改主配置文件,添加以下行 +Include conf/extra/php.conf + + +[root@zutuanxue conf]# cat extra/php.conf +LoadModule php7_module modules/libphp7.so + +AddType application/x-httpd-php .php + + + DocumentRoot "/usr/local/apache/htdocs/web1" + + + + Options Indexes FollowSymLinks + AllowOverride None + Require all granted + + + + DirectoryIndex index.php index.html + +``` + +## 四、PHP作为服务 + +#### tcp sock 模式 + +``` +1)修改apache子配置文件 +apache修改主配置文件,添加以下行 +Include conf/extra/php-fpm.conf + +[root@zutuanxue conf]# cat extra/php-fpm.conf +LoadModule proxy_module modules/mod_proxy.so +LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so + + +2)设置虚拟主机 关联php + + DocumentRoot "/usr/local/apache/htdocs/web1" + + + + Options Indexes FollowSymLinks + AllowOverride None + Require all granted + + + + DirectoryIndex index.php index.html + + + + + + SetHandler "proxy:fcgi://127.0.0.1:9000" + +``` + +#### unix sock模式 + +``` +1)apache修改主配置文件,添加以下行 +Include conf/extra/php-fpm.conf + +[root@zutuanxue conf]# cat extra/php-fpm.conf +LoadModule proxy_module modules/mod_proxy.so +LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so + + +2)修改PHP-FPM配置文件 +[root@zutuanxue extra]# egrep "^listen" /usr/local/php/etc/php-fpm.d/www.conf +listen = /usr/local/php/etc/php-fpm.socket +listen.backlog = 511 +#设置UNIX socket 权限 +listen.owner = www +listen.group = www +listen.mode = 0660 + + +3)设置虚拟主机 关联php-fpm + + DocumentRoot "/usr/local/apache/htdocs/web1" + + + + # Unix sockets require 2.4.7 or later + SetHandler "proxy:unix:/usr/local/php/etc/php-fpm.socket|fcgi://localhost/" + + + +``` + +## 五、测试页面 + +1)生成测试页面 + +echo “” /DR/phpinfo.php + +2)测试 + +打开浏览器输入 + +[http://ip或者域名/phpinfo.php](http://xn--ip-on6cx8lt2pxx7b/phpinfo.php) + +![phpinfo.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/18/1603014638162.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/Nginx url \351\207\215\345\206\231.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/Nginx url \351\207\215\345\206\231.md" new file mode 100644 index 0000000..0ef80ff --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/Nginx url \351\207\215\345\206\231.md" @@ -0,0 +1,230 @@ +## 一、URL重写介绍 + +和apache等web服务软件一样,rewrite的主要功能是实现URL地址的重定向。Nginx的rewrite功能需要PCRE软件的支持,即通过perl兼容正则表达式语句进行规则匹配的。默认参数编译nginx就会支持rewrite的模块,但是也必须要PCRE的支持。 + +Rewrite功功能是Nginx服务器提供的一个重要功能。几乎是所有的web产品必备技能,用于实现URL重写。URL重写是非常有用的功能,比如它可以在我们在改变网站结构后,不需要客户端修改原来的书签,也不需要其他网站修改对我们网站的友情链接,还可以在一定程度上提高网站的安全性,能够让我们的网站显得更专业。 + +## 二、应用场景 + +域名变更 (京东) + +用户跳转 (从某个连接跳到另一个连接) + +伪静态场景 (便于CDN缓存动态页面数据) + +## 三、URL重写原理 + +![URL重写原理.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/19/1603105353682.png) + +## 四、URL重写 + +#### URL 模块语法 + +- set 设置变量 +- if 负责语句中的判断 +- return 返回返回值或URL +- break 终止后续的rewrite规则 +- rewrite 重定向URL + +##### set指令 自定义变量 + +Syntax: + +set $variable value; + +Default: + +— + +Context: + +server, location, if + +``` +将http://www.ayitula.com 重写为 http://www.ayitula.com/baism +location / { + set $name baism; + rewrite ^(.*)$ http://www.ayitula.com/$name; + } +``` + +##### if 指令 负责判断 + +Syntax: + +if (condition) { … } + +Default: + +— + +Context: + +server, location + +条件匹配 + +\#模糊匹配 ~匹配 !~不匹配 ~* 不区分大小写的匹配 + +\#精确匹配 = != + +``` +location / { + root html; + index index.html index.htm; + if ($http_user_agent ~* 'Chrome') { + break; + return 403; + #return http://www.jd.com; + } + } +``` + +##### return 指令 定义返回数据 + +Syntax: return code [text]; + +return code URL; + +return URL; + +Default: — + +Context: server, location, if + +``` +location / { + root html; + index index.html index.htm; + if ($http_user_agent ~* 'Chrome') { + return 403; + #return http://www.jd.com; + } + } +``` + +##### break 指令 停止执行当前虚拟主机的后续rewrite指令集 + +Syntax: break; + +Default:— + +Context:server, location, if + +``` +location / { + root html; + index index.html index.htm; + if ($http_user_agent ~* 'Chrome') { + break; + return 403; + } + } +``` + +##### rewrite指令 实现重写url + +**rewrite [flag];** + +**关键字 正则 替代内容 flag标记** + +**flag:** + +- last #本条规则匹配完成后,继续向下匹配新的location URI规则 +- break #本条规则匹配完成即终止,不再匹配后面的任何规则 +- redirect #返回302临时重定向,浏览器地址会显示跳转后的URL地址 +- permanent #返回301永久重定向,浏览器地址栏会显示跳转后的URL地址 + +**重定向就是将网页自动转向重定向,permanent和redirect从定向的区别** + +301永久性重定向:新网址完全继承旧网址,旧网址的排名等完全清零 + +301重定向是网页更改地址后对搜索引擎友好的最好方法,只要不是暂时搬移的情况,都建议使用301来做转址。 + +302临时性重定向:对旧网址没有影响,但新网址不会有排名 + +搜索引擎会抓取新的内容而保留旧的网址 + +**permanent标志:永久重定向** + +``` +域名跳转 +www.ayitula.com 重写为 www.jd.com +server { + listen 80; + server_name www.ayitula.com; + location / { + rewrite ^/$ http://www.jd.com permanent; + + } +} +``` + +**redirect标志:临时重定向** + +``` +域名跳转 +www.ayitula.com 重写为 www.jd.com +server { + listen 80; + server_name www.ayitula.com; + location / { + rewrite ^/$ http://www.jd.com redirect; + + } +} +``` + +**break标志: 类似临时重定向** + +``` +域名跳转 +www.ayitula.com 重写为 www.jd.com +server { + listen 80; + server_name www.ayitula.com; + location / { + rewrite ^/$ http://www.jd.com break; + + } +} +``` + +**last标志:** + +url重写后,马上发起一个新的请求,再次进入server块,重试location匹配,超过10次匹配不到报500错误,地址栏url不变 + +last 一般出现在server或if中 + +根据用户浏览器重写访问目录 + +``` +如果是chrome浏览器 就将 +http://192.168.10.42/$URI + 重写为 +http://http://192.168.10.42/chrome/$URI + +实现 步骤 +1)URL重写 +2)请求转给本机location + + + +location / { +..... +if ($http_user_agent ~* 'chrome'){ + #^ 以什么开头 ^a + #$ 以什么结尾 c$ + #. 除了回车以外的任意一个字符 + #* 前面的字符可以出现多次或者不出现 + #更多内容看正则表达式 re + rewrite ^(.*)$ /chrome/$1 last; + } + + + location /chrome { + root html ; + index index.html; + } +} +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/Nginx\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/Nginx\344\273\213\347\273\215.md" new file mode 100644 index 0000000..79af982 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/Nginx\344\273\213\347\273\215.md" @@ -0,0 +1,33 @@ +## 一、Nginx介绍 + +Nginx(“engine x”)是一款是由俄罗斯的程序设计师Igor Sysoev所开发高性能的 Web和 反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。和apache一样,都是web服务器软件,因为其性能优异,所以被广大运维喜欢。又因为nginx是一个轻量级的web服务器,相比apache来说**资源消耗更低**。 + +延伸版本:**tengine(淘宝)、openresrt(章亦春)等** + +- http://nginx.org 官网 +- http://www.nginx.cn/doc/index.html 中文文档 + +**最近大事记:** + +锤子科技在 T2 鸟巢发布会上将门票收入捐赠给了 OpenResty 开源项目 +OpenResty(又称:ngx_openresty) 是一个基于 NGINX 的可伸缩的 Web 平台,由中国人章亦春发起,提供了很多高质量的第三方模块 + +## 二、为什么选择Nginx + +Nginx 是一个高性能的 Web 和反向代理服务器, 它具有有很多非常优越的特性: + +作为 Web 服务器:相比 Apache,Nginx 使用更少的资源,支持更多的并发连接,体现更高的效率,这点使 Nginx 尤其受到虚拟主机提供商的欢迎。能够支持高达 50,000 个并发连接数的响应,感谢 Nginx 为我们选择了 epoll and kqueue 作为开发模型. + +作为负载均衡服务器:Nginx 既可以在内部直接支持 Rails 和 PHP,也可以支持作为 HTTP代理服务器 对外进行服务。Nginx 用 C 编写, 不论是系统资源开销还是 CPU 使用效率都比 Perlbal 要好的多。 + +作为邮件代理服务器: Nginx 同时也是一个非常优秀的邮件代理服务器(最早开发这个产品的目的之一也是作为邮件代理服务器),Last.fm 描述了成功并且美妙的使用经验。 + +Nginx 安装非常的简单,配置文件 非常简洁(还能够支持perl语法),Bugs非常少的服务器: Nginx 启动特别容易,并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够在 不间断服务的情况下进行软件版本的升级。 + +## 三、Nginx和Apache对比 + +- 静态文件处理能力:nginx高于apache +- 资源消耗:nginx优于apache,因为nginx是异步处理模型,只需要几个进程就能够处理大量在线请求,而apache 2.4仍然是进程模型或者线程模型,即仍然采用大量线程来处理大量在线请求。 +- Apache支持的模块很多,而且也比较稳定。而nginx由于出现的比较晚,所以在这方面可能比不上Apache。 +- nginx本身就是一个反向代理服务器,而且支持7层负载均衡。 +- nginx处理动态页面很鸡肋,一般只用与处理静态页面和反向代理。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/Nginx\344\274\230\345\214\226.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/Nginx\344\274\230\345\214\226.md" new file mode 100644 index 0000000..7742b92 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/Nginx\344\274\230\345\214\226.md" @@ -0,0 +1,112 @@ +## 一、调优的必要性 + +在聊调优之前,我们先要知道为何调优,业务运行和调优的关系。 + +![42967083431970b0eb40b3949278a0d1.png](https://www.zutuanxue.com:8000/static/media/images/2020/12/6/1607251234038.png) + +业务运行:线上业务正常运行,承载了公司业务。 +监控业务:通过监控业务对线上业务进行监控,及时发现问题。 +优化业务:通过监控分析,发现业务问题或者瓶颈,及时对业务或者软件就行调整、优化。 +测试优化:优化完成后,需要对现有的优化进行测试,保证业务在当前优化模式中稳定、高效,能够解决当前问题。 +这就是业务运行的一个流程,也是我们保证业务稳定、高效、高可用的运维之道。 + +## 二、调优的维度和见解分歧 + + 调优类的文章是最难写的,因为我只能告诉你调优的选项,无法告诉你具体的阈值,因为不同的业务运行在不同的机器,所消耗的资源是不同的;又因为场景不同,对应的调优项及阈值是千变万化的,就好比你和你上铺的兄弟都是感冒了,去医院看病开的药却是截然不同的。正是如此,才会出现当很多人看到调优的文章,看到了具体的调优项或者阈值就会浮现出两个字,我不好意思说,配个图吧!大家意会就好。 + +![28a4aaa7cf00a2483492b17857a75176.png](https://www.zutuanxue.com:8000/static/media/images/2020/12/6/1607251822347.png) + +## Nginx跳跃 + +### 1、并发优化 + +nginx工作模式:主进程+工作进程 + +``` +启动工作进程数量 +worker_processes 4; +#指定运行的核的编号,采用掩码的方式设置编号 +worker_cpu_affinity 0001 0010 0100 1000; + + +events { +单个工作进程维护的请求队列长度 + worker_connections 1024; +} +``` + +### 2、长连接 + +减少服务器维护因为与客户端建立http连接产生的大量tcp三次握手四次断开的开销 + +``` +keepalive_timeout 0; 0代表关闭 +#keepalive_timeout 100; +#keepalive_requests 8192; +``` + +### 3、压缩 + +降低传输时间,增加用户体验度;降低公司带宽费用。 + +``` +gzip on; +gzip_proxied any; +gzip_min_length 1k; +gzip_buffers 4 8k; +gzip_comp_level 6; +gzip_types text/plain text/css application/x-javascript application/javascript application/xml; + + + # 开启gzip + gzip off; + + #Nginx做为反向代理的时候启用: + off – 关闭所有的代理结果数据压缩 + expired – 如果header中包含”Expires”头信息,启用压缩 + no-cache – 如果header中包含”Cache-Control:no-cache”头信息,启用压缩 + no-store – 如果header中包含”Cache-Control:no-store”头信息,启用压缩 + private – 如果header中包含”Cache-Control:private”头信息,启用压缩 + no_last_modified – 启用压缩,如果header中包含”Last_Modified”头信息,启用压缩 + no_etag – 启用压缩,如果header中包含“ETag”头信息,启用压缩 + auth – 启用压缩,如果header中包含“Authorization”头信息,启用压缩 + any – 无条件压缩所有结果数据 + + + gzip_proxied any; + + + # 启用gzip压缩的最小文件,小于设置值的文件将不会压缩 + gzip_min_length 1k; + + # gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明 + gzip_comp_level 1; + + # 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。 + gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml; + + # 增加响应头”Vary: Accept-Encoding” + # 是否在http header中添加Vary: Accept-Encoding,建议开启 + gzip_vary on; + + # 禁用IE 6 gzip + gzip_disable "MSIE [1-6]\."; + + # 设置压缩所需要的缓冲区大小 + gzip_buffers 32 4k; + + # 设置gzip压缩针对的HTTP协议版本 + gzip_http_version 1.0; +``` + +### 4、静态缓存 + +将部分数据缓存在用户本地磁盘,用户加载时,如果本地和服务器的数据一致,则从本地加载。提升用户访问速度,提升体验度。节省公司带宽成本。 + +``` +expires指令:开启缓存并指定静态缓存时间 + +location ~* \.(png|gif)$ { + expires 1h; + } +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/Nginx\345\256\211\350\243\205\351\203\250\347\275\262.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/Nginx\345\256\211\350\243\205\351\203\250\347\275\262.md" new file mode 100644 index 0000000..7d0a5fd --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/Nginx\345\256\211\350\243\205\351\203\250\347\275\262.md" @@ -0,0 +1,82 @@ +## 一、nginx源码下载 + +**官网:**http://nginx.org/ + +**源码包:** nginx-1.19.3.tar.gz + +**源码包下载:** wget http://nginx.org/download/nginx-1.19.3.tar.gz -P /usr/src + +## 二、nginx安装 + +``` +2.1、下载nginx源码包 +[root@zutuanxue ~]# wget http://nginx.org/download/nginx-1.19.3.tar.gz -P /usr/src +[root@zutuanxue src]# cd /usr/src + +2.2、安装nginx依赖包 +[root@zutuanxue ~]# yum -y install gcc pcre-devel zlib-devel + - gcc: 源码编译工具 + - pcre-devel: nginx url_rewrite 功能提供包 + - zlib-devel: nginx 压缩功能提供包 + +2.3、解压nginx源码,并进入源码包 +[root@zutuanxue src]# tar xf nginx-1.19.3.tar.gz +[root@zutuanxue src]# cd nginx-1.19.3 + + +2.4、配置nginx源码 + +[root@zutuanxue nginx-1.19.3]# ./configure --prefix=/usr/local/nginx + 配置目的: + 1)检查环境 是否 满足安装条件 依赖解决 + 2)指定安装方式 配置文件 命令文件 各种文件放哪里 开启模块功能【内置模块 三方模块】 + 3)指定软件安装在那里 + + +2.5、编译nginx源码 +[root@zutuanxue nginx-1.19.3]# make -j4 + +2.6、安装nginx +[root@zutuanxue nginx-1.19.3]# make install +``` + +## 三、nginx相关目录 + +nginx path prefix: “/usr/local/nginx” + +nginx binary file: “/usr/local/nginx/sbin/nginx” + +nginx modules path: “/usr/local/nginx/modules” + +nginx configuration prefix: “/usr/local/nginx/conf” + +nginx configuration file: “/usr/local/nginx/conf/nginx.conf” + +nginx pid file: “/usr/local/nginx/logs/nginx.pid” + +nginx error log file: “/usr/local/nginx/logs/error.log” + +nginx http access log file: “/usr/local/nginx/logs/access.log” + +## 四、nginx启动管理 + +配置文件测试:/usr/local/nginx/sbin/nginx -t + +Nginx启动:/usr/local/nginx/sbin/nginx + +Nginx关闭:killall –s QUIT nginx + +## 五、nginx启动测试 + +nginx安装完毕,接下来就可以启动nginx了,nginx启动后如何测试nginx的启动状态呢?可以通过以下三种方式去测试,这个可以根据自己的习惯选择一种测试就行了。 + +- 使用netsata命令查看启动端口 + [root@zutuanxue ~]# netstat –ntpl +- 使用losf命令查看启动端口 + [root@zutuanxue ~]# lsof -i :80 +- 使用文本浏览器访问nginx默认网站 + [root@zutuanxue ~]# elinks [http://IP](http://ip/) + +测试页面内容如下 + +![nginx默认网站页.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/19/1603105516493.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/\344\270\213\350\275\275\351\231\220\351\200\237.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/\344\270\213\350\275\275\351\231\220\351\200\237.md" new file mode 100644 index 0000000..c3e2c27 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/\344\270\213\350\275\275\351\231\220\351\200\237.md" @@ -0,0 +1,151 @@ +## 一、限速介绍 + +在生产环境中,为了保护WEB服务器的安全,我们都会对用户的访问做出一些限制,保证服务器的安全及资源的合理分配。 + +限流(rate limiting)是NGINX众多特性中最有用的,也是经常容易被误解和错误配置的,特性之一访问请求限速。该特性可以限制某个用户在一个给定时间段内能够产生的HTTP请求数。请求可以简单到就是一个对于主页的GET请求或者一个登陆表格的POST请求。用于安全目的上,比如减慢暴力密码破解攻击。通过限制进来的请求速率,并且(结合日志)标记出目标URLs来帮助防范DDoS攻击。一般地说,限流是用在保护上游应用服务器不被在同一时刻的大量用户请求湮没 + +限速说的很笼统,其实限速分为很多种限速方法: + +1)下载速度限速 + +2)单位时间内请求数限制 + +3)基于客户端的并发连接限速 + +nginx限速模块 + +Nginx官方版本限制IP的连接和并发分别有两个模块: + +limit_req_zone 用来限制单位时间内的请求数,即速率限制,采用的漏桶算法 “leaky bucket”。 + +limit_req_conn 用来限制同一时间连接数,即并发限制。 + +## 二、应用场景 + +下载限速:限制现在速度及并发连接数,应用在下载服务器中,保护带宽及服务器的IO资源。 + +请求限速:限制单位时间内用户访问请求,防止恶意攻击,保护服务器及资源安全。 + +## 三、限速原理 + +漏桶原理 + +![限速漏桶原理.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/19/1603105114856.png) + +``` +算法思想是: + 水(请求)从上方倒入水桶,从水桶下方流出(被处理); + 来不及流出的水存在水桶中(缓冲),以固定速率流出; + 水桶满后水溢出(丢弃)。 + 这个算法的核心是:缓存请求、匀速处理、多余的请求直接丢弃。 + 相比漏桶算法,令牌桶算法不同之处在于它不但有一只“桶”,还有个队列,这个桶是用来存放令牌的,队列才是用来存放请求的。 +``` + +## 四、限速实现 + +1)单位时间内请求数限制 + +``` +#基于IP对下载速率做限制 限制每秒处理1次请求,对突发超过5个以后的请求放入缓存区 +http { + limit_req_zone $binary_remote_addr zone=baism:10m rate=1r/s; + server { + location /abc { + limit_req zone=baism burst=5 nodelay; + } +} +limit_req_zone $binary_remote_addr zone=baism:10m rate=1r/s; +第一个参数:$binary_remote_addr 表示通过remote_addr这个标识来做限制,“binary_”的目的是缩写内存占用量,是限制同一客户端ip地址。 +第二个参数:zone=baism:10m表示生成一个大小为10M,名字为one的内存区域,用来存储访问的频次信息。 +第三个参数:rate=1r/s表示允许相同标识的客户端的访问频次,这里限制的是每秒1次,还可以有比如30r/m的。 + +limit_req zone=baism burst=5 nodelay; +第一个参数:zone=baism 设置使用哪个配置区域来做限制,与上面limit_req_zone 里的name对应。 +第二个参数:burst=5,重点说明一下这个配置,burst爆发的意思,这个配置的意思是设置一个大小为5的缓冲区当有大量请求(爆发)过来时,超过了访问频次限制的请求可以先放到这个缓冲区内。 +第三个参数:nodelay,如果设置,超过访问频次而且缓冲区也满了的时候就会直接返回503,如果没有设置,则所有请求会等待排队。 +``` + +2)限制并发连接数 + +``` +#基于IP做连接限制 限制同一IP并发为1 +limit_conn_zone $binary_remote_addr zone=addr:10m; + +server { + listen 80; + server_name localhost; + + location / { + root html; + index index.html index.htm; + } + + location /abc { + limit_conn addr 1; + } + + } + +} +``` + +3)限制下载速度 + +``` +下载速度为100k +server { + listen 80; + server_name localhost; + + location / { + root html; + index index.html index.htm; + } + + location /abc { + limit_rate 100k; + } + + } + +} +``` + +4)综合案例 + +限制web服务器请求处理为1秒一个,触发值为5; + +限制并发连接数为4; + +限制下载速度为100. + +``` +http { + include mime.types; + default_type application/octet-stream; + + sendfile on; + keepalive_timeout 65; +#基于IP做连接限制 限制同一IP并发为1 下载速度为100K +limit_conn_zone $binary_remote_addr zone=addr:10m; +#基于IP对下载速率做限制 限制每秒处理1次请求,对突发超过5个以后的请求放入缓存区 +limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; + server { + listen 80; + server_name localhost; + + location / { + root html; + index index.html index.htm; + } + + location /abc { + limit_req zone=one burst=5 nodelay; + limit_conn addr 4; + limit_rate 100k; + } + + } + +} +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/\345\217\215\345\220\221\344\273\243\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/\345\217\215\345\220\221\344\273\243\347\220\206.md" new file mode 100644 index 0000000..2d89df3 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/\345\217\215\345\220\221\344\273\243\347\220\206.md" @@ -0,0 +1,100 @@ +## 一、代理介绍 + +代理在网络中使用是比较常见的,比如我们说的最多的就是翻墙软件,比如ss、蓝灯等这些大家常用的软件,他们就是能改代理大家访问国内无法访问的一些国外网站,比如facebook、YouTube等网站。其原理也比较简单: + +1)用户将请求发给代理服务器 + +2)代理服务器代用户去访问数据 + +3)代理服务器将数据给用户 + +**正常没有代理情况上网** + +![反代1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/19/1603105139047.png) + +**代理服务器场景** + +![反代2.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/19/1603105146133.png) + +**代理服务器扮演的就是一个中间人的角色。** + +代理分为正向代理和反向代理两种类型: + +正向代理:代理用户访问其他网站,比如ss,蓝灯。 + +反向代理:用来发布服务器,比如nginx + +树明主要给大家介绍的是反向代理,使用反向代理发布公司的站点。**(国家严厉打击私单乱建翻墙代理服务器)** + +## 二、应用场景 + +1)堡垒机:堡垒机承担所有的外部访问,保护后端服务器的安全 + +![反代堡垒机.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/19/1603105157770.png) + +2)业务发布服务器:将多个服务器通过虚拟主机的方式发布到公网 + +![反代发布服务器.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/19/1603105225160.png) + +3)缓存服务器:CDN加速 +![反代缓存服务器.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/19/1603105185130.png) + +## 三、反向代理原理 + +\1) 客户端通过浏览器 发起请求 代理服务器 + +2)代理服务器 接受请求 + +\3) 代理服务器 发起请求 业务服务器 + +4)业务服务器 接受请求 + +5)业务服务器 处理请求 + +\6) 业务服务器 响应请求 代理服务器 + +7)代理服务器 响应请求 客户端 + +8)客户端通过浏览器渲染请求并展示给用户 + +## 四、反向代理实现 + +**proxy_pass: nginx反向代理指令** + +**反向代理实现** + +location / { + +index index.php index.html index.htm; #定义首页索引文件的名称 + +proxy_pass http://mysvr ;#请求转向mysvr 定义的服务器列表 + +} + +**反向代理优化** + +``` +proxy_set_header Host $host; #修改请求头,添加Host字段 + +proxy_set_header X-Real-IP $remote_addr; #修改请求头,添加X-Real-IP字段 + +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #修改请求头,添加X-Forwarded-For字段 + +client_max_body_size 10m; #允许客户端请求的最大单文件字节数 + +client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数, + +proxy_connect_timeout 90; #nginx跟后端服务器连接超时时间\(代理连接超时\) + +proxy_send_timeout 90; #后端服务器数据回传时间\(代理发送超时\) + +proxy_read_timeout 90; #连接成功后,后端服务器响应时间\(代理接收超时\) + +proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小 + +proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置 + +proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2) + +proxy_temp_file_write_size 64k; #设定缓存文件夹大小,大于这个值,将从upstream服务器传 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/\350\231\232\346\213\237\344\270\273\346\234\272.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/\350\231\232\346\213\237\344\270\273\346\234\272.md" new file mode 100644 index 0000000..cdb8dce --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/\350\231\232\346\213\237\344\270\273\346\234\272.md" @@ -0,0 +1,107 @@ +## 一、虚拟主机介绍 + +**虚拟主机** 就是把一台物理服务器划分成多个“虚拟”的服务器,每一个虚拟主机都可以有独立的域名和独立的目录,可以独立发布一个网站。 + +**实验案例:** 同时发布两个网站: + +- DocumentRoot /usr/local/nginx/html/web1 +- DocumentRoot /usr/local/nginx/html/web2 + +## 二、基于IP的虚拟主机 + +**应用场景:IP充足的环境,每个网站需要一个IP地址** + +``` +server { + listen 192.168.11.251:80; + location / { + root html/web1; + index index.html index.htm index.php; + } +} +server { + listen 192.168.11.252:80; +location / { + root html/web2; + index index.html index.htm; + } +} +``` + +#### 基于IP的虚拟主机特点 + +- 不同IP对应不同网站 +- 访问方便,用户直接使用默认端口即可访问 +- 服务器需要有多个IP地址(一个公网IP大概一年的费用是600左右) +- 维护方便,基于独立IP的站点,便于监控、维护。 + +## 三、基于端口的虚拟主机 + +**应用场景:IP不足的环境** + +- 优点: 多个网站发布使用该配置方法只需要一个IP,节省IP地址 +- 缺点 端口你是无法告诉公网用户,无法适用于公网客户,适合内部用户 + +``` +基于端口 +server { + listen 80; + #server_name www.zutuanxue.com; + location / { + root html/web1; + index index.html index.htm index.php; + } +} +server { + listen 8080; + #server_name www.zutuanxue.com; + location / { + root html/web2; + index index.html index.htm; + } +} +``` + +#### 基于端口的虚拟主机特点 + +- 不同端口对应不同网站 +- 访问需要加端口 +- 节省IP地址 +- 适合私网运行 + +## 四、基于域名的虚拟主机 + +**应用场景:一个网站需要有一个域名,目前公网发布网站的首选** + +``` +基于域名 +server { + listen 80; + server_name web1.zutuanxue.com; + + location / { + root html/web1; + index index.html index.htm index.php; + + } +} + + +server { + listen 80; + server_name web2.zutuanxue.com; + + location / { + root html/web2; + index index.html index.htm; + } +} +``` + +#### 基于域名的虚拟主机特点 + +- 不同域名对应不同网站 +- 需要多个域名 可以是二级或三级域名 +- 每个站点使用默认端口,方便用户访问 +- 只需要一个IP地址,节约成本 +- 适合公网环境 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/\351\273\230\350\256\244\347\275\221\347\253\231.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/\351\273\230\350\256\244\347\275\221\347\253\231.md" new file mode 100644 index 0000000..910c2cb --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Nginx/\351\273\230\350\256\244\347\275\221\347\253\231.md" @@ -0,0 +1,118 @@ +## 一、默认网站 + +``` +server { + listen 80; + + server_name localhost; + + location / { + + root html; + + index index.html index.htm; + + #支持目录浏览 + autoindex on; + + } + + error_page 500 502 503 504 /50x.html; + + location = /50x.html { + + root html; + + } + +} +``` + +## 二、访问控制 + +``` +location /a { + autoindex on; + allow 192.168.12.0/24; + deny all; + #基于客户端IP做过滤,符合条件的允许访问,不符合的返回404; + if ( $remote_addr !~ "192.168.12" ) { + #return 404; + return http://book.ayitula.com; + } + + } +``` + +## 三、登陆验证 + +``` +location /c { + auth_basic "登陆验证"; + auth_basic_user_file /etc/nginx/htpasswd; + +} +``` + +## 四、日志管理 + +Nginx访问日志主要有两个参数控制 + +log_format #用来定义记录日志的格式(可以定义多种日志格式,取不同名字即可) + +access_log #用来指定日至文件的路径及使用的何种日志格式记录日志 + +access_log logs/access.log main; + +``` +log_format格式变量: + $remote_addr #记录访问网站的客户端地址 + $remote_user #远程客户端用户名 + $time_local #记录访问时间与时区 + $request #用户的http请求起始行信息 + $status #http状态码,记录请求返回的状态码,例如:200、301、404等 + $body_bytes_sent #服务器发送给客户端的响应body字节数 + $http_referer #记录此次请求是从哪个连接访问过来的,可以根据该参数进行防盗链设置。 + $http_user_agent #记录客户端访问信息,例如:浏览器、手机客户端等 + $http_x_forwarded_for #当前端有代理服务器时,设置web节点记录客户端地址的配置,此参数生效的前提是代理服务器也要进行相关的x_forwarded_for设置 +``` + +自定义一个json格式的访问日志 + +``` +log_format main_json '{"@timestamp":"$time_local",' +'"client_ip": "$remote_addr",' +'"request": "$request",' +'"status": "$status",' +'"bytes": "$body_bytes_sent",' +'"x_forwarded": "$http_x_forwarded_for",' +'"referer": "$http_referer"' +'}'; +access_log logs/access_json.log main_json; +``` + +**日志截断** + +``` +mv access.log access.log.0 + +killall -USR1 \`cat master.nginx.pid\` + +sleep 1 + +gzip access.log.0 +``` + +## 五、防盗链 + +``` +location /images/ { +alias /data/images/; +valid_referers none blocked *.ayitula.com; + if ($invalid_referer) { + rewrite ^/ + http://www.ayitula.com/daolian.gif; + #return 403; + } +} +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat \345\217\221\345\270\203\345\212\250\346\200\201\351\241\265\351\235\242.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat \345\217\221\345\270\203\345\212\250\346\200\201\351\241\265\351\235\242.md" new file mode 100644 index 0000000..d2a39a6 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat \345\217\221\345\270\203\345\212\250\346\200\201\351\241\265\351\235\242.md" @@ -0,0 +1,50 @@ +我们知道tomcat是用来发布jsp网站的,jsp的网站,页面漂亮还安全,上节课我们已经知道如何发布静态页面了,本节课我们一起来看一下如何发布动态页面,我们通过jpress一个使用java开发的建站软件来实现jsp页面 + +``` +jpress下载地址:http://jpress.io/download +``` + +**step 1** 准备jsp页面 + +``` +[root@zutuanxue ~]# mv jpress-v3.2.1.war jpress.war + +[root@zutuanxue ~]# cp jpress.war /opt/tomcat1/webapps/ + +#重启tomcat +[root@zutuanxue ~]# cp jpress.war /opt/tomcat1/webapps/ +[root@zutuanxue ~]# sh /opt/tomcat1/bin/shutdown.sh + +[root@zutuanxue ~]# sh /opt/tomcat1/bin/startup.sh +#重启之后tomcat会自己将这个war的压缩包解压,生成一个同名的目录 +``` + +**step 2** 准备数据库 + +``` +[root@zutuanxue yum.repos.d]# dnf install mariadb mariadb-server -y + +[root@zutuanxue yum.repos.d]# systemctl restart mariadb.service + +[root@zutuanxue ~]# mysql -u root -p +Enter password: + +MariaDB [(none)]> create database jpress charset utf8; +MariaDB [(none)]> grant all on jpress.* to jpress@'localhost' identified by '123456'; +``` + +**step 3** 安装jpress + +![image20200313141545372.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603160976235.png) + +![image20200313141616340.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603160997472.png) + +![image20200313141647962.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603161027211.png) + +![image20200313141659536.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603161051771.png) + +![image20200313141725515.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603161069805.png) + +![image20200313141752995.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603161088428.png) + +![image20200313141822315.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603161108200.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat \347\233\256\345\275\225\344\270\216\351\205\215\347\275\256\346\226\207\344\273\266.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat \347\233\256\345\275\225\344\270\216\351\205\215\347\275\256\346\226\207\344\273\266.md" new file mode 100644 index 0000000..9f99eca --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat \347\233\256\345\275\225\344\270\216\351\205\215\347\275\256\346\226\207\344\273\266.md" @@ -0,0 +1,141 @@ +## 一、tomcat目录说明 + +**tomcat主目录** + +``` +bin:命令,存放不同平台上启动或关闭的脚本 +BUILDING.txt&RUNNING.txt:使用文档,告诉用户如何搭建 +conf:各种全局配置文件,最主要的是server.xml和web.xml +CONTRIBUTING.md:捐赠 +lib:tomcat需要用到的库,主要是各种jar包 +LICENSE:许可 +logs:存放tomcat的日志 +NOTICE:通知信息 +README.md:读我文档 +RELEASE-NOTES:版本信息 +temp:临时文件 +webapps:tomcat的web发布目录,类似于nginx或者apache的html目录 +work:tomcat的工作目录,存放的是jsp编译后产生的.class文件及.java文件。清空work目录,然后重启tomcat,可以达到清除缓存的作用。 +``` + +**bin目录** + +``` +bin目录下的文件主要有两类,一个是Linux使用的.sh结尾的文件,另外一个是windows使用的.bat结尾的文件, +catalina tomcat的设置脚本,也可以启动&关闭tomcat +[root@zutuanxue bin]# sh catalina.sh help +Using CATALINA_BASE: /opt/tomcat1 +Using CATALINA_HOME: /opt/tomcat1 +Using CATALINA_TMPDIR: /opt/tomcat1/temp +Using JRE_HOME: /usr +Using CLASSPATH: /opt/tomcat1/bin/bootstrap.jar:/opt/tomcat1/bin/tomcat-juli.jar +Usage: catalina.sh ( commands ... ) +commands: + debug Start Catalina in a debugger + debug -security Debug Catalina with a security manager + jpda start Start Catalina under JPDA debugger + run Start Catalina in the current window + run -security Start in the current window with security manager + start Start Catalina in a separate window + start -security Start in a separate window with security manager + stop Stop Catalina, waiting up to 5 seconds for the process to end + stop n Stop Catalina, waiting up to n seconds for the process to end + stop -force Stop Catalina, wait up to 5 seconds and then use kill -KILL if still running + stop n -force Stop Catalina, wait up to n seconds and then use kill -KILL if still running + configtest Run a basic syntax check on server.xml - check exit code for result + version What version of tomcat are you running? +Note: Waiting for the process to end and use of the -force option require that $CATALINA_PID is defined +[root@zutuanxue bin]# sh catalina.sh stop +[root@zutuanxue bin]# sh catalina.sh help + + +startup 启动脚本 +shutdown 关闭脚本 +``` + +**conf目录** + +``` +这个目录下主要存放的是与tomcat设置相关的文件,常用的配置文件主要包含 + +server.xml 可以设置端口号、设置域名或IP、默认加载的项目、请求编码 +web.xml 可以设置tomcat支持的文件类型 +context.xml 可以用来配置数据源之类的 +tomcat-users.xml 用来配置管理tomcat的用户与权限 +Catalina 此目录下可以设置默认加载的项目 +``` + +**webapps目录** + +``` +ROOT tomcat默认的页面 +docs 使用说明文档 +examples 例子--tomcat首页中的examples按钮对应的内容 +host-manager 首页Host Manager按钮对应的内容 +manager 首页 Manager App按钮对应的内容 +``` + +## 二、tomcat相关配置文件简介 + +**server.xml** + +| 元素名 | 属性 | 解释 | +| ------------------------------------------------------------ | ----------------- | ------------------------------------------------------------ | +| server | port | 指定一个端口,这个端口负责监听关闭tomcat的请求 | +| | shutdown | 指定向端口发送的命令字符串 | +| service | name | 指定service的名字 | +| Connector(表示客户端和service之间的连接) | port | 指定服务器端要创建的端口号,并在这个断口监听来自客户端的请求 | +| | minProcessors | 服务器启动时创建的处理请求的线程数 | +| | maxProcessors | 最大可以创建的处理请求的线程数 | +| | enableLookups | 如果为true,则可以通过调用request.getRemoteHost()进行DNS查询来得到远程客户端的实际主机名,若为false则不进行DNS查询,而是返回其ip地址 | +| | redirectPort | 指定服务器正在处理http请求时收到了一个SSL传输请求后重定向的端口号 | +| | acceptCount | 指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理 | +| | connectionTimeout | 指定超时的时间数(以毫秒为单位) | +| Engine(表示指定service中的请求处理引擎,接收和处理来自Connector的请求) | defaultHost | 指定缺省的处理请求的主机名,它至少与其中的一个host元素的name属性值是一样的 | +| Context(表示一个web应用程序,通常为WAR文件,关于WAR的具体信息见servlet规范) | docBase | 应用程序的路径或者是WAR文件存放的路径 | +| | path | 表示此web应用程序的url的前缀,这样请求的url为http://localhost:8080/path/ | +| | reloadable | 这个属性非常重要,如果为true,则tomcat会自动检测应用程序的/WEB-INF/lib 和/WEB-INF/classes目录的变化,自动装载新的应用程序,我们可以在不重起tomcat的情况下改变应用程序 | +| host(表示一个虚拟主机) | name | 指定主机名 | +| | appBase | 应用程序基本目录,即存放应用程序的目录 | +| | unpackWARs | 如果为true,则tomcat会自动将WAR文件解压,否则不解压,直接从WAR文件中运行应用程序 | +| Logger(表示日志,调试和错误信息) | className | 指定logger使用的类名,此类必须实现org.apache.catalina.Logger 接口 | +| | prefix | 指定log文件的前缀 | +| | suffix | 指定log文件的后缀 | +| | timestamp | 如果为true,则log文件名中要加入时间,如下例:localhost_log.004-mm-dd.txt | +| Realm(表示存放用户名,密码及role的数据库) | className | 指定Realm使用的类名,此类必须实现org.apache.catalina.Realm接口 | +| Valve(功能与Logger差不多,其prefix和suffix属性解释和Logger 中的一样) | className | 指定Valve使用的类名,如用org.apache.catalina.valves.AccessLogValve类可以记录应用程序的访问信息 | +| | directory | 指定log文件存放的位置 | +| | pattern | 有两个值,common方式记录远程主机名或ip地址,用户名,日期,第一行请求的字符串,HTTP响应代码,发送的字节数。combined方式比common方式记录的值更多 | + +**web.xml** + +默认Web应用的首页文件的设置 + +报错文件的设置 + +session 会话过期时间的设置,单位是分钟 + +servlet的设置(Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。) + +**tomcat-users.xml** + +管理用户配置文件 + +rolename 定义角色,不同的角色管理权限不同,相当于组 + +``` +manager-gui 允许访问html接口(即URL路径为/manager/html/*) +manager-script 允许访问纯文本接口(即URL路径为/manager/text/*) +manager-jmx 允许访问JMX代理接口(即URL路径为/manager/jmxproxy/*) +manager-status 允许访问Tomcat只读状态页面(即URL路径为/manager/status/*) +admin-gui 允许访问html管理界面 +admin-script 允许访问文本管理界面 +``` + +user 定义用户名 + +``` +username 定义用户名 +password 设置密码 +roles 属于那些角色/组 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\344\273\213\347\273\215.md" new file mode 100644 index 0000000..35d3c53 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\344\273\213\347\273\215.md" @@ -0,0 +1,47 @@ +## 一、Tomcat介绍 + +Apache Tomcat最早是由Sun开发的,在1999年被捐献给ASF(Apache 软件基金会 Apache Software Foundation),隶属于Jakarta(雅加达)项目,现在已经独立为一个顶级项目。因为Tomcat 技术先进、性能稳定,同时也是一个免费的开放源代码的Web 应用服务器,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,被很多企业普遍使用,也是开发和调试JSP程序的首选。成为目前比较流行的Web 应用服务器。 + +官方网站:http://tomcat.apache.org/ + +### **tomcat的同类产品** + +- Resin 服务器 + +Resin是Caucho公司的产品,速度非常快。可以显示动态内容,也可以显示静态内容,但是用户数量少,参考文档也少,使用起来不太方便,一旦涉及到相关文件和内容的更新,系统会自动重新部署并重启。 + +- Jetty 服务器 + +Jetty是一个纯粹的基于Java的web服务器,也是一个开源项目。架构简单,速度快,修改简单,但是对java的支持不如tomcat全面, + +- WebLogic 服务器 + +WebLogic 是BEA公司的产品,可进一步细分为 WebLogic Server、WebLogic Enterprise 和 WebLogic Portal 等系列,其中 WebLogic Server 的功能特别强大。WebLogic 支持企业级的、多层次的和完全分布式的Web应用,并且服务器的配置简单、界面友好。对于那些正在寻求能够提供Java平台所拥有的一切应用服务器的用户来说,WebLogic是一个十分理想的选择。但是不开源且收费 + +JBoss、WebSphere + +## 二、Apache nginx tomcat比较 + +Apache是用C写的; +Nigix是用C写的; +Tomcat是用Java写的。 + +Tomcat是Apache的拓展,更实质的说是Java应用服务器,用于处理JSP后台语言开发的应用,主要用于处理JSP动态网页。Tomcat 服务器是一个免费的开放源代码的Web 应用服务器(主要用于解析servlet/JSP,同时具备http服务),单纯的Tomcat性能有限,在很多地方表现有欠缺,如活动连接支持、静态内容、大文件和HTTPS等,因此多数都是Apache+Tomcat+JavaSDK的集成。严格的来说,Apache/Nginx 应该叫做[HTTP Server]而Tomcat 则是一个「Application Server」,或者更准确的来说,是一个「Servlet/JSP」应用的容器(Ruby/Python 等其他语言开发的应用也无法直接运行在 Tomcat 上)。 + +**Apache** + +优点:模块多,功能全面,性能稳定,适合静态HTML + +缺点:配置相对复杂,自身不支持动态页面 + +**Nginx** + +优点:功能较多,负载均衡、反向代理等,速度比Apache快 + +缺点:轻量级web服务器,功能不如Apache全面 + +**Tomcat** + +优点:能够处理动态请求,可以独立于Apache运行,支持JSP + +缺点:对静态内容和大文件的支持有所欠缺 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\345\216\213\345\212\233\346\265\213\350\257\225.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\345\216\213\345\212\233\346\265\213\350\257\225.md" new file mode 100644 index 0000000..be27d0f --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\345\216\213\345\212\233\346\265\213\350\257\225.md" @@ -0,0 +1,100 @@ +Apache JMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试领域。 它可以用于测试静态和动态资源,例如静态文件、Java 小服务程序、CGI 脚本、Java 对象、数据库、FTP 服务器, 等等。JMeter 可以用于对服务器、网络或对象模拟巨大的负载,来自不同压力类别下测试它们的强度和分析整体性能 + +### JMeter的作用 + +能够对HTTP和FTP服务器进行压力和性能测试, 也可以对任何数据库进行同样的测试(通过JDBC)。 + +完全的可移植性和100% 纯java。 + +完全多线程 框架允许通过多个线程并发取样和 通过单独的线程组对不同的功能同时取样。 + +精心的GUI设计允许快速操作和更精确的计时。 + +缓存和离线分析/回放测试结果。 + +``` +下载地址:http://jmeter.apache.org/download_jmeter.cgi +``` + +### JMeter安装使用 + +将下载好的压缩包在windows中解压(需要先安装JDK),解压后进入到bin目录双击jmeter.bat,等待启动 + +![image202003132046066284103573.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603162643439.png) + +设置中文 + +![image20200313204658512.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603162670876.png) + +创建测试 + +![image20200313205020894.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603162712089.png) + +添加线程组,使用线程模拟用户的并发 + +![image20200313205150993.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603162732432.png) + +![image20200313205306242.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603162745836.png) + +1000个线程循环10次,tomcat会收到10000个请求 + +添加并设置http请求 + +![image20200313205429005.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603162768123.png) + +![image20200313205601358.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603162783074.png) + +添加监控 + +![image20200313205836519.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603162795573.png) + +启动测试 + +![image20200313205920252.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603162808359.png) + +查看结果 + +![image20200313210311135.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603162821286.png) + +``` +标签:说明是请求类型,如Http,FTP等请求。 + +样本总数:也就是图形报表中的样本数目,总共发送到服务器的样本数目。 + +平均值:也就是图形报表中的平均值,是总运行时间除以发送到服务器的请求数。 + +居中的数值:也就是图形报表中的中间值,是代表时间的数字,有一半的服务器响应时间低于该值而另一半高于该值。 + +90%&95%&99%:有多少请求的响应时间比给出的数值还要小。 + +最小:是代表时间的数字,是服务器响应的最短时间。 + +最大: 是代表时间的数字,是服务器响应的最长时间。 + +异常%:请求的错误百分比。 + +吞吐量:也就是图形报表中的吞吐量,这里是服务器每单位时间处理的请求数,注意查看是秒或是分钟。 + +发送/接收KB/sec:是每秒钟发送/接收的字节数。(时间的单位为ms) +``` + +通过上面测试可以看出,tomcat在不做任何调整时,吞吐量为587次/秒。这个吞吐量跟接口的业务逻辑关系很大,如果业务逻辑复杂,需要比较长时间计算的,可能吞吐量只有几十次/秒,我这里测试的时候没有添加任务业务逻辑,才会出现吞吐量为587次/秒的情况。这里的吞吐量最好是经过多次测试取平均值,因为单次测试具有一定的随机性 + +### 调整tomcat线程池 + +``` +[root@zutuanxue bin]# vim /opt/tomcat1/conf/server.xml + +#调整最大线程数为1000,最小为200,这个线程的数量要反复调整,然后对比测试结果,找出一个适合自己的值 +``` + +### 调整队列 + +``` +[root@zutuanxue bin]# vim /opt/tomcat1/conf/server.xml + + +默认情况下,请求发送到tomcat,如果tomcat正忙,那么该请求会一直等待。这样虽然可以保证每个请求都能请求到,但是请求时间就会边长。有些时候,我们也不一定要求请求一定等待,可以设置最大等待队列大小,如果超过就不等待了。这样虽然有些请求是失败的,但是请求时间会虽短。典型的是12306。 +``` + +参数介绍可以去官网查看:https://tomcat.apache.org/tomcat-9.0-doc/config/executor.html \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\345\217\221\345\270\203\351\235\231\346\200\201\351\241\265\351\235\242.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\345\217\221\345\270\203\351\235\231\346\200\201\351\241\265\351\235\242.md" new file mode 100644 index 0000000..ed3dc10 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\345\217\221\345\270\203\351\235\231\346\200\201\351\241\265\351\235\242.md" @@ -0,0 +1,79 @@ +## 访问tomcat网站管理页面 + +打开浏览器,在地址栏中输入 http://localhost:8080 +看到如下页面,该页面是tomcat的默认网站,同时还提供了以下功能 + +- server status 查看服务器的状态,包括linux主机的信息,tomcat的版本信息,资源使用情况等 +- manager app 管理网站 +- host manager 虚拟主机的管理 + +![image20200312154145218.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603160256413.png) + +默认使用这三个功能需要提供账号密码,如果没有可以采用以下的方式去修改配置文件,设置用以访问的账号密码。 + +在提示登录的界面点击取消,会看到提示 + +![image20200312154227858.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603160330788.png) + +``` +[root@zutuanxue ~]# vim /opt/tomcat1/conf/tomcat-users.xml + + + + + + + +``` + +设置完成之后重启tomcat就可以登录后台管理页面了,其中在manager app中主要管理的是网站是否发布的操作,start=发布网站 + +stop=停止发布网站,reload=重新加载,undeploy=卸载/删除网站(慎用),expire session=会话过期时间 + +![image20200312160956755.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603160530000.png) + +与war文件部署相关的设置,包括定义war文件存放的位置,和上传war文件 + +``` +war是一个可以直接运行的web模块,通常用于网站,打包部署。以Tomcat来说,将war包放置在其\webapps\目录下,然后启动Tomcat, +这个包就会自动解压,就相当于发布了。war包是Sun提出的一种web应用程序格式,与jar类似,是很多文件的压缩包。war包中的文件按 +照一定目录结构来组织。简单来说,war包是JavaWeb程序打的包,war包里面包括写的代码编译成的class文件,依赖的包,配置文件, +所有的网站页面,包括html,jsp等等。一个war包可以理解为是一个web项目,里面是项目的所有东西。 +``` + +![image20200312161045722.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603160554207.png) + +configuration 定义TLS(安全传输协议)配置文件 + +diagnostics 检查网站在启动,重新加载或卸载时,是否造成内存溢出,这个操作会触发垃圾回收机制,生产环境中慎用 + +TLS connector configuration diagnostics 加密诊断,可以帮助用户诊断加密是否有问题 + +### firefox设置中文 + +``` +[root@zutuanxue ~]# dnf install ibus* -y +``` + +添加完整的中文环境后重启 + +![image20200313163452841.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603160597852.png) + +重启完成为浏览器添加中文后重启浏览器 + +![image20200313163127816.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603160616038.png) + +再次访问tomcat管理界面就会变成中文 + +![image20200313163617973.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603160631864.png) + +### **发布静态页面** + +``` +[root@zutuanxue webapps]# pwd +/opt/tomcat1/webapps +[root@zutuanxue webapps]# mkdir test +[root@zutuanxue webapps]# echo '<%= new java.util.Date() %>' > test/index.jsp +``` + +使用浏览器访问http://ip:8080/test,每次刷新时间都会改变 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\345\244\232\345\256\236\344\276\213.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\345\244\232\345\256\236\344\276\213.md" new file mode 100644 index 0000000..0291ffd --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\345\244\232\345\256\236\344\276\213.md" @@ -0,0 +1,60 @@ +Tomcat是一个单进程多线程的软件,在很早之前,我们都认为这种模式挺好的,因为早些年的CPU都是单核的,但是现在都是多核心的CPU了,如果还是一个进程的话呢,就比较浪费CPU资源,所以本节课我们要讨论下如果多开几个tomcat,也就是我们本节课要实现的是tomcat的多实例,这样可以提高资源的利用率,在之前的课程中我们提到过tomcat有三个端口8005 8009 8080,其中8005是用来关闭tomcat的端口,8080是访问端口,8009是ajp协议使用的端口,如果我想在一台机器上开启多个tomcat的话,首先要保证的就是端口不能冲突,否则开不了。 + +## Tomcat多实例实现 + +- 将之前部署好的tomcat复制一份 + +``` +[root@zutuanxue webapps]# cd /opt/ +[root@zutuanxue opt]# ls +tomcat1 +[root@zutuanxue opt]# cp -r tomcat1 tomcat2 +[root@zutuanxue opt]# ls +tomcat1 tomcat2 +``` + +- 修改刚刚部署完成的tomcat的相关配置文件 + +``` +[root@zutuanxue opt]# vim tomcat2/conf/server.xml + + +#修改端口 +``` + +- 启动tomcat + +``` +[root@zutuanxue opt]# sh /opt/tomcat1/bin/startup.sh +[root@zutuanxue opt]# sh /opt/tomcat2/bin/startup.sh + +[root@zutuanxue opt]# netstat -atnp +Active Internet connections (servers and established) +Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name +tcp6 0 0 127.0.0.1:8005 :::* LISTEN 16801/java +tcp6 0 0 127.0.0.1:8006 :::* +tcp6 0 0 :::8080 :::* LISTEN 16801/java +tcp6 0 0 :::8081 :::* LISTEN 17776/java +``` + +- 打开浏览器访问测试 + +![image20200313144207263.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603162375841.png) +![image20200313144222035.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603162404686.png) + +``` +注意:如果是不同用户使用的话,考虑到安全方面的问题,记得修改tomcat的用户管理文件。 +[root@zutuanxue conf]# pwd +/opt/tomcat2/conf +[root@zutuanxue conf]# vim tomcat-users.xml + + + + + + + + +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\350\260\203\344\274\230.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\350\260\203\344\274\230.md" new file mode 100644 index 0000000..0aa0f30 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\350\260\203\344\274\230.md" @@ -0,0 +1,168 @@ +tomcat的优化可以提高网站的并发能力,体现个人的价值,tomcat在java项目中的使用率非常高,所以在生产环境对tomcat的优化也就变得非常必要了,一般情况下tomcat的优化主要从两个方面入手,一个是自身配置,另一个是tomcat所运行的jvm虚拟机的优化,优化的工作可以从安装完tomcat就开始着手 + +## 一、AJP优化 + +在前面的课程中我们提到了一个叫AJP的协议,同时我们也知道了这个AJP的作用,但是在生产环境中一般使用的是nginx+tomcat的架构,所以大多数时候用不到AJP协议,所以我们可以禁用它,而在我们的server.xml文件中这个AJP默认就是禁用的,如果是其它版本最好看一下 + +``` + [root@zutuanxue conf]# vim /opt/tomcat1/conf/server.xml + + +``` + +## 二、运行模式优化 + +tomcat的运行模式有3种: + +**bio** + +性能非常低下,没有经过任何优化处理和支持,适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。 + +**nio** + +nio(new I/O),是Java SE 1.4及后续版本提供的一种新的I/O操作方式它拥有比传统I/O操作(bio)更好的并发运行性能。Tomcat9默认使用nio运行模式。适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂。AIO(NIO2)使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。 + +**apr** + +安装起来最困难,但是从操作系统级别来解决异步的IO问题,大幅度的提高性能 + +进入tomcat的服务器状态页面查看默认的模式 + +![image20200313202144717.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603162047961.png) + +如果默认使用的是bio模式 + +``` +设置使用nio模式 +[root@zutuanxue logs]# vim /opt/tomcat1/conf/server.xml + +``` + +### apr运行模式 + +APR(Apache portable Run-time libraries,Apache可移植运行库)的目的如其名称一样,主要为上层的应用程序提供一个可以跨越多操作系统平台使用的底层支持接口库。可以大大地提高Tomcat对静态文件的处理性能。 也是在Tomcat上运行高并发应用的首选模式。 + +系统自带的软件包不是最新的,且缺少相关软件包,所以我们选择源码包安装 + +所需软件包 + +apr-1.7.0.tar.gz 主程序包 包含了通用开发组件 + +apr-iconv-1.2.2.tar.gz 用于实现iconv编码 + +apr-util-1.6.1.tar.gz 额外的开发组件 + +tomcat-native.tar.gz 关联tomcat和apr的组件 + +arp相关软件包下载 https://mirrors.cnnic.cn/apache/apr/ + +tomcat-native在tomcat安装目录的bin下 + +### 部署apr环境 + +**step 1** 环境准备 + +``` +[root@zutuanxue ~]# dnf install -y apr-devel openssl-devel gcc make expat-devel libtool +``` + +**step 2** 安装apr主程序包 + +``` +[root@zutuanxue ~]# tar fx apr-1.7.0.tar.gz +[root@zutuanxue ~]# cd apr-1.7.0/ +[root@zutuanxue ~]# ./configure --prefix=/usr/local/apr +[root@zutuanxue apr-1.7.0]# make -j4 && make install +``` + +**step 3** 安装apr-iconv + +``` +[root@zutuanxue ~]# tar fx apr-iconv-1.2.2.tar.gz +[root@zutuanxue ~]# cd apr-iconv-1.2.2/ +[root@zutuanxue ~]# ./configure --with-apr=/usr/local/apr --prefix=/usr/local/apr-iconv +[root@zutuanxue apr-iconv-1.2.2]# make -j4 && make install +``` + +**step 4** 安装apr-util + +``` +[root@zutuanxue ~]# tar fx apr-util-1.6.1.tar.gz +[root@zutuanxue ~]# cd apr-util-1.6.1/ +[root@zutuanxue ~]# ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr --with-apr-iconv=/usr/local/apr-iconv/bin/apriconv +[root@zutuanxue apr-util-1.6.1]# make -j4 && make install +``` + +**step 5** 安装tomcat-native + +``` +[root@zutuanxue ~]# cd /opt/tomcat1/bin/ +[root@zutuanxue bin]# tar fx tomcat-native.tar.gz +[root@zutuanxue bin]# cd tomcat-native-1.2.23-src/native +[root@zutuanxue tomcat-native-1.2.23-src]# ./configure --with-apr=/usr/local/apr --with-java-home=/usr/java/jdk-13.0.2 +[root@zutuanxue tomcat-native-1.2.23-src]# make -j4 && make install +``` + +**step 6** 修改并加载环境变量 + +``` +[root@zutuanxue ~]# echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/apr/lib +export LD_RUN_PATH=$LD_RUN_PATH:/usr/local/apr/lib' >> /etc/profile +[root@zutuanxue ~]# source /etc/profile +``` + +**step 7** 修改tomcat配置文件 + +``` +[root@zutuanxue ~]# vim /opt/tomcat1/conf/server.xml + protocol="org.apache.coyote.http11.Http11AprProtocol" + connectionTimeout="20000" + redirectPort="8443" /> +``` + +**step 8** 测试 + +``` +#为了避免干扰先执行关闭 +[root@zutuanxue ~]# sh /opt/tomcat1/bin/shutdown.sh +#测试 +[root@zutuanxue ~]# sh /opt/tomcat1/bin/catalina.sh run +#如果没有问题可以看到 +14-Mar-2020 00:22:23.894 信息 [main] org.apache.coyote.AbstractProtocol.start 开始协议处理句柄["http-apr-8080"] +``` + +![image20200314122328676.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603162079362.png) + +``` +注意:如果非root用户启动失败,把apr环境变量在当前用户的.bash_profile中写一份 +[root@zutuanxue ~]# echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/apr/lib +export LD_RUN_PATH=$LD_RUN_PATH:/usr/local/apr/lib' >> /root/.bash_profile +[root@zutuanxue ~]# source /root/.bash_profile +``` + +### 其它优化参数 + +``` +[root@zutuanxue logs]# vim /opt/tomcat1/conf/server.xml + + +maxThreads:最大线程数,默认150。增大值避免队列请求过多,导致响应缓慢。 +minSpareThreads:最小空闲线程数。 +acceptCount:当处理请求超过此值时,将后来请求放到队列中等待。 +disableUploadTimeout:禁用上传超时时间 +connectionTimeout:连接超时,单位毫秒,0代表不限制 +URIEncoding:URI地址编码使用UTF-8 +enableLookups:关闭dns解析,提高响应时间 +compression:启用压缩功能 +compressionMinSize:最小压缩大小,单位Byte +compressibleMimeType :压缩的文件类型 + +官方参数文档:http://tomcat.apache.org/tomcat-9.0-doc/config/http.html +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\351\203\250\347\275\262\345\234\250linux\346\234\215\345\212\241\345\231\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\351\203\250\347\275\262\345\234\250linux\346\234\215\345\212\241\345\231\250.md" new file mode 100644 index 0000000..3dabfbe --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\351\203\250\347\275\262\345\234\250linux\346\234\215\345\212\241\345\231\250.md" @@ -0,0 +1,103 @@ +## 一、下载软件包 + +tomcat:https://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-9/v9.0.31/bin/apache-tomcat-9.0.31.zip + +jdk:https://www.oracle.com/java/technologies/javase-downloads.html + +如何想使用tomcat9的话,官方要求JRE的版本必须是8以上的,所以在安装之前,我们需要确认一下本机的版本,如果满足需求的话可以直接安装tomcat + + + +## 二、安装JDK + +``` +# 1、查看当前是否安装过jdk +[root@zutuanxue ~]# java -version +bash: java: 未找到命令... +文件搜索失败: Cannot update read-only repo +#系统提示没有找到命令,意味着没有安装相关软件包,所以我们要安装 + +# 2、安装jdk +[root@zutuanxue ~]# rpm -ivh jdk-13.0.2_linux-x64_bin.rpm +警告:jdk-13.0.2_linux-x64_bin.rpm: 头V3 RSA/SHA256 Signature, 密钥 ID ec551f03: NOKEY +Verifying... ################################# [100%] +准备中... ################################# [100%] +正在升级/安装... + 1:jdk-13.0.2-2000:13.0.2-ga ################################# [100%] + + +# 3、验证:安装完成后再次查看 +[root@zutuanxue ~]# java -version +java version "13.0.2" 2020-01-14 +Java(TM) SE Runtime Environment (build 13.0.2+8)#java的运行环境,也叫jre +Java HotSpot(TM) 64-Bit Server VM (build 13.0.2+8, mixed mode, sharing) + +#JVM java的虚拟机,可以使Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息, +使得Java语言编译程序只需生成在Java虚拟机上运行的字节码就可以了,这样就可以在多种平台上不加修改地运行。很多语言都采用了 +这种类似的思路,才使得他们具有可移植性,比如说python +``` + +## 三、安装Tomcat + +``` +# 1、tomcat 安装 +我们可以看到tomcat软件包的名称包含有apache字样,原因很简单,它是由apache资助的项目 +[root@zutuanxue ~]# unzip apache-tomcat-9.0.31.zip -d /opt/ +[root@zutuanxue ~]# cd /opt/ +[root@zutuanxue opt]# mv apache-tomcat-9.0.31 tomcat1 +解压完成,改个名就可以使用了,因为tomcat是一个二进制包,什么意思呢?就类似于我们下载游戏的时候的硬盘版,什么是硬盘版?解压就能玩, +所以这个tomcat我们就压之后就可以使用了,不需要安装。 + + +[root@zutuanxue bin]# sh startup.sh +Cannot find ./catalina.sh +The file is absent or does not have execute permission +This file is needed to run this program + +# 2、启动tomcat + + ## tomcat启动命令目录 +[root@zutuanxue bin]# pwd +/opt/tomcat1/bin + + ## 启动tomcat +[root@zutuanxue bin]# chmod +x catalina.sh +[root@zutuanxue bin]# sh startup.sh +Using CATALINA_BASE: /opt/tomcat1 +Using CATALINA_HOME: /opt/tomcat1 +Using CATALINA_TMPDIR: /opt/tomcat1/temp +Using JRE_HOME: /usr +Using CLASSPATH: /opt/tomcat1/bin/bootstrap.jar:/opt/tomcat1/bin/tomcat-juli.jar +Tomcat started. +[root@zutuanxue webapps]# netstat -antp | grep java +tcp6 0 0 127.0.0.1:8005 :::* LISTEN 46987/java +tcp6 0 0 :::8080 :::* LISTEN 46987/java + +tomcat的两个端口 +8005 是关闭tomcat使用的端口,可以使用telnet serverip 8005 然后输入大写的SHUTDOWN关闭tomcat,所以建议 +更改端口 或者把引号中了命令改成不容易记忆的,个人推荐改命令,因为改端口没有告诉负责网络安全的同事就会给你屏蔽掉 +……… + +8080 连接端口 + +8009 AJP协议使用的端口,tomcat的优势是处理jsp页面 但是对于图片,静态页面处理能力特别差,相对于apache来说, +那么这个时候怎么办 做个分流 jsp页面由tomcat完成,静态的页面 图片由AJP来完成,AJP是定向包协议 使用二进制格式 +来传输可读性文本,在server.xml配置文件中默认不生效 +``` + +**访问默认首页** [http://localhost:8080](http://localhost:8080/) +![tomcat默认页.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/19/1603105819709.png) + +注意: tomcat的访问端口是8080 + +``` +提示:如果之前系统中安装过java环境的话,可能会出现即便安装完成新的jdk之后,使用java -version命令所查询的结果依然是老版本的, +这个问题是由于环境变量引起的,所以需要修改环境变量设置文件 + +[root@zutuanxue ~]# vim /root/.bash_profile +#####java +JAVA_HOME=/usr/java/jdk-13.0.2#对应自己安装的版本 +PATH=$JAVA_HOME/bin:$PATH:$HOME/bin +CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar +export PATH JAVA_HOME CLASSPATH CATALINA_HOME +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\351\203\250\347\275\262\345\234\250windows\346\234\215\345\212\241\345\231\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\351\203\250\347\275\262\345\234\250windows\346\234\215\345\212\241\345\231\250.md" new file mode 100644 index 0000000..fb04db5 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/Tomcat\351\203\250\347\275\262\345\234\250windows\346\234\215\345\212\241\345\231\250.md" @@ -0,0 +1,51 @@ +## 一、软件包获得 + +tomcat:https://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-9/v9.0.31/bin/apache-tomcat-9.0.31-windows-x64.zip + +jdk:https://www.oracle.com/java/technologies/javase-jdk11-downloads.html + +## 二、安装jdk11 + +![image20200312092554544.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603159556295.png) + +![image20200312092614272.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603159569582.png) + +![image20200312092633326.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603159582416.png) + +![image20200312092648470.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603159592978.png) + +![image20200312092715347.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603159607021.png) + +![image20200312092735514.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603159618146.png) + +![image20200312092806792.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603159628663.png) + +![image20200312092836684.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603159640912.png) + +![image20200312092855640.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603159650428.png) + +![image20200312093114211.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603159694610.png) + +![image20200312093147558.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603159745216.png) + +![image20200312093219637.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603159755696.png) + +![image20200312093335434.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603159765040.png) + +如果使用java -version看到的还是以前的提示,重启一下系统 + +![image20200312093515212.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603159779581.png) + +## 三、安装tomcat + +解压tomcat的压缩包并进入到bin目录下 + +![image20200312094402600.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603159844856.png) + +## 四、访问tomcat默认网站 + +打开浏览器输入: http://localhost:8080 + +![image20200313140037287.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/20/1603159865746.png) + +看到这个页面说明部署成功了!完美! \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/\344\275\277\347\224\250nginx\345\217\221\345\270\203tomcat\347\253\231\347\202\271.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/\344\275\277\347\224\250nginx\345\217\221\345\270\203tomcat\347\253\231\347\202\271.md" new file mode 100644 index 0000000..28a9ecf --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/Web\346\234\215\345\212\241\345\231\250-Tomcat/\344\275\277\347\224\250nginx\345\217\221\345\270\203tomcat\347\253\231\347\202\271.md" @@ -0,0 +1,126 @@ +之前我们在访问的时候使用的都是类似http://serverip/test或者http://serverip/jpress这种字样的URL,使用起来比较麻烦,所以呢,我们可以将tomcat和nginx结合在一起,可以通过nginx以下功能发布: + +- 使用nginx url重写 +- 使用nginx的反向代理功能 + +## 一、部署tomcat网站 + +通过部署两个tomcat站点,分别采用nginx url rewrite方法和反向代理发布。 + +- 设置tomcat1 + +``` +[root@zutuanxue ~]# cd /opt/tomcat1/webapps/ +[root@zutuanxue webapps]# mv ROOT tomcat +[root@zutuanxue webapps]# mv jpress ROOT +``` + +- 设置tomcat2 + +``` +[root@zutuanxue ~]# cd /opt/tomcat2/webapps/ +[root@zutuanxue webapps]# mv ROOT tomcat +[root@zutuanxue webapps]# mv test ROOT +``` + +## 二、使用rewrite实现 + +### 2.1、部署nginx + +``` +[root@zutuanxue ~]# dnf install nginx -y +``` + +### 2.2、设置nginx配置文件 + +``` +[root@zutuanxue ~]# vim /etc/nginx/nginx.conf +[root@zutuanxue ~]# sed -i '/#/d' /etc/nginx/nginx.conf +[root@zutuanxue ~]# sed -i '/^$/d' /etc/nginx/nginx.conf +server { + listen 80; + listen [::]:80; + server_name www.a.com; + location / { + rewrite ^/$ http://127.0.0.1:8080/jpress break; + } + } + server { + listen 80; + listen [::]:80;127.0.0.1 + server_name www.b.com; + location / { + rewrite ^/$ http://127.0.0.1:8081/test break; + } + } +[root@zutuanxue ~]# systemctl restart nginx +``` + +### 2.3、修改测试机的hosts文件 + +``` +[root@zutuanxue conf]# vim /etc/hosts +192.168.98.200 www.a.com +192.168.98.200 www.b.com +``` + +### 2.4、 打开浏览器直接访问域名测试 + +测试方法: +打开浏览器输入之前设置好的域名 +http://www.a.com +http://www.b.com +查看是否能访问到对应的网站内容,能看到说明实验成功。 + +## 三、使用反向代理实现 + +### 3.1、设置nginx配置文件 + +``` +user nginx; +worker_processes auto; +error_log /var/log/nginx/error.log; +pid /run/nginx.pid; +include /usr/share/nginx/modules/*.conf; +events { + worker_connections 1024; +} +http { + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + access_log /var/log/nginx/access.log main; + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + include /etc/nginx/mime.types; + default_type application/octet-stream; + include /etc/nginx/conf.d/*.conf; + server { + listen 80; + listen [::]:80; + server_name www.a.com; + location / { + proxy_pass http://127.0.0.1:8080; + } + } + server { + listen 80; + listen [::]:80; + server_name www.b.com; + location / { + proxy_pass http://127.0.0.1:8081; + } + } +} +``` + +### 3.2、打开浏览器直接访问域名测试 + +测试方法: +打开浏览器输入之前设置好的域名 +http://www.a.com +http://www.b.com +查看是否能访问到对应的网站内容,能看到说明实验成功。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/for\345\265\214\345\245\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/for\345\265\214\345\245\227.md" new file mode 100644 index 0000000..70d398e --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/for\345\265\214\345\245\227.md" @@ -0,0 +1,77 @@ +## 一、for嵌套 + +**1.1、for嵌套if** + +**案例:** +输出1-9,当输出5时停止输出 + +**案例代码** + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description:输出1-9,当输出5时停止输出 + +for ((num=1;num<10;num++)) + do + echo $num + [ $num -eq 5 ]&& break +done +``` + +**1.2、for嵌套for** +**案例:** +打印99乘法表 + +**案例代码** + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: +#打印99乘法表,思考A*B的关系 +for ((A=1;A<=9;A++)) + do + for ((B=1;B<=$A;B++)) + do + echo -n -e "$B*$A=$((A*B)) \t" + done + #换行 + echo +done +``` + +## 二、for与数组 + +**for循环与数组** + +2.1、使用for循环遍历读出数组 + +``` +name=('tom' 'jarry' 'harry' 'barry') +for i in 0 1 2 3 + do + echo ${name[$i]} + done +``` + +2.2、使用for循环进行数组存值 + +``` +for i in `seq 0 9` + do + read -p "name: " name[$i] + done + echo ${name[@]} +``` + +## 三、学习视频 + +[视频:for嵌套](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=60) +[视频:for实战](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=61) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/if\350\257\255\345\217\245\344\270\216shell\350\277\220\347\256\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/if\350\257\255\345\217\245\344\270\216shell\350\277\220\347\256\227.md" new file mode 100644 index 0000000..2781b0e --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/if\350\257\255\345\217\245\344\270\216shell\350\277\220\347\256\227.md" @@ -0,0 +1,166 @@ +if是一个条件判断语句,判断的前提是得有个条件。so,条件就显得格外重要了,if中可以有哪些条件呢?接下来我们就来聊一聊if条件的问题。 +我们在之前的课程中学习了shell的运算,有比较运算、逻辑运算、文件运算等,这些运算可以植入到if条件中吗?答案是肯定的,接下来我就给大家演示一下如何在if条件中植入shell运算条件 + +## 一、与文件存在与否的判断 + +``` +-e 是否存在 不管是文件还是目录,只要存在,条件就成立 +-f 是否为普通文件 +-d 是否为目录 +-S socket +-p pipe +-c character +-b block +-L 软link +``` + +- **文件权限相关的判断** + +```l +-r 当前用户对其是否可读 +-w 当前用户对其是否可写 +-x 当前用户对其是否可执行 +-u 是否有suid +-g 是否sgid +-k 是否有t位 +``` + +- **两个文件的比较判断** + +``` +file1 -nt file2 比较file1是否比file2新 +file1 -ot file2 比较file1是否比file2旧 +file1 -ef file2 比较是否为同一个文件,或者用于判断硬连接,是否指向同一个inode +``` + +- **整数之间的判断** + +``` +-eq 相等 +-ne 不等 +-gt 大于 +-lt 小于 +-ge 大于等于 +-le 小于等于 + + +浮点比较运算 +比较两个浮点数字的大小 +给脚本两个浮点数字 返回他两的关系 + + +#思路 +1、获得两个浮点数字 +2、处理为整形 +3、比较 +4、输出 +``` + +- **字符串之间的判断** + +``` +-z 是否为空字符串 字符串长度为0,就成立 +-n 是否为非空字符串 只要字符串非空,就是成立 +string1 == string2 是否相等 +string1 != string2 不等 + + +#用户登录验证 + +[root@zutuanxue ~]# cat if-6.sh +#!/bin/bash +#1、交互式输入用户名 密码 +read -p "user: " myuser +if [ -z "$myuser" ];then + echo "用户名为空" + exit 1 +fi + +#从外往里写 +read -p "password: " mypw +if [ -n "$mypw" ];then + #2、判断是否正确 + #2.1 判断用户名 + if [ $myuser == "root" ];then + #2.2判断密码 + if [ $mypw == "abc-123" ];then + echo "welcome root" + else + echo "密码错误" + exit 1 + fi + + else + echo "用户名错误" + exit 1 + fi + +else + echo "密码不能为空" + exit 1 +fi +``` + +- **多重条件判断** + +```shell +逻辑判断符号: +&& (and 逻辑与) 两个条件同时满足,整个大条件为真 +|| (or 逻辑或) 两个条件满足任意一个,整个大条件为真 +! 非运算 + +#用户登录验证 +[root@zutuanxue ~]# cat if-6.sh +#!/bin/bash +#1、交互式输入用户名 密码 +read -p "user: " myuser +if [ -z "$myuser" ];then + echo "用户名为空" + exit 1 +fi + +#从外往里写 +read -p "password: " mypw +if [ -n "$mypw" ];then + #2、判断是否正确 + #2.1 判断用户名 + #if [ $myuser == "root" ];then + #2.2判断密码 + # if [ $mypw == "abc-123" ];then + # echo "welcome root" + #else + # echo "密码错误" + # exit 1 + # fi + # + #else + # echo "用户名错误" + # exit 1 + #fi + + if [ $myuser == 'root' ] && [ $mypw == 'abc-123' ];then + echo "welcome root" + else + echo "用户名或密码错误" + exit 1 + fi + +else + echo "密码不能为空" + exit 1 +fi +``` + +## 二、课后练习 + +``` +练习题1、判断/tmp/tyschool目录,如果没有则创建它 +练习题2、判断是否有/usr/bin/wget命令,没有则安装他 +练习题3、判断当前用户是否为管理员,UID为0或者为root都算管理员 +练习题4、打印物理内存使用率 +``` + +## 三、学习视频 + +[视频:if与shell运算01](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=47) +[视频:if与shell运算02](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=48) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/if\351\253\230\347\272\247\347\224\250\346\263\225.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/if\351\253\230\347\272\247\347\224\250\346\263\225.md" new file mode 100644 index 0000000..73eed4b --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/if\351\253\230\347\272\247\347\224\250\346\263\225.md" @@ -0,0 +1,67 @@ +## 一、if高级用法 + +### 1.1、条件符号使用双圆括号,可以在条件中植入数学表达式 if (()) + +``` +#!/bin/bash +#Author: www.zutuanxue.com +#Created Time: +#Script Description: + +if (( (5+5-5)*5/5 > 10 )) + then + echo "yes" +else + echo "no" +fi +``` + +### 1.2、使用双方括号,可以在条件中使用通配符 + +通过代码看下 ,为字符串提供高级功能,模式匹配 r* 匹配r开头的字符串 + +``` +#!/bin/bash +#Author: www.zutuanxue.com +#Created Time: +#Script Description: +for var in ab ac rx bx rvv vt + do + if [[ "$var" == r* ]] + then + echo "$var" + fi +done +``` + +## 二、简写if + +省去了关键字,条件为真采用&&符号链接命令块,条件为假采用||链接命令块 + +简写if一般用在简单的判断中 + +``` +if [ ! -d /tmp/baism ] + then + mkdir /tmp/baism +fi + +可以简写为 + +[ ! -d /tmp/baism ] && mkdir /tmp/baism + +if [ $USER == 'root' ] + then + echo "hello root" +else + echo "hello guest" +fi + +可以简写 +[ $USER == 'root' ]&&echo "hello root" || echo "hello guest" +``` + +## 三、学习视频 + +[视频:if高级用法](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=49) +[视频:if知识图谱总结](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=50) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell \346\225\260\347\273\204\350\257\246\350\247\243.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell \346\225\260\347\273\204\350\257\246\350\247\243.md" new file mode 100644 index 0000000..dd7cf87 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell \346\225\260\347\273\204\350\257\246\350\247\243.md" @@ -0,0 +1,170 @@ +有这样一个现实问题:一个班级学员信息系统,要求存储学员ID、NAME、SCORE、AGE、GENDER,班级有50个人,思考如何解决交互中数据存储的问题。很多人可能直接说或定义变量接收数据不就行了!nice,你很棒!! +解决方案如下: +1)每个学生通过5个变量,一个班级50个学生,5*50=250,妥妥的!我定义250个变量接收就可以了,美美哒! + +兄弟,现在不是全班了是全校的学生需要录入你这个信息系统,你写变量吧!!当我提出这个需求的时候,作为开发你会不会想骂娘呢? + +2)使用数组来定义,我只需要定义5个数组来接收所有用户的数据就可以了,5个数组就能解决一切,你觉得你会不会想了解下数组是什么呢? + +## 一、数组介绍 + +数组可以让用户一次赋予多个值,需要读取数据时只需通过索引调用就可以方便读出了。 + +普通数组:只能使用整数作为数组索引(元素的索引) +关联数组:可以使用字符串作为数组索引(元素的索引) + +## 二、数组定义 + +``` + 数组名称=(元素1 元素2 元素3 ...) +``` + +## 三、数组赋值方式 + +- 一次附一个值 + +``` +变量名=变量值 +array[0]=v1 +array[1]=v2 +array[3]=v3 +``` + +- 一次附多个值 + +``` +array=(var1 var2 var3 var4) +array1=(`cat /etc/passwd`) //将文件中每一行赋值给array1数组 +array2=(`ls /root`) +array3=(harry amy jack "Miss zhang") +array4=(1 2 3 4 "hello world" [10]=linux) +``` + +四、数组取值 +**取值方式:** ${数组名称[索引]} + +**索引:** 默认情况下索引是指数组中的元素[存的值]在数组中的顺序,从0开始计数,关联数组除外。比如: +array=(var1 var2 var3 var4) +array数组中存有4个元素,分别是:var1 var2 var3 var4 +那么我想取出var2这个元素,那么就得先看看他在数组中的位置,数组中的元素索引如下: + +``` + 元素 var1 var2 var3 var4 + 索引 0 1 2 3 +``` + +所以正确表示array数组中元素var2的方式是:${array[1]} + +**数组取值练习** + +``` +${array[i]} i表示元素的索引 +使用@ 或 * 可以获取数组中的所有元素: +获取第一个元素 +echo ${array[0]} +echo ${array[*]} 获取数组里的所有元素 +echo ${#array[*]} 获取数组里所有元素个数 +echo ${!array[@]} 获取数组元素的索引索引 +echo ${array[@]:1:2} 访问指定的元素;1代表从索引为1的元素开始获取;2代表获取后面几个元素 +``` + +## 五、关联数组 + +### 5.1 定义管理数组 + +关联数组使用首先需要申明该数组为关联数组,申明方式: declare -A 数组名称 + +``` +首先声明关联数组 +declare -A asso_array1 +declare -A asso_array2 +declare -A asso_array3 +``` + +### 5.2关联数组赋值 + +- 一次赋一个值 + +``` +数组名[索引]=变量值 +[root@zutuanxue ~]# asso_array1[linux]=one +[root@zutuanxue ~]# asso_array1[java]=two +[root@zutuanxue ~]# asso_array1[php]=three +``` + +- 一次附多个值 + +``` +[root@zutuanxue ~]# asso_array2=([name1]=harry [name2]=jack [name3]=amy [name4]="Miss zhang") +``` + +- 查看关联数组 + +``` +[root@zutuanxue ~]# declare -A +declare -A asso_array1='([php]="three" [java]="two" [linux]="one" )' +declare -A asso_array2='([name3]="amy" [name2]="jack" [name1]="harry" [name4]="Miss zhang" )' +``` + +### 管理数组取值 + +``` +[root@zutuanxue ~]# echo ${asso_array1[linux]} +one +[root@zutuanxue ~]# echo ${asso_array1[php]} +three +[root@zutuanxue ~]# echo ${asso_array1[*]} +three two one +[root@zutuanxue ~]# echo ${!asso_array1[*]} +php java linux +[root@zutuanxue ~]# echo ${#asso_array1[*]} +3 +[root@zutuanxue ~]# echo ${#asso_array2[*]} +4 +[root@zutuanxue ~]# echo ${!asso_array2[*]} +name3 name2 name1 name4 +``` + +## 六、课堂练习 + +#### 2.1 写一个监控CPU 平均负载值的脚本 + +**案例需求** +分别打印CPU 1min 5min 15min load负载值 + +**案例思路** + +- 1、如何取CPU负载值,有哪些命令 +- 2、如果存储在内存中,变量、数组 + +**案例步骤** + +- 1、收集cpu load 平均负载值到数组 +- 2、打印输出对应的负载值 + +**代码实现** + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +# +#Release: +#Description: 打印cpu 1min 5min 15min的负载值 + +#1、收集负载值 +cpu_load=(`uptime|tr -s " "|cut -d " " -f9-11|tr "," " "`) +#2、输出负载值 +echo "CPU 1 min平均负载为: ${cpu_load[0]}" +echo "CPU 5 min平均负载为: ${cpu_load[1]}" +echo "CPU 15 min平均负载为: ${cpu_load[2]}" +``` + +**代码效果** + +``` +[root@zutuanxue day2]# sh cpu_load.sh +CPU 1 min平均负载为: 0.00 +CPU 5 min平均负载为: 0.01 +CPU 15 min平均负载为: 0.05 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\345\207\275\346\225\260.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\345\207\275\346\225\260.md" new file mode 100644 index 0000000..3a44a80 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\345\207\275\346\225\260.md" @@ -0,0 +1,141 @@ +shell脚本中的代码是按照执行的优先级的顺序从上往下抒写的,代码量越大,在脚本调试的时候就越难排错,当因执行需要调整代码执行顺序的时候就需要不断的复制粘贴,或者删除部分代码来完成,这和从写一个脚本花费的时候相比甚至需要更长的时间。 + +代码量大后遇到的问题: + +- 单个脚本代码量大 (300-500行) +- 阅读修改耗时费力 +- 排错困难 +- 改变执行顺序困难 + +为了解决这些问题,我们可以把代码模块化,按需调用。 + +## 一、函数 + +### 1.1、函数介绍 + +shell中允许将**一组命令集合**或**语句**形成一段**可用代码**,这些代码块称为shell函数。给这段代码起个名字称为函数名,后续可以直接调用该段代码的功能。 + +将完成一个功能的一段代码进行命名、封装 + +函数的优点: + +1. 代码模块化,调用方便,节省内存 +2. 代码模块化,代码量少,排错简单 +3. 代码模块化,可以改变代码的执行顺序 + +### 1.2、函数定义 + +``` +语法一: + +函数名 () { + 代码块 + return N + } + + +语法二: +function 函数名 { + 代码块 + return N + } + + +函数中return说明: +1.return可以结束一个函数,类似于前面讲的循环控制语句break(结束当前循环,执行循环体后面的代码) +2.return默认返回函数中最后一个命令的退出状态,也可以给定参数值,该参数值的范围是0-256之间。 +3.如果没有return命令,函数将返回最后一个Shell的退出值。 +``` + +### 1.3、函数调用 + +- 当前命令行调用 + +``` +[root@zutuanxue shell04]# cat fun1.sh +#!/bin/bash +hello(){ +echo "hello zutuanxue $1" +hostname +} +menu(){ +cat <<-EOF +1. mysql +2. web +3. app +4. exit +EOF +} + +[root@zutuanxue shell04]# source fun1.sh +[root@zutuanxue shell04]# . fun1.sh + +[root@zutuanxue shell04]# hello 888 +hello zutuanxue 888 +MissHou.zutuanxue.cc +[root@zutuanxue shell04]# menu +1. mysql +2. web +3. app +4. exit +``` + +- 定义到用户的环境变量中 + +``` +/etc/profile /etc/bashrc ~/.bash_profile ~/.bashrc + +[root@zutuanxue shell04]# cat ~/.bashrc +# .bashrc + +# User specific aliases and functions + +alias rm='rm -i' +alias cp='cp -i' +alias mv='mv -i' +# Source global definitions +if [ -f /etc/bashrc ]; then + . /etc/bashrc +fi + +hello(){ +echo "hello zutuanxue $1" +hostname +} +menu(){ +cat <<-EOF +1. mysql +2. web +3. app +4. exit +EOF +} + +注意: +当用户打开bash的时候会读取该文件 +``` + +- 脚本中调用 + +``` +#!/bin/bash +#打印菜单 +source ./fun1.sh +menu(){ +cat <<-END + h 显示命令帮助 + f 显示磁盘分区 + d 显示磁盘挂载 + m 查看内存使用 + u 查看系统负载 + q 退出程序 + END +} +menu //调用函数 +``` + +## 二、学习视频 + +[视频:函数与case语句介绍](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=68) +[视频:函数介绍与定义](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=69) +[视频:函数调用](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=70) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\345\217\230\351\207\217\350\257\246\350\247\243.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\345\217\230\351\207\217\350\257\246\350\247\243.md" new file mode 100644 index 0000000..911c41a --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\345\217\230\351\207\217\350\257\246\350\247\243.md" @@ -0,0 +1,342 @@ +## 一、变量介绍 + +在编程中,我们总有一些数据需要临时存放在内存,以待后续使用时快速读出。先了解一下计算机的存储单位吧。 + +``` +计算机的单位: +1B=8bit + +1KB=1024B +1MB=1024KB +1GB=1024MB +1TB=1024GB +1PB=1024TB +1EB=1024PB +1ZB=1024EB +... +好了,已经够大了!当然还有YB、BB更大的单位,同样进制也是1024. + +1G=1024*1024*1024=1073741824B +``` + +假如你将一个1B的字符存入内存,如何读出呢?有没有一种大海捞针的感觉啊!我们讨论一下计算机是如何通过让我们人类快速将数据存在内存,如何从内存中读出数据的。我们研究过变量后就明白了。 + +变量:变量是编程中最常用的一种临时在内存中存取数据的一种方式。 + +变量存取原理 + +``` +关于内存的说明 +a、系统启动 内存被按照1B一个单位划分成N块 并且以十六进制为每一个空间编号 + +b、内存跟踪表记录 使用和未使用的内存的地址编号 + +c、内存申请 系统从未使用的内存中拿出一个或者一段连续空间 给你使用 同时在内存跟踪表中记录 +该地址被占用不在分给别人,同时在系统中建立映射机制 +比如:变量名 STRING1=‘ABC’ + +name<==>0x5 + +d、释放内存 +从内存跟踪表中将记录删除,下次存数据直接覆盖 +``` + +![变量存储.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/21/1600685218168.png) + +``` +CHAR1(0x3)=A +从图片可以看出,当我们在脚本中定义变量存值的时候,可以从以下方面看到变化: +a、内存占用:如果存的是一个字符则占用1个字节,如果存的是字符串则是字符串的长度加1个字节长度(\0是一个 +特殊字符,代表字符串结束)。 + +b、变量名与内存空间关系:计算机中会将对应的内存空间地址和变量名称绑定在一起,此时代表这段内存空间已经被 +程序占用,其他程序不可复用;然后将变量名对应的值存在对应内存地址的空间里。 +``` + +## 二、变量定义 + +##### 2.1、什么时候需要定义变量? + +如果某个内容需要多次使用,并且在代码中重复出现,那么可以用变量代表该内容。这样在修改内容的时候,仅仅需要修改变量的值。 +在代码运作的过程中,可能会把某些命令的执行结果保存起来,后续代码需要使用这些结果,就可以直接使用这个变量。 + +##### 2.2、定义一个变量 + +变量格式: 变量名=值 + +在shell编程中的变量名和等号之间不能有空格。 + +``` +变量名命名规则: + 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。 + 中间不能有空格,可以使用下划线(_)。 + 不能使用标点符号。 + 不能使用bash里的关键字(可用help命令查看保留关键字)。 +``` + +定义变量举例: +VAR1=1 +age=18 整形 +name=‘baism’ 字符串 +score=88.8 浮点 + +``` +注意:字符串要用单引号或双引号引起来 +建议变量名为大写,和命令区分 + _name +``` + +定义变量演示: + +``` +变量赋值,此种方法设置为本地变量 +[root@zutuanxue ~]# name="baism" +[root@zutuanxue ~]# school='ayitula' +[root@zutuanxue ~]# age=30 +[root@zutuanxue ~]# score=88.8 +``` + +##### 2.3、取消变量 unset + +``` +取消当前环境中的变量,如果是变量设置是保存在文件中,下次重启又会恢复 +[root@zutuanxue ~]# unset name +[root@zutuanxue ~]# echo $name +``` + +##### 2.4、 有类型变量 declare + +-i 将变量看成整数 +-r 使变量只读 readonly,该变量的值无法改变,并且不能为unset +-x 标记变量通过环境导出 export +-a 指定为索引数组(普通数组);查看普通数组 +-A 指定为关联数组;查看关联数组 + +``` +[root@zutuanxue ~]# declare -i num='asa' +[root@zutuanxue ~]# echo $num +0 +[root@zutuanxue ~]# num=100 +[root@zutuanxue ~]# echo $num +100 +[root@zutuanxue ~]# declare -r num +[root@zutuanxue ~]# echo $num +100 +[root@zutuanxue~]# num=200 +-bash: num: 只读变量 + +[root@zutuanxue ~]# declare -x +declare -x HISTCONTROL="ignoredups" +declare -x HISTSIZE="1000" +declare -x HOME="/root" +declare -x HOSTNAME="Bai_Shuming" +declare -x LANG="zh_CN.UTF-8" +declare -x LESSOPEN="||/usr/bin/lesspipe.sh %s" +``` + +## 三、变量分类 + +系统中的变量根据作用域及生命周期可以分为四类:本地变量、环境变量、全局变量、内置变量 + +##### 3.1、本地变量 + +用户自定义的变量,定义在脚本或者当前终端中,脚本执行完毕或终端结束变量失效。 + +##### 3.2、环境变量 + +定义在用户家目录下的.bashrc或.bash_profile文件中,用户私有变量,只能本用户使用。 + +查看当前用户的环境变量 env + +查询当前用户的所有变量(临时变量与环境变量) set + +##### 3.3、将当前变量变成环境变量 export + +``` +定义一个临时变量 +1、 +[root@zutuanxue tmp]# export A=hello //临时将一个本地变量(临时变量)变成环境变量 +[root@zutuanxue tmp]# env|grep ^A +A=hello +2、 +[root@zutuanxue tmp]# A=HELLO +[root@zutuanxue tmp]# export A + +3、定义一个永久生效变量: +vim .bash_profile 或者 ~/.bashrc +A=hello + + +关于export说明 +用户登录时: +1) 用户登录到Linux系统后,系统将启动一个用户shell。在这个shell中,可以使用shell命令或声明变量,也可以 +创建并运行 shell脚本程序。 + +运行脚本时: +2) 运行shell脚本程序时,系统将创建一个子shell。此时,系统中将有两个shell,一个是登录时系统启动的shell, +另一个是系统为运行脚本程序创建的shell。当一个脚本程序运行完毕,它的脚本shell将终止,可以返回到执行该脚本 +之前的shell。 + +从这种意义上来说,用户可以有许多 shell,每个shell都是由某个shell(称为父shell)派生的。 +在子shell中定义的变量只在该子shell内有效。如果在一个shell脚本程序中定义了一个变量,当该脚本程序运行时, +这个定义的变量只是该脚本程序内的一个局部变量,其他的shell不能引用它,要使某个变量的值可以在其他shell中 +被改变,可以使用export命令对已定义的变量进行输出。 + +export命令将使系统在创建每一个新的shell时定义这个变量的一个拷贝。这个过程称之为变量输出。 +``` + +父shell与子shell + +![shell父子关系.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/21/1600685550727.png) + +##### 3.4、全局变量 + +使用export命令将本地变量输出为当前shell中的环境变量 +所有用户及shell都可以使用,可以在/etc/profile /etc/bashrc下永久定义 + +``` +打印全局变量 printenv + +定义格式 +export SCHOOL='zutuanxue' + + +测试方法: +通过不同用户登录测试是否能读取变量 +``` + +##### 3.5、内置变量 + +系统变量(内置bash中变量) : shell本身已经固定好了它的名字和作用. + +``` +$?:上一条命令执行后返回的状态,当返回状态值为0时表示执行正常,非0值表示执行异常或出错 + 若退出状态值为0,表示命令运行成功 + 若退出状态值为127,表示command not found + 若退出状态值为126,表示找到了该命令但无法执行(权限不够) + 若退出状态值为1&2,表示没有那个文件或目录 + +$$:当前所在进程的进程号 echo $$ eg:kill -9 `echo $$` = exit 退出当前会话 + +$!:后台运行的最后一个进程号 (当前终端) # gedit & +!$ 调用最后一条命令历史中的参数 +!! 调用最后一条命令历史 + + +$#:脚本后面接的参数的个数 +$*:脚本后面所有参数,参数当成一个整体输出,每一个变量参数之间以空格隔开 +$@: 脚本后面所有参数,参数是独立的,也是全部输出 + +$0:当前执行的进程/程序名 echo $0 +$1~$9 位置参数变量 +${10}~${n} 扩展位置参数变量 第10个位置变量必须用{}大括号括起来 +./1.sh a b c + +[root@zutuanxue shell01]# cat 2.sh +#!/bin/bash +#xxxx +echo "\$0 = $0" +echo "\$# = $#" +echo "\$* = $*" +echo "\$@ = $@" +echo "\$1 = $1" +echo "\$2 = $2" +echo "\$3 = $3" +echo "\$11 = ${11}" +echo "\$12 = ${12}" + +了解$*和$@的区别: +$* :表示将变量看成一个整体 +$@ :表示变量是独立的 + +#!/bin/bash +for i in "$@" +do +echo $i +done + +echo "======我是分割线=======" + +for i in "$*" +do +echo $i +done + +[root@zutuanxue shell01]# bash 3.sh a b c +a +b +c +======我是分割线======= +a b c +``` + +变量总结说明: + +本地变量:当前用户自定义的变量。当前进程中有效,其他进程及当前进程的子进程无效。 + +环境变量:当前进程有效,并且能够被子进程调用。 + +全局变量:全局所有的用户和程序都能调用,且继承,新建的用户也默认能调用. + +内置变量:shell本身已经固定好了它的名字和作用. + +| 变量类型 | 作用域 | 生命周期 | +| -------- | ---------------------------- | ------------------ | +| 本地变量 | 当前shell环境(子shell不能用) | 脚本结束或终端结束 | +| 环境变量 | 当前shell或者子shell | 当前进程结束 | +| 全局变量 | 所有用户及shell环境 | 关机 | +| 内置变量 | 所有用户及shell环境 | 关机 | + +## 四、变量取值 + +读取变量内容符: 读取方法:变量名 + +``` +变量内容读出 +[root@zutuanxue ~]# echo $name +baism +[root@zutuanxue ~]# echo $school +ayitula +[root@zutuanxue ~]# echo $age +30 +[root@zutuanxue ~]# echo $score +88.8 +``` + +**注意** + +``` +变量读取过程中,默认单引号是不解释变量的.比如 +[root@zutuanxue ~]# echo '$name' +$name + +如果必须使用单引号还要读取变量的值可以使用eval命令[重新运算求出参数的内容] +[root@zutuanxue ~]# eval echo '$name' +baism +``` + +## 五、其他变量(扩展) + +``` +1)取出一个目录下的目录和文件:dirname和 basename +2)变量"内容"的删除和替换 +一个“%”代表从右往左去掉一个/key/ +两个“%%”代表从右往左最大去掉/key/ +一个“#”代表从左往右去掉一个/key/ +两个“##”代表从左往右最大去掉/key/ + +# A=/root/Desktop/shell/mem.txt +# echo $A +/root/Desktop/shell/mem.txt +# dirname $A 取出目录 +/root/Desktop/shell +# basename $A 取出文件 +mem.txt + +# url=www.taobao.com +# echo ${#url} 获取变量的长度 +# echo ${url#*.} 以分隔符.界限 *匹配所有 +# echo ${url##*.} +# echo ${url%.*} +# echo ${url%%.*} +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\345\257\271\346\226\207\344\273\266\347\232\204\346\223\215\344\275\234.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\345\257\271\346\226\207\344\273\266\347\232\204\346\223\215\344\275\234.md" new file mode 100644 index 0000000..e790192 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\345\257\271\346\226\207\344\273\266\347\232\204\346\223\215\344\275\234.md" @@ -0,0 +1,618 @@ +在shell脚本编写中,时常会用到对文件的相关操作,比如增加内容,修改内容,删除部分内容,查看部分内容等,但是上述举例的这些操作一般都是需要在文本编辑器中才能操作,常用的文本编辑器如:gedit、vim、nano等又是交互式文本编辑器,脚本无法自己独立完成,必须有人参与才可以完成。如果这样的话又违背了我们编写脚本的意愿(全部由机器来完成,减少人的工作压力,提升工作效率)。emm…如何才能让这些操作全部脚本自己就搞定,而不需要人的参与,而且又能按照我们的脚本预案来完成呢? + +为了解决上述问题,linux为大家提供了一些命令,比如Perl、sed等命令,今天我就着重为大家介绍一下sed命令。 + +## 一、sed介绍 + +sed是linux中提供的一个外部命令,它是一个行(流)编辑器,非交互式的对文件内容进行增删改查的操作,使用者只能在命令行输入编辑命令、指定文件名,然后在屏幕上查看输出。它和文本编辑器有本质的区别。 + +``` +区别是: + +文本编辑器: 编辑对象是文件 + +行编辑器:编辑对象是文件中的行 +``` + +也就是前者一次处理一个文本,而后者是一次处理一个文本中的一行。这个是我们应该弄清楚且必须牢记的,否者可能无法理解sed的运行原理和使用精髓。 + +**sed数据处理原理** + +![sed处理数据原理.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601961286169.png) + +## 二、sed语法 + +**sed 命令语法:** + +sed [options] ‘{command}[flags]’ [filename] + +``` +#命令选项 +-e script 将脚本中指定的命令添加到处理输入时执行的命令中 多条件,一行中要有多个操作 +-f script 将文件中指定的命令添加到处理输入时执行的命令中 +-n 抑制自动输出 +-i 编辑文件内容 +-i.bak 修改时同时创建.bak备份文件。 +-r 使用扩展的正则表达式 +! 取反 (跟在模式条件后与shell有所区别) + +#command 对文件干什么 +sed常用内部命令 +a 在匹配后面添加 +i 在匹配前面添加 + +d 删除 + +s 查找替换 字符串 +c 更改 +y 转换 N D P + + +p 打印 + + + +#flags +数字 表示新文本替换的模式 +g: 表示用新文本替换现有文本的全部实例 +p: 表示打印原始的内容 +w filename: 将替换的结果写入文件 +``` + +### 2.1)sed内部命令说明 + +**演示实例文档** + +``` +[root@zutuanxue ~]# cat data1 +1 the quick brown fox jumps over the lazy dog. +2 the quick brown fox jumps over the lazy dog. +3 the quick brown fox jumps over the lazy dog. +4 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. +``` + +文件内容增加操作,将数据追加到某个位置之后,使用命令a。 + +**演示案例** + +``` +在data1的每行后追加一行新数据内容: append data "haha" +[root@zutuanxue ~]# sed 'a\append data "haha"' data1 +1 the quick brown fox jumps over the lazy dog. +append data "haha" +2 the quick brown fox jumps over the lazy dog. +append data "haha" +3 the quick brown fox jumps over the lazy dog. +append data "haha" +4 the quick brown fox jumps over the lazy dog. +append data "haha" +5 the quick brown fox jumps over the lazy dog. +append data "haha" + + +在第二行后新开一行追加数据: append data "haha" +[root@zutuanxue ~]# sed '2a\append data "haha"' data1 +1 the quick brown fox jumps over the lazy dog. +2 the quick brown fox jumps over the lazy dog. +append data "haha" +3 the quick brown fox jumps over the lazy dog. +4 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. + +在第二到四行每行后新开一行追加数据: append data "haha" +[root@zutuanxue ~]# sed '2,4a\append data "haha"' data1 +1 the quick brown fox jumps over the lazy dog. +2 the quick brown fox jumps over the lazy dog. +append data "haha" +3 the quick brown fox jumps over the lazy dog. +append data "haha" +4 the quick brown fox jumps over the lazy dog. +append data "haha" +5 the quick brown fox jumps over the lazy dog. + +匹配字符串追加: 找到包含"3 the"的行,在其后新开一行追加内容: append data "haha" +[root@zutuanxue ~]# sed '/3 the/a\append data "haha"' data1 +1 the quick brown fox jumps over the lazy dog. +2 the quick brown fox jumps over the lazy dog. +3 the quick brown fox jumps over the lazy dog. +append data "haha" +4 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. + +//开启匹配模式 /要匹配的字符串/ +``` + +文件内容增加操作,将数据插入到某个位置之前,使用命令i。 + +**演示案例** + +``` +在data1的每行前插入一行新数据内容: insert data "haha" +[root@zutuanxue ~]# sed 'i\insert data "haha"' data1 +insert data "haha" +1 the quick brown fox jumps over the lazy dog. +insert data "haha" +2 the quick brown fox jumps over the lazy dog. +insert data "haha" +3 the quick brown fox jumps over the lazy dog. +insert data "haha" +4 the quick brown fox jumps over the lazy dog. +insert data "haha" +5 the quick brown fox jumps over the lazy dog. + + +在第二行前新开一行插入数据: insert data "haha" +[root@zutuanxue ~]# sed '2i\insert data "haha"' data1 +1 the quick brown fox jumps over the lazy dog. +insert data "haha" +2 the quick brown fox jumps over the lazy dog. +3 the quick brown fox jumps over the lazy dog. +4 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. + + +在第二到四行每行前新开一行插入数据: insert data "haha" +[root@zutuanxue ~]# sed '2,4i\insert data "haha"' data1 +1 the quick brown fox jumps over the lazy dog. +insert data "haha" +2 the quick brown fox jumps over the lazy dog. +insert data "haha" +3 the quick brown fox jumps over the lazy dog. +insert data "haha" +4 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. + + +匹配字符串插入: 找到包含"3 the"的行,在其前新开一行插入内容: insert data "haha" +[root@zutuanxue ~]# sed '/3 the/i\insert data "haha"' data1 +1 the quick brown fox jumps over the lazy dog. +2 the quick brown fox jumps over the lazy dog. +insert data "haha" +3 the quick brown fox jumps over the lazy dog. +4 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. +``` + +文件内容修改操作–替换,将一行中匹配的内容替换为新的数据,使用命令s。 + +**演示案例** + +``` +从标准输出流中做替换,将test替换为text +[root@zutuanxue ~]# echo "this is a test" |sed 's/test/text/' +this is a text + +将data1中每行的dog替换为cat +[root@zutuanxue ~]# sed 's/dog/cat/' data1 +1 the quick brown fox jumps over the lazy cat. +2 the quick brown fox jumps over the lazy cat. +3 the quick brown fox jumps over the lazy cat. +4 the quick brown fox jumps over the lazy cat. +5 the quick brown fox jumps over the lazy cat. + +将data1中第二行的dog替换为cat +[root@zutuanxue ~]# sed '2s/dog/cat/' data1 +1 the quick brown fox jumps over the lazy dog. +2 the quick brown fox jumps over the lazy cat. +3 the quick brown fox jumps over the lazy dog. +4 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. + +将data1中第二到第四行的dog替换为cat +[root@zutuanxue ~]# sed '2,4s/dog/cat/' data1 +1 the quick brown fox jumps over the lazy dog. +2 the quick brown fox jumps over the lazy cat. +3 the quick brown fox jumps over the lazy cat. +4 the quick brown fox jumps over the lazy cat. +5 the quick brown fox jumps over the lazy dog. + +匹配字符串替换:将包含字符串"3 the"的行中的dog替换为cat +[root@zutuanxue ~]# sed '/3 the/s/dog/cat/' data1 +1 the quick brown fox jumps over the lazy dog. +2 the quick brown fox jumps over the lazy dog. +3 the quick brown fox jumps over the lazy cat. +4 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. +``` + +文件内容修改操作–更改,将一行中匹配的内容替换为新的数据,使用命令c。 + +**演示案例** + +``` +将data1文件中的所有行的内容更改为: change data "data" +[root@zutuanxue ~]# sed 'c\change data "haha"' data1 +change data "haha" +change data "haha" +change data "haha" +change data "haha" +change data "haha" + +将data1文件第二行的内容更改为: change data "haha" +[root@zutuanxue ~]# sed '2c\change data "haha"' data1 +1 the quick brown fox jumps over the lazy dog. +change data "haha" +3 the quick brown fox jumps over the lazy dog. +4 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. + +将data1文件中的第二、三、四行的内容更改为:change data "haha" +[root@zutuanxue ~]# sed '2,4c\change data "haha"' data1 +1 the quick brown fox jumps over the lazy dog. +change data "haha" +5 the quick brown fox jumps over the lazy dog. + +将data1文件中包含"3 the"的行内容更改为: change data "haha" +[root@zutuanxue ~]# sed '/3 the/c\change data "data"' data1 +1 the quick brown fox jumps over the lazy dog. +2 the quick brown fox jumps over the lazy dog. +change data "data" +4 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. +``` + +文件内容修改操作–字符转换,将一行中匹配的内容替换为新的数据,使用命令y。 + +**演示案例** + +``` +将data1中的a b c字符转换为对应的 A B C字符 +[root@zutuanxue ~]# sed 'y/abc/ABC/' data1 +1 the quiCk Brown fox jumps over the lAzy dog. +2 the quiCk Brown fox jumps over the lAzy dog. +3 the quiCk Brown fox jumps over the lAzy dog. +4 the quiCk Brown fox jumps over the lAzy dog. +5 the quiCk Brown fox jumps over the lAzy dog. +``` + +文件内容删除,将文件中的指定数据删除,使用命令d。 + +**演示案例** + +``` +删除文件data1中的所有数据 +[root@zutuanxue ~]# sed 'd' data1 + +删除文件data1中的第三行数据 +[root@zutuanxue ~]# sed '3d' data1 +1 the quick brown fox jumps over the lazy dog. +2 the quick brown fox jumps over the lazy dog. +4 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. + +删除文件data1第三到第四行的数据 +[root@zutuanxue ~]# sed '3,4d' data1 +1 the quick brown fox jumps over the lazy dog. +2 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. + +删除文件data1中包含字符串"3 the"的行 +[root@zutuanxue ~]# sed '/3 the/d' data1 +1 the quick brown fox jumps over the lazy dog. +2 the quick brown fox jumps over the lazy dog. +4 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. +``` + +文件内容查看,将文件内容输出到屏幕,使用命令p。 + +**演示案例** + +``` +打印data1文件内容 +[root@zutuanxue ~]# sed 'p' data1 +1 the quick brown fox jumps over the lazy dog. +1 the quick brown fox jumps over the lazy dog. +2 the quick brown fox jumps over the lazy dog. +2 the quick brown fox jumps over the lazy dog. +3 the quick brown fox jumps over the lazy dog. +3 the quick brown fox jumps over the lazy dog. +4 the quick brown fox jumps over the lazy dog. +4 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. + +打印data1文件第三行的内容 +[root@zutuanxue ~]# sed '3p' data1 +1 the quick brown fox jumps over the lazy dog. +2 the quick brown fox jumps over the lazy dog. +3 the quick brown fox jumps over the lazy dog. +3 the quick brown fox jumps over the lazy dog. +4 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. + +打印data1文件第二、三、四行内容 +[root@zutuanxue ~]# sed '2,4p' data1 +1 the quick brown fox jumps over the lazy dog. +2 the quick brown fox jumps over the lazy dog. +2 the quick brown fox jumps over the lazy dog. +3 the quick brown fox jumps over the lazy dog. +3 the quick brown fox jumps over the lazy dog. +4 the quick brown fox jumps over the lazy dog. +4 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. + +打印data1文件包含字符串"3 the"的行 +[root@zutuanxue ~]# sed '/3 the/p' data1 +1 the quick brown fox jumps over the lazy dog. +2 the quick brown fox jumps over the lazy dog. +3 the quick brown fox jumps over the lazy dog. +3 the quick brown fox jumps over the lazy dog. +4 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. + + +可以看得出,打印内容是重复的行,原因是打印了指定文件内容一次,又将读入缓存的所有数据打印了一次,所以会看到这样的效果, +如果不想看到这样的结果,可以加命令选项-n抑制内存输出即可。 +``` + +### 2.2)命令选项说明 + +**sed语法** +**在sed命令中,命令选项是对sed中的命令的增强** + +在命令行中使用多个命令 -e + +``` +将brown替换为green dog替换为cat +[root@zutuanxue ~]# sed -e 's/brown/green/;s/dog/cat/' data1 +1 the quick green fox jumps over the lazy cat. +2 the quick green fox jumps over the lazy cat. +3 the quick green fox jumps over the lazy cat. +4 the quick green fox jumps over the lazy cat. +5 the quick green fox jumps over the lazy cat. +``` + +从文件读取编辑器命令 -f 适用于日常重复执行的场景 + +``` +1)将命令写入文件 +[root@zutuanxue ~]# vim abc +s/brown/green/ +s/dog/cat/ +s/fox/elephant/ + +2)使用-f命令选项调用命令文件 +[root@zutuanxue ~]# sed -f abc data1 +1 the quick green elephant jumps over the lazy cat. +2 the quick green elephant jumps over the lazy cat. +3 the quick green elephant jumps over the lazy cat. +4 the quick green elephant jumps over the lazy cat. +5 the quick green elephant jumps over the lazy cat. +``` + +抑制内存输出 -n + +``` +打印data1文件的第二行到最后一行内容 $最后的意思 +[root@zutuanxue ~]# sed -n '2,$p' data1 +2 the quick brown fox jumps over the lazy dog. +3 the quick brown fox jumps over the lazy dog. +4 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. +``` + +使用正则表达式 -r + +``` +打印data1中以字符串"3 the"开头的行内容 +[root@zutuanxue ~]# sed -n -r '/^(3 the)/p' data1 +3 the quick brown fox jumps over the lazy dog. +``` + +从上述的演示中,大家可以看出,数据处理只是在缓存中完成的,并没有实际修改文件内容,如果需要修改文件内容可以直接使用-i命令选项。在这里我需要说明的是-i是一个不可逆的操作,一旦修改,如果想复原就很困难,几乎不可能,所以建议大家在操作的时候可以备份一下源文件。-i命令选项提供了备份功能,比如参数使用-i.bak,那么在修改源文件的同时会先备份一个以.bak结尾的源文件,然后再进行修改操作。 + +``` +1)查看文件列表,没有发现data1.bak +[root@zutuanxue ~]# ls +abc apache data1 Dobby file node-v10.14.1 Python-3.7.1 soft1 vimset + +2)执行替换命令并修改文件 +[root@zutuanxue ~]# sed -i.bak 's/brown/green/' data1 + +3)发现文件夹中多了一个data1.bak文件 +[root@zutuanxue ~]# ls +abc data1 Dobby node-v10.14.1 soft1 +apache data1.bak file Python-3.7.1 vimset + +4)打印比较一下,发现data1已经被修改,data1.bak是源文件的备份。 +[root@zutuanxue ~]# cat data1 +1 the quick green fox jumps over the lazy dog. +2 the quick green fox jumps over the lazy dog. +3 the quick green fox jumps over the lazy dog. +4 the quick green fox jumps over the lazy dog. +5 the quick green fox jumps over the lazy dog. +[root@zutuanxue ~]# cat data1.bak +1 the quick brown fox jumps over the lazy dog. +2 the quick brown fox jumps over the lazy dog. +3 the quick brown fox jumps over the lazy dog. +4 the quick brown fox jumps over the lazy dog. +5 the quick brown fox jumps over the lazy dog. +``` + +### 2.3)标志 + +**在sed命令中,标志是对sed中的内部命令做补充说明** + +``` +演示文档 +[root@zutuanxue ~]# cat data2 +1 the quick brown fox jumps over the lazy dog . dog +2 the quick brown fox jumps over the lazy dog . dog +3 the quick brown fox jumps over the lazy dog . dog +4 the quick brown fox jumps over the lazy dog . dog +5 the quick brown fox jumps over the lazy dog . dog +``` + +数字标志:此标志是一个非零正数,默认情况下,执行替换的时候,如果一行中有多个符合的字符串,如果没有标志位定义,那么只会替换第一个字符串,其他的就被忽略掉了,为了能精确替换,可以使用数字位做定义。 + +``` +替换一行中的第二处dog为cat +[root@zutuanxue ~]# sed 's/dog/cat/2' data2 +1 the quick brown fox jumps over the lazy dog . cat +2 the quick brown fox jumps over the lazy dog . cat +3 the quick brown fox jumps over the lazy dog . cat +4 the quick brown fox jumps over the lazy dog . cat +5 the quick brown fox jumps over the lazy dog . cat +``` + +g标志:将一行中的所有符合的字符串全部执行替换 + +``` +将data1文件中的所有dog替换为cat +[root@zutuanxue ~]# sed 's/dog/cat/g' data2 +1 the quick brown fox jumps over the lazy cat . cat +2 the quick brown fox jumps over the lazy cat . cat +3 the quick brown fox jumps over the lazy cat . cat +4 the quick brown fox jumps over the lazy cat . cat +5 the quick brown fox jumps over the lazy cat . cat +``` + +p标志:打印文本内容,类似于-p命令选项 + +``` +[root@zutuanxue ~]# sed '3s/dog/cat/p' data2 +1 the quick brown fox jumps over the lazy dog . dog +2 the quick brown fox jumps over the lazy dog . dog +3 the quick brown fox jumps over the lazy cat . dog +3 the quick brown fox jumps over the lazy cat . dog +4 the quick brown fox jumps over the lazy dog . dog +5 the quick brown fox jumps over the lazy dog . dog +``` + +w filename标志:将修改的内容存入filename文件中 + +``` +[root@zutuanxue ~]# sed '3s/dog/cat/w text' data2 +1 the quick brown fox jumps over the lazy dog . dog +2 the quick brown fox jumps over the lazy dog . dog +3 the quick brown fox jumps over the lazy cat . dog +4 the quick brown fox jumps over the lazy dog . dog +5 the quick brown fox jumps over the lazy dog . dog + +可以看出,将修改的第三行内容存在了text文件中 +[root@zutuanxue ~]# cat text +3 the quick brown fox jumps over the lazy cat . dog +``` + +## 三、练习案例 + +3.1、写一个初始化系统的脚本 +**案例需求** +1)自动修改主机名(如:ip是192.168.0.88,则主机名改为server88.zutuanxue.cc) + +a. 更改文件非交互式 sed + +/etc/sysconfig/network + +b.将本主机的IP截取出来赋值给一个变量ip;再然后将ip变量里以.分割的最后一位赋值给另一个变量ip1 + +2)自动配置可用的yum源 + +3)自动关闭防火墙和selinux + +``` +1、关闭防火墙 +2、关闭selinux +3、配置yum源 +4、ntp时间服务器 +5、更新系统软件包 +``` + +**3.2、写一个搭建ftp服务的脚本,要求如下:** +**案例需求** +1)不支持本地用户登录 local_enable=NO +2) 匿名用户可以上传 新建 删除 anon_upload_enable=YES anon_mkdir_write_enable=YES +3) 匿名用户限速500KBps anon_max_rate=500000 + +``` +仅供参考: +#!/bin/bash +ipaddr=`ifconfig eth0|sed -n '2p'|sed -e 's/.*inet addr:\(.*\) Bcast.*/\1/g'` +iptail=`echo $ipaddr|cut -d'.' -f4` +ipremote=192.168.1.10 +#修改主机名 +hostname server$iptail.zutuanxue.com +sed -i "/HOSTNAME/cHOSTNAME=server$iptail.zutuanxue.com" /etc/sysconfig/network +echo "$ipaddr server$iptail.zutuanxue.cc" >>/etc/hosts +#关闭防火墙和selinux +service iptables stop +setenforce 0 >/dev/null 2>&1 +sed -i '/^SELINUX=/cSELINUX=disabled' /etc/selinux/config +#配置yum源(一般是内网源) +#test network +ping -c 1 $ipremote > /dev/null 2>&1 +if [ $? -ne 0 ];then + echo "你的网络不通,请先检查你的网络" + exit 1 +else + echo "网络ok." +fi +cat > /etc/yum.repos.d/server.repo << end +[server] +name=server +baseurl=ftp://$ipremote +enabled=1 +gpgcheck=0 +end + +#安装软件 +read -p "请输入需要安装的软件,多个用空格隔开:" soft +yum -y install $soft &>/dev/null + +#备份配置文件 +conf=/etc/vsftpd/vsftpd.conf +\cp $conf $conf.default +#根据需求修改配置文件 +sed -ir '/^#|^$/d' $conf +sed -i '/local_enable/c\local_enable=NO' $conf +sed -i '$a anon_upload_enable=YES' $conf +sed -i '$a anon_mkdir_write_enable=YES' $conf +sed -i '$a anon_other_write_enable=YES' $conf +sed -i '$a anon_max_rate=512000' $conf +#启动服务 +service vsftpd restart &>/dev/null && echo"vsftpd服务启动成功" + +#测试验证 +chmod 777 /var/ftp/pub +cp /etc/hosts /var/ftp/pub +#测试下载 +cd /tmp +lftp $ipaddr < >= == < <= != +3. 数学运算 + - * / % ** ++ – +4. 逻辑运算 && || ! +5. 匹配运算 ~ !~ 精确匹配 == != + +a.赋值运算:主要是对变量或者数组赋值,如: + +变量赋值 name=‘baism’ school=‘zutuanxue’ + +数组赋值 array[0]=100 + +``` +[root@zutuanxue ~]# awk -v name='baism' 'BEGIN{print name}' +baism + +[root@zutuanxue ~]# awk 'BEGIN{school="zutuanxue";print school}' +zutuanxue + +[root@zutuanxue ~]# awk 'BEGIN{array[0]=100;print array[0]}' +100 +``` + +b.比较运算,如果比较的是字符串则按ascii编码顺序表比较。如果结果返回为真则用1表示,如果返回为假则用0表示 + +ascii + +``` +[root@zutuanxue ~]# awk 'BEGIN{print "a" >= "b" }' +0 +[root@zutuanxue ~]# awk 'BEGIN{print "a" <= "b" }' +1 + +[root@zutuanxue ~]# awk '$1>4{print $0}' test +5 the quick brown fox jumps over the lazy cat . dog +[root@zutuanxue ~]# awk 'BEGIN{print 100 >= 1 }' +1 +[root@zutuanxue ~]# awk 'BEGIN{print 100 == 1 }' +0 +[root@zutuanxue ~]# awk 'BEGIN{print 100 <= 1 }' +0 +[root@zutuanxue ~]# awk 'BEGIN{print 100 < 1 }' +0 +[root@zutuanxue ~]# awk 'BEGIN{print 100 != 1 }' +1 +``` + +c.数学运算 + +``` +[root@zutuanxue ~]# awk 'BEGIN{print 100+3 }' +103 +[root@zutuanxue ~]# awk 'BEGIN{print 100-3 }' +97 +[root@zutuanxue ~]# awk 'BEGIN{print 100*3 }' +300 +[root@zutuanxue ~]# awk 'BEGIN{print 100/3 }' +33.3333 +[root@zutuanxue ~]# awk 'BEGIN{print 100**3 }' +1000000 +[root@zutuanxue ~]# awk 'BEGIN{print 100%3 }' +1 +[root@zutuanxue ~]# awk -v 'count=0' 'BEGIN{count++;print count}' +1 +[root@zutuanxue ~]# awk -v 'count=0' 'BEGIN{count--;print count}' +-1 +``` + +d.逻辑运算 + +``` +与运算:真真为真,真假为假,假假为假 +[root@zutuanxue ~]# awk 'BEGIN{print 100>=2 && 100>=3 }' +1 +[root@zutuanxue ~]# awk 'BEGIN{print 100>=2 && 1>=100 }' +0 + +或运算:真真为真,真假为真,假假为假 +[root@zutuanxue ~]# awk 'BEGIN{print 100>=2 || 1>=100 }' +1 +[root@zutuanxue ~]# awk 'BEGIN{print 100>=200 || 1>=100 }' +0 + +非运算 +[root@manage01 resource]# awk 'BEGIN{print ! (100>=2)}' +0 +``` + +e.匹配运算 + +``` +[root@zutuanxue ~]# awk -F ':' '$1 ~ "^ro" {print $0}' /etc/passwd +root:x:0:0:root:/root:/bin/bash + +[root@zutuanxue ~]# awk -F ':' '$1 !~ "^ro" {print $0}' /etc/passwd +bin:x:1:1:bin:/bin:/sbin/nologin +daemon:x:2:2:daemon:/sbin:/sbin/nologin +adm:x:3:4:adm:/var/adm:/sbin/nologin +lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin +sync:x:5:0:sync:/sbin:/bin/sync +shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown +halt:x:7:0:halt:/sbin:/sbin/halt +mail:x:8:12:mail:/var/spool/mail:/sbin/nologin +operator:x:11:0:operator:/root:/sbin/nologin +games:x:12:100:games:/usr/games:/sbin/nologin +ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin +nobody:x:99:99:Nobody:/:/sbin/nologin +systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin +dbus:x:81:81:System message bus:/:/sbin/nologin +polkitd:x:999:997:User for polkitd:/:/sbin/nologin +postfix:x:89:89::/var/spool/postfix:/sbin/nologin +chrony:x:998:996::/var/lib/chrony:/sbin/nologin +sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin +ntp:x:38:38::/etc/ntp:/sbin/nologin +tcpdump:x:72:72::/:/sbin/nologin +nscd:x:28:28:NSCD Daemon:/:/sbin/nologin +mysql:x:997:995::/home/mysql:/sbin/nologin +www:x:996:994::/home/www:/sbin/nologin +apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin +tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin +zabbix:x:995:993:Zabbix Monitoring System:/var/lib/zabbix:/sbin/nologin +saslauth:x:994:76:Saslauthd user:/run/saslauthd:/sbin/nologin +grafana:x:993:992:grafana user:/usr/share/grafana:/sbin/nologin +``` + +#### 5.3)awk 环境变量 + +| 变量 | 描述 | +| :---------- | :----------------------------------------------------- | +| FIELDWIDTHS | 以空格分隔的数字列表,用空格定义每个数据字段的精确宽度 | +| FS | 输入字段分隔符号 数据源的字段分隔符 -F | +| OFS | 输出字段分隔符号 | +| RS | 输入记录分隔符 | +| ORS | 输出记录分隔符号 | + +``` +FIELDWIDTHS:重定义列宽并打印,注意不可以使用$0打印所有,因为$0是打印本行全内容,不会打印你定义的字段 +[root@zutuanxue ~]# awk 'BEGIN{FIELDWIDTHS="5 2 8"}NR==1{print $1,$2,$3}' /etc/passwd +root: x: 0:0:root + +FS:指定数据源中字段分隔符,类似命令选项-F +[root@zutuanxue ~]# awk 'BEGIN{FS=":"}NR==1{print $1,$3,$NF}' /etc/passwd +root 0 /bin/bash + +OFS:指定输出到屏幕后字段的分隔符 +[root@zutuanxue ~]# awk 'BEGIN{FS=":";OFS="-"}NR==1{print $1,$3,$NF}' /etc/passwd +root-0-/bin/bash + +RS:指定记录的分隔符 +[root@zutuanxue ~]# awk 'BEGIN{RS=""}{print $1,$13,$25,$37,$49}' test +1 2 3 4 5 + +将记录的分隔符修改为空行后,所有的行会变成一行,所以所有字段就在一行了。 + +ORS:输出到屏幕后记录的分隔符,默认为回车 +[root@zutuanxue ~]# awk 'BEGIN{RS="";ORS="*"}{print $1,$13,$25,$37,$49}' test +1 2 3 4 5*[root@zutuanxue ~]# + +可以看出,提示符和输出在一行了,因为默认回车换成了* +``` + +#### 5.4)流程控制 + +**if判断语句** + +``` +学习用例 +[root@zutuanxue ~]# cat num +1 +2 +3 +4 +5 +6 +7 +8 +9 + +单if语句 +打印$1大于5的行 +[root@zutuanxue ~]# awk '{if($1>5)print $0}' num +6 +7 +8 +9 + +if...else语句 +假如$1大于5则除以2输出,否则乘以2输出 +[root@zutuanxue ~]# awk '{if($1>5)print $1/2;else print $1*2}' num +2 +4 +6 +8 +10 +3 +3.5 +4 +4.5 +``` + +**for循环语句** + +``` +学习用例 +[root@zutuanxue ~]# cat num2 +60 50 100 +150 30 10 +70 100 40 + +将一行中的数据都加起来 $1+$2+$3 +[root@zutuanxue ~]# awk '{sum=0;for (i=1;i<4;i++){sum+=$i}print sum}' num2 +210 +190 +210 + +如果看的不明白可以看下面格式 +[root@zutuanxue ~]# awk '{ +> sum=0 +> for (i=1;i<4;i++) { +> sum+=$i +> } +> print sum +> }' num2 +210 +190 +210 +``` + +**while循环语句**–先判断后执行 + +``` +学习用例 +[root@zutuanxue ~]# cat num2 +60 50 100 +150 30 10 +70 100 40 + +将文件中的每行的数值累加,和大于或等于150就停止累加 +[root@zutuanxue ~]# awk '{sum=0;i=1;while(sum<150){sum+=$i;i++}print sum}' num2 +210 +150 +170 + + + +如果看的不明白可以看下面格式 +[root@zutuanxue ~]# awk '{ +sum=0 +i=1 +while (sum<150) { + sum+=$i + i++ +} +print sum +}' num2 +210 +150 +170 +``` + +**do…while循环语句**–先执行后判断 + +``` +学习用例 +[root@zutuanxue ~]# cat num2 +60 50 100 +150 30 10 +70 100 40 + +将文件中的每行的数值累加,和大于或等于150就停止累加 +[root@zutuanxue ~]# awk '{sum=0;i=1;do{sum+=$i;i++}while(sum<150);print sum}' num2 +210 +150 +170 +如果看的不明白可以看下面格式 +[root@zutuanxue ~]# awk '{ +> sum=0 +> i=1 +> do { +> sum+=$i +> i++ +> }while (sum<150) +> print sum +> }' num2 +210 +150 +170 +``` + +**循环控制语句** + +break 跳出循环,继续执行后续语句 + +``` +学习用例 +[root@zutuanxue ~]# cat num2 +60 50 100 +150 30 10 +70 100 40 + +累加每行数值,和大于150停止累加 +[root@zutuanxue ~]# awk '{ +> sum=0 +> i=1 +> while (i<4){ +> sum+=$i +> if (sum>150){ +> break +> } +> i++ +> } +> print sum +> }' num2 +210 +180 +170 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\346\265\201\347\250\213\346\216\247\345\210\266-if\345\210\244\346\226\255\350\257\255\345\217\245.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\346\265\201\347\250\213\346\216\247\345\210\266-if\345\210\244\346\226\255\350\257\255\345\217\245.md" new file mode 100644 index 0000000..a671f04 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\346\265\201\347\250\213\346\216\247\345\210\266-if\345\210\244\346\226\255\350\257\255\345\217\245.md" @@ -0,0 +1,425 @@ +## 一、if介绍 + +如何写一个高可用性的脚本,赋予脚本智能化,赋予脚本执行逻辑。 + +比如nginx安装脚本中 + +- configure执行成功在执行make, +- make执行成功在执行make install +- 上一步错误就不需要执行后面的代码了。 + +answer: 加入判断 + +只要你想在代码中判断一下的时候就第一时间想到if就行了,适用于99%的语言。 + +当我们在写程序的时候,时常对上一步执行是否成功如何判断苦恼,当我们今天学习了if就可以解决你的苦恼。if语句在我们程序中就是用来做判断的,以后大家不管学习什么语言,以后只要涉及到判断的部分,大家就可以直接拿if来使用,不同的语言之间的if只是语法不同,原理是相同的。 + +## 二、单if语法 + +适用范围:只需要一步判断,条件返回真干什么。 + +语句格式 + +``` +if [ condition ] #condition 值为true or false + then #条件为真的时候执行 + commands #代码块 一行或者多行代码 +fi #语句的结束 +``` + +![流程判断11.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/25/1601016825298.png) + +该语句翻译成汉语大意如下: + +``` +假如 条件为真 + 那么 + 执行commands代码块 +结束 +``` + +通过一段代码来演示一下吧,判断 当前用户是不是root,如果不是那么返回”ERROR: need to be root so that!“ + +``` +#!/bin/bash +#Author: www.zutuanxue.com +#Created Time: +#Script Description: + +if [ $USER != 'root' ] + then + echo "ERROR: need to be root so that" + exit 1 +fi +``` + +## 三、if…else语句 + +适用范围==:两步判断,条件为真干什么,条件为假干什么。 + +``` +if [ condition ] + then 条件为真 + commands1 真 要执行代码块 +else 条件为假 + commands2 假 要执行的代码块 +fi 结束 +``` + +![流程判断2.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/25/1601016994805.png) + +该语句翻译成汉语大意如下: + +``` +假如条件为真 + 那么 + + 执行commands1代码块 +否则 + 执行commands2代码块 +结束 +``` + +通过一段代码演示一下吧,判断当前登录用户是管理员还是普通用户,如果是管理员输出”hey admin“ 如果是普通用户输出”hey guest“ + +``` +#!/bin/bash +#Author:www.zutuanxue.com +#Created Time: +#Script Description: + +if [ $USER == 'root' ] + then + echo "hey admin" +else + echo "hey guest" +fi +``` + +## 四、if…elif…else + +适用范围:多于两个以上的判断结果,也就是多于一个以上的判断条件。 + +``` +if [ condition 1] 满足第一个条件 + + then 真 + + command1 执行command1代码块 +elif [ condition 2] 满足第二个条件 + + then 真 + + commands2 执行command2代码块 + + ....... +else 如果条件都不满足 + + commandsX 执行commandX代码块 +fi 结束判断 +``` + +![流程判断3.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/25/1601017300715.png) + +该语句翻译成汉语大意如下: + +``` +假如 条件1 为真 + + 那么 + + 执行代码块1 +假如 条件2 为真 + + 那么 + + 执行代码块2 + + 以此类推的N个条件及对应的执行代码块 +否则 【以上所有条件中没有一个满足的】 + + 执行代码块X +结束 +``` + +通过一段代码演示一下吧,通过一个脚本,判断两个整数的关系 + +**案例需求** +判断内存的使用率 +60以下 ok +60以上 黄色警告 +70以上 橙色严重警告 +80以上 红色警告 + +**案例思考** + +- 内存使用率获得方式 + – 手动给出 + – 通过内存查看命令运算得出 + +**案例代码** + +``` +#!/bin/bash +#1、条件 +#判断内存的使用率 +#60以下 ok 绿色 32m +#60以上 黄色警告 33m +#70以上 粉色严重警告 35m +#80以上 红色警告 31m + +#2、算法 +#收集内存使用率 $1 +# +#多条件判断 + +if [ $1 -gt 80 ] +then + echo -e "\033[31m 警告 \033[0m" +elif [ $1 -gt 70 ] +then + echo -e "\033[35m 警告 \033[0m" +elif [ $1 -gt 60 ] +then + echo -e "\033[33m 警告 \033[0m" +else + echo -e "\033[32m OK \033[0m" +fi + + +#注意事项 +#多条件判断 需要从最严格开始判断 否者 后面的就不会生效 +#如果你第一个判断的是60以上,那么 70 80 都符合第一个条件。所以后面的判断70 80 就没有任何意义 +``` + +## 五、练习案例 + +**案例需求** +比较两个整数的关系 + +**案例思考** + +- 两个整数有几种关系 + – 大于 + – 等于 + – 小于 + +**案例代码** + +``` +#!/bin/bash +#Author: www.zutuanxue.com +#Created Time: +#Script Description: + +if [ $1 -gt $2 ] + then + echo "$1 > $2" +elif [ $1 -eq $2 ] + then + echo "$1 = $2" +else + echo "$1 < $2" +fi +``` + +## 六、if嵌套if + +当有多步判断的时候,可以使用if嵌套 + +**1、多步判断 类似于多条件if** +**2、依赖执行的环境 configure->make->make install** + +#### 6.1、使用if嵌套if的方式判断两个整数的关系 + +``` +#!/bin/bash +#Author: +#Created Time: +#Script Description: + +if [ $1 -ne $2 ] + then + if [ $1 -gt $2 ] + then + echo " $1 > $2 " + else + echo " $1 < $2 " + fi +else + echo " $1 = $2 " +fi +``` + +#### 6.2、写一个nginx安装初始化脚本 + +**案例需求** +写一个nginx业务初始化脚本,完成nginx软件自动安装。 + +**案例思考** + +- 1、nginx软件包获得方式 +- 2、nginx安装流程 +- 3、nginx安装依赖关系 + +**案例步骤** + +- 1、软件包下载 +- 2、软件包解压 +- 3、安装依赖包 +- 4、安装nginx +- 5、返回结果 + +**案例代码** + +``` +#!/bin/bash +#Author: www.zutuanxue.com +#Created Time: +#Script Description: nginx aoto install script + + +source_pkg=nginx-1.19.2.tar.gz +#1、软件包下载 +wget http://nginx.org/download/$source_pkg +#2、解压 +if [ -f $source_pkg ];then + tar xf $source_pkg && cd nginx-1.19.2 +else + echo "not found $source_pkg" + exit 1 +fi + +#3、安装依赖包 +if ! ( yum -y install pcre-devel zlib-devel );then + echo "yum: install soft error" + exit 1 +fi + +#4、配置 +#判断配置语句执行结果 +if ./configure 1>/dev/null + then + #判断make执行结果 + if make 1>/dev/null + then + #判断make install安装结果 + if make install 1>/dev/null + then + echo "nginx 安装成功" + else + echo "nginx 安装失败" + exit 1 + fi + else + echo "make fail" + exit 1 + fi +else + echo "configure fail" + exit 1 +fi + + + +#./configure +#if [ $? -eq 0 ];then + +#注意: 1>/dev/null +1 标准输出 +2 标准错误输出 +``` + +## 七、if高级用法 + +#### 7.1、条件符号使用双圆括号,可以在条件中植入数学表达式 if (()) + +``` +#!/bin/bash +#Author: +#Created Time: +#Script Description: + +if (( (5+5-5)*5/5 > 10 )) + then + echo "yes" +else + echo "no" +fi +``` + +#### 7.2、使用双方括号,可以在条件中使用通配符 + +通过代码看下 ,为字符串提供高级功能,模式匹配 r* 匹配r开头的字符串 + +``` +#!/bin/bash +#Author: +#Created Time: +#Script Description: +for var in ab ac rx bx rvv vt + do + if [[ "$var" == r* ]] + then + echo "$var" + fi +done +``` + +## 八、简写if + +省去了关键字,条件为真采用&&符号链接命令块,条件为假采用||链接命令块 + +简写if一般用在简单的判断中 + +``` +if [ ! -d /tmp/baism ] + then + mkdir /tmp/baism +fi + +可以简写为 + +[ ! -d /tmp/baism ] && mkdir /tmp/baism + +if [ $USER == 'root' ] + then + echo "hello root" +else + echo "hello guest" +fi + +可以简写 +[ $USER == 'root' ]&&echo "hello root" || echo "hello guest" +``` + +## 九、课后练习 + +``` +1、计算机状态监控。能ping通就算up,不通为down,需要考虑网络延迟问题造成的假报警问题。 +#1、分别ping 取三个值 判断三个值的结果 + 1.1 ping 3次 并取值 + 1.2 三次结果与运算 得出结论 + + +2、监控一个服务端口,判断其状态 + +3、打印内存使用率脚本,打印内存使用率、swap使用率、buff&cache使用量 + +4、打印磁盘使用率脚本,对本机的磁盘使用率统计并打印结果 + 使用率小于80,绿色输出 + 使用率小于90,大于80,黄色输出 + 使用率小于95,大于90,红色输出 + +5、网卡发送和就收数据量监控,按秒统计。 + +6、URL监控脚本,对某个URL进行监控,返回值为200则代表成功访问。 + +7、写一个mysql binlog备份脚本,要求每天0点0分,计算机自动备份前一天的binlog日志,打包后发送给备份服务器。 + +8、闰年判断 + +9、判断/tmp/run目录是否存在,如果不存在就建立,如果存在就删除目录里所有文件 + +10、写一个nginx安装脚本 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\344\270\255\345\270\270\347\224\250\345\221\275\344\273\244\345\244\215\344\271\240.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\344\270\255\345\270\270\347\224\250\345\221\275\344\273\244\345\244\215\344\271\240.md" new file mode 100644 index 0000000..8bfda64 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\344\270\255\345\270\270\347\224\250\345\221\275\344\273\244\345\244\215\344\271\240.md" @@ -0,0 +1,450 @@ +shell脚本可以让降低大家的工作强度,提升大家的管理能力和薪资报酬,还可以让大家有时间学习提升自己,更能让你有时间喝茶撩妹子。所以,学好shell那就是非常必要的啦,那么在学习shell之前我们得热热身,做一下准备工作了。 + +``` +学习之前首先要弄清什么是shell脚本: + + shell脚本本质上就是要将完成一件事情的所有命令按照执行的先后顺序写入一个文件,并给予文件执行权限 +``` + +so!想学好shell脚本首先要考核一下自己的linux命令学的是否扎实,接下来为了能让大家学习shell更加顺畅,我把常用的一些数据处理的命令给大家回顾一下。 + +``` +我们重点回顾以下几类命令 + +数据检索命令 + + 行检索:grep egrep + + 字符串检索:cut tr + +数据处理命令 + + 数据排序:sort + + 数据去重: uniq + + 文本数据合并: paste + + 数据输出: tee + + 数据处理: xargs +``` + +![image-20220604181148091](C:\Users\MISSXP\AppData\Roaming\Typora\typora-user-images\image-20220604181148091.png) + +## 一、 数据处理命令 + +### 1、grep: 负责从数据源中检索对应的字符串,行过滤。 + +``` +grep用于根据关键字进行行过滤 +grep options 'keys' filename +OPTIONS: + -i: 不区分大小写 + -v: 查找不包含指定内容的行,反向选择 + -w: 按单词搜索 + -n: 显示行号 + -A: 显示匹配行及后面多少行 -A 5 + -B: 显示匹配行及前面多少行 + + + -o: 打印匹配关键字 + -c: 统计匹配到的次数 + -r: 逐层遍历目录查找 + -C: 显示匹配行前后多少行 + -l:只列出匹配的文件名 + -L:列出不匹配的文件名 + -e: 使用正则匹配 + -E:使用扩展正则匹配 + ^key:以关键字开头 + key$:以关键字结尾 + ^$:匹配空行 + --color=auto :可以将找到的关键词部分加上颜色的显示 + + +常用命令选项必知必会 示例: +# grep -i root passwd 忽略大小写匹配包含root的行 +# grep -w ftp passwd 精确匹配ftp单词 +# grep -wo ftp passwd 打印匹配到的关键字ftp +# grep -n root passwd 打印匹配到root关键字的行好 +# grep -ni root passwd 忽略大小写匹配统计包含关键字root的行 +# grep -nic root passwd 忽略大小写匹配统计包含关键字root的行数 +# grep -i ^root passwd 忽略大小写匹配以root开头的行 +# grep bash$ passwd 匹配以bash结尾的行 +# grep -n ^$ passwd 匹配空行并打印行号 +# grep ^# /etc/vsftpd/vsftpd.conf 匹配以#号开头的行 +# grep -v ^# /etc/vsftpd/vsftpd.conf 匹配不以#号开头的行 +# grep -A 5 mail passwd 匹配包含mail关键字及其后5行 +# grep -B 5 mail passwd 匹配包含mail关键字及其前5行 +# grep -C 5 mail passwd 匹配包含mail关键字及其前后5行 + + + +centos8中已经为大家设置了,存放在/etc/profile.d/colorgrep.sh文件中,如若大家使用的系统中没有设置颜色输出, +可以使用以下方法来自行设置 + +临时设置: +# alias grep='grep --color=auto' //只针对当前终端和当前用户生效 + +永久设置: +1)全局(针对所有用户生效) +vim /etc/bashrc +alias grep='grep --color=auto' +source /etc/bashrc + +2)局部(针对具体的某个用户) +vim ~/.bashrc +alias grep='grep --color=auto' + +注意:如果希望你对环境变量的设置立刻生效,可以使用以下命令而不需要重启计算机 +source ~/.bashrc +``` + +### 2、cut数据截取 + +``` +cut用于列截取 +-c: 以字符为单位进行分割。 +-d: 自定义分隔符,默认为制表符。\t +-f: 与-d一起使用,指定显示哪个区域。 + +# cut -d: -f1 1.txt 以:冒号分割,截取第1列内容 +# cut -d: -f1,6,7 1.txt 以:冒号分割,截取第1,6,7列内容 +# cut -c4 1.txt 截取文件中每行第4个字符 +# cut -c1-4 1.txt 截取文件中每行的1-4个字符 +# cut -c4-10 1.txt +# cut -c5- 1.txt 从第5个字符开始截取后面所有字符 +``` + +### 3、tr 字符转换:替换,删除 + +``` +tr用来从标准输入中通过替换或删除操作进行字符转换;主要用于删除文件中控制字符或进行字符转换。 +使用tr时要转换两个字符串:字符串1用于查询,字符串2用于处理各种转换。 + +语法: +commands|tr 'string1' 'string2' +tr 'string1' 'string2' < filename + +tr options 'string1' < filename + +-d 删除字符串1中所有输入字符。 +-s 删除所有重复出现字符序列,只保留第一个;即将重复出现字符串压缩为一个字符串。 + + +a-z 任意小写 +A-Z 任意大写 +0-9 任意数字 + +[root@zutuanxue shell01]# cat 3.txt 自己创建该文件用于测试 +ROOT:x:0:0:root:/root:/bin/bash +bin:x:1:1:bin:/bin:/sbin/nologin +daemon:x:2:2:daemon:/sbin:/sbin/nologin +adm:x:3:4:adm:/var/adm:/sbin/nologin +lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin +sync:x:5:0:sync:/sbin:/bin/sync +shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown +halt:x:7:0:halt:/sbin:/sbin/halt +mail:x:8:12:mail:/var/spool/mail:/sbin/nologin +uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin +boss02:x:516:511::/home/boss02:/bin/bash +vip:x:517:517::/home/vip:/bin/bash +stu1:x:518:518::/home/stu1:/bin/bash +mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin +smmsp:x:51:51::/var/spool/mqueue:/sbin/nologin +aaaaaaaaaaaaaaaaaaaa +bbbbbb111111122222222222233333333cccccccc +hello world 888 +666 +777 +999 + + +# tr -d '[:/]' < 3.txt 删除文件中的:和/ +# cat 3.txt |tr -d '[:/]' 删除文件中的:和/ +# tr '[0-9]' '@' < 3.txt 将文件中的数字替换为@符号 +# tr '[a-z]' '[A-Z]' < 3.txt 将文件中的小写字母替换成大写字母 +# tr -s '[a-z]' < 3.txt 匹配小写字母并将重复的压缩为一个 +# tr -s '[a-z0-9]' < 3.txt 匹配小写字母和数字并将重复的压缩为一个 +``` + +### 4、sort排序 + +``` +sort:将文件的每一行作为一个单位,从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。 + +语法: +sort [options] [filename] + +-u :去除重复行 +-r :降序排列,默认是升序 +-o : 将排序结果输出到文件中 类似 重定向符号 > +-n :以数字排序,默认是按字符排序 +-t :分隔符 +-k :第N列 + +-b :忽略前导空格。 +-R :随机排序,每次运行的结果均不同。 + + 示例: +# sort -n -t: -k3 1.txt 按照用户的uid进行升序排列 +# sort -nr -t: -k3 1.txt 按照用户的uid进行降序排列 +# sort -n 2.txt 按照数字排序 +# sort -nu 2.txt 按照数字排序并且去重 +# sort -nr 2.txt +# sort -nru 2.txt +# sort -nru 2.txt +# sort -n 2.txt -o 3.txt 按照数字排序并将结果重定向到文件 +# sort -R 2.txt +# sort -u 2.txt +``` + +### 5、uniq 去除连续的重复行 + +**应用技巧:去重前先使用sort排序** + +``` +uniq:去除连续重复行 + +语法: +uniq [options] [filename] + +-i: 忽略大小写 +-c: 统计重复行次数 +-d:只显示重复行 + +# uniq 2.txt +# uniq -d 2.txt +# uniq -dc 2.txt +``` + +### 6、tee 双向输出 + +``` +tee工具从标准输入读取并写入标准输出和文件,即:双向覆盖重定向<屏幕输出|文本输入> +somecommand |tee filename + +-a 双向追加重定向 + +# echo hello world +# echo hello world|tee file1 +# cat file1 +# echo 999|tee -a file1 +# cat file1 +``` + +### 7、paste + +``` +paste工具用于合并文件行输出到屏幕,不会改动源文件 + +-d:自定义间隔符,默认是tab,只接受一个字符 +-s:将每个文件中的所有内容按照一行输出,文件中的行与行以TAB间隔。 + +[root@zutuanxue shell01]# cat a.txt +hello +[root@zutuanxue shell01]# cat b.txt +hello world +888 +999 +[root@zutuanxue shell01]# paste a.txt b.txt +hello hello world + 888 + 999 +[root@zutuanxue shell01]# paste b.txt a.txt +hello world hello +888 +999 + +[root@zutuanxue shell01]# paste -d'@' b.txt a.txt +hello world@hello +888@ +999@ + +[root@zutuanxue shell01]# paste -s b.txt a.txt +hello world 888 999 +hello +``` + +### 8、xargs 上一个命令的输出作为下一个命令的命令行参数 + +管道(|):上一个命令的输出作为下一个命令的输入,做的是**数据源**。 + +``` +[root@manage01 ~]# sort -n 2.txt |uniq +1 +2 +3 +5 +6 +10 +99 +9999 + +如何将上一个命令的输出,作为下一个命令的参数呢? + +xargs 上一个命令的输出作为下一个命令的命令行参数 + +回顾: +linux 命令格式 +命令 命令选项 参数 +ls -l / +======================== +xargs 可以将管道或标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据。 + +xargs 一般是和管道一起使用。 + +命令格式: +''[somecommand]|[filename]'' |xargs -item command + +OPTIONS: +-a file 从文件中读入作为sdtin +-E flag flag必须是一个以空格分隔的标志,当xargs分析到含有flag这个标志的时候就停止。 +-p 当每次执行一个argument的时候询问一次用户。 +-n num 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的。 +-t 表示先打印命令,然后再执行。 +-i 或者是-I,这得看linux支持了,将xargs的每项名称,一般是一行一行赋值给 {},可以用 {} 代替。 +-r no-run-if-empty 当xargs的输入为空的时候则停止xargs,不用再去执行了。 +-d delim 分隔符,默认的xargs分隔符是回车,argument的分隔符是空格,这里修改的是xargs的分隔符。 + + +注意:linux命令格式一般为 +命令 命令选项 参数 +上一个命令的输出就是下一个命令的参数 这句话结合命令语法 应该知道输出的内容在下一个命令的位置了吧。 + + +案例 +[root@zutuanxue ~]# find / -name zutuanxue |xargs gzip +[root@zutuanxue ~]# cat 1 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +[root@zutuanxue ~]# xargs -a 1 +1 2 3 4 5 6 7 8 9 10 + +[root@zutuanxue ~]# xargs -a 1 -E 5 +1 2 3 4 + +这样就明白使用xargs -a 为什么读取文件的时候会把文件中的所有内容都输出了吧 +[root@zutuanxue ~]# xargs -a 1 -p +echo 1 2 3 4 5 6 7 8 9 10 ?...y +1 2 3 4 5 6 7 8 9 10 +[root@zutuanxue ~]# xargs -a 1 -p +echo 1 2 3 4 5 6 7 8 9 10 ?...n + +同理为什么把文件中的所有行按一行输出呢,原因就是默认输出所有 +[root@zutuanxue ~]# xargs -a 1 -n3 +1 2 3 +4 5 6 +7 8 9 +10 +[root@zutuanxue ~]# xargs -a 1 -n3 -p +echo 1 2 3 ?...y +echo 4 5 6 ?...1 2 3 +y +echo 7 8 9 ?...4 5 6 +y +echo 10 ?...7 8 9 +y +10 + +和-p命令选项一样,显示他是怎么执行的,只不过这个不需要确认。 +[root@zutuanxue ~]# cat 1 |xargs -t +echo 1 2 3 4 5 6 7 8 9 10 +1 2 3 4 5 6 7 8 9 10 + +为何读入文件会把所有行都放在一行呢?这个和xargs的列分割符有关系 +默认是回车 +我们可以使用-d 改掉默认列与列的默认分割符为其他,自然就会换行了 +[root@zutuanxue ~]# xargs -a 1 -d "@" +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +``` + +### 9、shell字符 + +``` +有基础的同学不要和正则表达式中的符号含义搞混淆了。 + !: 执行历史命令 !! 执行上一条命令 + $: 变量中取内容符 + + - * / %: 对应数学运算 加 减 乘 除 取余数 + &: 后台执行 + ;: 分号可以在shell中一行执行多个命令,命令之间用分号分割 + \: 转义字符 + ``: 反引号 命令中执行命令 echo "today is `date +%F`" + ' ': 单引号,脚本中字符串要用单引号引起来,但是不同于双引号的是,单引号不解释变量 + " ": 双引号,脚本中出现的字符串可以用双引号引起来 + +通配符 + ~: 家目录 # cd ~ 代表进入用户家目录 + *: 星号是shell中的通配符 匹配所有 + ?: 问号是shell中的通配符 匹配除回车以外的一个字符 + [list]: 匹配[list]中的任意单个字符 +[!list]: 匹配除list中的任意单个字符 +{string1,string2,...}: 匹配string1,string2或更多字符串 + + +重定向 +> 覆盖输入 +>> 追加输入 +< 输出 +<< 追加输出 + +管道命令 +|: 管道符 上一个命令的输出作为下一个命令的输入 cat filename | grep "abc" +``` + +### 10、组合命令实战 + +``` +job1: 检索本机的IP、NETMASK、MAC地址、广播地址 +IP: 172.20.10.3 +NetMask: 255.255.255.240 +Broadcast: 172.20.10.15 +MAC Address: 00:0c:29:8d:49:ea + + +job2: 将系统中所有普通用户的用户名、密码和默认shell保存到一个文件中,要求用户名密码和默认shell之间用tab键分割 +ayitula x /bin/bash + +组合命令实战代码 + +job1: 检索本机的IP、NETMASK、MAC地址、广播地址 +[root@zutuanxue ~]# ifconfig ens33 检索网卡信息 +[root@zutuanxue ~]# ifconfig ens33|grep -w inet|tr -d '[a-zA-Z]'|tr -s " " 处理检索行 + +IP地址 +[root@zutuanxue ~]# ifconfig ens33|grep -w inet|tr -d [a-zA-Z]|tr -s " "|cut -d " " -f2|xargs echo "IP: " +IP: 172.20.10.3 + +NetMask地址 +[root@zutuanxue ~]# ifconfig ens33|grep -w inet|tr -d [a-zA-Z]|tr -s " "|cut -d " " -f3|xargs echo "NetMask: " +NetMask: 255.255.255.240 + +广播地址 +[root@zutuanxue ~]# ifconfig ens33|grep -w inet|tr -d [a-zA-Z]|tr -s " "|cut -d " " -f4|xargs echo "Broadcast: " +Broadcast: 172.20.10.15 + +MAC地址 +[root@zutuanxue ~]# ifconfig ens33|grep -w ether|tr -s " "|cut -d " " -f3|xargs echo "MAC Address: " +MAC Address: 00:0c:29:8d:49:ea + +job2: 将系统中所有普通用户的用户名、密码和默认shell保存到一个文件中,要求用户名密码和默认shell之间用tab键分割 +[root@zutuanxue ~]# cut -d ":" -f1,2,7 /etc/passwd|tr ":" "\t"|grep -i "bash"|grep -v "root" +ayitula x /bin/bash +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\344\273\213\347\273\215.md" new file mode 100644 index 0000000..ba874d0 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\344\273\213\347\273\215.md" @@ -0,0 +1,51 @@ +## 一、shell脚本是什么 + + 通过shell语言将完成一个任务的所有代码写入一个文件,并给执行权限。 + +## 二、**为什么要学shell,而不是其他计算机语言** + +- 上手快 +- 入门简单 +- 学习周期短 + +## 三、学习这门课程的优势 + +- 解放运维人员:7X24小时监控,监控为例,监控帮你干活,你只需要处理问题就好。 +- 提升业务能力:业务初始化,自动备份,日志分析,你的工作脚本来做,效率更高。 +- 提升管理能力:从系统安装到业务部署,再到服务器管理维护,实现自动化运维,批量管理机器与业务。 +- 提升运维薪资:技术能力和工资成正比。 + +## 四、学了能干什么 + +**重点:重复性的工作,全部通过脚本来完成。高效的同时还不出错。** + +- 根据企业架构自定义监控系统,量身打造企业级监控系统 +- 业务初始化部署系统,业务初始化全部一键搞定,省去繁琐的安装与排错 +- 一键备份,分分钟搞定备份问题 +- 日志分析,繁琐又复杂的日志分析让机器取做吧。 +- 三方软件模块插件的编写:根据业务定制三方软件的功能,更贴合自己的业务。 + +## 五、学习什么内容 + +![shell学习路线图.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/24/1600908281266.png) + +## 六、学习的技巧 + +好的编程是代码喂出来的。提升自己的代码量,把所有想到的事情都用代码实现出来 + +## 七、成长路径 + +![shell编程掌握等级图.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/24/1600908316400.png) + +``` +1.能看到代码实现的算法、原理 +2、能根据自己的脚本应用要求修改脚本 +3、能根据业务需求写脚本 +4、能根据脚本执行问题优化脚本代码 +``` + +## 八、学习环境 + +centos8:官网 centos.org + +光盘镜像:http://mirrors.tuna.tsinghua.edu.cn/centos/8.2.2004/isos/x86_64/CentOS-8.2.2004-x86_64-dvd1.iso \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\345\256\236\346\210\230\346\241\210\344\276\213-\346\225\260\346\215\256\347\243\201\347\233\230\345\210\235\345\247\213\345\214\226.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\345\256\236\346\210\230\346\241\210\344\276\213-\346\225\260\346\215\256\347\243\201\347\233\230\345\210\235\345\247\213\345\214\226.md" new file mode 100644 index 0000000..03aee99 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\345\256\236\346\210\230\346\241\210\344\276\213-\346\225\260\346\215\256\347\243\201\347\233\230\345\210\235\345\247\213\345\214\226.md" @@ -0,0 +1,115 @@ +## 一、案例应用场景 + +生产环境中的服务器一般会分为系统盘和数据盘两种磁盘,以dell R730举例,该服务器是一个2U的机架式服务器,满载可以挂载14块磁盘[2块在机箱内做系统盘,12块在面板做数据盘],我们一般的策略是系统盘做raid1,保障系统稳定性12块数据磁盘我们做raid10 或者 raid50,保障数据盘容错的同时还能做到优化IO的效果。 + +raid磁盘的容量是一定的,线上的数据又是不断增长的,也就是说总有一天会把你的数据磁盘填满,那怎么办?为了解决这个问题,人们想到了LVM[逻辑卷管理系统],当前数据盘容量不够用的时候,我们可以通过san存储获得网络磁盘,然后将该网络存储动态加入LVM中的卷组后就可以扩大LV了。整个过程采用在线扩容的方式,不会影响线上业务正是基于这个原因,我们又在系统中把raid数据盘在存数据之前做成了LVM磁盘,方便后续的扩容。 + +注意:有数据的磁盘不能再做LVM,因为需要格式化,数据会全部丢失。必须提前布局,否则就得提前准备跑路资金了。 + +## 二、案例需求 + +``` +给虚拟机添加一块磁盘(以sdb为例),要求使用脚本对该磁盘分三个区: + + 1)主分区 /dev/sdb3 543M 文件系统 ext4 要求开机自动挂载到/data/data1目录 + + 2) 逻辑分区 /dev/sdb5 2G + + 3) 逻辑分区 /dev/sdb6 3G + +使用/dev/sdb5 /dev/sdb6 新建卷组vg100,并创建一个PE为16M,容量为2.5G的逻辑卷lv100, +格式化为xfs,默认开机自动挂载到/data/data2目录 +``` + +## 三、案例算法 + +算法:完成一个任务的代码思路。 + +``` +脚本思路---算法 +1、分区 +2、创建逻辑卷 + 2.1 创建物理卷 + 2.2 创建卷组 + 2.3 创建逻辑卷 +3、格式化 /dev/sdb3 /dev/vg100/lv100 +4、修改/etc/fstab文件 +5、挂载分区 +6、验证并输出挂载结果 +``` + +## 四、代码实现 + +代码实现的要点:要清楚每一步的步骤,不同的系统可能有细微的差别,一味的复制可不行的,需要提前手动做一下,把步骤捋清楚。 + +``` +实验代码 01_disk_partition.sh +#!/bin/bash +# +#Author: Bai Shuming +#Created Time: 2019/11/1 21:05 +#Release: +#Description: +# +#给虚拟机添加一块磁盘(以sdb为例),要求使用脚本对该磁盘分三个区: +# 1)主分区 /dev/sdb3 543M 文件系统 ext4 要求开机自动挂载到/data/data1目录 +# 2) 逻辑分区 /dev/sdb5 2G +# 3) 逻辑分区 /dev/sdb6 3G +#使用/dev/sdb5 /dev/sdb6 新建卷组vg100,并创建一个PE为16M,容量为2.5G的逻辑卷lv100, +#格式化为xfs,默认开机自动挂载到/data/data2目录 + +#1、分区 +fdisk /dev/sdb <> /etc/fstab +echo "/dev/vg100/lv100 /data/data2 xfs defaults 0 0" >> /etc/fstab + +#5、挂载分区 +mkdir -p /data/data{1..2} +mount -a + +#6、验证并输出挂载结果 +mount |grep "/dev/sdb3" +test $? -eq 0&&echo "/dev/sdb3 挂载成功" || echo "/dev/sdb3挂载失败" + +##注意检索的时候,mount输出中LV的表示方式,或者直接检索挂载点/data/data2也可以。 +mount |grep "vg100-lv100" +test $? -eq 0&&echo "/dev/vg100/lv100 挂载成功" || echo "/dev/vg100/lv100挂载失败" +``` + +## 五、实现验证 + +``` +使用如下命令查看是否挂载成功 +[root@zutuanxue ~]# df -Th +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\240\274\345\274\217\345\214\226\350\276\223\345\207\272.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\240\274\345\274\217\345\214\226\350\276\223\345\207\272.md" new file mode 100644 index 0000000..7113956 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\240\274\345\274\217\345\214\226\350\276\223\345\207\272.md" @@ -0,0 +1,162 @@ +计算机程序其实就是三步:输入、运算、输出,这个理论也适应于shell编程。 + +那么计算机是如何将信息按照比较舒服的格式输出到屏幕或者KFC的打印纸上的呢!如果让计算机能够输出一种格式,让人看起来很舒服,那么我们就要学习一下计算机的格式化输出,让计算机程序将信息输出的时候美美哒!让人一目了然看到需要的信息。 + +## 一、shell格式化输出 + +一个赏心悦目的界面是一个程序给用户的第一个映像,好的界面可以让用户更加容易上手使用。windows之所以能被个人用户喜欢就是因为它的界面更加容易和用户交互,只要用户能识别文字,懂得点击鼠标就能操作电脑;而linux之所以无法被广大个人用户使用的瓶颈就是图形界面无法完成所有工作,需要命令配合才可以,这就把非专业用户拒之门外了,想用就必须去学习命令。 +我们在使用shell写一个程序的时候,如果想让广大的用户都能使用,都能快速上手,那么好的交互界面就太重要了。我们可以使用多种方法开发好的、易交互的界面,常用的工具有:dialog、echo、printf等命令。 +本节课主要给大家介绍一个最简单易用的命令:echo + +#### 1、echo命令 + +**功能:将内容输出到默认显示设备** + +**应用场景:需要计算机程序输出的地方** + +echo命令的功能是在显示器上显示一段文字,一般起到一个提示的作用。 功能说明:显示文字。 + +``` +语法:echo [-ne][字符串] + +补充说明: +1、echo会将输入的字符串送往标准输出。 +2、输出的字符串间以空白字符隔开,并在最后加上换行号。 + +OPTIONS: +-n 不要在最后自动换行 +-e 若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出: + +转义字符 +\a 发出警告声; +\b 删除前一个字符; +\t 插入tab; +\n 换行且光标移至行首; + +\c 最后不加上换行符号; +\f 换行但光标仍旧停留在原来的位置; +\r 光标移至行首,但不换行; +\v 与\f相同; +\ 插入\字符; +\0nnn 打印nnn(八进制)所代表的ASCII字符; 备注:数字0 不要理解成字母o +\xNN 打印NN(十六进制)所代表的ASCII字符; + +-–help 显示帮助 +-–version显示版本信息 + + +你的进制转换过关吗? +[root@zutuanxue ~]# echo -e "\0123" #ot(123) = 83 对应ascii表的S +S +[root@zutuanxue ~]# echo -e "\x61" #ox(61) = 97 对应ascii表的a +a +``` + +#### 2、输出颜色字体 + +脚本中echo显示内容带颜色显示,echo显示带颜色,**需要使用参数-e** + +``` +格式如下: + +echo -e "\033[字背景颜色;文字颜色m字符串\033[0m" +``` + +例如: echo -e “\033[41;36m something here \033[0m” + +其中41的位置代表底色, 36m的位置是代表字的颜色 + +1、字背景颜色和文字颜色之间是英文的 + +2、文字颜色后面有个m + +3、字符串前后可以没有空格,如果有的话,输出也是同样有空格 + +``` +下面是相应的字和背景颜色,可以自己来尝试找出不同颜色搭配 + +  例 +  echo -e “\033[31m 红色字 \033[0m” +  echo -e “\033[34m 黄色字 \033[0m” +  echo -e “\033[41;33m 红底黄字 \033[0m” +  echo -e “\033[41;37m 红底白字 \033[0m” +   +字颜色:30—–37 +  echo -e “\033[30m 黑色字 \033[0m” +  echo -e “\033[31m 红色字 \033[0m” +  echo -e “\033[32m 绿色字 \033[0m” +  echo -e “\033[33m 黄色字 \033[0m” +  echo -e “\033[34m 蓝色字 \033[0m” +  echo -e “\033[35m 紫色字 \033[0m” +  echo -e “\033[36m 天蓝字 \033[0m” +  echo -e “\033[37m 白色字 \033[0m” + +   +字背景颜色范围:40—–47 +  echo -e “\033[40;37m 黑底白字 \033[0m” +  echo -e “\033[41;37m 红底白字 \033[0m” +  echo -e “\033[42;37m 绿底白字 \033[0m” +  echo -e “\033[43;37m 黄底白字 \033[0m” +  echo -e “\033[44;37m 蓝底白字 \033[0m” +  echo -e “\033[45;37m 紫底白字 \033[0m” +  echo -e “\033[46;37m 天蓝底白字 \033[0m” +  echo -e “\033[47;30m 白底黑字 \033[0m” +   +最后面控制选项说明 +  \033[0m 关闭所有属性 +  \033[1m 设置高亮度 +  \033[4m 下划线 +  \033[5m 闪烁 +  \033[7m 反显 +  \033[8m 消隐 + +  \033[30m — \33[37m + +设置前景色 +  \033[40m — \33[47m 设置背景色 +   +   +  \033[nA 光标上移n行 +  \033[nB 光标下移n行 +  \033[nC 光标右移n行 +  \033[nD 光标左移n行 +  \033[y;xH设置光标位置 +  \033[2J 清屏 +  \033[K 清除从光标到行尾的内容 +  \33[s 保存光标位置 +  \033[u 恢复光标位置 +  \033[?25l 隐藏光标 +  \033[?25h 显示光标 +   +用法例子 光标下移三行   +[root@zutuanxue ~]# echo -e "\033[0m today is fine \033[3B" + today is fine +``` + +#### 3、jobs + +需求:输出一个水果购物界面 fruits_shop.sh + +![image20190612094713385.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/24/1600908891935.png) + +案例要点: + +- echo输出缩进问题 +- 字体颜色输出 + +代码实现: + +``` +job代码 01_fruits_shop.sh +#!/bin/bash +# +#Author: www.zutuanxue.com +#Release: +#Description:打印水果超市列表 + +echo -e "\t\t \033[32m Fruits List \033[0m \n" +echo -e "\t \033[31mFruit\033[0m \t\t \033[31mPrice\033[0m \t\t\033[31mWeight\033[0m" +echo -e "\t\033[34m1)Apple\t\t¥10.00\t\t1KG\033[0m" +echo -e "\t\033[34m2)Banana\t¥9.00\t\t1KG\033[0m" +echo -e "\t\033[34m3)Orange\t¥15.20\t\t1KG\033[0m" +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-Python\345\256\211\350\243\205\350\204\232\346\234\254.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-Python\345\256\211\350\243\205\350\204\232\346\234\254.md" new file mode 100644 index 0000000..1ec29b7 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-Python\345\256\211\350\243\205\350\204\232\346\234\254.md" @@ -0,0 +1,95 @@ +## 案例需求 + +使用shell脚本安装Python环境 + +## 应用场景 + +服务器业务初始化 + +## 解决问题 + +避免人工多次安装,节省人工成本 +避免人工错误,提高工作效率 + +## 脚本思路 + +1、获得软件包 +2、源码安装 +3、升级pip命令 + +## 案例代码 + +``` +#!/bin/bash +#Description: python install from zutuanxue(http://www.zutuanxue.com) +#Release: python 3.7.6 +#Auther: zutuanxue +#Email: +#OS: Centos 8.X + + +#variables +python_download_url=https://www.python.org/ftp/python/3.7.6/Python-3.7.6.tgz +python_source_pkg=Python-3.7.6.tgz +python_code=Python-3.7.6 + + +#functions +#安装前准备,安装必要依赖包 +per_install () { + if ( ! yum -y install gcc-* openssl-* libffi-devel sqlite-devel &>/dev/null );then + #if ( ! yum -y install gcc-* openssl-* libffi-devel sqlite-devel ) &>/dev/null ;then + echo -e "\033[31m network connection error,exit... \033[0m" + exit 130 +fi +} + +#安装python +install () { + #下载软件包 + wget $python_download_url + #解压软件包 + if [ -f $python_source_pkg ];then + tar xf $python_source_pkg + [ $? -ne 0 ]&&echo "$python_source_pkg unzip fail"&&exit 1 + cd $python_code + #配置,开启ssl支持https + if ./configure --with-openssl=/usr/bin/openssl 1>/dev/null;then + #mv Modules/Setup Modules/Setup.bak + cp -f ../Setup Modules/ + if make 1>/dev/null;then + #if make ;then + if make install 1>/dev/null;then + #if make install ;then + #if pip3 install --upgrade pip 1>/dev/null;then + #安装完成后更新pip + if pip3 install --upgrade pip;then + echo "python install success" + else + echo "pip3 install fail" + exit 1 + fi + else + echo "python install fail" + exit 1 + fi + else + echo "python make fail" + exit 1 + fi + else + echo "python configure fail" + exit + fi + else + echo "not found $python_source_pkg" + exit 1 + fi +} + + + +per_install;install +rm -rf $python_code +rm -rf python_source_pkg +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-mysql\345\244\207\344\273\275\350\204\232\346\234\254.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-mysql\345\244\207\344\273\275\350\204\232\346\234\254.md" new file mode 100644 index 0000000..963328c --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-mysql\345\244\207\344\273\275\350\204\232\346\234\254.md" @@ -0,0 +1,99 @@ +## 案例需求 + +写一个mysql binlog备份脚本,要求每天0点0分,计算机自动备份前一天的binlog日志,打包后发送给备份服务器。 + +## 脚本应用场景: + +文件备份 + +## 解决问题 + +日常文件备份 + +日常数据备份 + +## 脚本思路 + +1、确定binlog的位置及备份时间间隔 每天 + + 当前要备份的binlog是谁 + + 刷新binlog日志,生成新的binlog用于存储备份节点后的数据 + +2、打包binlog日志 以年-月-日_binlog.tar.gz格式 + +3、生成校验码 md5sum + +4、将校验码和压缩包存入到文件夹 文件夹命名 年-月-日 再次打包 + +5、使用scp拷贝到备份机器 + +6、备份机器解压收到的目录压缩包 通过校验码 教研binlog压缩包是否完整 + + 完整 完成备份 -----发邮件给管理员,明确备份成功 + + 不完整 报错------发邮件给管理员,要求手动备份 + +## 实现代码 + +``` +#!/bin/bash +#Description: +#Author: www.zutuanxue.com +#Created Time: +#将mysql的binlog日志备份到备份服务器 + + +########variables +db_user='root' +db_password='' +log='/var/log/mysql_backup.log' + + + +###main +#获得信息 +binlog_dir='/var/lib/mysql' +current_binlog=`mysql -u $db_user -e "show master status"|egrep "binlog.[[:digit:]]*"|awk '{print $1}'` + +date >> $log +#准备备份 +#1 刷新binlog +mysql -u $db_user -e "flush logs" +#2 打包要备份的binlog +tar czf `date +%F`_binlog.tar.gz $binlog_dir/$current_binlog &>>$log +#3 生成校验码 +md5sum `date +%F`_binlog.tar.gz > "`date +%F`_md5sum.txt" +#4 存入文件夹 +[ ! -d `date +%F` ]&&mkdir `date +%F` +mv `date +%F`_binlog.tar.gz `date +%F` +mv `date +%F`_md5sum.txt `date +%F` + +# 打包目录 +tar czf `date +%F`.tar.gz `date +%F` &>>$log + +#5 拷贝 +#要求提前做证书信任 +scp `date +%F`.tar.gz root@192.168.11.241:/opt/backup &>>$log +if [ $? -ne 0 ];then + echo "ERROR:scp `date +%F`.tar.gz fail" &>>$log + exit 1 +fi + +#6 校验 +ssh root@192.168.11.241 "tar xf /opt/backup/`date +%F`.tar.gz -C /opt" +#ssh root@192.168.11.241 "cd /opt/backup`date +%F`" +ssh root@192.168.11.241 "cd /opt/`date +%F`;md5sum -c `date +%F`_md5sum.txt" &>>$log +if [ $? -eq 0 ];then + echo "success" &>>$log + ssh root@192.168.11.241 "rm -rf /opt/`date +%F`" +else + echo "fail" &>>$log +fi +``` + +## 案例思考 + +``` +双机同步实现方式 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-nginx\345\256\211\350\243\205\350\204\232\346\234\254.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-nginx\345\256\211\350\243\205\350\204\232\346\234\254.md" new file mode 100644 index 0000000..51984d7 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-nginx\345\256\211\350\243\205\350\204\232\346\234\254.md" @@ -0,0 +1,110 @@ +## 案例需求 + +通过shell脚本安装nginx + +## 应用场景 + +web服务器业务初始化 + +## 案例思路 + +1、软件获得 +2、源码安装 + +## 案例代码 + +``` +#!/bin/bash +#Description: nginx install script from zutuanxue(http://www.zutuanxue.com) +#Release: 1.0 +#Auther: www.zutuanxue.com +#Email: +#OS: Centos 8.X + +cat </dev/null);then + echo "yum install soft package fail" + exit 1 +fi + +if ! (egrep "^www" /etc/passwd &>/dev/null);then + useradd -s /sbin/nologin -r -M www +fi + +} + + + +nginx_install () { +#1、下载软件包 +#if wget $nginx_pkg_url &>/dev/null;then + #2、解压软件包 + echo $nginx_pkg_url|awk -F "/" '{print $5}'|xargs tar xf + nginx_source_doc=`echo $nginx_pkg_url|awk -F "/" '{print $5}'|cut -d "." -f 1-3` + #3、进入软件包 + if [ ! -d $nginx_source_doc ];then + echo "unzip `echo $nginx_pkg_url|awk -F "/" '{print $5}'` fail" + exit 1 + fi + + cd $nginx_source_doc + + #4、configure nginx + ./configure --prefix=$nginx_install_doc/nginx --user=$nginx_manage_user --group=$nginx_manage_user 1>/dev/null + [ $? -ne 0 ]&&echo "nginx configure fail"&&exit 1 + + #5、make nginx + make -j $cpu_count 1>/dev/null + [ $? -ne 0 ]&&echo "nginx make fail"&&exit 1 + + #6、install nginx + make install 1>/dev/null + [ $? -ne 0 ]&&echo "nginx install fail"&&exit 1||echo "`clear`nginx install success..." + + #7、delete nginx soft package + cd .. + rm -rf ${nginx_source_doc}* + +#else +# echo "$nginx_pkg_url download fail" +# exit 1 +#fi + + +} + +#####callable function +check;nginx_install +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\344\270\273\346\234\272\347\212\266\346\200\201\347\233\221\346\216\247\350\204\232\346\234\254.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\344\270\273\346\234\272\347\212\266\346\200\201\347\233\221\346\216\247\350\204\232\346\234\254.md" new file mode 100644 index 0000000..2a76fd9 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\344\270\273\346\234\272\347\212\266\346\200\201\347\233\221\346\216\247\350\204\232\346\234\254.md" @@ -0,0 +1,88 @@ +## 案例需求 + +通过脚本判断远程计算机的存活状态 + +## 脚本应用场景 + +1、通过监控平台调用监控脚本对服务器进行监控 + +2、机器扫描 + +## 解决问题 + +1、运维人员实时掌控机器的状态,防止宕机或者由于压力过大造成请求处理延时,保障业务的稳定、高效运行 + +## 脚本思路 + +1、通过ICMP协议的ping命令ping目标主机 + +``` +网络延迟,假报警如何解决? + 3次 +``` + +2、分析ping结果 + +3、给出结论 + +``` +全部ping结果为假,报宕机 +全部ping成功,报正常 +否则报警告 +``` + + + +## 实现代码 + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: + + +#1、ping 目标主机三次,并接收每次的状态值,ping成功返回1,不成功返回0 +for ((i=1;i<4;i++));do +#测试代码 + if ping -c1 $1 &>/dev/null;then + + #分析结果 + export ping_count"$i"=1 + + else + export ping_count"$i"=0 + fi + +#时间间隔 + sleep 0.3 +done + +#3、分析结果 +# 3次ping失败报警 +# +if [ $ping_count1 -eq $ping_count2 ] && [ $ping_count2 -eq $ping_count3 ]&&[ $ping_count1 -eq 0 ];then + echo "$1 宕机" +elif [ $ping_count1 -eq $ping_count2 ] && [ $ping_count2 -eq $ping_count3 ]&&[ $ping_count1 -eq 1 ];then + echo "$1 正常" +else + echo "warn: $1 网络延迟" +fi + +#4、释放变量 +unset ping_count1 +unset ping_count2 +unset ping_count3 +``` + +## 案例思考 + +``` +当你的机器放在IDC机房的时候,你如何判断各个运营商的用户到你服务器的以下数据。 + +网络延迟如何获得 + +网络丢包率如何获得 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\345\210\244\346\226\255\346\234\215\345\212\241\347\212\266\346\200\201.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\345\210\244\346\226\255\346\234\215\345\212\241\347\212\266\346\200\201.md" new file mode 100644 index 0000000..3e0ccdd --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\345\210\244\346\226\255\346\234\215\345\212\241\347\212\266\346\200\201.md" @@ -0,0 +1,71 @@ +## 案例需求 + +判断计算机某个端口是否为OPEN状态,且能正常访问 + +## 脚本应用场景: + +服务监控脚本+监控平台 + +手动监控 + +## 解决问题 + +实时掌握服务的运行状态,及时处理问题。 + +## 脚本思路 + +1、使用telnet命令连接远端机器的远端端口 + +2、接收连接反馈并分析结果 + +3、分析文件内容 + +4、打印结果 + +## 实现代码 + +``` +#!/bin/bash +#Description: +#Author: www.zutuanxue.com +#Created Time: +#监控一个服务端口 + + +#main + +temp_file=`mktemp port_status.XXX` + +#1、判断依赖命令telnet是否存在 +[ ! -x /usr/bin/telnet ]&&echo "telnet: not found command"&& exit 1 + +#2、测试端口 $1 IP $2 port +( telnet $1 $2 <$temp_file + +#3、分析文件中的内容,判断结果 +if egrep "\^]" $temp_file &>/dev/null;then + #4、打印结果 + echo "$1 $2 is open" +else + echo "$1 $2 is close" +fi + +#5、删除临时文件 +rm -f $temp_file +``` + +## 案例思考 + +``` +#监控方法 +#1)通过systemctl service 服务启动状态 +#2)lsof 查看端口是否存在 +#3)查看进程是否存在 + 注意 压力过大 无法响应 | 服务down了 上述东西还在 监测不准确 + +#4)测试端口是否有响应 推荐 + #telnet 协议 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\345\210\244\346\226\255\351\227\260\345\271\264.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\345\210\244\346\226\255\351\227\260\345\271\264.md" new file mode 100644 index 0000000..7de40c2 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\345\210\244\346\226\255\351\227\260\345\271\264.md" @@ -0,0 +1,57 @@ +## 案例需求 + +闰年判断:判断某年是否问闰年 + +## 闰年判断方法: + +普通闰年:能被4整除但不能被100整除的年份为普通闰年。(如2004年就是闰年,1900年不是闰年) +世纪闰年:能被400整除的为世纪闰年。(如2000年是世纪闰年,1900年不是世纪闰年) + +## 脚本应用场景: + +时间类型脚本总总时间的统计。 + +## 解决问题 + +时间计算中从某一年到某一年天数的统计 ,解决了闰年、平年的天数不同的问题。 + +## 脚本思路 + +1、交互输入year + +2、根据公式判断输出 + +3、输出判断结果 + +## 实现代码 + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description:闰年判断脚本 + +#variables + + +#main +#1、交互输入要判断的年 +read -p "输入一个年份: " year + + + +#2、判断 +if [ -z "$year" ];then + echo "$0 year" + exit 1 +elif (($year%400==0));then +#3、输出结果 + echo "$year: 闰年" +elif (($year%4==0));then + echo "$year: 闰年" +else + echo "$year: 平年" +fi +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\221\346\216\247\345\206\205\345\255\230\344\275\277\347\224\250\347\216\207.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\221\346\216\247\345\206\205\345\255\230\344\275\277\347\224\250\347\216\207.md" new file mode 100644 index 0000000..1b8b0be --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\221\346\216\247\345\206\205\345\255\230\344\275\277\347\224\250\347\216\207.md" @@ -0,0 +1,68 @@ +## 案例需求 + +打印内存使用率脚本,打印内存使用率、swap使用率、buff&cache使用量 + +**实现效果** + +``` +#实现演示 +内存使用率: 2.69%,buff&cache:535 MB +Swap使用率: 0% +``` + +## 脚本应用场景: + +监控平台+内存监控脚本 + +手动监控 + +## 解决问题 + +随时掌握业务对内存的占用,合理使用内存资源 + +## 脚本思路 + +1、获取物理内存、swap的相关数据 + + 1.1通过数据检索获得物理内存总量、Swap的总量 + + 1.2通过数据检索获得物理内存的使用量,Swap的使用量 + + 1.3通过检索获得物理内存buff&cache的量 + +2、调用相关数据进行运算,并输出结果 + +## 实现代码 + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description:内存使用率计算脚本 + +#1、通过free命令结合数据处理获得对应数据 +#1.1、获得内存总量 +memory_totle=`free -m|grep -i "mem"|tr -s " "|cut -d " " -f2` +swap_totle=`free -m|grep -i "swap"|tr -s " "|cut -d " " -f2` +#1.2、获得内存使用的量 +memory_use=`free -m|grep -i "mem"|tr -s " "|cut -d " " -f3` +swap_use=`free -m|grep -i "swap"|tr -s " "|cut -d " " -f3` +#1.3、buff/cache +buff_cache=`free -m|grep -i "mem"|tr -s " "|cut -d " " -f6` + +#2、计算输出 +#运算的时候是否需要小数点 浮点运算,要考虑使用的命令 (难点 重点) +#echo "内存使用率: $((memory_use*100/memory_totle))%" +#难点:浮点运算中,同优先级的情况下,大数除以小数 尽可能保证精确 +echo "内存使用率: `echo "scale=2;$memory_use*100/$memory_totle"|bc`%,buff&cache:$buff_cache MB" +echo "Swap使用率: `echo "scale=2;$swap_use*100/$swap_totle"|bc`%" +``` + +## 案例思考 + +``` +内存获取的方式 +内存占用的优先级 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\221\346\216\247\346\216\245\345\217\243.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\221\346\216\247\346\216\245\345\217\243.md" new file mode 100644 index 0000000..4d6852c --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\221\346\216\247\346\216\245\345\217\243.md" @@ -0,0 +1,82 @@ +## 案例需求 + +URL监控脚本,对某个URL进行监控,返回值为200则代表成功访问。 + +## 脚本应用场景: + +WEB站点监控 + +## 解决问题 + +URL监控 + +页面监控 + +## 脚本思路 + +1、使用curl访问一次URL,并将输出保存 + +2、访问输出文件,获取返回值 + +3、判断返回值是否和初始预设的返回值相等,并对应输出 + +## 实现代码 + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: URL监控脚本 +#监控阈值可以是: 状态码、页面字符串、页面所有内容 +#本例以状态码为例 + +#variables +init_url_status=200 +temp_file=`mktemp /tmp/check_url.XXX` + +#help +if [ -z "$1" ]||[ "$1" == "--help" ];then + echo "$0 url" + echo "--help: 打印该帮助" +fi + +#如果用户没有传参则退出 +[ $# -lt 1 ]&&exit 1 +#main + +#1、使用curl命令访问一次URL +#1.1 判断脚本依赖命令是否存在 +[ ! -x /usr/bin/curl ]&&echo "curl: not found command"&&exit 1 + +#1.2 访问一次URL +curl -I $1 &> $temp_file + + +#2、从输出中截取状态码 +url_status=`grep "HTTP/1.1" $temp_file|cut -d " " -f2` + +#2.1如果取值失败直接报错(测试发现当无法访问URL时会在第三步中报比较错误,所以这里取不到值就不往下走了) +[ -z "$url_status" ]&&echo -e "\033[31mstatus:NULL\033[0m"&&exit 1 + + +#3、判断状态码是否和预设的一致 + #3.1 一致 输出绿色字体 "status:200" + #3.2 不一致 输出红色字体 "status:XXX" + +if [ $init_url_status -eq $url_status ];then + echo -e "\033[32mstatus:$url_status\033[0m" +else + echo -e "\033[31mstatus:$url_status\033[0m" +fi + +#4、删除临时文件 +rm -f $temp_file +``` + +## 案例思考 + +``` +页面监控方法(监控页面字符串或全页内容) +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\221\346\216\247\347\243\201\347\233\230\344\275\277\347\224\250\347\216\207.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\221\346\216\247\347\243\201\347\233\230\344\275\277\347\224\250\347\216\207.md" new file mode 100644 index 0000000..6a1e881 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\221\346\216\247\347\243\201\347\233\230\344\275\277\347\224\250\347\216\207.md" @@ -0,0 +1,68 @@ +# job-监控磁盘使用率 + +## 案例需求 + +打印磁盘使用率脚本,对本机的磁盘使用率统计并打印结果 +使用率小于80,绿色输出 +使用率小于90,大于80,黄色输出 +使用率小于95,大于90,红色输出 + +## 脚本应用场景: + +磁盘使用率监控一般周期为小时、天,不会太频繁。 + +监控平台+监控脚本 + +计划任务+监控脚本 + +手动监控 + +## 解决问题 + +及时掌握磁盘容量,防止100%造成磁盘无法读取。 + +## 脚本思路 + +1. 检索本机磁盘 +2. 判断磁盘使用率 +3. 输出结果 + +## 实现代码 + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: + +#指定for条件的分割符为回车,一行一个条件 +IFS=$'\n' + +#1、遍历符合条件的每一行磁盘数据 +for i in `df -Th|egrep -v "(tmpfs|sr0)"|tail -n +2|tr -s " "`;do +size=`echo $i|cut -d " " -f6|tr -d "%"` +name=`echo $i|cut -d " " -f1` + +#2、判断每行中的磁盘使用率并输出结果 + if [ $size -ge 95 ];then + #3、输出日志并关机,不许在写入数据 + logger "ERROR:$name use is $size.halt" + halt -p + elif [ $size -ge 90 ];then + + echo -e "\033[31m $name use is ${size}%\033[0m" + elif [ $size -ge 80 ];then + echo -e "\033[33m $name use is ${size}%\033[0m" + else + echo -e "\033[32m$name use is ${size}%\033[0m" + fi +done +``` + +## 案例思考 + +``` +思考磁盘IO队列、吞吐率、IOPS的监控方法 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\221\346\216\247\347\275\221\345\215\241\346\265\201\351\207\217.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\221\346\216\247\347\275\221\345\215\241\346\265\201\351\207\217.md" new file mode 100644 index 0000000..38cdb4b --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\221\346\216\247\347\275\221\345\215\241\346\265\201\351\207\217.md" @@ -0,0 +1,95 @@ +# job-网卡流量监控 + +## 案例需求 + +网卡发送和就收数据量监控,按秒统计。 + +**思考:** 如何获取某块网卡上一秒的流入、流出数据流量 +ifconfig中可以获得,你知道吗? + +![网卡流量.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601963911887.png) + +## 脚本应用场景: + +动态监控网卡的流量 + +## 解决问题 + +实时掌握网卡的流量,掌握带宽使用情况 + +## 脚本思路 + +1、获得网卡当前流入流出总量 + +2、休息一秒 + +3、获得网卡当前流入流出总量 + +4、运算得出上一秒网卡流量 + +5、输出结果 + +## 实现代码 + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: 网卡流量监控 + + +#脚本用法 +#判断用户是否传参 +if [ -z "$1"] || [ "$1" == "--help" ];then + cat << EOF +$0 网卡名称 +--help 打印帮助菜单 +EOF +fi + + + +#如果用户没有传参,则退出脚本 +[ $# -lt 1 ]&&exit 1 + +#第一次取值 +#1、获得当前网卡流量 初始化值 +NIC_RX=`ifconfig $1|grep "RX packets"|tr -s " "|cut -d " " -f6` +NIC_TX=`ifconfig $1|grep "TX packets"|tr -s " "|cut -d " " -f6` + +#休息一秒开始循环 +sleep 1 + + +#循环开始监控网卡流量 监控频率 1s +while : + do + #2、监控当前网络的流量,第二次取值 + NIC_RX_1=`ifconfig $1|grep "RX packets"|tr -s " "|cut -d " " -f6` + NIC_TX_1=`ifconfig $1|grep "TX packets"|tr -s " "|cut -d " " -f6` + + #3、制作输出 + #3.1、清屏输出下文 + clear + echo -e "\t$1 网卡流量监控" + echo "----------------------------------------" + echo -e "网卡: $1\n" + #3.2、运算得出结论 + echo -e "发送:\t$((NIC_TX_1-NIC_TX))B/s\t接收:\t$((NIC_RX_1-NIC_RX))B/s" + + #重新赋值网卡初始化流入流出变量 + NIC_RX=$NIC_RX_1 + NIC_TX=$NIC_TX_1 + + #休眠1秒,进入下一次循环 + sleep 1 +done +``` + +## 案例思考 + +``` +如何采用图表的方式输出网卡信息 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\256\345\275\225\345\210\244\346\226\255.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\256\345\275\225\345\210\244\346\226\255.md" new file mode 100644 index 0000000..bd33b1d --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\346\241\210\344\276\213-\347\233\256\345\275\225\345\210\244\346\226\255.md" @@ -0,0 +1,37 @@ +## 案例需求 + +判断/tmp/run目录是否存在,如果不存在就建立,如果存在就删除目录里所有文件 + +## 脚本应用场景: + +脚本中对文件和文件夹类型的及权限的判断 + +## 解决问题 + +避免文件或者文件夹的重复建立问题 + +## 脚本思路 + +1. 判断文件夹/tmp/run目录是否存在 +2. 存在 删除目录下内容 +3. 不存在 退出脚本 + +## 实现代码 + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: 判断/tmp/run目录是否存在 + +#1、判断文件夹/tmp/run目录是否存在 +if [ -d /tmp/run ];then + #2、存在 删除目录下内容 + rm -rf /tmp/run/* +else + #3、不存在 退出脚本 + exit 0 +fi +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\347\224\250\346\210\267\344\272\244\344\272\222.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\347\224\250\346\210\267\344\272\244\344\272\222.md" new file mode 100644 index 0000000..5c9c366 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\204\232\346\234\254\347\224\250\346\210\267\344\272\244\344\272\222.md" @@ -0,0 +1,68 @@ +学会了输出,那么输出什么呢?当然是人类让计算机运算的数据,那么运算的数据来自哪里? + +可以肯定是你或其他人给的,那如何给程序数据呢? + +**那么我们就得看看如何实现人机交互了。** + +- 比如计算机程序 +- 比如信息录入系统 + +## 一、read命令 + +功能:默认接受键盘的输入,回车符代表输入结束 +应用场景:人机交互 +命令选项 + +``` +-p打印信息 +-t限定时间 +-s不回显 +-n输入字符个数 +``` + +## 二、交互输入案例 + +**案例需求:** +写一个系统用户交互登录界面脚本,仿linux文本界面登录 +**案例要点:** +了解linux文本界面登陆所需要的输出信息及界面布局 + +![login.gif](https://www.zutuanxue.com:8000/static/media/images/2020/9/24/1600910891275.gif) + +**job实现步骤:** +1、根据linux文本界面登陆窗口输出信息,打印登陆提示信息 +2、交互输入登陆账号 +3、交互输入登陆密码 + +**代码实现:** + +``` +#job实现代码 02_login.sh +#!/bin/bash +# +#Author: www.zutuanxue.com +#Release: +#Description: 仿真登陆 + +IP=`ifconfig ens33|egrep -w "inet"|awk '{print $2}'` + +#1、清屏 +clear +#2、输出提示信息 +echo "CentOS Linux 8 (Core)" +echo -e "Kernel `uname -r` on an `uname -m`\n" + +echo -e "Web console: https://localhost:9090/ or https://$IP:9090/ \n" + +#3、交互输入登陆名 +echo -n "$HOSTNAME login: " +read account + +#4、交互输入密码 +read -s -t30 -p "Password: " pw +echo +``` + +**实现效果:** + +![login2.gif](https://www.zutuanxue.com:8000/static/media/images/2020/9/24/1600912191604.gif) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\277\220\347\256\227\345\256\236\346\210\230\346\241\210\344\276\213-KFC\347\202\271\351\244\220\347\263\273\347\273\237.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\277\220\347\256\227\345\256\236\346\210\230\346\241\210\344\276\213-KFC\347\202\271\351\244\220\347\263\273\347\273\237.md" new file mode 100644 index 0000000..94cb583 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/shell\350\277\220\347\256\227\345\256\236\346\210\230\346\241\210\344\276\213-KFC\347\202\271\351\244\220\347\263\273\347\273\237.md" @@ -0,0 +1,79 @@ +## 写一个KFC餐厅点餐程序 + +**案例需求** +写一个程序,模拟KFC点餐系统,要求有以下功能: + +- 1、点餐功能 +- 2、结算功能 +- 3、打印流水单 + +**案例步骤** + +- 1、交互点餐 +- 2、结账收银 +- 3、打印流水单给客户 + +**案例代码** + +``` +#!/bin/bash +# +#Author:www.zutuanxue.com +# +#Release: +#Description: + +#1)录入单价 +HBB=19.8 +JC=12.3 +KL=9.9 + +#2)定义输出 +cat < $2 " +elif [ $1 -eq $2 ];then + echo "$1 = $2" +else + echo "$1 < $2" +fi +``` + +**实现结果:** + +![比较两个数关系.gif](https://www.zutuanxue.com:8000/static/media/images/2020/9/24/1600942462497.gif) + +#### 3.2.2 判断两个浮点数的关系 + +**案例思考** +shell中的浮点类型如何做比较运算? + +``` +默认情况下shell是不能判断浮点的,那么在linux中又避免不了需要进行浮点运算,那怎么解决 + +解决思路如下: +1)两个数据同时放大到整数倍 +2)处理掉小数点位,保留整数位 +3)进行整形判断 +``` + +**实现代码** + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +# +#Release: +#Description:判断两位小数点的关系 + +#1、交互或者外传参的方式获得两个整数 +#$1 $2 +[ $# -lt 2 ]&&echo "need two args"&&exit 1 + +#采用外传参的方式接收数据并放大100倍,并处理为整数 +num1=`echo "scale=2;$1*100"|bc|cut -d "." -f1` +num2=`echo "scale=2;$2*100"|bc|cut -d "." -f1` + +#2、比较运算 +if [ $num1 -gt $num2 ];then + #3、输出结果 + echo "$1 > $2" +elif [ $num1 -lt $num2 ];then + echo "$1 < $2" +else + echo "$1 = $2" +fi +``` + +**实现结果** + +![比较两个浮点数关系.gif](https://www.zutuanxue.com:8000/static/media/images/2020/9/24/1600942985455.gif) + +### 3.3、字符串比较运算 + +#### 3.3.1 字符串比较运算符 + +``` +运算符解释,注意字符串一定别忘了使用引号引起来 + == 等于 + != 不等于 + -n 检查字符串的长度是否大于0 + -z 检查字符串的长度是否为0 +``` + +#### 3.3.2 比较两个字符串关系 + +``` +[root@zutuanxue ~]# test 'root' == 'root';echo $? +0 +[root@zutuanxue ~]# test 'root' != 'root1';echo $? +0 +[root@zutuanxue ~]# name= +[root@zutuanxue ~]# test -n "$name";echo $? +1 +[root@zutuanxue ~]# test -z "$name";echo $? +0 +``` + +#### 3.3.3 练习案例 + +**案例需求:** +模拟一个linux文本界面登陆程序,要求账号密码验证成功进入系统,账号密码验证失败退回登陆界面 + +**案例思考:** + +- 1、熟悉linux文本界面登陆步骤 +- 2、熟悉字符串比较运算 + +**案例步骤:** + +- 1、预设正确账号、密码 +- 2、输出提示登录信息并实现交互登录 +- 3、输出密码输入信息并实现交互 +- 4、判断输入是否正确 + – 4.1)正确,进入系统 + – 4.2)不正确 继续运行该脚本 + +**实现代码** + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: 仿真登陆 +#### +default_account='root' +default_pw='123456' + + +######main +#1、清屏 +clear +#2、输出提示信息 +echo "CentOS Linux 7 (Core)" +echo -e "Kernel `uname -r` on an `uname -m`\n" + +#3、交互输入登陆名 +echo -n "$HOSTNAME login: " +read account + +#4、交互输入密码 +read -s -t30 -p "Password: " pw + +#5、判断用户输入是否正确 +if [ "$default_account" == "$account" ] && [ "$default_pw" == "$pw" ];then + clear + echo -e "\nwelcome to root" +else + echo "用户名或密码错误..." + #输入错误,再次调用本脚本 + sh $0 +fi +``` + +**实现效果** +账号:root 密码:123456 + +![仿真登陆01.gif](https://www.zutuanxue.com:8000/static/media/images/2020/9/24/1600943778077.gif) + +## 四、逻辑运算 + +完成一个任务中需要多个条件都满足或者多个条件中只要满足一个即可,那么这就是我们的逻辑运算。 +通过多个条件判断结果,才能得出结论 + +#### 4.1、逻辑运算应用场景 + +``` +多条件同时判断 +``` + +#### 4.2、逻辑运算符 + +- 逻辑与运算 && +- 逻辑或运算 || +- 逻辑非运算 ! + +**逻辑运算秘籍** + +``` +逻辑运算注意事项: + 逻辑与 或 运算都需要两个或以上条件 + 逻辑非运算只能一个条件。 + 口诀: 逻辑与运算 真真为真 真假为假 假假为假 + 逻辑或运算 真真为真 真假为真 假假为假 + 逻辑非运算 非假为真 非真为假 + + +逻辑与或的短路运算 +逻辑与中靠前的条件中出现了假,后面的就不在判断了,因为已经是假的了 +逻辑或中靠前的条件中出现了真,后不在往后判断了,结果已经为真了 +``` + +### 4.3、练习案例 + +明白了逻辑运算符和逻辑运算的口诀和短路运算后,我们来通过练习加深理解,接下来我们来看一个案例。 +上一个字符串运算练习案例(3.3.3)中我们练习的是仿真用户登录,判断登陆的方式是分步判断的,既先判断用户名,不管是否正确都会继续判断密码的正确性,这样是两步判断,既然已知用户名是错误的啦,完全没必要在判断密码的正确性了,因为结果都一样,你不能进入系统。既然判断一个用户输入的用户名和密码是否正确,且一个不正确就不能进入系统,那么我们可以这么去思考一下:**两个条件全为真则进入系统,两个条件一个为假则重新登陆**。这样是不是就满足了逻辑与运算了,同时思考逻辑与运算的短路运算,逻辑与条件中的判断顺序是从前往后,前边一个条件为假的时候,后边的条件就不用判断了,那么就减少了判断的次数,加快了运算速度。你品!你细品!!是不是这个道理。 + +#### 4.3.1、就按照刚才的思路再去写一个升级版的仿真用户登录系统。 + +**案例需求** +使用逻辑运算写一个仿真用户登录验证程序 + +**案例思路** + +- 1、输入用户名 +- 2、输入密码 +- 3、与运算返回结果 + +**案例代码** + +``` +#!/bin/bash +echo "CentOS linux 8 (Core)" +echo -e "Kernel `uname -r` on an `uname -m` \n" + +#1、输入用户名 +echo -n "$HOSTNAME login: " +read myuser + +#echo -n "password: " +#read -s -t 5 -n 2 pw + +#2、输入密码 +read -p "password: " -s -t 5 -n 6 pw + +#3、与运算返回结果 +[ $myuser == 'root' ] && [ $pw == '123456' ] && echo yes || echo no +``` + +#### 4.3.2 丈母娘择婿 + +**案例需求** +伟大、慈祥的丈母娘有女儿,她想给自己的女儿选一个女婿,所以就想通过网上招婿的方式去处理,为了节约成本,让你帮忙开发一个小程序来自动过滤一下不满足条件的男士。 +改程序为了能够满足大量丈母娘的需求,所以可以根据女儿的年龄做出不同的判断 + +- 姑娘20岁 应征男士条件:房子需要两套及以上、存款100W及以上、车子1辆以上,条件必须全部满足 +- 姑娘30岁 应征男士条件:房子需要两套及以上、存款100W及以上、车子1辆以上,条件满足其中一个即可 +- 姑娘40岁 应征男士条件:是男的都可以报名 + 注意:应征者必须全是男性 + +**案例思考** +因为是多条件判断,复合逻辑运算的条件,重点在不同年龄段的逻辑判断方式! + +**案例步骤** + +- 1、要求传入两个参数:姑娘年龄、应征者行吧 +- 2、交互输入用户条件 +- 3、判断用户条件并输出结果 + +**案例代码** + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +# +#Release: +#Description: 丈母娘选女婿 练习逻辑运算 + +cat </dev/null +fi +} + +restart () { + stop + sleep 1 + start +} + +reload () { +#重载的目的是让主进程重新加载配置文件,但是前提是服务必须开启 +#这里先判断服务是否开启,开启就执行加载,没有开启直接报加载错误 +if [ -f $pid_file ]&&[ $nginx_process_num -ge 1 ];then + action "nginx reload" killall -s HUP $proc +else + action "nginx reload" killall -s HUP $proc 2>/dev/null +fi +} + +status () { +if [ -f $pid_file ]&&[ $nginx_process_num -ge 1 ];then + echo "nginx running..." +else + echo "nginx stop" +fi +} + +#callable +case $1 in +start) start;; +stop) stop;; +restart) restart;; +reload) reload;; +status) status;; +*) echo "USAGE: $0 start|stop|restart|reload|status";; +esac +``` + +## 三、学习视频 + +[视频:case语句介绍](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=71) +[视频:job-Nginx启动管理脚本](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=72) +[视频:函数与case知识图谱总结](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=73) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/\346\265\201\347\250\213\346\216\247\345\210\266-for\345\276\252\347\216\257\350\257\255\345\217\245.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/\346\265\201\347\250\213\346\216\247\345\210\266-for\345\276\252\347\216\257\350\257\255\345\217\245.md" new file mode 100644 index 0000000..39716dc --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/\346\265\201\347\250\213\346\216\247\345\210\266-for\345\276\252\347\216\257\350\257\255\345\217\245.md" @@ -0,0 +1,219 @@ +工作中总是有很多工作需要重复性来完成,比如每天都需要执行一次备份、每天都需要分析一次业务的access.log日志,每分钟都需要监测一次主机的状态等等工作,这些重复性的工作我们一般都是使用脚本来完成,对于不需要频繁执行的任务,可以结合计划任务➕脚本完成,但是系统的计划任务只能精确到分,不能满足更频繁的重复工作。 + +这个时候我们除了依赖计划任务之外还有很多选择,比如脚本中的循环语句。 + +循环的优点 + +- 1)节省内存 10M脚本 1M脚本 哪个更剩内存 完成同一个任务 +- 2)结构更清晰 +- 3)节省开发时间成本 + +## 一、循环语句-for + +### 1.1、for介绍 + +脚本在执行任务的时候,总会遇到需要循环执行的时候,比如说我们需要脚本每隔五分钟执行一次ping的操作,除了计划任务,我们还可以使用脚本来完成,那么我们就用到了循环语句。 + +### 1.2、for基本语法 for条件循环 + +- 列表for循环:用于将一组命令执行**已知的次数**,下面给出了for循环语句的基本格式: + +``` +for variable_name in {list} + do + command + command + … + done +或者 +for variable in a b c + do + command + command + done +``` + +### 1.3、for条件应用 + +for条件不同的赋值方式 +a、赋值来自一个范围 + +``` +for var in {1..10} + do + echo $var +done +``` + +b、直接赋值 + +``` +for var in 1 2 3 4 5 + do + echo $var +done +``` + +c、赋值来自命令 + +``` +for var in `seq 10` + do + echo $var +done +``` + +体验不同的方式 + +``` +赋值来自一个范围 +for var in $(seq 10) + do + echo $var +done + +for var in {0..10..2} + do + echo $var +done + + +for var in {10..1} + do + echo $var +done + + +for var in {10..1..-2} + do + echo $var +done + + +for var in `seq 10 -2 1` + do + echo $var +done +``` + +- 不带列表循环 + +不带列表的for循环执行时由**用户指定参数和参数的个数**,下面给出了不带列表的for循环的基本格式: + +``` +for variable + do + command + command + … + done +``` + +语法结构举例说明: + +``` +#!/bin/bash +for var +do +echo $var +done + +echo "脚本后面有$#个参数" +``` + +### 1.4、for C格式语法 + +- 类C风格的for循环 + +``` +for(( expr1;expr2;expr3 )) + do + command + command + … + done +for (( i=1;i<=5;i++)) + do + echo $i + done + + +expr1:定义变量并赋初值 变量初始值 +expr2:决定是否进行循环(条件) 变量的条件 +expr3:决定循环变量如何改变,决定循环什么时候退出 自增或自减运算 + + + +多变量用法 +for ((A=1,B=10;A<10,B>1;A++,B--)) +``` + +**语法结构举例说明:** + +``` +for ((i=1;i<=5;i++));do echo $i;done +for ((i=1;i<=10;i+=2));do echo $i;done +for ((i=2;i<=10;i+=2));do echo $i;done +``` + +## 二、练习案例 + +**jobs: 写一个扫描软件,扫描本地网络中存活的机器** + +**案例需求:** +判断本地网络中哪些IP被使用 + +**案例分析:** +采用ping的方式判断IP是否被占用 + +``` + a、能ping通说明占用 + b、不能ping通说明未被占用 +``` + +b、命令 + +``` +ping -c1 IP +``` + +**算法:** +1、ping ip +2、分析ping结果 +3、输出结果 + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: 扫描本地网络中存活的主机,以C类地址为例 + + +#variables +netsub="192.168.1." + +#main +#1、循环ping IP地址,能ping通说明IP存在。 +for ip in `seq 1 254` + do + ( + #2、判断Ping结果 + if ping -c1 $netsub$ip &>/dev/null;then + #3、输出结果 + echo "$netsub$ip is open" + else + echo "$netsub$ip is close" + fi + ) & +done +``` + +## 三、学习视频 + +[视频:流程控制-循环课程介绍](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=51) +[视频:for循环介绍](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=52) +[视频:for条件赋值](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=53) +[视频:for仿C语法](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=54) +[视频:job-扫描局域网IP](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=55) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/\346\265\201\347\250\213\346\216\247\345\210\266-until\350\257\255\345\217\245.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/\346\265\201\347\250\213\346\216\247\345\210\266-until\350\257\255\345\217\245.md" new file mode 100644 index 0000000..4ec89c2 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/\346\265\201\347\250\213\346\216\247\345\210\266-until\350\257\255\345\217\245.md" @@ -0,0 +1,51 @@ +## 一、循环语句-until + +系统中还有一个类似while的循环语句,大家可以看看until语句,不同于while的是,当条件为假时开始until循环。 + +### 1.1、until介绍 + +特点:条件为假就进入循环;条件为真就退出循环 + +### 1.2、until语法 + +``` +until expression [ 1 -eq 1 ] (( 1 >= 1 )) + do + command + command + ... + done +``` + +## 二、案例: + +使用while循环和until循环打印数字接龙,要求while循环输出1-5,until循环输出6-9. + +**案例代码** + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: 数字接龙 + +i=1 +while [ $i -le 5 ] +do + echo $i + let i++ + until [ $i -le 5 ] + do + echo $i + let i++ + [ $i -eq 10 ]&&break + done +done +``` + +## 三、学习视频 + +[视频:until语句](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=66) +[视频:shell循环知识图谱总结](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=67) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/\346\265\201\347\250\213\346\216\247\345\210\266-while\345\276\252\347\216\257.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/\346\265\201\347\250\213\346\216\247\345\210\266-while\345\276\252\347\216\257.md" new file mode 100644 index 0000000..993b515 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/\346\265\201\347\250\213\346\216\247\345\210\266-while\345\276\252\347\216\257.md" @@ -0,0 +1,352 @@ +while在shell中也是负责循环的语句,和for一样。因为功能一样,很多人在学习和工作中的脚本遇到循环到底该使用for还是while呢?很多人不知道,就造就了有人一遇到循环就是for或者一位的while。我个人认为可以按照我说的这个思想来使用,既知道循环次数就可以用for,比如说一天需要循环24次;如果不知道代码要循环多少次,那就用while,比如我们作业中要求写的猜数字,每个人猜对一个数字的次数都是不能固定的,也是未知的。所以这样的循环我就建议大家用while了。 + +## 一、while介绍 + +**特点:**条件为真就进入循环;条件为假就退出循环,一般应用在未知循环次数的环境。 + +### 1.1、while语法 + +``` +while [ 表达式 ] + do + command... + done + +while [ 1 -eq 1 ] 或者 (( 1 > 2 )) + do + command + command + ... + done +``` + +**案例** +使用for循环和while循环分别循环打印数组1-5 + +**案例代码** + +``` +for循环打印: +for ((i=1;i<=5;i++)) +do + echo $i +done + +while循环打印: +#打印数字1-5 +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: 打印1-5 + +num=1 +while [ $num -le 5 ] + do + echo $num + let num++ +done +``` + +**备注:** 知道循环次数就可以用for,比如说一天需要循环24次;如果不知道代码要循环多少次,那就用while,比如我们作业中要求写的猜数字,每个人猜对一个数字的次数都是不能固定的,也是未知的。 + +## 二、while与shell运算 + +### 2.1、比较运算 + +**案例:** +循环交互输入一个小写字母,按Q退出循环 + +**案例代码** + +``` +#按Q退出场景 +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: +read -p "请输入一个小写字母,按Q退出: " choose +while [ $choose != 'Q' ] + do + echo "你输入的是: $choose" + read -p "请输入一个小写字母,按Q退出: " choose +done +``` + +### 2.2、逻辑运算 + +**案例:** +使用循环语句帮助丈母娘批量选择女婿 + +**案例代码** + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: + +#丈母娘选女婿 分别按照姑娘20 30 40 进行与或非模拟 + +#1.第一个应征者回答 +read -p "你有多少钱: " money +read -p "你有多少车: " car +read -p "你家房子有几套: " house + + +#while [ $money -lt 10000 ]&&[ $car -lt 1 ]&&[ $house -lt 2 ] +while [ $money -lt 10000 ]||[ $car -lt 1 ]||[ $house -lt 2 ] + do + #应征者不满住条件开始下一次循环 + echo "有请下一个" + read -p "你有多少钱: " money + read -p "你有多少车: " car + read -p "你家房子有几套: " house +done + +#应征者满足条件 +echo "乖女婿,你怎么才来啊!女儿给你了" +``` + +### 2.3、文件类型判断 + +**案例:** +使用循环判断/tmp/xxx目录下的文件,如果不是文件类型的打印字符串"目录" + +**案例代码** + +``` +文件类型判断 +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: + +while [ ! -f /tmp/xxx ] + do + echo “目录” + sleep 1 +done +``` + +### 2.4、特殊条件 + +while语句中可以使用特殊条件来进行循环: + +- 符号":" 条件代表真,适用与无限循环 +- 字符串 “true” 条件代表真,适用与无限循环 +- 字符串 "false"条件代表假 + +**代码展示** + +``` +特殊符号 : 代表真 +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: + +while : + do + echo haha + sleep 1 +done + + +true 字符串代表真,和:类似 +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: + +while true + do + echo haha + sleep 1 +done + + +false 字符串代表假,在while中不会开始循环 +``` + +## 三、while与循环控制语句 + +### 3.1、sleep语句 + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: 倒计时游戏 + +#1.定义初始值 +time=9 + +#2.循环输出,1秒一次 +while [ $time -ge 0 ] + do + echo -n -e "\b$time" + let time-- + #控制循环 1秒一次 + sleep 1 +done + +#回车 +echo +``` + +### 3.2、break + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: 输出数字1-9,当输出5时停止 + +#1、定义初始值 +num=1 + +while [ $num -lt 10 ] + do + echo $num + + #判断当前num的值,如果等于5就跳出循环 + if [ $num -eq 5 ] + then + break + fi + + #自动累加 + let num++ +done +``` + +### 3.3、continue + +``` +#!/bin/bash +# +#Author: +#Created Time: +#Release: +#Description: 输出数字1-9,当等于5时跳过本次循环,输出1、2、3、4、6、7、8、9 + +#1、定义初始值 +num=0 + +while [ $num -lt 9 ] + do + #自动累加 + let num++ + + #判断当前num的值,如果等于5就跳过本次循环 + if [ $num -eq 5 ] + then + continue + fi + + #输出num的值 + echo $num +done +``` + +## 四、while嵌套其他语句 + +### 4.1、while嵌套if + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: 输出数字1-9,当输出5时停止 + +#1、定义初始值 +num=1 + +while [ $num -lt 10 ] + do + echo $num + + #判断当前num的值,如果等于5就跳出循环 + if [ $num -eq 5 ] + then + break + fi + + #自动累加 + let num++ +done +``` + +### 4.2、while嵌套for + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: 99乘法表 + +A=1 +while [ $A -lt 10 ] + do + for ((B=1;B<=$A;B++)) + do + echo -n -e "$B*$A=$((A*B)) \t" + done + echo + let A++ +done +``` + +### 4.3、while嵌套while + +``` +#!/bin/bash +# +#Author: www.zutuanxue.com +#Created Time: +#Release: +#Description: 99乘法表 + +#定义A +A=1 +while [ $A -lt 10 ] + do + #定义B + B=1 + while [ $B -le $A ] + do + echo -n -e "$B*$A=$((A*B)) \t" + let B++ + done + + echo + let A++ +done +``` + +## 五、学习视频 + +[视频:while介绍](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=62) +[视频:while与shell运算](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=63) +[视频:while循环控制](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=64) +[视频: while嵌套](https://www.bilibili.com/video/BV1Tf4y1v7E2?p=65) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/\347\274\226\347\250\213\350\257\255\350\250\200\344\270\216shell\350\204\232\346\234\254.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/\347\274\226\347\250\213\350\257\255\350\250\200\344\270\216shell\350\204\232\346\234\254.md" new file mode 100644 index 0000000..c142921 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/shell\350\204\232\346\234\254\351\253\230\346\211\213\351\200\237\346\210\220/\347\274\226\347\250\213\350\257\255\350\250\200\344\270\216shell\350\204\232\346\234\254.md" @@ -0,0 +1,228 @@ +## 一、编程语言介绍 + +编程语言是指计算机能理解的语言,人类通过使用计算机语言可以给计算机批量下达任务,让其按照人类的思想去完成工作。最常见的语言有:汇编语言、C语言、java语言、php语言、Python语言、golang语言等等。 + +编程语言分类: + +- 编译型语言 + 程序在执行之前需要一个专门的编译过程,把程序编译成为机器语言文件,运行时不需要重新翻译,直接使用编译的结果就行了。程序执行效率高,依赖编译器,跨平台性差些。如C、C++、java +- 解释型语言 + 程序不需要编译,程序在运行时由解释器翻译成机器语言,每执行一次都要翻译一次。因此效率比较低。比如Python/JavaScript/ Perl /ruby/Shell等都是解释型语言。 + +## 二、shell介绍 + +shell在计算机中起到什么作用呢?为什么要求shell呢,我们可以看看计算机操作系统的组成: + +![OS分层.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/14/1600050867343.png) + +看图之前问大家个问题,两个人在电话聊天:只会说法语的法国人,只会说汉语的你。如何沟通呢? + +请个翻译在你两中间 + +同理,系统内核只知道二进制 + +如果你想给计算机内核下任务,让其驱动硬件干活,那么有两种选择 + +1、你学会二进制 + +2、找个翻译 + +### 1、shell介绍 + +shell就是我们找来的翻译 + +shell是一个程序,采用C语言编写,是用户和linux内核沟通的桥梁。它既是一种命令语言,又是一种解释性的编程语言。通过一个图表来查看一下shell的作用。 + +![00_shell.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/14/1600050927043.png) + +### 2、bash shell基本特性 + +知己知彼方可百战百胜,如何应用Bash shell,我们先看看他的特性,有助于我们快速应用。 + +2.1、 命令和文件自动补全 + +Tab只能补全命令和文件 (RHEL6/Centos6) + +2.2、 常见的快捷键—提升操作熟练度 + +``` +^c 终止前台运行的程序 +^z 将前台运行的程序挂起到后台 +^d 退出 等价exit +^l 清屏 +^a |home 光标移到命令行的最前端 +^e |end 光标移到命令行的后端 +^u 删除光标前所有字符 +^k 删除光标后所有字符 +^r 搜索历史命令 +``` + +### 3、shell脚本介绍 + +shell脚本是什么 + +简单来说就是将需要完成某个任务所执行的命令按照执行顺序保存到文本中,并给予执行权限。 + +``` + shell脚本精髓 学会60% +``` + +按照顺序执行。 + +它是解释型的,意味着不需要编译。 + +准确来说 + +若干命令 + 脚本的基本格式 + 脚本特定语法 + 思想= shell脚本 + +``` +脚本命令演示 +创建一个用户:harry useradd harry +密码设置为:yunwei.98989 echo "yunwei.98989"|passwd --stdin harry +该用户创建文件夹/tmp/zutuanxue mkdir /tmp/zutuanxue +该用户创建文件/tmp/zutuanxue/README touch /tmp/zutuanxue/README +将“hello world“输入到/tmp/zutuanxue/README echo 'hello world' > /tmp/zutuanxue/README + +实现代码 01_task.sh +#!/bin/bash + +#DESC: this is a test script +#AUTHOR: Bai Shuming +#RELEASE: 1.0 + +#main + +#创建用户harry +useradd harry + +#设置用户密码 yunwei.98989 +echo "yunwei.98989"|passwd --stdin harry + + +#使用harry创建文件夹,文件,输入文件中内容 +su - harry -c "mkdir /tmp/zutuanxue" +su - harry -c "touch /tmp/zutuanxue/README" +su - harry -c "echo 'hello world' > /tmp/zutuanxue/README" +``` + +什么时候用到脚本? + +重复化、复杂化的工作,通过把工作的命令写成脚本,以后仅仅需要执行脚本就能完成这些工作。 + +①自动化分析处理 + +②自动化备份 + +③自动化批量部署安装 + +④等等… + +如何学习shell脚本? + +尽可能记忆更多的命令 + +掌握脚本的标准的格式(指定魔法字节、使用标准的执行方式运行脚本) + +必须熟悉掌握脚本的基本语法(重点) + +学习脚本的秘诀: + +多看(看懂)——>多模仿(多练)——>多思考 + +### 4、shell脚本语法 + +来吧,光说不练嘴把式,我们来看看如何书写一个脚本呢,写好一个脚本有哪些规范呢? + +- shell脚本组成 + +![shell程序组成.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/14/1600051087772.png) + +- 脚本命名 + nginx_install.sh 脚本名称 脚本扩展名 .sh + 名字不要太长 26个字节内 +- 代码规范: + +``` +1、#!/bin/bash +//脚本第一行, #!魔法字符,指定脚本代码执行的程序。即它告诉系统这个脚本需要什么解释器来执行,也就是使用 +哪一种Shell + +2、#代表注释,#!特例 + +3、//以下内容是对脚本的基本信息的描述,大家可以根据实际情况尽可能的写详细一些,方便后续使用者 +# Name: 脚本名字 +# Desc:描述describe +# Path:存放路径 +# Usage:用法 +# Update:更新时间 +# Author:作者 +# Release: 分发版本 + +//下面就是脚本的具体内容 +commands +... +``` + +- 脚本执行方法: + – 标准脚本执行方法(建议): + +``` +[root@zutuanxue shell01]# cat 1.sh +#!/bin/bash +#xxxx +#xxx +#xxx +hostname +date +[root@zutuanxue shell01]# chmod +x 1.sh +[root@zutuanxue shell01]# ll +total 4 +-rwxr-xr-x 1 root root 42 Jul 22 14:40 1.sh +[root@zutuanxueshell01]# /shell/shell01/1.sh +zutuanxue +Sun Jul 22 14:41:00 CST 2018 +[root@zutuanxue shell01]# ./1.sh +zutuanxue +Sun Jul 22 14:41:30 CST 2018 +``` + +– 非标准的执行方法(不建议): + +``` +[root@zutuanxue shell01]# bash 1.sh +zutuanxue +Sun Jul 22 14:42:51 CST 2018 +[root@zutuanxue shell01]# sh 1.sh +zutuanxue +Sun Jul 22 14:43:01 CST 2018 +[root@zutuanxue shell01]# +[root@zutuanxue shell01]# bash -x 1.sh ++ hostname +zutuanxue ++ date +Sun Jul 22 14:43:20 CST 2018 + +-x:一般用于排错,查看脚本的执行过程 +-n:用来查看脚本的语法是否有问题 + +注意:如果脚本没有加可执行权限,不能使用标准的执行方法执行,bash 1.sh + +其他: +[root@zutuanxueshell01]# source 2.sh +server +Thu Nov 22 15:45:50 CST 2018 +[root@zutuanxue shell01]# . 2.sh +server +Thu Nov 22 15:46:07 CST 2018 + +source 和 . 表示读取文件,执行文件里的命令 +``` + +– 命令式脚本执行方法: + +``` +定义命令路径变量 PATH +PATH=$PATH:脚本路径 + +备注:脚本必须给执行权限 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix web\347\233\221\346\265\213,md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix web\347\233\221\346\265\213,md" new file mode 100644 index 0000000..e116dd5 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix web\347\233\221\346\265\213,md" @@ -0,0 +1,51 @@ +业务中总会让我们去监控一些URL,比如支付接口中的微信支付,支付宝支付,那么这些URL是怎么监控的呢?可以使用zabbix提供的web监测功能。 + +web监控一般在生产环境中一般不会配置到模板,一般都是某个业务机由于业务需要去监控本机或者下游某个机器的URL的,所以我这里配置也是针对某个机器来配置的。本实验中我是给node1来配置 + +**实验步骤** + +1. 给node1安装一个web站点,然后用web监测来监控该web +2. 监控平台配置web监测 + +### a、为node1部署一个站点 + +``` +#安装服务 +[root@node1 ~]# dnf -y install httpd + +#配置页面 +[root@node1 ~]# echo haha > /var/www/html/index.html + +#启动服务 +[root@node1 ~]# systemctl start httpd +[root@node1 ~]# systemctl enable httpd +Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service. +``` + +### b、监控平台配置web监测 + +配置—主机—选择被监控机的web监测 + +![web_check1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530856580.png) + +点击web监测进入本机的web监测管理页面,这里继续选择创建 web场景 + +![web_check2.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530869849.png) + +点击 创建web场景 + +![web_check3.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530881058.png) + +按要求填写内容后选择步骤 + +![web_check4.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530893761.png) + +点击添加后、web方案步骤就设置好了 + +![web_check5.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530908605.png) + +继续选择添加,WEB监测就做好了 + +测试一下,监测—web监测—node1_web,如下图 + +![web_check6.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530925622.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \344\270\273\345\212\250\347\233\221\346\216\247\345\222\214\350\242\253\345\212\250\347\233\221\346\216\247.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \344\270\273\345\212\250\347\233\221\346\216\247\345\222\214\350\242\253\345\212\250\347\233\221\346\216\247.md" new file mode 100644 index 0000000..24b52ce --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \344\270\273\345\212\250\347\233\221\346\216\247\345\222\214\350\242\253\345\212\250\347\233\221\346\216\247.md" @@ -0,0 +1,33 @@ +zabbix在监控的时候有两种模式,一种是主动模式,另外一种是被动模式 + +## 一、被动模式 + +所谓的被动模式,是以zabbix-agent做为参考对象,也就是表示是server或proxy去找agent拿数据,agent被动的等待指令的下达,让我干什么活,我就去干什么活,这也是zabbix server的默认模式,为什么这么说?我们可以随便找一台主机的查看它的监控项中在名称下面有一个类型,在这里面我们看到的是“zabbix客户端”这个值 + +![image20200215184213711.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603594519820.png) + +这个值在已经设置好的监控项当中是不能更改的,但是如果我们新建监控项的时候你就会发现,类型里面还有一个叫“zabbix客户端(主动式)”的选项。所以说zabbix默认的都是被动模式 + +配置方法如下: + +``` +agent端配置被动模式的参数如下 +[root@agent1 ~]# vim /etc/zabbix/zabbix_agentd.conf +Server=10.1.1.13 --IP为zabbix_proxy的ip(如果没有proxy,则直接为zabbix_server的ip) +[root@agent1 ~]# systemctl restart zabbix-agent +``` + +## 二、主动模式 + +也就是agent主动把数据传给server或proxy + +agent主动模式的优点是: 当agent太多的情况下,server或proxy去找这么多agent搜集数据,压力负载过大。用主动模式就可以缓解server或proxy的压力。 + +但用主动模式的问题是: 监控项当中的类型,也要转为主动式才行,而且很多zabbix自带模板里的监控项不支持转为主动式. + +``` +agent端配置主动模式的参数如下 +[root@agent1 ~]# vim /etc/zabbix/zabbix_agentd.conf +Serveractive=10.1.1.13 --IP为zabbix_proxy的ip(如果没有proxy,则直接为zabbix_server的ip) +[root@agent1 ~]# systemctl restart zabbix-agent +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \346\250\241\346\235\277\347\256\241\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \346\250\241\346\235\277\347\256\241\347\220\206.md" new file mode 100644 index 0000000..2fafe24 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \346\250\241\346\235\277\347\256\241\347\220\206.md" @@ -0,0 +1,132 @@ +**模板(template)**: 对于我们来说是非常重要的,因为它保存了监控项,应用集(给监控项分的组),触发器,图形,聚合图形,自动发现规则,web监测等的一组实体。最主要的是给懒人们提供了方便 + +我们使用模板可以方便应用到主机,更改模板也会将更改应用到所有链接的主机。避免了每一台主机都需要手动去添加,手动去更改的麻烦 + +参考: https://www.zabbix.com/documentation/3.4/zh/manual/config/templates + +在工作中,我们也可以根据自己公司的实际情况去创建模板,然后将目标应用到公司的服务器上去 + +## 一、创建一个模板 + +配置—模板 + +![模板1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603593961462.png) + +点击创建模板进入模板菜单 + +![模板2.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603593971773.png) + +模板创建成功后,需要设置模板中的相关属性 + +![模板3.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603593979759.png) + +由于我们之前修改过系统自带的模板,我们现在把他还原,也就是把之前我们添加的那个查看用户数量的相关信息都删除,然后再将监控用户数量这个设置添加到自己的模板中 + +首先找到之前添加的位置 + +![image20200215142907258.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603594059969.png) + +选择“监控项”把之前我们手动添加的内容并删除 + +![image20200215143108427.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603594004364.png) + +注意:如果是先删除“监控项”中的记录,那么“触发器”和“图形”中的也会跟着删除,如果是先删除“触发器”和“图形”中的记录,一定要记得回到“监控项”中将记录删除,删除完成之后,找到我们自己的模板选择监控项 + +![image20200215153151362.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603594087710.png) + +然后我们创建一个监控项 + +![image20200215153833443.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603594114851.png) + +监控项添加好了我们接着添加图形 + +点击图形–创建图形 + +![image20200215154057905.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603594145519.png) + +接下来是触发器–创建触发器 + +![image20200215154323984.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603594169936.png) + +设置完成之后点击“插入”和“添加” + +现在这个模板我就定义完成了,那这个模板怎么使用呢? + +直接点击配置–主机,选择node2 + +![image20200215155458753.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603594203095.png) + +然后选择模板,取消并清理,选择我们自己创建的模板,点击更新 + +![image20200215155614926.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603594219316.png) + +然后你就可以看到了 + +![image20200215155638220.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603594230717.png) + +切换到监测–图形就可以查看到图形内容了 + +``` +注意:设置完成之后建议重新启动zabbix-proxy和zabbix-agent服务,如果是新的主机,新的主机上要存在相关的脚本和配置文件,相关操作还记得吧 +mkdir /etc/zabbix/libexec + +cat/etc/zabbix/libexec/check_user_number.sh +#!/bin/bash +#Description: 登陆用户监控脚本 +count=`who |wc -l` +echo $count + +chmod 755 /etc/zabbix/libexec/check_user_number.sh + +/etc/zabbix/libexec/check_user_number.sh + +vim /etc/zabbix/zabbix_agentd.d/check_user.conf + +UserParameter=check.user,/etc/zabbix/libexec/check_user_number.sh + +systemctl restart zabbix-agent zabbix-proxy +``` + +## 二、导出一个模板 + +导入导出模式是一个非常好的功能,在一台监控主机上的设置如果想用再其它监控主机而不想从头建立模板的时候,就需要用到这个功能 + +**导入导出**可以帮你轻松实现,导出的是**xml**格式文件. + +配置--主机--选取要导出的主机(前面打勾)--下面选择导出 + +![image20200215175546553.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603594286591.png) + +各位要注意,导出的只是模板,如果想拿到其它主机上使用的话,模板里面所涉及到的key,插件也需要一起保存,所谓的插件就是存放在/etc/zabbix/libexec目录下的内容,而key就是存放在/etc/zabbix/zabbix_agent.d/*.conf文件 + +## 三、导入一个模板 + +你可以在网上下载好zabbix的监控模板,下载的时候记得把相关的key文件和插件文件一同下载,下载完成之后将对应的key文件和插件拷贝到对应目录 + +在被监控主机上添加key和插件 + +``` +[root@node2 ~]# cd znginx-master/ +[root@node2 znginx-master]# ls +Readme.txt userparameter_znginx.conf.sample zbx_export_templates.xml znginx +[root@node2 znginx-master]# cp znginx /etc/zabbix/libexec/ +[root@node2 znginx-master]# cp userparameter_znginx.conf.sample /etc/zabbix/zabbix_agentd.d/ +[root@node2 znginx-master]# cd /etc/zabbix/zabbix_agentd.d/ +[root@node2 zabbix_agentd.d]# mv userparameter_znginx.conf.sample userparameter_znginx.conf +``` + +配置—模板—导入 + +![image20200215182702772.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603594316548.png) + +点击导入文件部分的按钮,选择对应的xml文件,点击导入 + +![image20200215182818104.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603594328789.png) + +返回模板中看下是否有新导入的模板 + +![image20200215182935259.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603594344461.png) + +然后你就可以正常使用了 + +注意:在导入过程中记得选择xml文件,而下载模板文件的时候注意版本跨度不要太大,否则模板会无法正常使用。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \347\224\250\346\210\267\347\256\241\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \347\224\250\346\210\267\347\256\241\347\220\206.md" new file mode 100644 index 0000000..24de188 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \347\224\250\346\210\267\347\256\241\347\220\206.md" @@ -0,0 +1,55 @@ +看过了对本机的监控之后,我们来看一下zabbix的用户,Zabbix有多个默认的用户群组,其中最常用的是Zabbix administrators超级管理员组,其它的几乎没什么用。 + +安装完zabbix后,已经自带了两个用户 + +- Admin +- Guests + +**超级管理员默认账号:** Admin,密码:zabbix,这是一个超级管理员。 + +**Guests用户:** 使用guest账号,密码为空,只能看到zabbix后台,没有具体内容。我们可以启用来宾账户,使用来宾账户登录到zabbix页面看一下。 + +**用户群组:** 群组的增删改查,和权限管理 + +**用户管理:** 用户增删改查、用户报警媒介管理、用户权限查看。 + +要添加一个用户,有三类属性要填写。 + +| 属性 | 描述 | +| ------------ | ---------------------------------------- | +| **用户信息** | 账号密码、所属组等基本信息 | +| **示警媒介** | 报警相关信息,例如邮箱地址、接受报警时段 | +| **许可权** | 权限,当前用户对哪些主机有权限 | + +zabbix 用户和权限类似windows,用户的有什么权限是组说了算 + +**案例:** 创建一个群组和用户 + +**群组创建** +选择 管理–>用户群组–>创建用户群组 + +![image20200206152939063.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603529646527.png) + +![image20200206153014812.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603529662642.png) + +![image20200206153034828.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603529674722.png) + +![image20200206153102222.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603529685233.png) + +**用户创建** + +管理–>用户–>创建用户 + +![image20200206153449530.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603529748943.png) + +![image20200206153539824.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603529760946.png) + +![image20200206153750908.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603529772009.png) + +最后再点击添加 + +验证用户是否为只读权限 + +![image20200206154053192.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603529783971.png) + +由于新建的用户只有只读的权限,所以根本没有“配置”、“管理”字样的选项 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \347\233\221\346\216\247\346\212\245\350\255\246-onealter\346\217\222\344\273\266\345\256\211\350\243\205.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \347\233\221\346\216\247\346\212\245\350\255\246-onealter\346\217\222\344\273\266\345\256\211\350\243\205.md" new file mode 100644 index 0000000..848bb96 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \347\233\221\346\216\247\346\212\245\350\255\246-onealter\346\217\222\344\273\266\345\256\211\350\243\205.md" @@ -0,0 +1,89 @@ +监控报警机制是我们四要素中的一个重要要素,当机器或者监控资源达到阈值,就应该受到管理员关注。但是那么多的机器靠管理员去用眼睛看肯定是不行的,那么怎么能做到管理员只看有问题的机器呢,大家可能都能想到筛选机制吧!对的,我们把有问题的筛选出来就可以了,怎么筛选呢?那就让监控平台根据触发器筛选出来,并通过邮件、微信、钉钉等方式推送给管理员就可以了,做到有的放矢。 + +关于监控报警有很多种方式,常见的有两种 + +1)通过本机邮件客户端生成邮件, + + - 通过传输代理发给邮件服务器, + + - 通过邮件投递代理发给管理员。 + +2)三方报警插件:如 onealter + +由于自己配置报警比较复杂,而且邮件容易被拒或当做垃圾邮件。有些专业的报警平台就可以帮你简单实现。 + +如:onealeart +参考:https://www.aiops.com/ + +## onealter报警设置 + +### 1、 onealter设置 + +访问官网 + +可以访问http://www.onealert.com/;也可以访问https://www.aiops.com/,注册账户 + +如果访问的是http://www.onealert.com/,点击免费试用之后注册 + +![image20200213164140494.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603531757916.png) + +如果访问的是https://www.aiops.com/,直接注册 + +![image20200213193407234.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603531778720.png) + +注册一个账号并登陆 + +![image20200213164226522.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603531793906.png) + +登陆后选择CA + +![image20200213164348628.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603531813053.png) + +点击集成–选择zabbix + +![image20200213164622598.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603531830834.png) + +可以看到onealter很强大,支持多种监控类型,课程中用的是zabbix,所有我们选项zabbix,然后点击配置。 + +![image20200213164941337.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603531851905.png) + +应用名称:为这个应用起一个名字 + +自动关闭时间:如果没有手动关闭告警,多久内自动关闭 + +点击保存应获取应用Key,为该应用生成一个key + +![image20200213165138456.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603531864612.png) + +key生成成功了,接下来就要在监控平台按照上述的命令执行安装告警插件了。 + +``` +#zabbix 监控平台 插件目录 +[root@zabbix ~]# mkdir -p /usr/local/zabbix-server/share/zabbix/alertscripts + +[root@zabbix ~]# cd /usr/local/zabbix-server/share/zabbix/alertscripts + + +#下载监控插件 +[root@zabbix alertscripts]# wget https://download.aiops.com/ca_agent/zabbix/ca_zabbix_release-2.1.0.tar.gz + +#安装监控插件 +[root@zabbix alertscripts]# tar -xzf ca_zabbix_release-2.1.0.tar.gz + +[root@zabbix alertscripts]# cd cloudalert/bin + +[root@zabbix bin]# bash install.sh 188728c3-c12b-fd2f-f3fd-bf8eb761e919 + +./log.sh:行6: /etc/zabbix/libexec/cloudalert/bin/cloudalert.conf: 没有那个文件或目录 +start to create config file... + +##输入交互信息 +Zabbix管理地址: http://192.168.98.200/zabbix +Zabbix管理员账号: Admin +Zabbix管理员密码: +. +. +. +create action success! +安装成功. +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \347\233\221\346\216\247\346\212\245\350\255\246.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \347\233\221\346\216\247\346\212\245\350\255\246.md" new file mode 100644 index 0000000..d1841c1 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix \347\233\221\346\216\247\346\212\245\350\255\246.md" @@ -0,0 +1,116 @@ +## 一、onealter 报警插件设置 + +告警插件安装成功了,接下来我们要设置告警通知了 + +告警通知有多种,比如:邮件、微信、钉钉、APP、电话、短信等 + +这里主要给大家介绍:邮件、微信、APP + +![image20200213184629351.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603532085724.png) + +点击配置—通知策略进入通知页面 + +在这里可以设置邮件报警,同时右侧也给出了APP下载地址,下载后直接安装登陆即可。 + +这里我们先把告警状态、告警级别、通知方式、通知人都设置一下。 + +![image20200213194108292.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603532099750.png) + +好了,我点点添加,全部都设置成功了 + +### 添加多个人 + +**step 1** 为团队添加成员 + +![image20200213201420457.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603532119396.png) + +![image20200213200952058.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603532136205.png) + +![image20200213194416754.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603532167206.png) + +**step 2** 登录被邀请的用户邮箱选择接受邀请 + +![image20200213195116050.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603532405930.png) + +可以选择新用户,也可以选择已有账户,完成注册/登录的操作后使用被邀请的用户进入到配置中的团队管理界面,看下能否看到两个用户 + +![image20200213201542249.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603532435392.png) + +如果不可以看到的话就切换到添加成员的界面,刷新一下就可以看到成员已经添加进来了,并且在团队管理中也可以看到响应的用户 + +![image20200213200626704.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603532461447.png) + +![image20200213201741467.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603532475611.png) + +**step 3** 在配置,通知策略中可以新建通知了 + +![image20200213202254560.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603532516890.png) + +**step 4** 选择保存之后,就可以看到两个用户都有显示了 + +![image20200213202350511.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603532561877.png) + +以上就是单人通知和多人通知的设置方式。 + +接下来我们在设置一下微信报警 + +点击右上角的人头像—个人中心 + +![image20200213202703413.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603532579455.png) + +点击绑定微信,使用微信扫描即可绑定。 + +好了到此我们的告警插件就设置好了,接下来要设置zabbix-server平台。 + +## 二、zabbix监控平台调用报警插件 + +**案例: 监控平台调用onealter插件,实现报警** + +点击管理—报警媒介类型 + +可以看到我们安装好的onealter,我们点击后边的测试,看看是否能正常工作 + +![onealter8.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603532954403.png) + +``` +如果测试失败,一般是找不到文件,做个链接 +[root@manage01 bin]# ln -s /usr/local/zabbix-server/share/zabbix/alertscripts/cloudalert /usr/lib/zabbix/alertscripts/ +``` + +再次测试 + +![image20200215220103776.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603533012961.png) + +输入收件人地址后,点击测试 + +![image20200215220148496.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603533038982.png) + +如上图,测试成功了。 + +回到zabbix告警平台点击右上角 人头像—报警媒介—添加收件人 + +![image20200214161626166.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603533071992.png) + +设置告警收件人,可以设置多个人。 + +![image20200214155900052.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603533104780.png) + +ok,我们zabbix监控平台设置好了。 + +### 测试报警 + +之前设置过一个自定义监控,我们监控了登陆用户数量,我们通过同时登陆node1超过三个用户,验证报警。 + +![onealter12.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603533145726.png) + +可以看到,node1的当前用户量已经超过了预警值 + +看看邮箱吧,是否收到报警 + +![image20200214155944190.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603533167741.png) + +当你把多余的用户退出以后还会收到邮件 + +![image20200214161309486.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603533227451.png) + +ok,完美了,如果你下载了APP和微信,看看他们是否也收到了,答案是肯定的。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix\345\210\206\345\270\203\345\274\217\347\233\221\346\216\247\347\263\273\347\273\237.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix\345\210\206\345\270\203\345\274\217\347\233\221\346\216\247\347\263\273\347\273\237.md" new file mode 100644 index 0000000..9929d29 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix\345\210\206\345\270\203\345\274\217\347\233\221\346\216\247\347\263\273\347\273\237.md" @@ -0,0 +1,251 @@ +生产环境中,我们为了实现地域容灾,我们会把服务器放在不同的地域,如果一台zabbix server去监控的话,延迟会高,因为中国的网络由很多运营商在经营,包括联通,移动,电信,教育等等,有玩游戏的同学应该清楚,家里是联通的网络,你去会去电信的服务器么?不会,因为延迟太高。为什么延迟高?因为运营商之间的出口带宽是有限制的,为什么有限制?因为费用不一样,你在便宜的运营商这里办宽带,在贵的运营商这里玩,这种事,换做是谁都不会高兴的。有的同学说我用游戏加速器怎么延迟就低了?使用游戏加速器相当于在大家都从一扇门进出的时候,你发现了一扇窗,而这扇窗就你自己在用,但是当其他人也发现了这扇窗之后呢?所以即便是使用了游戏加速器,在上网高峰时,延迟还是高,只不过没有那么拥挤而已。说完了为什么延迟会高,我们再看一下另外一个问题,这种把服务器放在不同的地域也会造成zabbix server压力也会很大,所以为了避免这种情况,我们的处理方法就是将权利下发,在不同的地域都找一个机器来充当代理,本地的监控工作由代理(proxy)来完成,代理完成收集工作后交给zabbix server,zabbix server在将收到的数据统一整理展示到web。 + +其实这个例子很简单就是你开了很多分公司,你一个人去管理这些分公司的员工的话,你是管不全面的,所以我们的方法是在每个分公司弄一个负责人,负责人管当地的员工,你管负责人。有问题他们集中向你汇报就好了。这样你就能很顺利的掌控全局了。 + +**架构图** + +![image20200219101305467.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603593373704.png) + +所以在这个分布式监控的架构中的流程是 + +1、zabbix server发布指令给代理 + +2、zabbix-proxy将指令发给被监控主机 + +3、被监控机将数据汇报给zabbix-proxy + +4、zabbix-proxy再交给zabbix-server + +5、zabbix-server将数据展示 + +这样解决了延迟问题,只要保证一条线路畅通就可以了,至于保证一条线路畅通的手段就看你的公司了,有钱可以接专线,没钱可以使用VPN,实在不行可以直接走广域网 + +### 实验拓扑图 + +![zabbix_proxy.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603593518849.png) + +在这个架构中我们至少需要三台机器,他们的角色为 + +- **zabbix-server:** 192.168.98.200 +- **zabbix-proxy:** 192.168.98.205 +- **被监控主机:** 192.168.98.xxx + +### 实验步骤 + +部署server监控平台 (略) + +部署proxy代理平台 + +被监控机安装zabbix-agent(略) + +## 一、部署zabbix-proxy代理平台 + +### 1.1、安装zabbix-proxy平台 + +``` +#设置yum源 +[root@proxy ~]# cat >> /etc/yum.repos.d/zabbix.repo < create database zabbix_proxy character set utf8 collate utf8_bin; +Query OK, 1 row affected (0.00 sec) + +MariaDB [(none)]> grant all privileges on zabbix_proxy.* to zabbix@localhost identified by '123456'; +Query OK, 0 rows affected (0.00 sec) + +MariaDB [(none)]> flush privileges; +Query OK, 0 rows affected (0.00 sec) + +MariaDB [(none)]> exit +Bye + +#导入数据 +[root@proxy ~]# zcat /usr/share/doc/zabbix-proxy-mysql/schema.sql.gz |mysql -u zabbix -p123456 zabbix_proxy +``` + +### 1.2、修改proxy配置文件 + +``` +[root@proxy ~]# egrep "^(Server|Hostname|DBPass)" /etc/zabbix/zabbix_proxy.conf +Server=192.168.98.200 #将数据汇报给谁 +Hostname=zabbix_proxy #自己的名字 +DBPassword=123456 #数据库密码 +``` + +### 1.3、关于proxy的监控问题 + +由于proxy既是监控也是被监控机,所以本机的agent的服务器地址可以设置本机或者server地址,这里建议设置server地址。因为这样zabbix server能够直接监控到本机的状态 + +``` +[root@proxy ~]# egrep "^(Server|Hostname)" /etc/zabbix/zabbix_agentd.conf +Server=192.168.98.200 +ServerActive=192.168.98.200 +Hostname=proxy +``` + +### 1.4、启动服务 + +``` +[root@proxy ~]# systemctl enable zabbix-proxy zabbix-agent +Created symlink from /etc/systemd/system/multi-user.target.wants/zabbix-proxy.service to /usr/lib/systemd/system/zabbix-proxy.service. +Created symlink from /etc/systemd/system/multi-user.target.wants/zabbix-agent.service to /usr/lib/systemd/system/zabbix-agent.service. +[root@proxy ~]# systemctl start zabbix-proxy zabbix-agent +``` + +查看一下日志显示的内容,以及确认下端口是否打开 + +``` +[root@proxy ~]# tail -f /var/log/zabbix/zabbix_proxy.log +34539:20200215:133633.989 proxy #13 started [history syncer #2] + 34547:20200215:133633.990 proxy #21 started [poller #4] + 34548:20200215:133633.996 proxy #22 started [poller #5] + 34546:20200215:133633.998 proxy #20 started [poller #3] + 34551:20200215:133634.000 proxy #25 started [preprocessing manager #1] + 34550:20200215:133634.003 proxy #24 started [icmp pinger #1] + 34549:20200215:133634.003 proxy #23 started [unreachable poller #1] + 34552:20200215:133635.011 proxy #26 started [preprocessing worker #1] + 34554:20200215:133635.014 proxy #28 started [preprocessing worker #3] + 34553:20200215:133635.019 proxy #27 started [preprocessing worker #2] + 34534:20200215:133641.038 cannot send proxy data to server at "192.168.98.200": proxy "zabbix_proxy" not found + 34534:20200215:133642.041 cannot send proxy data to server at "192.168.98.200": proxy "zabbix_proxy" not found + 34534:20200215:133643.044 cannot send proxy data to server at "192.168.98.200": proxy "zabbix_proxy" not found + 34534:20200215:133644.046 cannot send proxy data to server at "192.168.98.200": proxy "zabbix_proxy" not found + 34534:20200215:133645.049 cannot send proxy data to server at "192.168.98.200": proxy "zabbix_proxy" not found + +[root@proxy ~]# netstat -ntlp +Active Internet connections (only servers) +Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name +tcp 0 0 0.0.0.0:10050 0.0.0.0:* LISTEN 33953/zabbix_agentd +tcp 0 0 0.0.0.0:10051 0.0.0.0:* LISTEN 33960/zabbix_proxy +tcp6 0 0 :::10050 :::* LISTEN 33953/zabbix_agentd +tcp6 0 0 :::10051 :::* LISTEN 33960/zabbix_proxy +tcp6 0 0 :::3306 :::* LISTEN 33219/mysqld +``` + +通过查看日志,我们发现日志当中好像有报错,这个我们一会再说,通过查看端口可以发现zabbix_proxy与zabbix_server使用的端口是一样的,所以这两个角色不能配置在一台主机上 + +### 1.5、监控平台设置 + +刚才我们在查看日志的时候发现日志中好像有错误提示,这个提示产生的原因就是服务端不认这个代理,代理给服务端发数据,服务端不要,所以我们要告诉服务端,它的代理是谁 + +管理—agent代理程序 + +![zabbixproxy1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603593691636.png) + +选择 创建代理 进入代理设置模式 + +![zabbixproxy2.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603593701268.png) + +设置代理名称:一定要和proxy配置文件中的Hostname一致 + +设置代理模式:主动 + +1)proxy主动模式 + +zabbix_proxy主动发数据给zabbix_server(proxy的默认模式) + +``` +# vim /etc/zabbix/zabbix_proxy.conf +ProxyMode=0 --此参数为0表示proxy主动模式 +``` + +2)proxy被动模式 + +zabbix_server找zabbix_proxy为收集数据 + +``` +# vim /etc/zabbix/zabbix_proxy.conf +ProxyMode=1 --此参数为1表示proxy主动模式 +``` + +警告 + +``` +为了避免服务端不识别代理或者其它主机的情况,建议在zabbix_server最好给代理名字及其它主机做个解析 +[root@zabbix ~]# vim /etc/hosts +192.168.98.205 proxy zabbix_proxy +``` + +## 二、设置被监控机 + +``` +[root@node4 ~]# egrep "^(Server|Hostname)" /etc/zabbix/zabbix_agentd.conf +Server=192.168.98.205 +ServerActive=192.168.98.205 +Hostname=node4 + +[root@node4 ~]# systemctl restart zabbix-agent +[root@node2 ~]# netstat -ntlp +Active Internet connections (only servers) +Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name +tcp 0 0 0.0.0.0:10050 0.0.0.0:* LISTEN 7836/zabbix_agentd +tcp6 0 0 :::10050 :::* LISTEN 7836/zabbix_agentd +``` + +## 三、验证 + +由于之前配置过自动注册,所以应该在主机列表中能看到就算成功了。 + +配置—主机 + +![image20200215140100181.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603593756229.png) + +看到了,node2后面有一个zabbix_proxy 说明该主机走的是代理模式。 + +如果查看监测–图形时很久不出图,建议分别重启zabbix_proxy和客户端的zabbix-proxy以及zabbix-agent服务 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix\347\233\221\346\216\247\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix\347\233\221\346\216\247\344\273\213\347\273\215.md" new file mode 100644 index 0000000..0749598 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix\347\233\221\346\216\247\344\273\213\347\273\215.md" @@ -0,0 +1,39 @@ +在前面的课程中我们已经知道zabbix是一个分布式的监控软件,是一个高度集成的网络监控解决方案,简单来说就是一个监控平台,并且可以提供企业级的开源(免费)分布式监控解决方案,由一个国外的团队持续维护更新,软件可以自由下载使用,运作团队靠提供收费的技术支持赢利。它支持分布式监控,使用简单方便,比nagios更加容易上手,又拥有cacti那样支持数据持久化保存。Zabbix 通过 C/S 模式采集数据,通过 B/S 模式在 web 端展示和配置。 + +官方下载地址:[https://www.zabbix.com](https://www.zabbix.com/) + +![image20200215233224237.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603528388290.png) + +LTS=Long Term Support 长期支持 zabbix将为客户提供5年的支持服务。前三年完全支持与后两年有限制支持。前三年包括一般、关键、安全性问题解决,后两年包括关键、安全性问题解决。超出时间不提供技术支持服务。然而标准版,只提供6+1月支持。zabbix LTS与zabbix标准发行版本的生命周期区别,普通版本6个月开发发行,支持6个月无限制支持,外加一个月有限制支持。然后LTS版本1.5年开发发行,3年无限制支持,2年有限制支持。 + +**监控原理** + +``` +zabbix-server平台根据监控项发指令给zabbix-agent +zabbix-agent执行key对应的脚本,并把值返回给zabbix-server +zabbix-server接收数据并绘图 +``` + +1、user—>web—>zabbix-server[监控平台] + +用户通过web界面对zabbix监控平台进行操作 + +2、zabbix-server[监控平台]—>监控插件[被监控机]执行 + +zabbix监控平台会执行任务,也就是调用对应的插件在被监控主机上执行(告诉被监控机去执行xx插件) + +3、监控插件[被监控机]执行–>zabbix-server + +被监控机执行完成后将结果反馈给zabbix-server + +4、zabbix-server—>zabbix-web—>user + +zabbix-server通过web界面展现,最终用户查看到相应信息 + +**监控主机和被监控主机是如何通信的?** + +- zabbix-server—zabbix-agent + + 在被监控主机上安装一个zabbix-agent软件包,所有的动作都由agent去执行,并将结果反馈给server + +- snmp协议 简单网络管理协议 缺点是无法自定义监控 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix\347\233\221\346\216\247\345\233\276\345\203\217\345\261\225\347\244\272.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix\347\233\221\346\216\247\345\233\276\345\203\217\345\261\225\347\244\272.md" new file mode 100644 index 0000000..5b71156 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/Zabbix\347\233\221\346\216\247\345\233\276\345\203\217\345\261\225\347\244\272.md" @@ -0,0 +1,47 @@ +## 一、聚合图形设置方法 + +通过聚合图形可以将你感兴趣的几个图形放在一个页面,方便查看 + +### 将多个图形聚合到一个页面 + +![聚合图形1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603531158678.png) + +点击 创建聚合图形 + +![聚合图形2.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603531172310.png) + +这里设置的是聚合图形页面的名字 页面的格式 几行几列 + +![聚合图形3.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603531181792.png) + +编辑聚合图形页面,放置需要放置的图形 + +![自定义监控监控项4.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603531190801.png) + +聚合图形创建成功了 + +## 二、幻灯片轮询播放聚合图形 + +我们还可以通过幻灯片的方式,让过个聚合图形轮动展示 + +幻灯片创建方法 + +监测—聚合图形 + +![ppt1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603531218266.png) + +右上角选择 幻灯片演示,点击创建幻灯片播放 + +![ppt2.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603531230383.png) + +- 给幻灯片起个名称 +- 定义幻灯片内的聚合页面切换时间 +- 添加聚合页面 + +配置完成后选择添加 + +测试一下,看看是否能播放吧 + +监测—聚合图形—【右上角】幻灯片演示—PPT1 + +![ppt3.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603531247944.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\346\234\215\345\212\241\345\231\250\347\233\221\346\216\247\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\346\234\215\345\212\241\345\231\250\347\233\221\346\216\247\344\273\213\347\273\215.md" new file mode 100644 index 0000000..b5913cb --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\346\234\215\345\212\241\345\231\250\347\233\221\346\216\247\344\273\213\347\273\215.md" @@ -0,0 +1,71 @@ +## 一、监控思考 + +**监控只能让维护人员查看到主机的状态么?** + +答: 实时收集数据,通过报警及时发现问题,及时处理,所获取的数据也可以为系统优化提供依据。 + +**监控四要素** + +如果我想让你监控一个人 你最想知道的是什么? + +1、监控谁 监控什么 + +2、什么时候监控 你现在就去 全天跟着 还是看十分钟就回来? 也就是说是一次性的还是循环的? + +3、有问题如何汇报? 管理员还是其他用户 + +4、监控方法 明着跟着 还是暗地跟着 + +监控一个设备也是这样的 + +- 监控对象 [主机状态 服务 资源 页面,url] +- 用什么监控 [zabbix-server zabbix-agent] +- 什么时间监控 [7x24 5x8] +- 报警给谁 [管理员] + +## 二、主流的开源监控平台分析 + +- **mrtg** (Multi Router Traffic Grapher)通过**snmp**协议得到设备的流量信息,并以包含PNG格式的图形的HTML页面方式显示给用户。 +- **cacti** (仙人掌) 用php语言实现的一个软件,它的主要功能是用snmp服务获取数据,然后用rrdtool储存和更新数据。现在主要在IDC机房使用,主要用在监控网卡以及交换机路由器的端口,由于出图慢,默认5分钟更新一次(最快可以调成一分钟),而现在很多领域都要求实时的,这个时间就显得有些长,又很难自定义监控,所以很少用它监控除了交换机路由器以外的设备 + +![image20200215230745016.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603527916848.png) + +**官网地址:** https://www.cacti.net/ + + + +- **ntop** 官网地址: https://www.ntop.org/ +- **nagios** 能够跨平台,插件多(监控的东西多),可以自定义–灵活,报警功能强大。或者说nagios就是一个平台,这个平台依靠插件来工作,想要什么样的插件可以用任意语言 自己写,但是由于机器数量越来越多,并且还要求地域性容灾,所以服务器都存放在不同的机房里面,这个时候nagios的不能分布式监控的缺陷就显现出来了。如果想监控这些服务器,就需要在每一个机房都部署一台nagios,然后分别去登录这些服务器查看。 + +![image20200215230831917.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603527942944.png) + +**官网地址:** https://www.nagios.org/ + +- **centreon** 底层使用的就是nagios。是一个nagios整合版软件。界面比nagios要好看很多。 + +![image20200215231227341.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603527997788.png) + +**官网地址:** https://www.centreon.com/ + +- **ganglia** 设计用于测量数以千计的节点,资源消耗非常小。 + **官网地址:** http://ganglia.info/ +- **open-falcon** 小米发布的运维监控软件,高效率,高可用。时间较短,用户基数小。 + **官网地址:** http://open-falcon.org/ +- **zabbix** 跨平台,支持分布式,可以集中管理,可以画图,能够持久化保存数据,多条件告警,多种API接口,扩展性非常强。使用基数特别大,阿里云使用的就是zabbix。 + **官网地址:** https://www.zabbix.com/ +- **prometheus** 是一个基于时间序列的数值数据的容器监控解决方案。 + **官网地址:** https://prometheus.io/ + +**综合分析:zabbix比较适合公司的监控需求,主要特点如下:** + +1、丰富的模板 + +2、可以自定义监控项 + +3、完善的告警机制** + +4、适合分布式监控 + +5、集中管理系统 + +6、开源、免费系统 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\347\233\221\346\216\247\346\241\210\344\276\213 \347\233\221\346\216\247\344\270\200\345\217\260\344\270\232\345\212\241\346\234\215\345\212\241\345\231\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\347\233\221\346\216\247\346\241\210\344\276\213 \347\233\221\346\216\247\344\270\200\345\217\260\344\270\232\345\212\241\346\234\215\345\212\241\345\231\250.md" new file mode 100644 index 0000000..f5bc95f --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\347\233\221\346\216\247\346\241\210\344\276\213 \347\233\221\346\216\247\344\270\200\345\217\260\344\270\232\345\212\241\346\234\215\345\212\241\345\231\250.md" @@ -0,0 +1,93 @@ +**案例: 通过监控平台监控一台远端的业务机器** + +![监控远端机器.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530035321.png) + +监控方法:zabbix-agent + +监控步骤: + +1、在被监控机安装zabbix-agent客户端服务 + +2、修改配置文件指定监控平台 + +3、启动服务 + +4、zabbix server监控平台添加 + +### a、部署zabbix-agent监控服务 + +``` +#设置源 +[root@node1 ~]# cat /etc/yum.repos.d/zabbix.repo +[zabbix] +name=Zabbix Official Repository - $basearch +#baseurl=http://repo.zabbix.com/zabbix/4.4/rhel/8/$basearch/ +baseurl=https://mirrors.aliyun.com/zabbix/zabbix/4.4/rhel/8/$basearch/ +enabled=1 +gpgcheck=0 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-ZABBIX-A14FE591 + +[zabbix-non-supported] +name=Zabbix Official Repository non-supported - $basearch +baseurl=http://repo.zabbix.com/non-supported/rhel/8/$basearch/ +enabled=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-ZABBIX +gpgcheck=0 + +#安装zabbix-agent服务 +[root@node1 ~]# dnf -y install zabbix-agent +``` + +### b、修改配置文件 + +``` +[root@node1 ~]# vim /etc/zabbix/zabbix_agentd.conf +Server=192.168.98.200 #指定监控平台IP地址 +``` + +### c、启动服务 + +``` +#启动服务 +[root@node1 ~]# systemctl enable zabbix-agent + +Created symlink from /etc/systemd/system/multi-user.target.wants/zabbix-agent.service to /usr/lib/systemd/system/zabbix-agent.service. + +[root@node1 ~]# systemctl start zabbix-agent +``` + +### d、在监控平台添加被监控机器 + +配置——主机——创建主机 + +![zabbix_agent1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530153425.png) + +进入创建主机菜单 + +![zabbix_agent2.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530169082.png) + +主机名称:可以随便写,但是要有意义,建议按照城市名称+机房名称+主机IP这样比较好识别 + +群组:可以理解为业务组 + +IP地址:填入被监控机的IP地址 + +模板:链接一个监控模板,里面已经设置好了监控项和图形、报警等 + +![zabbix_agent3.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530184146.png) + +选择一个适合的模板,这里我们监控的node1是个linux机器,所以我选择的是Template OS Linux模板,注意一定别忘了点击模板下的添加小按钮,将其链接过来 + +最后点击下方添加,主机就添加成功了 + +![zabbix_agent4.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530197581.png) + +稍等一会,等被监控机的可用性ZBX[因为我们是基于zabbix-agent监控的]变成绿色,我们的任务就完成了 + +![zabbix_agent5.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530210348.png) + +看到标记处变成绿色也就放心了。 + +我们可以通过监控——图形来看看是不是有图形了 + +![zabbix_agent6.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530223831.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\347\233\221\346\216\247\350\207\252\345\212\250\345\214\226-\350\207\252\345\212\250\346\267\273\345\212\240\344\270\232\345\212\241\346\234\272\345\231\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\347\233\221\346\216\247\350\207\252\345\212\250\345\214\226-\350\207\252\345\212\250\346\267\273\345\212\240\344\270\232\345\212\241\346\234\272\345\231\250.md" new file mode 100644 index 0000000..5247e90 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\347\233\221\346\216\247\350\207\252\345\212\250\345\214\226-\350\207\252\345\212\250\346\267\273\345\212\240\344\270\232\345\212\241\346\234\272\345\231\250.md" @@ -0,0 +1,156 @@ +现在有这样一个需求,公司采购了100台主机,并且需要监控这100台主机,这个工作量有点大。如果真是一台一台的去弄的话,最近这一两天就什么都别做了,而且效率还低。我们可以把这100台连好网络,在部署系统的过程中让这些主机自动配置并启动好zabbix-agent服务。然后让zabbix server自动添加这100台主机,这样的话不仅提升效率,还能节省下大量时间,这个自动添加有两种方式: + +- 自动发现 +- 自动注册 + +## 一、自动发现 + +自动发现是由**服务端主动发起**,Zabbix Server开启发现进程,定时扫描(非常消耗资源)本网络中符合条件的主机。发现了相应的主机后,通过“动作”来添加监控主机、链接模板。这样我们就可以看到了 + +**教学案例:通过自动发现自动添加业务机器** + +1. 设置被监控机配置文件 +2. 配置自动发现发现主机 +3. 配置动作添加主机 + +### 1.1、设置被监控机配置文件 + +``` +[root@node2 ~]# rpm -Uvh https://repo.zabbix.com/zabbix/4.4/rhel/8/x86_64/zabbix-release-4.4-1.el8.noarch.rpm + +[root@node2 ~]# dnf -y install zabbix-agent + +[root@node2 ~]# egrep "^(Server|Hostname)" /etc/zabbix/zabbix_agentd.conf +Server=192.168.98.200 #被动模式zabbix服务器的IP +ServerActive=192.168.98.200 #主动模式zabbix服务器的IP +Hostname=node2 + +[root@node2 ~]# systemctl start zabbix-agent.service +[root@node2 ~]# systemctl enable zabbix-agent.service +``` + +### 1.2、配置自动发现-发现机器 + +配置—自动发现—创建发现规则 + +![自动发现1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603592102422.png) + +该页面是自动发现管理页面,可以看到系统提供了一个demo,我们不用他提供的,因为网段不对,所以我打算在创建一个 + +![image20200214210142325.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603592139930.png) + +关于IP范围,我不建议大家写整个网段。因为zabbix-server针对会对全网段做扫描的,那样对zabbix-server压力是很大的。所以大家尽可能写的范围小一点。 + +- 更新间隔:代表扫描的频率,这里千万不要设置过小,频繁扫描会造成服务器压力巨大。 +- 键值:定义的是zabbix需要获取到的被监控主机的什么信息,可以按照如下步骤操作,找到zabbix的键值。 + +![image20200214184321212.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603592171871.png) + +点击完监控项之后,选择右上角的创建监控项,在新的页面中“键值”的位置点击选择,就能看到系统中的键值及作用了。 + +主机名称和可见的名称这两部分建议选择IP地址,相信大家装系统的时候很少有特意设置主机名的吧?如果选择DNS或者是主机名的话,一会测试结果的时候看到的都是localhost,你根本不知道谁是谁 + +如上图设置完成后,我们可以验证一下。看看是否真的发现了我们的主机:监测—自动发现 + +![image20200214184647398.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603592213820.png) + +发现主机了,第一步完成了。 + +主机是发现了,但是并没有添加到监控队列中,原因是我们还没有设置要求监控平台将符合的机器加入监控队列。如果需要设置,就要通过配置—动作 来完成。 + +### 1.3、配置自动发现动作,实现机器自动添加到监控队列 + +为了让发现的机器自动添加到监控队列,需要在zabbix-server监控平台设置动作来完成添加。 + +具体方法如下: + +配置—动作在动作管理页面,该页面中为自动发现提供了一个动作模板,点击这个模板,选择克隆 + +![image20200214202229503.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603592230661.png) + +然后取个名字,选择已启用,在这个模板中的A,B,C三个条件是与的关系,也就是说满足这三个条件 客户端系统是linux,状态是UP的状态,并可装的是zabbix客户端,你也可以再添加,这三条已经够了 + +![image20200214202648838.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603592248883.png) + +如果这三个条件都匹配的话,就执行操作,执行什么操作呢?我们点击动作胖点的“操作”按钮,点击“新的”加入两步操作“添加主机”和“启用主机”,加上原来的一共是四步 + +![image20200214203844140.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603592272397.png) + +所以说自动发现呢分为这么几个步骤,先自动发现主机,然后根据动作去匹配,如果匹配我给出的条件就会执行操作中所定义的工作,从添加主机一直到启用主机 + +以上是使用原有的模板克隆,现在我们自己新建一个 + +选择右上角 事件源: 自动发现 然后点击创建动作, 进入自动发现 动作创建页面 + +![自动发现动作4.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603592321102.png) + +![image20200214204339859.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603592343712.png) + +这里要做条件匹配,只有匹配添加的机器才会被执行对应的操作 + +我这里条件是根据IP地址来匹配的,也就是被监控机的IP地址必须是192.168.98.199-220之间,除此之外还可以和demo动作中的一样,也可以做匹配。 + +选择操作来定义如何将符合条件的机器加入到监控队列 + +![image20200214204622681.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603592429218.png) + +注意操作选项,我添加了四个动作: + +- 添加主机 +- 添加到主机群组 +- 链接到模板 +- 启用主机 + +顺序不能错的,大家想想是不是我们手动添加也是这个顺序啊? + +完成后选择添加,自动发现动作就完成了, + +**注意** +关于自动发现主机添加问题 +可能时间会比较长,实验中需要等一会,过一会儿你就会点击检测–图形就可以查看到自动添加的主机了。同时你也会发现多了一个叫“Discovered hosts”的主机群组,如果不喜欢可以选择管理–一般–其他,然后去调整设置 + +![image20200214211213424.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603592494368.png) + +## 二、自动注册 + +自动发现是主动去扫描对应的网段的IP段,带来的问题是比较浪费监控平台资源且不能实时添加,而且遇到**不在同一网段**的主机显得比较无力,为了解决这个问题,我们换一种方式:自动注册 + +自动注册是被监控机主动找监控平台,监控平台发现其满足自动注册的条件后就直接根据操作添加到监控队列了。 + +自动注册不需要配置自动发现,监控平台被动等待被监控机向其发起连接;只需要配置动作即可 + +自动注册步骤 + +1. 客户端配置文件设置 +2. 设置动作 + +### 2.1、客户端配置文件 + +``` +[root@node2 ~]# egrep "^(Server|Hostname)" /etc/zabbix/zabbix_agentd.conf +Server=192.168.98.200 +ServerActive=192.168.98.200 +Hostname=node2 +``` + +### 2.2、设置动作 + +配置—动作 + +![自动注册1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603592652691.png) + +事件源: 自动注册 + +点击创建动作,进入动作菜单 + +![自动注册2.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603592667240.png) + +这里的条件是根据计算机名来匹配的 + +![自动注册3.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603592685621.png) + +操作中没有启用主机,默认自动注册就会启用主机,所以操作中没有该选项。 + +![自动发现7.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603592702828.png) + +配置完成后,点击配置—主机。可以看到主机已经添加成功了。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\347\273\231\347\233\221\346\216\247\351\241\271\350\256\276\345\256\232\351\230\210\345\200\274.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\347\273\231\347\233\221\346\216\247\351\241\271\350\256\276\345\256\232\351\230\210\345\200\274.md" new file mode 100644 index 0000000..64e5b09 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\347\273\231\347\233\221\346\216\247\351\241\271\350\256\276\345\256\232\351\230\210\345\200\274.md" @@ -0,0 +1,27 @@ +## 给监控项设置触发器 + +定义好了图形,我们的监控就完成了,但是怎么判断当前的监控值是否健康呢?那么我们就应该设置一个阈值了,也就是我们常说的警戒线,达到这个警戒线就应该报警通知管理员了。 + +接下来我来带大家看看如何定义一个阈值来判定监控项的健康情况,我们来学习触发器 + +选择 配置—模板— Template OS Linux 选择触发器 + +![触发器1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530732457.png) + +点击 触发器后进入触发器管理界面,此页面可以管理所有触发器,我们需要创建一个触发器 + +![触发器2.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530742404.png) + +点击 添加触发器,进入触发器设置菜单 + +![触发器3.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530751064.png) + +OK!触发器设置成功了,我们验证看一下吧 + +我们通过多个终端同时登陆node1,登陆数量超过3个,我们来看看在监测—仪表盘是否会报警呢 + +![触发器4.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530760018.png) + +报警啦,说明我们的触发器设置正确,同时我们看看node1的用户监控[Current_login_user]的那个图形吧 + +![触发器5.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530771991.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\350\207\252\345\256\232\344\271\211\344\270\200\344\270\252\347\233\221\346\216\247\351\241\271.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\350\207\252\345\256\232\344\271\211\344\270\200\344\270\252\347\233\221\346\216\247\351\241\271.md" new file mode 100644 index 0000000..6cde014 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\350\207\252\345\256\232\344\271\211\344\270\200\344\270\252\347\233\221\346\216\247\351\241\271.md" @@ -0,0 +1,104 @@ +在zabbix当中默认给我们提供了很多监控项,但是,有些监控项我们用不到,而有些监控项又没有,那这个时候怎么办呢? + +1. 定义一个监控脚本 +2. 定义一个键值对 +3. 创建一个监控项 +4. 设置一个图形 + +教学案例: + +自定义一个当前登陆用户数量监控脚本 + +### a、自定一个用户数量收集脚本 + +``` +#创建一个插件目录,用于以后存放插件 +[root@zutuanxue ~]# mkdir /etc/zabbix/libexec + +#编写一个统计用户登陆数量的脚本 +[root@zutuanxue ~]# cat/etc/zabbix/libexec/check_user_number.sh +#!/bin/bash +#Description: 登陆用户监控脚本 +count=`who |wc -l` +echo $count + +#给脚本执行权限 +[root@zutuanxue ~]# chmod 755 /etc/zabbix/libexec/check_user_number.sh + +#测试脚本执行 +[root@zutuanxue ~]# /etc/zabbix/libexec/check_user_number.sh +1 +``` + +### b、定义一个键值 + +``` +[root@zutuanxue ~]# vim /etc/zabbix/zabbix_agentd.d/check_user_number.conf +UserParameter=check.user.number,/etc/zabbix/libexec/check_user_number.sh + 插件配置文件的格式 + 指令=kye,value 按照格式写就可以了 + + +#重启生效 +[root@manage01 zabbix]# systemctl restart zabbix-agent +``` + +**注意:如果是监控其它主机,请将libexec目录以及zabbix_agentd.d目录下的配置文件都拷贝到远程主机的/etc/zabbix目录下,并重启zabbix-agent服务** + +### c、新建一个监控项,调用键值 + +``` +注意:如果是希望所有主机都应用该监控项,那么就在对应的模板中创建监控项、图形 + 如果只是个别机器,那么就针对主机来设置监控项、图形 +``` + +给 Template OS Linux 模板添加一个监控项 + +依次点击 配置——模板 找到Template OS Linux选项,如图 + +![自定义监控监控项1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530411363.png) + +``` +应用集: 监控项分组 + +监控项: 监控什么 + +触发器: 监控阈值 + +图形: 监控图形 + +自动发现: 自动添加监控业务 + +WEB监测: 监控WEB站点 +``` + +点击 监控项,可以看到模板中的所有监控项,该页面可以对模板中的监控项进行管理。 + +![自定义监控监控项2.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530435453.png) + +点击 创建监控项 后会弹出一个创建监控项菜单,依次填入对应的信息,就可以创建一个自定义的监控项了。 +![自定义监控监控项3.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530451585.png) + +单击 添加后,监控项就添加成功了。 + +创建好了监控项不是最终的目的,最终的目的是通过监控项绘制图形,我们可以通过图表能看到信息,接下来我们来为这个监控项创建一个图表吧。 + +点击当前界面的图形,就可以进入模板的图表管理界面了,如图 + +![自定义监控监控项4.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530465210.png) + +图表管理界面可以对图形就行管理,我们这里选择 创建图形。 + +![自定义监控图形5.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530478014.png) + +点击创建图形后,就会出现一个创建图形菜单 + +![自定义监控图形62579308.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530492871.png) + +根据提示就把图形名称和对应的监控项填入即可。 + +图形创建成功了,接下来测试一下吧。 + +我们去找一个应用该模板的机器来看看是否有图形,图形是否有数据。 + +![自定义监控图形7.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603530507481.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\351\203\250\347\275\262zabbix\347\233\221\346\216\247\345\271\263\345\217\260.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\351\203\250\347\275\262zabbix\347\233\221\346\216\247\345\271\263\345\217\260.md" new file mode 100644 index 0000000..96064be --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\344\274\201\344\270\232\347\272\247\347\233\221\346\216\247\347\263\273\347\273\237-Zabbix/\351\203\250\347\275\262zabbix\347\233\221\346\216\247\345\271\263\345\217\260.md" @@ -0,0 +1,191 @@ +通过前面的课程我们知道了zabbix的官网给我们提供了一个安装的指导流程,那我们按照这个流程来部署一下zabbix + +- 部署zabbix监控平台 +- 站点设置 +- 界面介绍与用户管理 + +## 一、部署zabbix监控平台 + +a. 安装zabbix下载源 + +``` +[root@zutuanxue ~]# rpm -Uvh https://repo.zabbix.com/zabbix/4.4/rhel/8/x86_64/zabbix-release-4.4-1.el8.noarch.rpm +[root@zutuanxue ~]# dnf clean all +``` + +b. 安装Zabbix server,Web前端,agent + +``` +[root@zutuanxue ~]# dnf -y install zabbix-server-mysql zabbix-web-mysql zabbix-apache-conf zabbix-agent + +## +注意:如果国外的官方源下载失败或者速度慢,直接切换阿里的源即可 +[root@zutuanxue ~]# cat /etc/yum.repos.d/zabbix.repo +[zabbix] +name=Zabbix Official Repository - $basearch +baseurl=https://mirrors.aliyun.com/zabbix/zabbix/4.4/rhel/8/$basearch/ +enabled=1 +gpgcheck=0 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-ZABBIX-A14FE591 + +[zabbix-non-supported] +name=Zabbix Official Repository non-supported - $basearch +baseurl=http://repo.zabbix.com/non-supported/rhel/8/$basearch/ +enabled=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-ZABBIX +gpgcheck=1 +## +``` + +c. 创建初始数据库 + +``` +[root@zutuanxue ~]# systemctl restart mariadb.service +[root@zutuanxue ~]# mysqladmin -u root password '123456' +[root@zutuanxue ~]# mysql -u root -p +Enter password: +Welcome to the MariaDB monitor. Commands end with ; or \g. +Your MariaDB connection id is 9 +Server version: 10.3.11-MariaDB MariaDB Server + +Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +MariaDB [(none)]> create database zabbix character set utf8 collate utf8_bin; +Query OK, 1 row affected (0.001 sec) + +MariaDB [(none)]> grant all privileges on zabbix.* to zabbix@localhost identified by '123456'; +Query OK, 0 rows affected (0.000 sec) + +MariaDB [(none)]> quit +Bye + +导入初始架构和数据 +[root@zutuanxue ~]# zcat /usr/share/doc/zabbix-server-mysql/create.sql.gz | mysql -uzabbix -p zabbix +Enter password: +``` + +d. 为Zabbix server配置数据库 +编辑配置文件 /etc/zabbix/zabbix_server.conf + +``` +[root@zutuanxue ~]# vim /etc/zabbix/zabbix_server.conf +DBPassword=123456 +``` + +e. 为Zabbix前端配置PHP +编辑配置文件 /etc/php-fpm.d/zabbix.conf + +``` +[root@zutuanxue ~]# vim /etc/php-fpm.d/zabbix.conf +php_value[date.timezone] = Asia/Shanghai +``` + +f. 启动Zabbix server和agent进程 +启动Zabbix server和agent进程,并为它们设置开机自启: + +``` +[root@zutuanxue ~]# systemctl restart zabbix-server zabbix-agent httpd php-fpm +[root@zutuanxue ~]# systemctl enable zabbix-server zabbix-agent httpd php-fpm +[root@zutuanxue ~]# netstat -ntlp #zabbix_server的端口是10051 +Active Internet connections (only servers) +Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name +tcp 0 0 0.0.0.0:10051 0.0.0.0:* LISTEN 2106/zabbix_server +tcp6 0 0 :::10051 :::* LISTEN 2106/zabbix_server +``` + +g. 配置Zabbix前端 +连接到新安装的Zabbix前端: http://server_ip_or_name/zabbix + +## 二、站点设置 + +![image20200206131850564.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603529129928.png) + +图:zabbix-web-setup-01 + +![image20200206132044127.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603528792468.png) + +图:zabbix-web-setup-02 + +![zabbix_web3.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603528835307.png) + +图:zabbix-web-setup-03 + +![zabbix_web4.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603528855897.png) + +图:zabbix-web-setup-04 + +![zabbix_web5.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603528868438.png) + +图:zabbix-web-setup-05 + +![zabbix_web6.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603528880574.png) + +图:zabbix-web-setup-06 + +![image20200206132343605.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603528902697.png) + +图:zabbix-web-setup-07 + +![image20200206132450564.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603528915822.png) + +图:zabbix-web-setup-08 + +![image20200206132720327.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603528929618.png) + +![image20200206132751747.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603528945191.png) + +![image20200206132813412.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603528963513.png) + +## 三、zabbix web界面介绍 + +我们现在已经登录了zabbix的页面,并且设置成了中文,那我们一起来看一下这个设置成中文后的界面 + +监测—仪表盘 + + 在仪表板当中我们可以查看到很多信息,如果感觉信息不够丰富的话,在右上角可以选择编辑仪表盘,添加新的内容。 + +可以挨着点一下后面的选项,都是没有内容的,这个我们后面都会说到 + +监测—图形 + +在这里可以查看各种类型的图表,比如 + +![image20200206133841844.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603529260849.png) + +通过右上方的时间选项你可以获取到不同时间范围的信息,这就是可持续化的体现,因为这些数据都存放到数据库里面了,但是不管选择哪个时间范围的,你都会发现有乱码,为什么会有乱码?因为没有相关的字库,所以我们要解决乱码的问题 + +关于zabbix web设置成中文后图形上的汉字显示乱码问题-解决方案。 + +``` +复制本地电脑C:\Windows\Fonts\simkai.ttf(楷体)上传到zabbix服务器 +[root@zutuanxue ~]# cp SIMKAI.TTF /usr/share/fonts/dejavu/ +[root@zutuanxue ~]# chmod 644 /usr/share/fonts/dejavu/SIMKAI.TTF +[root@zutuanxue ~]# cd /etc/alternatives/ +[root@zutuanxue alternatives]# rm -fr zabbix-web-font +[root@zutuanxue alternatives]# ln -s /usr/share/fonts/dejavu/SIMKAI.TTF /etc/alternatives/zabbix-web-font + +刷新页面 +``` + +## 四、监控本机 + +zabbix默认就是对本机进行监控的,但是一定要开启zabbix-agent服务,在对应的界面,我们可以看到,zabbix的监控有四种: + +- ZBX +- SNMP +- JMX +- IPMI + +![image20200216003900217.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603529384793.png) + +- 绿色表示正常 +- 红色则表示有问题 + 如果出现红色了,首先要检查系统中是否安装了zabbix-agent软件包,然后再确认服务是否开启,第三个要检查状态是否已启用。各位可以尝试停止zabbix-agent服务,并且点击一下状态下的已启用按钮改为停用,看一下彻底不好用是什么样的。 + +``` +systemctl stop zabbix-agent +``` + +![image20200216004245599.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/24/1603529402589.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/Grafana\346\212\245\350\255\246.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/Grafana\346\212\245\350\255\246.md" new file mode 100644 index 0000000..10163de --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/Grafana\346\212\245\350\255\246.md" @@ -0,0 +1,47 @@ +接下来设置grafana的报警通道 + +![image20200225174606552.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603600915168.png) + +点击左侧铃铛图表—notification channels—Add channel + +![image20200225175559736.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603600940885.png) + +- Name 部分:填一个名字 +- Type 部分:选择 **webhook** 方式 +- Send on all alerts:勾选后表示默认所有的报警都会通过这个通道发 +- Include image:勾选后表示在报警的时候同时截图发送,因为目前的报警通知不支持图片,所以这里不用勾选 +- Disable Resolve Message:勾选后表示当状态从报警中恢复到正常时,不再发送信息,即不告知恢复正常,这里不用勾选 +- Send reminders:勾选后表示除了状态刚变成报警中时会发报警消息,过后每隔一段时间,如果依然处于报警中的状态,那么还会发一次重复报警 +- Send reminder every:表示每隔多长时间发送重复报警,这里填默认30分钟 +- Url:正式服的报警服务器 +- Http Method:选择 POST + +设置完成后点击send test可以去注册账号时使用的邮箱查看报警邮件 + +![image20200225175125898.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603601003371.png) + +设置好通道并完成验证后,为图表设置报警 + +![onealter7.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603601023842.png) + +选择图表 点击图表名称的下拉菜单—edit 进入编辑菜单 + +![onealter8.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603601034286.png) + +选择铃铛图表—create alert 设置图表报警 + +![onealter9.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603601048614.png) + +这里报警阈值设置的是取CPU Load平均值 因为是实验,所以预警值是0.5方便测试报警 + +![onealter10.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603601059715.png) + +设置完成后,发现图表上出现了预警线,点击保存吧 + +接下来在node2上搞大CPU的负载吧 + +![image20200225220905872.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603601078926.png) + +![image20200225222218919.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603601092958.png) + +报警了,完美。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/Prometheus\347\233\221\346\216\247\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/Prometheus\347\233\221\346\216\247\344\273\213\347\273\215.md" new file mode 100644 index 0000000..5830932 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/Prometheus\347\233\221\346\216\247\344\273\213\347\273\215.md" @@ -0,0 +1,50 @@ +Prometheus(由go语言开发)是一套开源的监控&报警&时间序列(按照时间排序)数据库的组合。适合监控docker 容器。因为kubernetes(俗称k8s)的流行带动了prometheus的发展。它可以监控主机,服务,容器 + +https://prometheus.io/docs/introduction/overview/ + +**时间序列数据**(TimeSeries Data) : 按照时间顺序记录系统、设备状态变化的数据被称为时序数据。这种时序数据,会应用到很多场景, 如: + +- 最常见的就是我们系统中的日志 +- 无人驾驶车辆运行中要记录的经度,纬度,速度,方向,旁边物体的距离等等。每时每刻都要将数据记录下来做分析。 +- 某一个地区的各车辆的行驶轨迹数据、车流量 +- 传统证券行业实时交易数据 +- 实时运维监控数据,网卡流量图,服务的当前状态,资源的使用情况,比如说,你所监控的内容出现了直线飙升、断崖式下跌、断线,一般都意味着出现了问题,不管是什么时候发生的,都要赶紧查一下出了什么问题 + +## 时间序列数据库的主要优点: + +时间序列数据库主要用于指处理带时间标签(按照时间的顺序变化,即时间序列化)的数据,带时间标签的数据也称为时间序列数据。 + +- 性能好 + +关系型数据库对于大规模数据的处理性能糟糕,这一点可以从I/O上有明显的体现。使用NOSQL可以比较好的处理大规模数据,但是依然比不上时间序列数据库。 + +- 存储成本低 + + 由于采用的是metrics:key=value(标签:关键字=值)的数据存储方式,又使用了高效的压缩算法,平均消耗的存储成本在3.5个字节左右 ,所以比较节省存储空间 ,并且能有效降低IO + +Prometheus有着非常高效的时间序列数据存储方法,每个采样数据仅仅占用3.5byte左右空间,上百万条时间序列数据,每隔30秒采集一次,保留60天,大概占用200多G的空间(来自官方文件数据) + +## Prometheus的主要特征 + +1. 多维度数据模型,可以通过多个维度对数据建模,也可以通过多个维度对数据进行查询 + +2. 灵活的查询语言,由于采用的是新兴的go语言进行开发,在灵活性和速度上都有明显的优势,有兴趣的同学可以去了解一下这门语言 + +3. 不依赖分布式存储,单个服务器节点是自主的 + +4. 以HTTP方式,通过pull模型拉取时间序列数据 + +5. 也可以通过中间网关支持push模型 + + 这种推,拉监控其实就是我们之前说的主动和被动监控,默认情况下是以pull(拉)的方式,也就是监控主机去找被监控主机将数据要过来,如果要实现push(推)的方式需要中间网关的支持,这只是与zabbix的叫法不同而已 + +6. 通过服务发现或者静态配置来发现目标服务对象 + +7. 支持多种多样的图表和界面展示,可以使用第三方的工具来展示内容,如grafana + +## 监控原理 + +1. **Prometheus Server负责定时在目标上抓取metrics(指标)数据,** +2. **每个抓取目标[主机、服务]都需要暴露一个HTTP服务接口用于Prometheus定时抓取。也就是说prometheus会将获取到的监控数据打包成一个可访问的web页面,通过访问指定的url来确定主机的状态** + +Pull方式的优势是能够自动进行上游监控和水平监控,配置更少,更容易扩展,更灵活,更容易实现高可用。简单来说就是Pull方式可以降低耦合。由于在推送系统中很容易出现因为向监控系统推送数据失败而导致被监控系统瘫痪的问题。因为如果同一时间有很多被监控主机都把数据推送给监控主机的话,就很可能导致监控主机处理不过来,所以通过Pull方式,被采集端无需感知监控系统的存在,完全独立于监控系统之外,这样数据的采集完全由监控系统控制。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/prometheus+Grafana\346\225\260\346\215\256\345\261\225\347\244\272.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/prometheus+Grafana\346\225\260\346\215\256\345\261\225\347\244\272.md" new file mode 100644 index 0000000..468c6c7 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/prometheus+Grafana\346\225\260\346\215\256\345\261\225\347\244\272.md" @@ -0,0 +1,231 @@ +通过前面课程的学习我们知道了如何部署和设置prometheus,但是这个监控软件的展示界面实在是有些难看,所以我们换一个展示方式Grafana,是一个开源的度量分析和可视化工具(没有监控功能),可以通过将采集的数据分析,查询,然后进行可视化的展示,并能实现报警。 + +## 一、部署grafana + +### 1.1、grafana安装 + +软件包获得 + +官方网站: grafana:https://grafana.com/ + +**软件包安装** + +``` +[root@manage01 ~]# dnf -y localinstall grafana-6.6.1-1.x86_64... +``` + +**服务启动** + +``` +#服务启动 +[root@manage01 ~]# systemctl enable grafana-server +Created symlink from /etc/systemd/system/multi-user.target.wants/grafana-server.service to /usr/lib/systemd/system/grafana-server.service. +[root@manage01 ~]# systemctl start grafana-server + +#验证启动 +[root@manage01 ~]# lsof -i :3000 +COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME +grafana-s 17154 grafana 8u IPv6 53939 0t0 TCP *:hbci (LISTEN) +``` + +grafana启动成功后,可以通过页面访问到grafana页面 + +**在浏览器中输入http://IP或者域名:3000** + +![grafana1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603596947237.png) + +**要求输入账号密码:** admin/admin(默认) + +当看到这个页面说明grafana已经安装成功并且工作了。 + +输入账号密码登录时,由于是第一次登录,为了安全要求必须更改密码后才能登录 + +![grafana2.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603596961840.png) + +输入两次新密码后,点击save即可登录 + +### 1.2、grafana页面设置-添加prometheus数据源 + +登录成功后,会发现页面为你提供了一个使用引导线,按着引导我们需要都设置一下,首先第一步就是告诉grafana,他需要展示谁的数据。也就是说数据源是谁 + +![image20200225145354437.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603597166730.png) + +从图标上可以看出,我们需要设置数据源—展示仪表盘—添加用户这些操作,我们先来完成添加数据源吧。 + +点击Add data source 增加数据源 + +![image20200225145454014.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603597180856.png) + +看到主角了把,Prometheus出现了。赶快点击进入下一步吧。 + +![image20200225153536052.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603598098895.png) + +auth部分的设置,主要是与HTTPS配合使用的,如果使用的是https的话就需要证书啊,认证啊这些,需要对此部分内容进行一些配置 + +按照页面要求填入对应信息即可,一般错误都是因为输入错误造成的。点击Save & Test后保存成功 + +![grafana6.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603598136429.png) + +我们可以通过左侧导航栏中的齿轮图标下拉菜单中的Data Source看到我们刚才添加的数据源 + +## 二、绘制图形 + +### 2.1 仪表盘管理 + +![grafana7.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603598153820.png) + +添加完数据源后,可以继续添加仪表盘了,这样我们就能以图表的方式看到数据了,继续点击New Dshboard + +![grafana8.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603598164980.png) + +图上显示你可以增加一个图形到仪表盘,也可以选择一个样式图标 + +这里任选一个都可以,这个版本不知道作者怎么想的,其实功能都能实现 + +我选择第一个 Add query + +![grafana9.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603598174144.png) + +进入页面后,左侧有四个标识,分别是 + +数据源 +![image20200225154121203.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603598195711.png) + +图表 +![image20200225154146665.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603598252585.png) + +设置 +![image20200225154213541.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603598296388.png) + +告警 +![image20200225154254663.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603598314569.png) + +我们按照图标步骤先来设置数据源吧 + +如上图,在A项中根据需求,匹配你的监控项,如果有多项,可以通过右上角的add query增加,设置完成后就可以设置图表样式了,点击图表 + +![grafana10.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603598371614.png) + +图表主要说的就是图表的样式,主要的我给大家展示一下 + +第一个Draw Modes 说的是图表中图的展示方式,有条状 线 点三种,看你喜好了 + +第二个Mode Options 说的是图表的填充阴影透明度 图上线的粗细 + +最后一个 是否开启图表堆叠和显示百分比 + +设置完成后再看看设置图标 + +该页面主要是设置图表名称和注释的 + +![grafana11_1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603598409137.png) + +设置好后我们图表设置就暂时这样,后续告警再细说告警设置。 + +点击保存后图表就保存好了。 + +![grafana11.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603598419929.png) + +保存图表时会要求你输入仪表盘名称。这里输入Node2 + +![grafana12.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603598428790.png) + +确认无误后,点击保存 + +![grafana13.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603598439982.png) + +仪表盘做好了,同时也看到我们的图形了。 + +接下来应该设置用户了,这个用户添加,采用的是邀请机制,也就是需要我们生成邀请链接,然后发给对应的用户,然后对方访问相应的链接注册,这样,这个用户才能添加成功 点击Add users按钮 + +![grafana14.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603598459372.png) + +按照要求添加一个用户 + +![grafana15.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603598467834.png) + +点击邀请用户 + +![image20200225161454447.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603598506824.png) + +输入用户名称、用户角色点击邀请 + +![image20200225161653564.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603599969045.png) + +点击邀请后,需要将邀请链接发给用户或者自己在浏览器中打开确认邀请 + +我们切换到另一台主机在浏览器中打开 + +![image20200225162223119.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603599989091.png) + +输入email地址和用户密码第几注册即可成功 + +![image20200225162409462.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603600009892.png) + +回到使用admin账号登录grafana的主机,刷新后就可以看到新注册的用户,也可以对用户进行删除,修改权限的操作 + +### 2.2、grafana设置–添加监控cpu负载的图形 + +点击左边侧栏:➕—Choose Visualization(这次练习这个) + +选择graph图表样式 + +按照要求输入数据项: + +- node_load1 CPU一分钟平均负载 +- node_load5 CPU五分钟平均负载 +- node_load15 CPU十五分钟平均负载 + +注意:如果同时监控了多个机器,图表会显示所有机器的,如果只想显示某个机器的可以使用监控匹配。 + +输入方法如下: + +监控项{instance=“被监控机IP:port”} + +如下图 + +![image20200225163828382.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603600129701.png) + +这样就可以显示一台机器了。 + +### 2.3、grafana设置—使用模板图表展示MySQL监控 + +**mysql监控模板下载** +https://github.com/percona/grafana-dashboards + +模板设置 + +``` +#在grafana配置文件中添加插件信息 +[root@manage01 ~]# vim /etc/grafana/grafana.ini +[root@manage01 grafana]# tail -3 /etc/grafana/grafana.ini +[dashboards.json] +enabled = true +path = /var/lib/grafana/dashboards + +#下载插件 +[root@manage01 ~]# unzip grafana-dashboards-master.zip + + +#拷贝插件到指定位置 +[root@manage01 ~]# cd grafana-dashboards-master/ +[root@manage01 grafana-dashboards-master]# cp -r dashboards /var/lib/grafana/ +[root@manage01 dashboards]# vim /var/lib/grafana/dashboards/MySQL_Overview.json +#搜索pmm-singlestat-panel替换为singlestat +#重启生效 +[root@manage01 grafana]# systemctl restart grafana-server.service +``` + +web界面导入模板 + +![grafana20.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603600176233.png) + +选择左侧菜单—➕—Import + +选择对应的json文件,然后导入即可 + +![grafana21.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603600190604.png) + +点击导入后就可以看到图片了 + +![image20200225171755015.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603600206867.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/\344\275\277\347\224\250prometheus\347\233\221\346\216\247\344\270\200\344\270\252\344\270\232\345\212\241.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/\344\275\277\347\224\250prometheus\347\233\221\346\216\247\344\270\200\344\270\252\344\270\232\345\212\241.md" new file mode 100644 index 0000000..e42e651 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/\344\275\277\347\224\250prometheus\347\233\221\346\216\247\344\270\200\344\270\252\344\270\232\345\212\241.md" @@ -0,0 +1,76 @@ +**案例需求** + +通过prometheus监控MariaDB业务 + +**案例分析** +要监控mysql需要两个条件,一个是系统中有mysql,另一个是要有监控插件,现在监控插件我已经下载好了,所以我们要先安装mysql,然后进行相应的授权,让插件可以获取到所需要的信息,然后再设置相关插件,修改prometheus配置文件 + +## 案例实现 + +### a、部署mysql业务 + +``` +[root@node2 node_exporter-0.18.1.linux-amd64]# dnf -y install mariadb-server mariadb +[root@node2 mysqld_exporter-0.12.0.linux-amd64]# systemctl enable mariadb +Created symlink from /etc/systemd/system/multi-user.target.wants/mariadb.service to /usr/lib/systemd/system/mariadb.service. +[root@node2 mysqld_exporter-0.12.0.linux-amd64]# systemctl start mariadb + +#创建监控用户 +MariaDB [(none)]> grant select,replication client,process on *.* to 'hello'@'localhost' identified by '123456'; +Query OK, 0 rows affected (0.00 sec) + +MariaDB [(none)]> flush privileges; +Query OK, 0 rows affected (0.00 sec) +``` + +### b、部署监控插件 + +``` +[root@node2 ~]# tar xf mysqld_exporter-0.12.1.linux-amd64.tar.gz -C /usr/local +[root@node2 ~]# vim /usr/local/mysqld_exporter-0.12.1.linux-amd64/.my.cnf +[root@node2 ~]# cat /usr/local/mysqld_exporter-0.12.1.linux-amd64/.my.cnf +[client] +user=hello +password=123456 + +#启动 +[root@node2 ~]# nohup /usr/local/mysqld_exporter-0.12.1.linux-amd64/mysqld_exporter --config.my-cnf=/usr/local/mysqld_exporter-0.12.1.linux-amd64/.my.cnf & + +[root@node2 ~]# lsof -i :9104 +COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME +mysqld_ex 7698 root 3u IPv6 46415 0t0 TCP *:peerwire (LISTEN) +``` + +### c、在prometheus主配置文件中添加监控 + +``` +# +[root@node1 prometheus-2.11.1.linux-amd64]# tail -10 prometheus.yml + static_configs: + - targets: ['localhost:9090'] + + - job_name: 'node2' + static_configs: + - targets: ['192.168.98.202:9100'] + + - job_name: 'mariadb' + static_configs: + - targets: ['192.168.98.202:9104'] +``` + +### d、重启prometheus服务 + +``` +[root@node1 prometheus-2.11.1.linux-amd64]# pkill prometheus +[root@node1 prometheus-2.11.1.linux-amd64]# ./prometheus --config.file=prometheus.yml & +``` + +### e、通过监控页面查看服务 + +![Prometheus_node2_mysql9.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603596540745.png) + +通过Graph页面看看相关图表吧 + +![Prometheus_node2_mysql8.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603596551382.png) + +出图了,可以勾选stacked将图形显示为堆叠状。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/\344\275\277\347\224\250prometheus\347\233\221\346\216\247\344\270\200\344\270\252\344\270\232\345\212\241\346\234\272.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/\344\275\277\347\224\250prometheus\347\233\221\346\216\247\344\270\200\344\270\252\344\270\232\345\212\241\346\234\272.md" new file mode 100644 index 0000000..503e537 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/\344\275\277\347\224\250prometheus\347\233\221\346\216\247\344\270\200\344\270\252\344\270\232\345\212\241\346\234\272.md" @@ -0,0 +1,63 @@ +**案例要求:** +通过prometheus监控业务机器192.168.98.202(node2) + +## 一、案例实现 + +### a、安装监控客户端 + +``` +[root@node2 ~]# tar xf node_exporter-0.18.1.linux-amd64.tar.gz -C /usr/local/ +[root@node2 ~]# cd /usr/local/node_exporter-0.18.1.linux-amd64/ +[root@node2 node_exporter-0.18.1.linux-amd64]# ls +LICENSE node_exporter NOTICE + +#后台启动 +[root@node2 node_exporter-0.18.1.linux-amd64]# nohup /usr/local/node_exporter-0.18.1.linux-amd64/node_exporter & +[1] 7281 +[root@node2 node_exporter-0.18.1.linux-amd64]# nohup: 忽略输入并把输出追加到"nohup.out" + + +#业务机器监控插件服务端口 +[root@node2 node_exporter-0.18.1.linux-amd64]# lsof -i :9100 +COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME +node_expo 7281 root 3u IPv6 42486 0t0 TCP *:jetdirect (LISTEN) + +#验证 http://被监控机名称:9100/metrics +http://192.168.98.202:9100/metrics +现在我们这台机器上的数据被打包成了一个可以访问的页面,所以我们可以使用浏览器去访问这个页面,看下能否获取到相关的数据,如果能够获取的话就表示没有问题了。 +``` + +### b、在prometheus添加监控信息 + +``` +#被监控主机设置完成之后,需要在prometeus主配置文件中添加被监控机信息 +[root@node1 prometheus-2.11.1.linux-amd64]# tail -4 prometheus.yml + + - job_name: 'node2' #定义名称 + static_configs:#定义具体配置 + - targets: ['192.168.98.202:9100']#定义目标 + + ####注意缩进 两个空格 + + #重启服务 +[root@node1 prometheus-2.11.1.linux-amd64]# pkill prometheus +[root@node1 prometheus-2.11.1.linux-amd64]# ./prometheus --config.file=prometheus.yml & + + +注意:prometheus启动报错 +**lock DB directory: resource temporarily unavailable"** +原因:prometheus没有正常关闭,锁文件存在 +rm $prometheus_dir/data/lock +``` + +## 二、测试验证 + +设置完毕看看prometheus页面吧 + +![Prometheus_6.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603595672827.png) + +查看Status-Targets页面后可以看到被监控机node2(192.168.98.202)已经在监控列表中了,同时可以通过浏览器看看其监控数据。 + +![Prometheus_node2_metrics5.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603595697191.png) + +在浏览器中输入http://192.168.98.202:9100/metrics 既可以看到数据了 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/\351\203\250\347\275\262prometheus\347\233\221\346\216\247\345\271\263\345\217\260.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/\351\203\250\347\275\262prometheus\347\233\221\346\216\247\345\271\263\345\217\260.md" new file mode 100644 index 0000000..6373edf --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\345\256\271\345\231\250\347\233\221\346\216\247-Prometheus/\351\203\250\347\275\262prometheus\347\233\221\346\216\247\345\271\263\345\217\260.md" @@ -0,0 +1,65 @@ +## 部署prometheus监控平台 + +- 安装部署prometheus服务监控端 +- 监控一个远端机器 +- 监控一个服务—mysql + +## 一、软件获得 + +官方网站:https://prometheus.io/download/ + +``` +prometheus 主程序包:wget https://github.com/prometheus/prometheus/releases/download/v2.11.1/prometheus-2.16.0.linux-amd64.tar.gz + +远端主机监控插件(类似于zabbix-agent): wget https://github.com/prometheus/node_exporter/releases/download/v0.18.1/node_exporter-1.0.0-rc.0linux-amd64.tar.gz + +mysql业务监控插件: wget https://github.com/prometheus/mysqld_exporter/releases/download/v0.12.0/mysqld_exporter-0.12.1.linux-amd64.tar.gz +``` + +## 二、实验拓扑图 + +![prometheus实验图.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603595224470.png) + +## 三、软件安装与启动 + +``` +[root@node1 ~]# tar xf prometheus-2.11.1.linux-amd64.tar.gz -C /usr/local/ + + +[root@node1 ~]# cd /usr/local/prometheus-2.11.1.linux-amd64/ +[root@node1 prometheus-2.11.1.linux-amd64]# ./prometheus --config.file=prometheus.yml & +``` + +## 四、启动测试 + +![Prometheus_1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603595254983.png) + +看到这个页面说明prometheus启动成功了,默认监控了自己,我们来看一下本机的监控状态 + +![Prometheus_2.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603595266461.png) + +点击 status—targets即可看到监控的机器或者资源 + +![Prometheus_3.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603595289849.png) + +看到本机了,同时也可以根据提示在浏览器中输入http://IP或者域名:9090/metrics查看监控数据。 + +``` +显示监控数据 + +http://192.168.98.201:9090/metrics +``` + +![Prometheus_node1_metrics4.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603595312946.png) + +如果能看到这些信息就说明监控拿到了数据,拿到数据就可以正常显示了。通过这个URL我们可以知道prometheus把监控的数据都统一存放在一起,然后生成一个web页面,用户可以通过web页面查看相关的数据,这些数据遵循了时序数据库的格式,也就是key=value的形式.这些数据就是我们的监控指标,只不过现在我们还没有办法分析,借助图形展示才会更方便阅读 + +prometheus显示同样也提供了图表,可以通过图表很直观的看到监控项的状态,只不过自带的图形实在是不怎么好看。 + +通过点击Graph可以显示到下列图表,在搜索栏中输入关键字可以匹配出你想看的监控项 + +![image20200225140312916.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/25/1603595335039.png) + +这里输入的是process_cpu_seconds_total,CPU使用状态表就出现了,注意要点一下图表左上角的Graph按钮,默认是在console按钮页面。 + +至于报警,这里我们就不介绍了,因为我们不用prometheus自带的报警功能 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\225\260\346\215\256\345\256\211\345\205\250\344\271\213\344\274\201\344\270\232\345\255\230\345\202\250/NFS\346\226\207\344\273\266\346\234\215\345\212\241\345\231\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\225\260\346\215\256\345\256\211\345\205\250\344\271\213\344\274\201\344\270\232\345\255\230\345\202\250/NFS\346\226\207\344\273\266\346\234\215\345\212\241\345\231\250.md" new file mode 100644 index 0000000..3badb0a --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\225\260\346\215\256\345\256\211\345\205\250\344\271\213\344\274\201\344\270\232\345\255\230\345\202\250/NFS\346\226\207\344\273\266\346\234\215\345\212\241\345\231\250.md" @@ -0,0 +1,316 @@ +``` +一、NFS介绍 +NFS就是Network File System的缩写,最早由Sun公司所发展出来的.最大的功能就是可以通过网络,让不同的主机能共享文件。在NFS的应用中,本地NFS的客户端应用可以透明地读写位于远端NFS服务器上的文件,就像访问本地文件一样。 + +NFS优势: + +可以把服务器上的文件像本地一样的操作,节省本地的存储空间 + +nfs配置简单,而且服务本身对系统资源占用较少 + +nfs服务可以支持很多其它的服务,如kickstart,配合在一起,可以实现更多功能 + +应用场景 + +共享存储服务器: 图片服务器、视频服务器等 + +家目录漫游:域用户家目录服务器 + +文件服务器:内容文件存储服务器 + +工作原理 + +NFS体系有两个主要部分: + +NFS服务端机器:通过NFS协议将文件共享到网络。 + +NFS客户端机器:通过网络挂载NFS共享目录到本地。 + +NFS服务器与客户端在进行数据传输时,需要先确定端口,而这个端口的确定需要借助RPC(Remote Procedure Call,远程过程调用)协议的协助。RPC最主要的功能就是在指定每个NFS服务所对应的端口号,并且告知客户端,让客户端可以连接到正确的端口上去。当我们启动NFS服务时会随机取用数个端口,并主动向RPC注册,因此RPC可以知道每个端口对应的NFS,而RPC又是固定使用 port 111监听客户端的需求并且能够准确的告知客户端正确的端口。 + +image20200307151530148.png + +1.客户端向服务器的111端口发送nfs请求 + +2.RPC找到对应的nfs端口并告知客户端 + +3.客户端知道正确的端口后,直接与nfs server端建立连接 + +二、安装部署 +[root@zutuanxue ~]# rpm -qa | grep nfs-utils +nfs-utils-2.3.3-14.el8.x86_64 +#管理用户登录及文件权限 +[root@zutuanxue ~]# rpm -qa | grep rpcbind +rpcbind-1.2.5-3.el8.x86_64 +#管理端口 + + +[root@zutuanxue ~]# systemctl is-enabled rpcbind +enabled +#检查rpcbind服务的状态 + +[root@zutuanxue ~]# systemctl enable nfs-server.service +Created symlink /etc/systemd/system/multi-user.target.wants/nfs-server.service → /usr/lib/systemd/system/nfs-server.service. +[root@zutuanxue ~]# systemctl start nfs-server.service +#设置开机启动,并启动nfs服务 +相关文件 + +/etc/exports: 共享配置文件,用来设置共享 + +/etc/nfs.conf: nfs服务的配置文件,可以设置端口和超时时间等,大多数时候不需要修改 + +/etc/sysconfig/nfs: 端口设置文件,重启服务后系统会自动调整nfs.conf内容 + +/var/lib/nfs/etab: 记录nfs共享的完整权限设定值 + +三、配置说明 +/etc/exports + +格式: + +共享目录 客户端(权限1,权限2) + +共享目录:在本地的位置(绝对路径) +客户端:一台主机,一群主机(IP地址、网段、主机名、域名) +权限: +ro + 只读访问(默认) +rw + 读写访问 +sync + 将数据同步写入内存缓冲区与磁盘中,效率低,但可以保证数据的一致性;(默认) +async + 将数据先保存在内存缓冲区中,必要时才写入磁盘; +secure + 客户端只能使用小于1024的端口连接(默认) +insecure + 允许客户端使用大于1024的端口连接 +wdelay + 检查是否有相关的写操作,如果有则将这些写操作一起执行,这样可以提高效率(默认); +no_wdelay + 若有写操作则立即执行,应与sync配合使用; +hide + 在NFS共享目录中不共享其子目录(默认) +no_hide + 共享NFS目录的子目录 +subtree_check + 如果共享目录是子目录时,强制NFS检查父目录的权限(默认) +no_subtree_check + 和上面相对,不检查父目录权限 +all_squash + 共享文件的UID和GID映射匿名用户anonymous,适合公用目录。 +no_all_squash + 保留共享文件的UID和GID(默认) +root_squash + root用户的所有请求映射成如anonymous用户一样的权限(默认) +no_root_squash + root用户具有根目录的完全管理访问权限 +anonuid=xxx + 指定NFS服务器/etc/passwd文件中匿名用户的UID +anongid=xxx + 指定NFS服务器/etc/passwd文件中匿名用户的GID +相关命令 + +exportfs - 管理NFS共享文件系统列表 + -a 发布获取消所有目录共享。 + -r 重新挂载/etc/exports里面的共享目录,同时更新/etc/exports 和/var/lib/nfs/xtab的内容 + -u 取消一个或多个目录的共享。 + -v 输出详细信息。 + -o options,... 指定一系列共享选项(如rw,async,root_squash) + -i 忽略/etc/exports和/etc/exports.d目录下文件。此时只有命令行中给定选项和默认选项会生效。 + + +例如: +#exportfs -rv //重新挂载共享目录,并且显示。 +#exportfs -au //卸载所有共享目录。 + + + +showmount 可以在server/client上使用此命令来查看server +#showmount [-ae] hostname/ip +-a或--all + 以 host:dir 这样的格式来显示客户主机名和挂载点目录。 +-d或--directories + 仅显示被客户挂载的目录名。 +-e或--exports + +[root@zutuanxue ~]# showmount -e +Export list for manage01: +/opt * + +四、NFS共享案例 +案例需求 + +新建目录/ro,/rw + +以只读的方式共享目录 /ro 同时只能被 192.168.98.0 域中的系统访问 + +以读写的方式共享目录 /rw 能被 192.168.98.0 域中的系统访问 + +实验环境 + +两台安装了CentOS8的主机,关闭selinux,关闭防火墙 + +zutuanxue: NFS server +node1: NFS client +image20200307195109955.png + +创建共享目录 +[root@zutuanxue ~]# mkdir /ro +[root@zutuanxue ~]# mkdir /rw +由于客户端挂载用户是nfsnobody,本题要求客户端挂载后可读写,我们是用root用户建立的目录,所以要给其他人7的权限 +[root@zutuanxue ~]# chmod 757 /rw/ + +通过/etc/exports文件定义共享目录 +[root@zutuanxue ~]# cat /etc/exports +/ro 192.168.98.0/24(ro) +/rw 192.168.98.0/24(rw) + +启动nfs服务 +[root@zutuanxue ~]# systemctl restart nfs-server.service + + +[root@zutuanxue opt]# ps aux | egrep "rpc|nfs" +rpc.nfsd(nfsd):基本的NFS守护进程(2049端口),主要负责登录权限检测。 +rpc.mountd(mountd):负责管理NFS的文件系统,对客户端存取服务器的文件进行一系列的管理。 +rpc.rquotad(rquotad):提供远程磁盘限额服务。 +rpc.lockd(nlockmgr):用于管理文件的锁定,防止多个客户端同时写入某个文件时产生的冲突。 +rpc.statd(staus):用来检查共享目录的一致性 + + +如果服务之前已经启动可以重新加载所有共享 +[root@zutuanxue ~]# exportfs -rv +exporting 192.168.98.0/24:/rw +exporting 192.168.98.0/24:/ro + +查看共享目录 +[root@zutuanxue ~]# exportfs -v +/ro 192.168.98.0/24(sync,wdelay,hide,no_subtree_check,sec=sys,ro,secure,root_squash,no_all_squash) +/rw 192.168.98.0/24(sync,wdelay,hide,no_subtree_check,sec=sys,rw,secure,root_squash,no_all_squash) +五、客户端访问 +使用showmount命令查看远程nfs服务器共享目录 +[root@node1 ~]# showmount -e 192.168.98.200 +Export list for 192.168.98.200: +/protected 192.168.98.0/24 +/public 192.168.98.0/24 + +新建挂载点 +[root@node1 ~]# mkdir /mnt/ro +[root@node1 ~]# mkdir /mnt/rw + +挂载NFS服务器共享目录 +[root@node1 ~]# mount -t nfs 192.168.98.200:/ro /mnt/ro/ +[root@node1 ~]# mount -t nfs 192.168.98.200:/rw /mnt/rw/ + +验证挂载 +[root@node1 ~]# mount | grep mnt + + +测试权限 +[root@node1 ~]# touch /mnt/ro/test +touch: 无法创建"/mnt/public/test": 只读文件系统 +[root@node1 ~]# touch /mnt/rw/test +[root@node1 ~]# ls /mnt/rw/ -l +总用量 0 +-rw-r--r-- 1 nfsnobody nfsnobody 0 2月 28 11:52 test + +如果需要开机挂载的话可以修改/etc/fstab +192.168.98.200:/ro /mnt/ro nfs defaults 0 0 +192.168.98.200:/rw /mnt/rw nfs defaults 0 0 + +温馨提示:还可以使用前面课程提到过的autofs实现自动挂载 +六、nfs固定端口 +nfs工作需要的端口除了2049和111之外还有额外的端口,而这些端口都是随机的,所以在有安全防护的时候,为了保证NFS可以正常工作就需要将这些随机的端口固定 + +我们可以使用rpcinfo命令来查看nfs的端口 +[root@zutuanxue ~]# rpcinfo -p + program vers proto port service + 100000 4 tcp 111 portmapper + 100000 3 tcp 111 portmapper + 100000 2 tcp 111 portmapper + 100000 4 udp 111 portmapper + 100000 3 udp 111 portmapper + 100000 2 udp 111 portmapper + 100024 1 udp 37242 status + 100024 1 tcp 39231 status + 100005 1 udp 20048 mountd + 100005 1 tcp 20048 mountd + 100005 2 udp 20048 mountd + 100005 2 tcp 20048 mountd + 100005 3 udp 20048 mountd + 100005 3 tcp 20048 mountd + 100003 3 tcp 2049 nfs + 100003 4 tcp 2049 nfs + 100227 3 tcp 2049 nfs_acl + 100021 1 udp 41958 nlockmgr + 100021 3 udp 41958 nlockmgr + 100021 4 udp 41958 nlockmgr + 100021 1 tcp 35847 nlockmgr + 100021 3 tcp 35847 nlockmgr + 100021 4 tcp 35847 nlockmgr +重启nfs服务 +[root@zutuanxue ~]# systemctl restart nfs-server.service +再次查看端口 +[root@zutuanxue ~]# rpcinfo -p + program vers proto port service + 100000 4 tcp 111 portmapper + 100000 3 tcp 111 portmapper + 100000 2 tcp 111 portmapper + 100000 4 udp 111 portmapper + 100000 3 udp 111 portmapper + 100000 2 udp 111 portmapper + 100024 1 udp 37242 status + 100024 1 tcp 39231 status + 100005 1 udp 20048 mountd + 100005 1 tcp 20048 mountd + 100005 2 udp 20048 mountd + 100005 2 tcp 20048 mountd + 100005 3 udp 20048 mountd + 100005 3 tcp 20048 mountd + 100003 3 tcp 2049 nfs + 100003 4 tcp 2049 nfs + 100227 3 tcp 2049 nfs_acl + 100021 1 udp 45032 nlockmgr + 100021 3 udp 45032 nlockmgr + 100021 4 udp 45032 nlockmgr + 100021 1 tcp 36303 nlockmgr + 100021 3 tcp 36303 nlockmgr + 100021 4 tcp 36303 nlockmgr +你会发现除了2049和111之外的端口都是在随机变化的,而这些随机变化的端口会在我们进行安全设置的时候带来困扰,所以我们需要讲端口固定 + +[root@zutuanxue ~]# vim /etc/sysconfig/nfs +MOUNTD_PORT=10001 # rpc.mountd使用的端口 +STATD_PORT=10002 # rpc.statd使用的端口 +LOCKD_TCPPORT=10003 # nlockmgr使用的TCP端口(rpc.lockd) +LOCKD_UDPPORT=10003 # nlockmgr使用的UDP端口 +RQUOTAD_PORT=10004 # rpc.rquotad使用的端口 +重新启动服务 + +[root@zutuanxue ~]# systemctl restart nfs-server.service nfs-convert.service +[root@zutuanxue ~]# rpcinfo -p + program vers proto port service + 100000 4 tcp 111 portmapper + 100000 3 tcp 111 portmapper + 100000 2 tcp 111 portmapper + 100000 4 udp 111 portmapper + 100000 3 udp 111 portmapper + 100000 2 udp 111 portmapper + 100005 1 udp 10001 mountd + 100005 1 tcp 10001 mountd + 100005 2 udp 10001 mountd + 100005 2 tcp 10001 mountd + 100005 3 udp 10001 mountd + 100005 3 tcp 10001 mountd + 100024 1 udp 10002 status + 100024 1 tcp 10002 status + 100003 3 tcp 2049 nfs + 100003 4 tcp 2049 nfs + 100227 3 tcp 2049 nfs_acl + 100021 1 udp 10003 nlockmgr + 100021 3 udp 10003 nlockmgr + 100021 4 udp 10003 nlockmgr + 100021 1 tcp 10003 nlockmgr + 100021 3 tcp 10003 nlockmgr + 100021 4 tcp 10003 nlockmgr +注意:如果之前没有启动过nfs服务的话,直接启动就可以,如果之前启动过nfs服务,需要同时重启nfs-convert服务,将我们刚才调整的设置写入到nfs.conf配置文件中,启动完成之后我们之前设置的/etc/sysconfig/nfs文件的名称会改为nfs.rpmsavexxxxxxxxxx27 1[root@zutuanxue ~]# systemctl restart nfs-server.service nfs-convert.service 2[root@zutuanxue ~]# rpcinfo -p3   program vers proto   port service4   100000   4   tcp   111 portmapper5   100000   3   tcp   111 portmapper6   100000   2   tcp   111 portmapper7   100000   4   udp   111 portmapper8   100000   3   udp   111 portmapper9   100000   2   udp   111 portmapper10   100005   1   udp 10001 mountd11   100005   1   tcp 10001 mountd12   100005   2   udp 10001 mountd13   100005   2   tcp 10001 mountd14   100005   3   udp 10001 mountd15   100005   3   tcp 10001 mountd16   100024   1   udp 10002 status17   100024   1   tcp 10002 status18   100003   3   tcp   2049 nfs19   100003   4   tcp   2049 nfs20   100227   3   tcp   2049 nfs_acl21   100021   1   udp 10003 nlockmgr22   100021   3   udp 10003 nlockmgr23   100021   4   udp 10003 nlockmgr24   100021   1   tcp 10003 nlockmgr25   100021   3   tcp 10003 nlockmgr26   100021   4   tcp 10003 nlockmgr27注意:如果之前没有启动过nfs服务的话,直接启动就可以,如果之前启动过nfs服务,需要同时重启nfs-convert服务,将我们刚才调整的设置写入到nfs.conf配置文件中,启动完成之后我们之前设置的/etc/sysconfig/nfs文件的名称会改为nfs.rpmsave +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\225\260\346\215\256\345\256\211\345\205\250\344\271\213\344\274\201\344\270\232\345\255\230\345\202\250/Samba\346\226\207\344\273\266\346\234\215\345\212\241\345\231\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\225\260\346\215\256\345\256\211\345\205\250\344\271\213\344\274\201\344\270\232\345\255\230\345\202\250/Samba\346\226\207\344\273\266\346\234\215\345\212\241\345\231\250.md" new file mode 100644 index 0000000..87d39ca --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\225\260\346\215\256\345\256\211\345\205\250\344\271\213\344\274\201\344\270\232\345\255\230\345\202\250/Samba\346\226\207\344\273\266\346\234\215\345\212\241\345\231\250.md" @@ -0,0 +1,844 @@ +## 一、samba介绍 + +在早期的网络世界当中,不同主机的文件传输大多使用FTP来进行。不过FTP却有个小小的问题, 那就是你无法直接修改主机上面的文件内容!也就是说,你想要更改Linux主机上面的某个文件时,你必须要将该文件下载后才能修改。在日常办公环境中,操作系统除了windows以外,还有linux或者UNIX。windows和linux或UNIX之间共享文件是无法直接完成的,为了解析不同系统之间的文件和打印机等资源的共享,我们今天来介绍一下samba服务。他可以解决不同系统平台之间的共享问题。 + +Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服务器及客户端程序构成,也是一个C/S软件。 + +``` + SMB(Server Messages Block,信息服务块)是一种在局域网上共享文件和打印机的一种通信协议,它为局域网内的不同计算机之间提供文件及打印机等资源的共享服务。SMB协议是客户机/服务器型协议,客户机通过该协议可以访问服务器上的共享文件系统、打印机及其他 +``` + +### 应用场景 + +**文件与打印机共享:** samba的主要功能,samba进程实现资源共享,将文件和打印机甚至是设备(如:CDROM)发布到网络中,以供用户访问 + +**身份验证和权限验证:** 对用户身份进行验证及权限设置,通过加密的方式保护共享文件和打印机 + +**名称解析:** 通过nmbd服务实现名称解析,将NetBIOS名称解析为IP地址 + +**浏览服务:** 在局域中,samba可以成为本地主浏览器,保存可用 + +资源列表,当用户访问时,会提供浏览列表 + +### SAMBA与NetBIOS + +samba是构建在NetBIOS这个协议之上的,而NetBIOS最早是从IBM诞生的,目的是让局域网内的计算机能够进行网络连接,由于不是针对于大型网络,所以NetBIOS是无法跨路由的。而windows操作系统也支持这个协议,所以在Linux主机上使用SAMBA部署的共享服务是可以使用windows主机访问的。那么SAMBA是不是就不能跨路由提供服务了呢?并不是,我们可以通过一个叫NetBIOS over TCP/IP的技术实现跨路由的SAMBA服务,但是目前SAMBA还是在局域网用的较多 + +### SAMBA的相关守护进程 + +**nmbd**:使用UDP的137、138来提供名称解析服务(NetBIOS) + +**smbd**:管理共享和数据传输,使用的端为TCP的139、445 + +### SAMBA的工作流程 + +1、协议协商 + +![image20200306095957499.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603932158638.png) + +客户端在访问服务器时,发送negprot请求,告知服务器自己所支持的SMB类型,samba服务器根据客户端的情况,选择最优的SMB类型并作出回应 + +2、建立连接 + +![image20200306100342210.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603932179228.png) +当SMB类型确认后,客户端会发送session setup指令数据包,提交账号和密码,请求与samba服务器建立连接,如果客户端通过身份验证,服务器会作出回应,并为用户分配一个唯一的UID,在客户端与服务器通信时使用。 + +3、访问共享资源 + +![image20200306101103005.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603932192673.png) + +当客户端需要访问共享资源时,会发送tree connect数据包,告知服务器需要访问的共享资源的名称,如果设置允许,samba服务器会为每个客户端与共享资源连接分配一个TID(线程标识符),客户端就可以访问相应的共享资源 + +4、断开连接 + +![image20200306101521438.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603932207260.png) + +共享使用完毕,客户端向服务器发送tree disconnect报文关闭对共享的访问,与服务器断开连接 + +### 相关软件包 + +samba 主程序包,服务端需要 + +samba-client 客户端工具包 + +samba-common 通用工具和库文件,客户端服务器端都需要安装 + +### 相关文件 + +- /etc/samba/smb.conf 主配置文件 +- /etc/samba/smb.conf.example 模板文件 +- /var/log/samba/log.nmbd nmbd进程的解析信息 +- /var/log/samba/log.smbd 记录用户的访问记录、服务器的问题 + +## 二、samba安装部署 + +a、安装软件包 + +``` +[root@node1 ~]# dnf install samba samba-client -y +``` + +b、设置服务开机启动 + +``` +[root@node1 ~]# systemctl enable nmb.service smb.service +Created symlink /etc/systemd/system/multi-user.target.wants/nmb.service → /usr/lib/systemd/system/nmb.service. +Created symlink /etc/systemd/system/multi-user.target.wants/smb.service → /usr/lib/systemd/system/smb.service. +``` + +c、开启服务 + +``` +[root@node1 ~]# systemctl start nmb smb +``` + +## 三、samba配置文件详解 + +主配文件路径: /etc/samba/smb.conf + +模板文件:/etc/samba/smb.conf.example + +``` +[root@baism ~]# cat smb.conf.example +# This is the main Samba configuration file. For detailed information about the +# options listed here, refer to the smb.conf(5) manual page. Samba has a huge +# number of configurable options, most of which are not shown in this example. +# +# The Samba Wiki contains a lot of step-by-step guides installing, configuring, +# and using Samba: +# https://wiki.samba.org/index.php/User_Documentation +# +# In this file, lines starting with a semicolon (;) or a hash (#) are +# comments and are ignored. This file uses hashes to denote commentary and +# semicolons for parts of the file you may wish to configure. +# +# NOTE: Run the "testparm" command after modifying this file to check for basic +# syntax errors. +# +#--------------- +# +SAMBA selinux相关设置,如果你开启了selinux,请注意下面的说明 +# +# +#Security-Enhanced Linux (SELinux) Notes: +# +# Turn the samba_domain_controller Boolean on to allow a Samba PDC to use the +# useradd and groupadd family of binaries. Run the following command as the +# root user to turn this Boolean on: +如果你在域环境中使用samba那么请设置下面的bool值 +# setsebool -P samba_domain_controller on +# +# Turn the samba_enable_home_dirs Boolean on if you want to share home +# directories via Samba. Run the following command as the root user to turn this +# Boolean on: +# +假如希望通过samba共享用户家目录请设置下面的bool值 +# setsebool -P samba_enable_home_dirs on +# +# If you create a new directory, such as a new top-level directory, label it +# with samba_share_t so that SELinux allows Samba to read and write to it. Do +# not label system directories, such as /etc/ and /home/, with samba_share_t, as +# such directories should already have an SELinux label. +# +加入你想将目录通过samba共享,请确认其目录标签为sambe_share_t +# Run the "ls -ldZ /path/to/directory" command to view the current SELinux +# label for a given directory. +# +# Set SELinux labels only on files and directories you have created. Use the +# chcon command to temporarily change a label: +标签设置方法 +# chcon -t samba_share_t /path/to/directory +# +# Changes made via chcon are lost when the file system is relabeled or commands +# such as restorecon are run. +# +# Use the samba_export_all_ro or samba_export_all_rw Boolean to share system +# directories. To share such directories and only allow read-only permissions: +对共享目录的权限的bool设置,只读或读写 +# setsebool -P samba_export_all_ro on +# To share such directories and allow read and write permissions: +# setsebool -P samba_export_all_rw on +# +# To run scripts (preexec/root prexec/print command/...), copy them to the +# /var/lib/samba/scripts/ directory so that SELinux will allow smbd to run them. +# Note that if you move the scripts to /var/lib/samba/scripts/, they retain +# their existing SELinux labels, which may be labels that SELinux does not allow +# smbd to run. Copying the scripts will result in the correct SELinux labels. +# Run the "restorecon -R -v /var/lib/samba/scripts" command as the root user to +# apply the correct SELinux labels to these files. +# +#-------------- +# +#======================= Global Settings ===================================== +全局设置,对整个服务都生效 +[global] + + +网络设置 +# ----------------------- Network-Related Options ------------------------- +# +# workgroup = the Windows NT domain name or workgroup name, for example, MYGROUP. +# +# server string = the equivalent of the Windows NT Description field. +# +# netbios name = used to specify a server name that is not tied to the hostname, +# maximum is 15 characters. +# +# interfaces = used to configure Samba to listen on multiple network interfaces. +# If you have multiple interfaces, you can use the "interfaces =" option to +# configure which of those interfaces Samba listens on. Never omit the localhost +# interface (lo). +# +# hosts allow = the hosts allowed to connect. This option can also be used on a +# per-share basis. +# +# hosts deny = the hosts not allowed to connect. This option can also be used on +# a per-share basis. +# +定义计算机的工作组,如果希望和windows共享,可以设置为workgroup,这样就可以在windows的网上邻居中找到linux计算机 + workgroup = MYGROUP +对samba服务器的描述信息 + server string = Samba Server Version %v +设置netbios计算机名称 +; netbios name = MYSERVER + +samba使用本机的那块网卡 +; interfaces = lo eth0 192.168.12.2/24 192.168.13.2/24 +允许那个网段访问samba服务器共享,还可以使用“hosts deny”设置禁止的网段,“hosts allow”的优先级高,表现形式可以是具体的IP地址和域名,还可以是*、?、local、all,也可以使用EXCEPT排除 +如:hosts allow = 192.168.0. EXCEPT 192.168.0.100 +; hosts allow = 127. 192.168.12. 192.168.13. + +# +日志选项 +# --------------------------- Logging Options ----------------------------- +# +# log file = specify where log files are written to and how they are split. +# +# max log size = specify the maximum size log files are allowed to reach. Log +# files are rotated when they reach the size specified with "max log size". +# +samba日志文件路径,%m表示客户端的NetBios名称,还有其它的变量,可以使用man smb.conf通过man手册去查看 + # log files split per-machine: + log file = /var/log/samba/log.%m +日志文件大小,0为不限制,注意不建议这样设置 + # maximum size of 50KB per log file, then rotate: + max log size = 50 + +独立服务选项 +# ----------------------- Standalone Server Options ------------------------ +# +# security = the mode Samba runs in. This can be set to user, share +# (deprecated), or server (deprecated). +# +# passdb backend = the backend used to store user information in. New +# installations should use either tdbsam or ldapsam. No additional configuration +# is required for tdbsam. The "smbpasswd" utility is available for backwards +# compatibility. +# +samba安全级别 +share: 不需要账号密码,公开共享 +user: 需要提供samba账号密码才能访问共享,私密共享 +server:依靠其他Windows NT/2000或Samba Server来验证用户的账号和密码,是一种代理验证。此种安全模式下,系统管理员可以把所有的Windows用户和口令集中到一个NT系统上,>使用Windows NT进行Samba认证, 远程服务器可以自动认证全部用户和口令,如果认证失败,Samba会使用user级别。 +domain:如果samba服务器加入到域环境中,验证工作由域控制器完成。 +ads:具备domain级别的所有功能,并且具备域控制器功能 +auto:安全级别会受“server role”字段的值影响,“server role”字段默认值为auto(用户通过验证后可以使用),其余的参数决定了samba服务器加入到window域环境中的角色是成员还是域控制器 + + +一般情况下我们使用share和user的比较多,除非公司有完整的域环境 + security = user + +用户及密码的管理方式,有三种smbpasswd、tdbsam、ldapsam +smbpasswd:使用samba自带的工具smbpasswd命令为用户(真实用户或虚拟用户)设置密码,密码默认存放在/var/lib/samba/private/smbpasswd文件中,也可以使用“ +smb passwd file = /etc/samba/smbpasswd"指定密码文件位置 + smbpasswd -a username 添加一个用户/修改用户密码 + smbpasswd -d username 禁用用户 + smbpasswd -e username 启用用户 + smbpasswd -x username 删除用户 +tdbsam:在/var/lib/samba/private建立一个passdb.tdb存放密码,也可以使用“smb passwd file”字段指定存放位置,除了可以使用smbpasswd命令管理用户之外,还可以使用pdbedit命令指定,而且只能是系统用户(真实用户),用户的建立可以使用mksmbpasswd命令建立一个smbpasswd文件,再使用pdbedit将文件里的用户导入数据库 +cat /etc/passwd | mksmbpasswd > /etc/samba/smbpasswd +pdbedit -i smbpasswd:/etc/samba/smbpasswd + +额外的用法 +pdbedit -a username:新建Samba账户。 +pdbedit -x username:删除Samba账户。 +pdbedit -L:列出Samba用户列表,读取passdb.tdb数据库文件。 +pdbedit -Lv:列出Samba用户列表的详细信息。 +pdbedit -c “[D]” –u username:禁用该Samba用户的账号。 +pdbedit -c “[]” –u username:恢复该Samba用户的账号。 + + +ldapsam:基于LDAP的认证方式,首先要有LDAP服务,并且加入到LDAP中 + + passdb backend = tdbsam + + +域成员选项 +# ----------------------- Domain Members Options ------------------------ +# +# security = must be set to domain or ads. +# +# passdb backend = the backend used to store user information in. New +# installations should use either tdbsam or ldapsam. No additional configuration +# is required for tdbsam. The "smbpasswd" utility is available for backwards +# compatibility. +# +# realm = only use the realm option when the "security = ads" option is set. +# The realm option specifies the Active Directory realm the host is a part of. +# +# password server = only use this option when the "security = server" +# option is set, or if you cannot use DNS to locate a Domain Controller. The +# argument list can include My_PDC_Name, [My_BDC_Name], and [My_Next_BDC_Name]: +# +# password server = My_PDC_Name [My_BDC_Name] [My_Next_BDC_Name] +# +# Use "password server = *" to automatically locate Domain Controllers. +#设置域共享 +; security = domain +; passdb backend = tdbsam +#定义域名称 +; realm = MY_REALM +#域验证服务器 +; password server = + + + +#域控选项 +# ----------------------- Domain Controller Options ------------------------ +# +# security = must be set to user for domain controllers. +# +# passdb backend = the backend used to store user information in. New +# installations should use either tdbsam or ldapsam. No additional configuration +# is required for tdbsam. The "smbpasswd" utility is available for backwards +# compatibility. +# +# domain master = specifies Samba to be the Domain Master Browser, allowing +# Samba to collate browse lists between subnets. Do not use the "domain master" +# option if you already have a Windows NT domain controller performing this task. +# +# domain logons = allows Samba to provide a network logon service for Windows +# workstations. +# +# logon script = specifies a script to run at login time on the client. These +# scripts must be provided in a share named NETLOGON. +# +# logon path = specifies (with a UNC path) where user profiles are stored. +# +# +; security = user +; passdb backend = tdbsam + +让samba成为域的主浏览器 +; domain master = yes +允许samba为windows提供网络登录服务 +; domain logons = yes + + + + + + + # the following login script name is determined by the machine name + # (%m): +定义客户端在登录时要执行的脚本 +; logon script = %m.bat + # the following login script name is determined by the UNIX user used: +; logon script = %u.bat +定义记录用户个性化信息的文件存放的位置,空值表示禁用个性化设置 +; logon path = \\%L\Profiles\%u + # use an empty path to disable profile support: +; logon path = + + # various scripts can be used on a domain controller or a stand-alone + # machine to add or delete corresponding UNIX accounts: +定义做为域控时,针对于用户和主机的添加、删除时需要执行的具体操作 +; add user script = /usr/sbin/useradd "%u" -n -g users +; add group script = /usr/sbin/groupadd "%g" +; add machine script = /usr/sbin/useradd -n -c "Workstation (%u)" -M -d /nohome -s /bin/false "%u" +; delete user script = /usr/sbin/userdel "%u" +; delete user from group script = /usr/sbin/userdel "%u" "%g" +; delete group script = /usr/sbin/groupdel "%g" + + + + + + + +这些设置选项主要用于SMB网络中进行浏览时,设置samba服务器的行为。缺省情况不让 samba服务器参加broswser的推举过程,为了使得samba服务器能成为browser,就需要设定local master =yes。然后samba服务就可以根据os level设置的权重进行推举,缺省的os level为0,这个权重不会赢得推举。但可以取消注释,将os level设置为33,这将在与所有Windows计算机(包括Windows NT)的推举竞赛中获得胜利,因为NT server的权重为32。设置比33更高的权重,只是在不同的samba 服务器之间进行选择时才有意义。 +# +preferred master 可以设置自己优先成为浏览服务器候选人 +# +# ----------------------- Browser Control Options ---------------------------- +# +# local master = when set to no, Samba does not become the master browser on +# your network. When set to yes, normal election rules apply. +# +# os level = determines the precedence the server has in master browser +# elections. The default value should be reasonable. +# +# preferred master = when set to yes, Samba forces a local browser election at +# start up (and gives itself a slightly higher chance of winning the election). +# +; local master = no +; os level = 33 +; preferred master = yes + +# +# +wins服务,如果网络中配置了wins服务器可以在此设置wins相关项 +#----------------------------- Name Resolution ------------------------------- +# +# This section details the support for the Windows Internet Name Service (WINS). +# +# Note: Samba can be either a WINS server or a WINS client, but not both. +# +# wins support = when set to yes, the NMBD component of Samba enables its WINS +# server. +# +# wins server = tells the NMBD component of Samba to be a WINS client. +# +# wins proxy = when set to yes, Samba answers name resolution queries on behalf +# of a non WINS capable client. For this to work, there must be at least one +# WINS server on the network. The default is no. +# +# dns proxy = when set to yes, Samba attempts to resolve NetBIOS names via DNS +# nslookups. +设置nmb进程支持wins服务 +; wins support = yes +设置wins服务器ip +; wins server = w.x.y.z +设置wins代理IP +; wins proxy = yes +设置Samba服务器是否在无法联系WINS服务器时通过DNS去解析主机的NetBIOS名 +; dns proxy = yes + + +该部分包括Samba服务器打印机相关设置 +# --------------------------- Printing Options ----------------------------- +# +# The options in this section allow you to configure a non-default printing +# system. +# +# load printers = when set you yes, the list of printers is automatically +# loaded, rather than setting them up individually. +# +# cups options = allows you to pass options to the CUPS library. Setting this +# option to raw, for example, allows you to use drivers on your Windows clients. +# +# printcap name = used to specify an alternative printcap file. +# +是否启用共享打印机 + load printers = yes + cups options = raw +打印机配置文件 +; printcap name = /etc/printcap + # obtain a list of printers automatically on UNIX System V systems: +; printcap name = lpstat +打印机的系统类型,现在支持的打印系统有:bsd, sysv, plp, lprng, aix, hpux, qnx,cups +; printing = cups + + + + +该部分包括Samba服务器如何保留从Windows客户端复制或移动到Samba服务器共享目录文件的Windows文件属性的相关配置. +# --------------------------- File System Options --------------------------- +# +# The options in this section can be un-commented if the file system supports +# extended attributes, and those attributes are enabled (usually via the +# "user_xattr" mount option). These options allow the administrator to specify +# that DOS attributes are stored in extended attributes and also make sure that +# Samba does not change the permission bits. +# +# Note: These options can be used on a per-share basis. Setting them globally +# (in the [global] section) makes them the default for all shares. + +当Windows客户端将文件复制或移动到Samba服务器共享目录时,是否保留文件在Windows中的存档属性。默认no。 +; map archive = no +当Windows客户端将文件复制或移动到Samba服务器共享目录时,是否保留文件在Windows中的隐藏属性。默认no。 +; map hidden = no +当Windows客户端将文件复制或移动到Samba服务器共享目录时,是否保留文件在Windows中的只读属性。默认为no。 +; map read only = no +当Windows客户端将文件复制或移动到Samba服务器共享目录时,是否保留文件在Windows中的系统文件属性。默认为no。 +; map system = no +当Windows客户端将文件复制或移动到Samba服务器共享目录时,是否保留文件在Windows中的相关属性(只读、系统、隐藏、存档属性)。默认为yes。 +; store dos attributes = yes + + + +共享设置 +#============================ Share Definitions ============================== +#用户家目录共享 +#共享名称 +[homes] +描述 + comment = Home Directories +是否为隐藏共享 + browseable = no +是否允许写入 + writable = yes +允许访问该共享资源的smb用户,@组 +; valid users = %S +; valid users = MYDOMAIN\%S + +打印机共享 +[printers] +描述 + comment = All Printers +路径 + path = /var/spool/samba +是否可浏览,no类似隐藏共享 + browseable = no +是否支持guest访问,和public指令类似 + guest ok = no +是否可写 + writable = no +是否允许打印 + printable = yes + + + + +# Un-comment the following and create the netlogon directory for Domain Logons: +; [netlogon] +; comment = Network Logon Service +; path = /var/lib/samba/netlogon +; guest ok = yes +; writable = no +; share modes = no + +# Un-comment the following to provide a specific roaming profile share. +# The default is to use the user's home directory: +; [Profiles] +; path = /var/lib/samba/profiles +; browseable = no +; guest ok = yes + +# A publicly accessible directory that is read only, except for users in the +# "staff" group (which have write permissions): +; [public] +; comment = Public Stuff +; path = /home/samba +; public = yes +; writable = no +; printable = no +定义允许哪些smb用户写入,+和@表示一个组 +; write list = +staff +``` + +## 四、samba文件共享案例 + +拓扑图 + +![image20200306155842923.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603932305163.png) + +环境:两台安装CentOS8的主机,关闭selinux,关闭防火墙 + +**案例需求:** + +1)、新建文件夹/common + +2)、在server上配置SMB服务 + +3)、您的 SMB 服务器必须是 workgroup 工作组的一个成员 + +4)、共享 /common 目录 共享名必须为 common + +5)、只有 192.168.11.0网段内的客户端可以访问 common 共享 + +6)、common 必须是可以浏览的 + +7)、用户hello 必须能够读取共享中的内容,如果需要的话,验证的密码是 hello + +8)、用户 test 必须能够拥有写权限,如果需要的话,验证的密码是 test + +a、创建共享目录 + +``` +[root@node1 ~]# mkdir /common +``` + +b、设置共享目录权限,因为默认权限是755除了管理员外,其他人只能读不能写,本实验中要求test能写,所以其他人加写权限。在samba中共享目录的权限除了看samba服务的设置之外,还要看系统的权限设置,系统针对于权限不一致的处理方式是取交集。所以各位在建立共享时一定要注意权限方面的问题 + +``` +[root@node1 ~]# chmod 757 /common +[root@node1 ~]# cd /etc/samba/ +[root@node1 ~]# vim /etc/samba/smb.conf +# read the smb.conf manpage. +# Run 'testparm' to verify the config is correct after +# you modified it. + +[global] + #设置工作组为workgroup + workgroup = workgroup + security = user + + passdb backend = tdbsam + + printing = cups + printcap name = cups + load printers = yes + cups options = raw + +[homes] + comment = Home Directories + valid users = %S, %D%w%S + browseable = no + read only = no + inherit acls = yes + +[printers] + comment = All Printers + path = /var/tmp + printable = yes + create mask = 0600 + browseable = no + +#共享设置,参考配置文件详解理解以下选项 +[common] + comment = samba file share test + path = /common #绝对路径 + browseable = yes + hosts allow = 192.168.11.0/255.255.255.0 + valid users = hello,test + writable = no + write list = test + public = no +``` + +c、重启服务生效 + +``` +[root@node1 ~] systemctl restart smb nmb +``` + +d、创建samba用户 +使用useradd命令创建hello和test用户并设置密码 + +``` +[root@node1 ~]# smbpasswd -a hello +New SMB password: +Retype new SMB password: +[root@node1 ~]# smbpasswd -a test +New SMB password: +Retype new SMB password: +``` + +**共享指令拓展** + +``` +valid users 指定能够进入此资源的特定用户和组 +invalid users 指定不能够使用该共享资源的用户和组 +read list 指定只能读取该共享资源的用户和组。 +write list 指定能读取和写该共享资源的用户和组。 +admin list 指定能管理该共享资源(包括读写和权限赋予等)的用户和组。 +public 指明该共享资源是否能给游客帐号访问,这个开关有时候也叫guest ok,所以有的配置文件中出现guest ok = yes其实和public = yes是一样的。 +hide dot files 指明是不是像unix那样隐藏以“.”号开头的文件。 +create mask 指明新建立的文件的属性,一般是0755。 +directory mode 指明新建立的目录的属性,一般是0755。 +sync always 指明对该共享资源进行写操作后是否进行同步操作。 +preserve case 指明保持大小写。yes/no +case sensitive 指明是否对大小写敏感,一般选no,不然可能引起错误。 +default case 指明缺省的文件名是全部大写还是小写。upper/lower +force user 强制把建立文件的属主是谁。如果我有一个目录,让来宾用户可以写,那么来宾用户就可以删除,如果我用 force user=王老师 强制建立文件的属主是 王老师 ,同时限制create mask=0755,这样来宾用户就不能删除了 +wide links 指明是否允许共享外符号连接,比如共享资源里面有个连接指向非共享资源里面的文件或者目录,如果设置wide links = no将使该连接不可用。 +max connections = n 设定同时连接数是n。 +delete readonly 指明能否删除共享资源里面已经被定义为只读的文件 +``` + +## 五、共享案例-客户端访问共享 + +创建好了共享了,如果用户希望访问samba共享,windows用户通过网上邻居或者在运行中输出[\IP\共享名]的方式访问samba共享,也可以通过网络映射的方式将共享挂载的本地。linux或者UNIX用户则可以使用samba提供的客户端smbclient或者通过CIFS协议将共享挂载到本地。 + +**smbclient 客户端命令** + +``` +smbclient - 类似FTP操作方式的访问SMB/CIFS服务器资源的客户端 +常用命令选项 +-L 此选项允许你查看服务器上可以获得的服务资源 +-U|--user=username[%password] 这个参数指定程序联接时使用的用户名或者用户名和密码,如果没指定%password,将提示用户输入。 +-W|--workgroup=domain 设置用户名的SMB域。这个选项越过了smb.conf配置文件中的默认域。 +-N 如果指定了这个选项,就会省略通常的口令提示。当访问无需口令的服务资源时它很有用。 +``` + +**任务需求** +linux下访问samba共享 + +a、客户端信息 + +``` +[root@slave ~]# ifconfig ens33 +ens33: flags=4163 mtu 1500 + inet 192.168.11.116 netmask 255.255.255.0 broadcast 192.168.11.255 + inet6 fe80::20c:29ff:fe8e:ea58 prefixlen 64 scopeid 0x20 + ether 00:0c:29:8e:ea:58 txqueuelen 1000 (Ethernet) + RX packets 5166 bytes 3736352 (3.5 MiB) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 2311 bytes 297960 (290.9 KiB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 +``` + +b、使用smbclient访问共享,验证第四点教学案例设置 + +``` +测试用户 hello +[root@manage01 ~]# smbclient //192.168.11.16/common -U hello +Enter SAMBA\hello's password: +或 +[root@manage01 ~]# smbclient //192.168.11.16/common -U hello%hello +Try "help" to get a list of possible commands. +smb: \> ls +smb: \> lcd /etc/ +smb: \> put passwd 写入失败 +NT_STATUS_ACCESS_DENIED opening remote file \passwd + + + +测试用户test +[root@manage01 ~]# smbclient //192.168.11.16/common -U test%test +Try "help" to get a list of possible commands. +smb: \> lcd /etc/ +smb: \> put passwd +putting file passwd as \passwd (728.2 kb/s) (average 728.2 kb/s) 可以上传 +smb: \> exit + + +samba命令类似于ftp文本界面命令,参考之前的vsftp使用。 +``` + +c、linux挂载共享 + +``` +[root@manage01 ~]# mkdir /opt/samba_share +[root@manage01 ~]# mount -o username=hello,password=hello -t cifs //192.168.11.16/common /opt/samba_share +[root@manage01 ~]# cd /opt/samba_share/ +[root@manage01 ~]# mount +...... +//192.168.11.16/common on /opt/samba_share type cifs (rw,relatime,vers=default,cache=strict,username=hello,domain=,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.11.16,file_mode=0755,dir_mode=0755,soft,nounix,serverino,mapposix,rsize=1048576,wsize=1048576,echo_interval=60,actimeo=1) + +[root@manage01 ~]# ls /mnt/samba_share/ +initial-setup-ks.cfg passwd +``` + +d、windows访问共享 + +打开开始菜单如下输入 + +![image20200306180124957.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603932645309.png) + +回车以后出现下图,输入账号密码 + +![image20200306180151262.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603932658185.png) + +点击确定按钮 + +![image20200306180244476.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603932672237.png) + +## 六、用户账号映射与访问控制 + +**账号映射** + +samba的用户帐号信息是保存在smbpasswd文件中,而 且可以访问samba服务器的帐号也必须对应一个同名的系 统帐号。基于这一点,所以,对于一些hacker来说,只要 知道samba服务器samba帐号,就等于是知道了Linux系 统帐号,只要crack其samba帐号密码加以利用就可以攻 击samba服务器。所以我们要使用用户帐号映射这个功能 来解决这个问题 + +- 用户帐号映射这个功能需要建立一个帐号映射关系表,里 面记录了samba帐号和虚拟帐号的对应关系,客户端访问 samba服务器时就使用虚拟来登录。 +- 编辑主配置文件/etc/samba/smb.conf在global下添加一行字段username map = /etc/samba/smbusers 开启用户帐号映射功能。 + +![image20200306183028366.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603932687479.png) + +编辑/etc/samba/smbusers + +smbusers文件保存帐号映射关系,其有固 定格式: + +samba帐号 = 虚拟帐号(映射帐号) + +![image20200306183052382.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603932698858.png) + +重新启动服务 + +**访问控制** + +对于samba服务器的安全性,我们已经说过可以使用valid users字段去实现用户访问控制,但是如果企业庞大,存在大量用户的话,这种方法操作起来就显得比较麻烦比如samba服务器共享出一个目录来访问,但是要禁止某个IP子网或某个域的客户端访问此资源,这样情况使用valid users字段就无法实现客户端访问控制。使用hosts allow和hosts deny两个字段来实现该功能。而用好这两个字段关键在于熟悉和清楚它们的使用方法和作用范围 + +1)hosts allow 和 hosts deny 字段的使用 + +``` + hosts allow 字段定义允许访问的客户端 + + hosts deny 字段定义禁止访问的客户端 +``` + +2)使用IP地址进行限制 + +比如公司内部samba服务器上共享了一个目录sales,这个目录是存放销售部的共享目录,公司规定192.168.0.0/24这个网段的IP地址禁止访问此sales共享目录,但是其中192.168.0.24这个IP地址可以访问。 + +``` +hosts deny = 192.168.0. 172.16. +hosts allow = 192.168.0.24 +hosts deny = 192.168.0. 表示禁止所有来自192.168.0.0/24网段的IP地址访问 +hosts allow = 192.168.0.24 表示允许192.168.0.24这个IP地址访问 +当host deny和hosts allow字段同时出现并定义内容相互冲突时,hosts allow优先。现在设置的意思就是禁止C类地址192.168.0.0/24网段主机访问,但是允许192.168.0.24主机访问。如果后面的内容有多个时,需要用空格隔开,也可以是域名,如:.hello.com +``` + +如果我们规定所有人不能访问security目录,只允许192.168.0.0网段的IP地址可以访问,但是192.168.0.10及192.168.0.78的主机是要禁止访问。我们可以使用hosts deny禁止所有用户访问,再设置hosts allow允许192.168.0.0网段主机,但当hosts deny和hosts allow同时出现而且冲突的时候,hosts allow生效,如果这样,那么允许192.168.0.0网段的IP地址可以访问,但192.168.0.100及192.168.0.78的主机禁止访问就无法生效了 + +``` +hosts allow = 192.168.0. EXCEPT 192.168.0.100 192.168.0.78 + +表示允许192.168.0.0网段IP地址访问,但是192.168.0.100和192.168.0.78除外 +``` + +## 七、SAMBA的排错 + +**Linux 服务一般排错方法** +1、错误信息 + +一般仔细看下显示的错误信息,根据错误提示一般就可以判断问题出在 什么地方。 + +2、配置文件 + +第2个我们可以查配置文件,有时可能误操作导致配置失误,服务无法正 常运行,我们可以通过检查配置文件来确认问题。现在很多服务的软件 包有自带配置文件检查工具,我们可以通过这些工具对配置文件进行检 查 + +3、日志文件 +如果服务出现问题,我们还可以使用 tail -f命令来动态监控日志文件 + +**Samba排错** + +1、使用testparm命令检查,软件包有自带的配置文件检查工具,我们可以使testparm 命令检测smb.conf文件的语法,如果报错,说明smb.conf文 件设置有错误,这样我们可以根据提示信息来修改主配置文 件和独立配置文件。 + +``` +[root@node1 ~]# testparm /etc/samba/smb.conf +Load smb config files from /etc/samba/smb.conf +rlimit_max: increasing rlimit_max (1024) to minimum Windows limit (16384) +Processing section "[homes]" +Processing section "[printers]" +Processing section "[common]" +Loaded services file OK. +Server role: ROLE_STANDALONE +``` + +2、使用ping命令测试 + +samba服务器主配置文件排除错误后重启 smb服务,如果客户端仍然 无法连 接samba服务器,我们在客户端可以使用 ping命令进行测试,这个我们微软的系统中排障一样,根据出现的不同情况可以进行分析。 + +(1)如果没有收到任何提示,说明客户端 TCP/IP协议安装有问题,需要重 新安装客户端 TCP/IP 协议,然后重新测试。 + +(2)如果提示“host not found ”则检查客户端DNS或者/etc/hosts文件有没正确设置,确保客户端能够使用名称访问 samba服务器。 + +(3)无法 ping 通还可能是防火墙设置问题,需要重新设置防火墙的 规则,开启samba 与外界联系的端口。 +(4)当然还有一种低级的情况,那就是由于主机名输入错误导致不 能ping 通 + +3、使用smbclient命令进行测试 + +如果客户端与samba服务器可以ping通,说明客户端与服务器间的连接没有问题,如果还是不能访问samba共享资源,可以执行smbclient命令进一步测试服务器端的配置。 如果测试samba服务器正常,并且输入了正确的帐号和密码,那么执行smbclient命令就可以获得共享列表。 + +``` +smbclient -L 192.168.0.188 -U joy%123 +``` + +如果我们看到了错误信息提示“tree connect failed”则说明可以在smb.conf文件中设置了host deny字段拒绝了客户端的IP地址或域 名,我们可以修改smb.conf配置文件允许客户端访问就可以了 + +如果返回信息是“connection refused ”提示拒绝连接则说明是samba服务器smbd进程可以没有被开启,我们必须确保smbd和 nmbd进程处于开启状态,并使用netstat命令检查netbios所使用的139端口是否处于监听状态。 + +如果提示“session setup failed ”连接建立失败则说明服务器拒绝了连接请求,这是因为输入的用户名和密码错误引起 + +有时也会收到比如“Your server software is being unfriendly ”错误信息,提示服务器软 件存在问题,这个故障一般是因为配置 smbd时使用了错误的参数或者启用 smbd时 遇到的类似严重破坏错误,我们可以使用 testparm来检查相应的配置文件并同时检查 相关日志文件。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\225\260\346\215\256\345\256\211\345\205\250\344\271\213\344\274\201\344\270\232\345\255\230\345\202\250/\345\210\206\345\270\203\345\274\217\345\255\230\345\202\250-GlusterFS.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\225\260\346\215\256\345\256\211\345\205\250\344\271\213\344\274\201\344\270\232\345\255\230\345\202\250/\345\210\206\345\270\203\345\274\217\345\255\230\345\202\250-GlusterFS.md" new file mode 100644 index 0000000..8439e81 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\225\260\346\215\256\345\256\211\345\205\250\344\271\213\344\274\201\344\270\232\345\255\230\345\202\250/\345\210\206\345\270\203\345\274\217\345\255\230\345\202\250-GlusterFS.md" @@ -0,0 +1,810 @@ +## 一、分布式存储介绍 + +我们知道NAS是远程通过网络共享目录, SAN是远程通过网络共享块设备。那么分布式存储你可以看作拥有多台存储服务器连接起来的存储输出端。把这多台存储服务器的存储合起来做成一个整体再通过网络进行远程共享,共享的方式有目录(文件存储),块设备(块存储),对象网关或者说一个程序接口(对象存储)。 + +常见的分布式存储开源软件有:GlusterFS,Ceph,HDFS,MooseFS,FastDFS等。 + +分布式存储一般都有以下几个优点: + +1. 扩容方便,轻松达到PB级别或以上 +2. 提升读写性能或数据高可用 +3. 避免单个节点故障导致整个架构问题 +4. 价格相对便宜,大量的廉价设备就可以组成,比光纤SAN这种便宜很多 + +## 二、GlusterFS介绍 + +glusterfs是一个免费,开源的分布式文件系统(它属于**文件存储类型**)。主要由 Z RESEARCH 公司负责开发。GlusterFS 具有强大的横向扩展能力,通过扩展能够支持数PB存储容量和处理数千客户端。GlusterFS 可以将物理分布的存储资源聚集在一起,使用单一全局命名空间来管理数据,可为各种不同的数据负载提供优异的性能。 + +GlusterFS 主要由存储服务器(Brick Server)、客户端以及 NFS/Samba 存储网关组成。在GlusterFS 架构中没有元数据服务器组件,这是其最大的设计这点,对于提升整个系统的性能、可靠性和稳定性都有着决定性的意义。 + +GlusterFS 支持 TCP/IP 和 高速网络互联。客户端可通过原生 GlusterFS 协议访问数据,其他没有运行 GlusterFS 客户端的终端可通过 NFS/CIFS 标准协议通过存储网关访问数据。存储服务器主要提供基本的数据存储功能,客户端弥补了没有元数据服务器的问题,承担了更多的功能,包括数据卷管理、I/O 调度、文件定位、数据缓存等功能,利用 FUSE(File system in User Space)模块将 GlusterFS 挂载到本地文件系统之上,来访问系统数据。 + +## 三、raid级别回顾 + +raid级别有很多种,下面主要介绍常用的几种: + +**raid0** 读写性能佳,坏了其中一块,数据挂掉,可靠性低(stripe条带化),磁盘利用率100% + +![raid0.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603943799737.png) + +**raid1** 镜像备份(mirror),同一份数据完整的保存在多个磁盘上,写的性能不佳,可靠性高,读的性能还行,磁盘利用率50% + +![raid1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603943809143.png) + +**raid10** 先做raid 1 再做raid 0 + +![raid10.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603943824194.png) + +**raid5** 由多块磁盘做raid 5,磁盘利用率为n-1/n, 其中一块放校验数据,允许坏一块盘,数据可以利用校验值来恢复 + +![raid5.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603943841660.png) + +**raid6** 在raid5的基础上再加一块校验盘,进一步提高数据可靠性 + +![raid6.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603943857634.png) + +``` +注意:生产环境中最常用的为raid5和raid10 +``` + +## GlusterFS名词解释 + +- Brick: 最基本的存储单元,表示为trusted storage pool中输出的目录,供客户端挂载用,一般表示方式为“主机名:目录名” +- Volume: 一个卷。在逻辑上由N个bricks组成. +- FUSE: Unix-like OS上的可动态加载的模块,允许用户不用修改内核即可创建自己的文件系统。 + +## 四、GlusterFS卷类型 + +**基本卷** + +**distribute volume分布式卷 默认:** + +![image20200227101111403.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603943932241.png) + +说明:根据hash算法,将文件随机存储在一个的brick上,文件不能拆分。此时volume的容量是所有brick的和;方便扩展空间,但无冗余保护;由于使用本地文件系统进行存储(brick server 的本地文件系统),存取效率不高;受限于本地文件系统对单文件容量的限制,支持超大型文件系统有问题。 + +**stripe volume 条带卷:** + +![image20200227101206255.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603943950850.png) + +说明:每个文件被分片数据块,然后以round robin的方式将每个chunk存储到1个brick,相当于raid0;比如,对于一个文件,奇数行存储在第一个brick上,偶数行存储在第二个brick。单一超大容量文件可被分片,不受brick server本地文件系统的限制;分布式读写性能较高,但分片随机读写可能会导致硬盘iops较高;无冗余,1个server节点故障会导致所有数据丢失。 + +**replica volume 复制卷(类似Raid 1):** + +![image20200227101247582.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603943983306.png) + +说明:每个文件同步复制镜像到多个brick,相当于文件级raid1,一个是存储一个是备份;读性能提升,写性能下降;提升数据可靠性,但磁盘利用率低;如果两台存储服务器不同,就会出现木桶效应 + +**复合卷** + +**distribute replica volume 分布式复制卷:** + +![image20200227121736499.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603943999454.png) + +说明:是分布式卷与复制卷的组合,兼具两者的功能,若干brick组成1个复制卷,另外若干brick组成其他复制卷;单个文件在复制卷内数据保持副本,不同文件在不同复制卷之间进行哈希分布 + +**distribute stripe volume分布式条带卷:** + +![image20200227101726471.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603944017603.png) + +说明:分布式卷与条带卷的组合,兼具两者的功能,若干brick组成1个条带卷,另外若干brick组成其他条带卷;单个文件在条带卷内数据以条带的形式存储,不同文件在不同条带卷之间进行哈希分布; + +**striped replicated volume条带镜像卷:** + +![image20200227125132180.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603944030297.png) + +说明:条带与复制卷的组合,兼具两者的功能,若干brick组成1个复制卷,另外若干brick组成其他复制卷;单个文件以条带的形式存储在2个或多个复制集(replicated sets ),复制集内文件分片以副本的形式保存; + +**distribute stripe replica volume 混合卷:** 三种基本卷的复合卷,分布式卷,条带与复制卷的组合,兼具三者的功能 + +**dispersed volume:** 分散式(冗余式),例如,数据保存在10个brick中,每个brick有1T,10个brick中有3个是作为冗余brick,作为数据校验,不做存储。此时volume只有7T,volume中允许有3个brick损坏 + +## 五、glusterfs集群 + +目前为止stripe(条带)类型已经用的越来越少,我们以一个案例说明distribute(分布式),replica(复制),distribute replica(分布式复制),dispersed(冗余)四种常用的类型如何使用 + +### 学习案例 + +**案例需求:** 部署一个glusterfs存储集群 + +**集群部署:** 案例步骤 + +1. 部署集群 +2. 创建卷并启动 +3. 客户端连接挂载 + +#### 实验拓扑图 + +![GfusterFS集群.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/29/1603944160202.png) + +| 计算机名称 | IP地址 | 角色 | +| :--------: | :------------: | :----------: | +| manage01 | 192.168.98.200 | client | +| node1 | 192.168.98.201 | storage_node | +| node2 | 192.168.98.202 | storage_node | +| node3 | 192.168.98.203 | storage_node | +| node4 | 192.168.98.204 | storage_node | +| node5 | 192.168.98.205 | storage_node | + +#### 实验环境 + +- CentOS8系统 +- 关闭防火墙 +- 关闭selinux +- 网络连通 +- 时间同步 + +#### 实验步骤 + +**时间同步** + +``` +[root@manage01 ~]# vim /etc/chrony.conf +server 192.168.98.200 iburst +driftfile /var/lib/chrony/drift +makestep 1.0 3 +rtcsync +allow 192.168.98.0/24 +local stratum 10 +leapsectz right/UTC +logdir /var/log/chrony +bindaddress 192.168.98.200 +[root@manage01 ~]# systemctl restart chrony +server 192.168.98.200 iburst +[root@node1 ~]# systemctl restart chronyd.service +``` + +**gluster集群部署** + +1、安装软件[ 安装软件、启动服务] + +2、部署集群 + +**存储端设置** + +a、所有存储机器,设置Yum源,安装gluster + +``` +#官方源地址https://download.gluster.org/pub/gluster/glusterfs/LATEST/CentOS/glusterfs-rhel8.repo +[root@node2 ~]#vim /etc/yum.repos.d/glusterfs.repo +# Place this file in your /etc/yum.repos.d/ directory +[glusterfs-rhel8] +name=GlusterFS is a clustered file-system capable of scaling to several petabytes. +baseurl=https://download.gluster.org/pub/gluster/glusterfs/7/LATEST/RHEL/el-$releasever/$basearch/ +enabled=1 +skip_if_unavailable=1 +gpgcheck=1 +gpgkey=https://download.gluster.org/pub/gluster/glusterfs/7/rsa.pub + +[glusterfs-noarch-rhel8] +name=GlusterFS is a clustered file-system capable of scaling to several petabytes. +baseurl=https://download.gluster.org/pub/gluster/glusterfs/7/LATEST/RHEL/el-$releasever/noarch +enabled=1 +skip_if_unavailable=1 +gpgcheck=1 +gpgkey=https://download.gluster.org/pub/gluster/glusterfs/7/rsa.pub + +[glusterfs-source-rhel8] +name=GlusterFS is a clustered file-system capable of scaling to several petabytes. - Source +baseurl=https://download.gluster.org/pub/gluster/glusterfs/7/LATEST/RHEL/el-$releasever/SRPMS +enabled=0 +skip_if_unavailable=1 +gpgcheck=1 +gpgkey=https://download.gluster.org/pub/gluster/glusterfs/7/rsa.pub +[root@node1 yum.repos.d]# vim /etc/yum.repos.d/CentOS-PowerTools.repo +[PowerTools] +name=CentOS-$releasever - PowerTools +mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=PowerTools&infra=$infra +#baseurl=http://mirror.centos.org/$contentdir/$releasever/PowerTools/$basearch/os/ +gpgcheck=1 +enabled=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial +``` + +b、安装glusterfs软件包,并启动服务 + +``` +[root@node2 ~]# dnf install glusterfs-server +[root@node2 ~]# systemctl enable glusterd +[root@node2 ~]# systemctl start glusterd +``` + +**glusterfs集群组成** + +brick端:manager/node + +client端:挂载存储业务机器 + +``` +[root@node2 ~]# gluster peer help + +#将node节点加入集群 +[root@node2 ~]# gluster peer probe node1 +peer probe: success. + +#从集群中删除node +[root@node2 ~]# gluster peer detach node4 +All clients mounted through the peer which is getting detached need to be remounted using one of the other active peers in the trusted storage pool to ensure client gets notification on any changes done on the gluster configuration and if the same has been done do you want to proceed? (y/n) y +peer detach: success + +#查看集群信息 +[root@node2 ~]# gluster peer status +[root@node2 ~]# gluster pool list + + +[root@node2 ~]# gluster peer status +Number of Peers: 2 + +Hostname: node1 +Uuid: 809111f4-8a0e-40fb-af53-d2d8a56cd41e +State: Peer in Cluster (Connected) + +Hostname: 192.168.98.203 +Uuid: 7396a19d-a2a7-4b27-86d3-12c89ac4df39 +State: Peer in Cluster (Connected) + +或者 + + +[root@node2 ~]# gluster pool list +UUID Hostname State +809111f4-8a0e-40fb-af53-d2d8a56cd41e node1 Connected +7396a19d-a2a7-4b27-86d3-12c89ac4df39 192.168.98.203 Connected +0ace00a1-0612-4395-ac9b-f1516207ead1 localhost Connected +``` + +##### + +c、所有storage服务器建立连接,成为一个集群 + +``` +4个storage服务器建立连接不用两两连接,只需要找其中1个,连接另外3个各一次就OK了 + +##集群管理 +#将node节点加入集群 +[root@node2 ~]# gluster peer probe node1 +peer probe: success. +[root@node2 ~]# gluster peer probe node4 +peer probe: success. +[root@node2 ~]# gluster peer probe node3 --这里使用ip,主机名,主机名别名都可以 + +然后在所有存储上都可以使用下面命令来验证检查 + +[root@node2 ~]# gluster peer status +Number of Peers: 3 + +Hostname: node1 +Uuid: 809111f4-8a0e-40fb-af53-d2d8a56cd41e +State: Peer in Cluster (Connected) + +Hostname: 192.168.98.203 +Uuid: 7396a19d-a2a7-4b27-86d3-12c89ac4df39 +State: Peer in Cluster (Connected) + +Hostname: node4 +Uuid: b2ea8b19-658c-40ec-84b4-6568c627eefd +State: Peer in Cluster (Connected) +``` + +**注意**: + +如果这一步建立连接有问题(一般问题会出现在网络连接,防火墙,selinux,主机名绑定等); + +如果想重做这一步,可以使用gluster peer detach xxxxx [force] 来断开连接,重新做 + +**存储收集** + +必须是一个文件夹 + +1)一块磁盘[分区 格式化 挂载到节点上的指定目录] + +1. 一个磁盘文件[分区 格式化 挂载到节点上的指定目录] + +3)分区上的一个文件夹 + +d、所有storage服务器准备存储目录 + +``` +[root@node2 ~]# mkdir /opt/data{1..5} +``` + +e、创建存储卷,创建存储卷(在任意一个storage服务器上做) + +``` +glusterfs支持多种卷 +Distribut卷 分布卷 +Replica卷 复制卷 +Disperse卷 冗余卷 + +注意:从6.0版本开始之前和Striped卷相关的卷类型就全部废弃了。 +https://docs.gluster.org/en/latest/Administrator%20Guide/Setting%20Up%20Volumes/ +``` + +**Replica卷** + +文件同步复制到多个brick上,文件级RAID 1,具有容错能力,写性能下降,读性能提升。缺点是磁盘利用率低。 + +``` +#创建一个replica卷(raid1) 数据会在每个brick上存储一份 +#复制卷类似raid1 所有一般会选择两台来完成,文件保存两份,如果希望保存多个机器,可以用多台机器,这里用两台。 + +[root@node2 ~]# gluster volume create gv1-replica replica 2 node{1..2}:/opt/data force +volume create: gv1-replica: success: please start the volume to access data +replica 代表创建的是镜像卷 2 代表2个台机器 由于使用的是根分区 所以要加上强制 force + + +#查看卷创建情况 +[root@node2 ~]# gluster volume info gv1-replica + +Volume Name: gv1-replica +Type: Replicate +Volume ID: f93a83dc-9ed6-43fe-99e4-5346d5d1d702 +Status: Created +Snapshot Count: 0 +Number of Bricks: 1 x 2 = 2 +Transport-type: tcp +Bricks: +Brick1: node1:/opt/data +Brick2: node2:/opt/data +Options Reconfigured: +transport.address-family: inet +nfs.disable: on +performance.client-io-threads: off +``` + +**Distribut卷—数据随机存储在某个brick** + +文件通过hash算法分布到所有brick server上,这种卷是glusterfs的基础和最大特点。优点是容量大,缺点是没冗余。 + +``` +#如果不指定创建卷的类型,则默认是Distribute卷,可以是多个机器。 +#分布卷数据随机存储在某个brick,一般是应用在不需要冗余的环境。 + +[root@node2 ~]# gluster volume create gv2-distribute node{1..3}:/opt/data2 force +volume create: gv2-distribute: success: please start the volume to access data + + +#查看卷 +[root@node2 ~]# gluster volume info gv2-distribute + +Volume Name: gv2-distribute +Type: Distribute +Volume ID: 079a2f5c-23ac-43f8-9f54-f6a454a53706 +Status: Created +Snapshot Count: 0 +Number of Bricks: 3 +Transport-type: tcp +Bricks: +Brick1: node1:/opt/data2 +Brick2: node2:/opt/data2 +Brick3: node3:/opt/data2 +Options Reconfigured: +transport.address-family: inet +nfs.disable: on +``` + +**Disperse 卷( 冗余卷)** + +disperse卷是v3.6版本后发布的一种卷模式,类似于raid5/6,分布式分散卷 disperse必须大于2,大于4才可以有一块redundancy盘 大于5块可有redundancy盘两块 + +文件分片存储在各个硬盘上,但有部分硬盘用于冗余用途,数量可以指定。比如一共10块硬盘,2块盘用于冗余,那么就可以承受同时损坏两块硬盘,总容量是8块盘。 + +优点是在冗余和性能之间取得平衡 + +``` +#创建卷(raid5 raid6) +#建议不少于4个机器 +[root@node2 ~]# gluster volume create gv3-disperse disperse 4 node{1..4}:/opt/data3 force +There isn't an optimal redundancy value for this configuration. Do you want to create the volume with redundancy 1 ? (y/n) y 指定一个磁盘为校验磁盘 +volume create: gv3-disperse: success: please start the volume to access data + +#查看卷信息 +[root@node2 ~]# gluster volume info gv3-disperse + +Volume Name: gv3-disperse +Type: Disperse +Volume ID: 754523b3-7e8e-4133-bb77-60c2247711d9 +Status: Created +Snapshot Count: 0 +Number of Bricks: 1 x (3 + 1) = 4 +Transport-type: tcp +Bricks: +Brick1: node1:/opt/data3 +Brick2: node2:/opt/data3 +Brick3: node3:/opt/data3 +Brick4: node4:/opt/data3 +Options Reconfigured: +transport.address-family: inet +nfs.disable: on +``` + +**distribute replica 分布复制卷** + +``` +#创建分布复制卷,机器为偶数 +#每两个分布卷组成一个复制卷,创建两个复制卷 +[root@node2 ~]# gluster volume create gv2-distribute-replica replica 2 node{1..4}:/opt/data4 force +volume create: gv2-distribute-replica: success: please start the volume to access data + +#查看磁盘信息 +[root@node2 ~]# gluster volume info gv2-distribute-replica + +Volume Name: gv2-distribute-replica +Type: Distributed-Replicate +Volume ID: 90d70fef-54a9-4555-98ad-0d1a342f6763 +Status: Created +Snapshot Count: 0 +Number of Bricks: 2 x 2 = 4 +Transport-type: tcp +Bricks: +Brick1: node1:/opt/data4 +Brick2: node2:/opt/data4 +Brick3: node3:/opt/data4 +Brick4: node4:/opt/data4 +Options Reconfigured: +transport.address-family: inet +nfs.disable: on +performance.client-io-threads: off +``` + +f、启动卷 + +gluster volume star 卷名称 + +``` +#查看卷 +[root@node2 ~]# gluster volume list +gv1-replica +gv2-distribute +gv2-distribute-replica +gv3-disperse + +#启动卷 +[root@node2 ~]# gluster volume start gv1-replica +volume start: gv1-replica: success +[root@node2 ~]# gluster volume start gv2-distribute +volume start: gv2-distribute: success +[root@node2 ~]# gluster volume start gv2-distribute-replica +volume start: gv2-distribute-replica: success +[root@node2 ~]# gluster volume start gv3-disperse +volume start: gv3-disperse: success +``` + +**存储卷管理-卷的增删改查** + +``` +# +[root@node2 ~]# gluster volume help 打印帮助信息 + +#卷的创建 gluster volume create +[root@node2 ~]# gluster volume create [stripe ] [replica [arbiter ]] [disperse []] [disperse-data ] [redundancy ] [transport ] ... [force] + + 卷名 +[stripe ] [replica [arbiter ]] [disperse []] [disperse-data ] 卷类型 + stripe 条带 + replica 复制 + 什么都不加 默认分布 + disperse 冗余 + redundancy 校验磁盘 + transport 传输方式 tcp rdma内存 + force 强制,如果存储在根分区 + +#卷删除 +[root@node2 ~]# gluster volume delete + +#卷查看 +[root@node2 ~]# gluster volume list #卷列表 + +[root@node2 ~]# gluster volume info [ | all] #卷详细信息 + +[root@node2 ~]# gluster volume status [ | all] #卷启动或关闭的状态信息 + +#扩容卷 +[root@node2 ~]# gluster volume add-brick [ [arbiter ]] ... [force] + +#缩减卷 +[root@node2 ~]# gluster volume remove-brick + +#卷启动 +[root@node2 ~]# gluster volume start + +#卷关闭 +[root@node2 ~]# gluster volume stop + +#卷替换 +[root@node2 ~]# gluster volume replace-brick +``` + +**客户端设置挂载分布式卷** + +客户端安装软件 + +``` +[root@manage01 ~]# dnf install glusterfs glusterfs-fuse -y +#客户端在安装软件的时候注意版本,如果服务端与客户端使用的版本不一致,会导致挂载失败 +``` + +客户端挂载,验证上述卷数据存储方式 + +``` +#建立挂载点并挂载 +[root@manage01 ~]# mkdir /opt/gluster_disk{1..4} +[root@manage01 ~]# mount -t glusterfs node1:/gv1-replica /opt/gluster_disk1/ +[root@manage01 ~]# mount -t glusterfs node1:/gv2-distribute /opt/gluster_disk2 +[root@manage01 ~]# mount -t glusterfs node1:/gv2-distribute-replica /opt/gluster_disk3 +[root@manage01 ~]# mount -t glusterfs node1:/gv3-disperse /opt/gluster_disk4 + +#查看挂载 +[root@manage01 ~]# mount |grep "gluster" +node1:/gv1-replica on /opt/gluster_disk1 type fuse.glusterfs (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other,max_read=131072) +node1:/gv2-distribute on /opt/gluster_disk2 type fuse.glusterfs (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other,max_read=131072) +node1:/gv2-distribute-replica on /opt/gluster_disk3 type fuse.glusterfs (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other,max_read=131072) +node1:/gv3-disperse on /opt/gluster_disk4 type fuse.glusterfs (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other,max_read=131072) + + +#分别存储数据 +[root@manage01 ~]# dd if=/dev/zero of=/opt/gluster_disk1/file bs=1M count=100 +记录了100+0 的读入 +记录了100+0 的写出 +104857600字节(105 MB)已复制,1.281 秒,81.9 MB/秒 +[root@manage01 ~]# dd if=/dev/zero of=/opt/gluster_disk2/file bs=1M count=100 +记录了100+0 的读入 +记录了100+0 的写出 +104857600字节(105 MB)已复制,0.974837 秒,108 MB/秒 +[root@manage01 ~]# dd if=/dev/zero of=/opt/gluster_disk3/file bs=1M count=100 +记录了100+0 的读入 +记录了100+0 的写出 +104857600字节(105 MB)已复制,1.53898 秒,68.1 MB/秒 +[root@manage01 ~]# dd if=/dev/zero of=/opt/gluster_disk4/file bs=1M count=100 +记录了100+0 的读入 +记录了100+0 的写出 +104857600字节(105 MB)已复制,1.80071 秒,58.2 MB/秒 + + +#验证 +#复制卷 数据每个节点都存储了一份 +[root@node1 ~]# ls /opt/data -lh +总用量 100M +-rw-r--r-- 2 root root 100M 7月 7 08:51 file +[root@node2 ~]# ls /opt/data -lh +总用量 100M +-rw-r--r-- 2 root root 100M 7月 7 08:51 file + +#分布卷 数据存在了node1 +[root@node1 ~]# ls /opt/data2 -lh +总用量 100M +-rw-r--r-- 2 root root 100M 7月 7 08:51 file +[root@node2 ~]# ls /opt/data2 -lh +总用量 0 +[root@node3 ~]# ls /opt/data2 -lh +总用量 0 + +#冗余卷 发现数据平均分布在每个存储节点 +[root@node1 ~]# ls /opt/data3 -lh +总用量 34M +-rw-r--r-- 2 root root 34M 7月 7 08:52 file + +[root@node2 ~]# ls /opt/data3 -lh +总用量 34M +-rw-r--r-- 2 root root 34M 7月 7 08:52 file + +[root@node3 ~]# ls /opt/data3 -lh +总用量 34M +-rw-r--r-- 2 root root 34M 7月 7 08:52 file + +[root@node4 ~]# ls /opt/data3/ -lh +总用量 34M +-rw-r--r-- 2 root root 34M 7月 7 08:52 file + + +#分布复制卷 发现数据存在了node3 node4 这对复制卷上, +[root@node1 ~]# ls /opt/data4 -lh +总用量 0 +[root@node2 ~]# ls /opt/data4 -lh +总用量 0 +[root@node3 ~]# ls /opt/data4 -lh +总用量 100M +-rw-r--r-- 2 root root 100M 7月 7 08:51 file +[root@node4 ~]# ls /opt/data4/ -lh +总用量 100M +-rw-r--r-- 2 root root 100M 7月 7 08:51 file +``` + +**删除卷** + +1. 删除卷中数据 +2. 客户端卸载 +3. 在任意一个节点执行删除 +4. 验证删除 + +**实践练习** + +删除卷中数据 + +``` +[root@manage01 ~]# rm -rf /opt/gluster_disk1/* +``` + +客户端卸载 + +``` +[root@manage01 ~]# umount /opt/gluster_disk1/ +``` + +卷删除 + +``` +#3.在任意一个节点删除 +[root@node1 ~]# gluster volume stop gv1-replica +[root@node1 ~]# gluster volume delete gv1-replica +Deleting volume will erase all information about the volume. Do you want to continue? (y/n) y +volume delete: gv1-replica: failed: Volume vg0 does not exist +``` + +验证删除 + +``` +[root@node1 ~]# gluster volume info gv1-replica +Volume gv1-replica does not exist +``` + +**在线裁减与在线扩容** + +在线裁减要看是哪一种模式的卷,比如stripe模式就不允许在线裁减。下面我以distributed卷来做裁减与扩容 + +**在线扩容** + +``` +#查看卷 +[root@node2 ~]# gluster volume info gv2-distribute + +Volume Name: gv2-distribute +Type: Distribute +Volume ID: 079a2f5c-23ac-43f8-9f54-f6a454a53706 +Status: Started +Snapshot Count: 0 +Number of Bricks: 3 +Transport-type: tcp +Bricks: +Brick1: node1:/opt/data2 +Brick2: node2:/opt/data2 +Brick3: node3:/opt/data2 +Options Reconfigured: +transport.address-family: inet +nfs.disable: on + +#扩容 +[root@node2 ~]# gluster volume add-brick gv2-distribute node4:/opt/data2 force +volume add-brick: success + +#验证 +[root@node2 ~]# gluster volume info gv2-distribute + +Volume Name: gv2-distribute +Type: Distribute +Volume ID: 079a2f5c-23ac-43f8-9f54-f6a454a53706 +Status: Started +Snapshot Count: 0 +Number of Bricks: 4 +Transport-type: tcp +Bricks: +Brick1: node1:/opt/data2 +Brick2: node2:/opt/data2 +Brick3: node3:/opt/data2 +Brick4: node4:/opt/data2 +Options Reconfigured: +transport.address-family: inet +nfs.disable: on +``` + +**在线裁减**(注意要remove没有数据的brick) + +``` +#裁剪卷. +[root@node2 ~]# gluster volume remove-brick gv2-distribute node4:/opt/data2 force +Remove-brick force will not migrate files from the removed bricks, so they will no longer be available on the volume. +Do you want to continue? (y/n) y +volume remove-brick commit force: success + +#查看验证 +[root@node2 ~]# gluster volume info gv2-distribute + +Volume Name: gv2-distribute +Type: Distribute +Volume ID: 079a2f5c-23ac-43f8-9f54-f6a454a53706 +Status: Started +Snapshot Count: 0 +Number of Bricks: 3 +Transport-type: tcp +Bricks: +Brick1: node1:/opt/data2 +Brick2: node2:/opt/data2 +Brick3: node3:/opt/data2 +Options Reconfigured: +performance.client-io-threads: on +transport.address-family: inet +nfs.disable: on + + + +关于裁剪卷,线上几乎不会裁剪,基本上都是扩容,而且裁剪只能裁剪没有数据的,否则可能数据丢失。所以,有些卷是不支持裁剪的。 +``` + +**在线替换卷** + +``` +[root@node2 ~]# gluster volume list +gv1-replica +gv2-distribute +gv2-distribute-replica +gv3-disperse +[root@node2 ~]# gluster volume info gv1-replica + +#查看源信息 +Volume Name: gv1-replica +Type: Replicate +Volume ID: f93a83dc-9ed6-43fe-99e4-5346d5d1d702 +Status: Started +Snapshot Count: 0 +Number of Bricks: 1 x 2 = 2 +Transport-type: tcp +Bricks: +Brick1: node1:/opt/data +Brick2: node2:/opt/data +Options Reconfigured: +transport.address-family: inet +nfs.disable: on +performance.client-io-threads: off + +#卷替换 +[root@node2 ~]# gluster volume replace-brick gv1-replica node2:/opt/data node4:/opt/data commit force +volume replace-brick: success: replace-brick commit force operation successful + + +#验证替换 +[root@node2 ~]# gluster volume info gv1-replica + +Volume Name: gv1-replica +Type: Replicate +Volume ID: f93a83dc-9ed6-43fe-99e4-5346d5d1d702 +Status: Started +Snapshot Count: 0 +Number of Bricks: 1 x 2 = 2 +Transport-type: tcp +Bricks: +Brick1: node1:/opt/data +Brick2: node4:/opt/data +Options Reconfigured: +transport.address-family: inet +nfs.disable: on +performance.client-io-threads: off +``` + +拓展:4个存储想扩容为5个存储怎么做? + +``` +答案: 第5个存储服务器安装服务器软件包,启动服务,然后gluster peer probe storage5加入集群 + + +#加入集群 +[root@node2 ~]# gluster peer probe node5 +peer probe: success. +[root@node2 ~]# gluster peer status +Number of Peers: 4 + +Hostname: node1 +Uuid: 809111f4-8a0e-40fb-af53-d2d8a56cd41e +State: Peer in Cluster (Connected) + +Hostname: 192.168.98.203 +Uuid: 7396a19d-a2a7-4b27-86d3-12c89ac4df39 +State: Peer in Cluster (Connected) + +Hostname: node4 +Uuid: b2ea8b19-658c-40ec-84b4-6568c627eefd +State: Peer in Cluster (Connected) + +Hostname: node5 +Uuid: 82f424cb-1c7d-4057-8f40-f236015f8940 +State: Peer in Cluster (Connected) +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-Logstash\346\227\245\345\277\227\346\224\266\351\233\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-Logstash\346\227\245\345\277\227\346\224\266\351\233\206.md" new file mode 100644 index 0000000..3bf722c --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-Logstash\346\227\245\345\277\227\346\224\266\351\233\206.md" @@ -0,0 +1,387 @@ +ES负责存储、分析数据,但是这一切前提是需要有数据,ES本身是不能够收集数据的,数据的收集如何来做呢?我们可以通过两个软件来实现数据的收集,那就是: + + Logstash:收集、处理数据然后交给ES + + Beats:收集数据交给ES + +两者不同点在于Logstash能够更像一个数据中转站,它能够收集数据,并且对收集的数据进行处理,所以logstash消耗的计算机资源也是比较大的。Beats只负责收集数据,将数据收集后交给ES,和logstash相比其消耗的计算机资源更少,可以忽略。 + +## 一、logstash介绍 + +logstash是一个开源的数据采集工具,通过数据源采集数据.然后进行过滤,并自定义格式输出到目的地。 + +数据分为: + +1. 结构化数据 如:mysql数据库里的表等 +2. 半结构化数据 如: xml,yaml,json等 +3. 非结构化数据 如:文档,图片,音频,视频等 + +logstash可以采集任何格式的数据,当然我们这里主要是讨论采集系统日志,服务日志等日志类型数据。 + +官方产品介绍:https://www.elastic.co/cn/products/logstash + +![logstash工作流.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601976604309.png) + +input插件: 用于导入日志源 (**配置必须**) + +https://www.elastic.co/guide/en/logstash/current/input-plugins.html + +filter插件: 用于过滤(**不是配置必须的**) + +https://www.elastic.co/guide/en/logstash/current/filter-plugins.html + +output插件: 用于导出(**配置必须**) + +https://www.elastic.co/guide/en/logstash/current/output-plugins.html + +## 二、logstash安装部署 + +a、安装前准备 + +机器准备:node3 + +- 静态IP(要求能上公网,最好用虚拟机的NAT网络类型上网) +- 主机名及主机名绑定 +- 关闭防火墙和selinux +- 时间同步 +- yum源(centos安装完系统后的默认yum源就OK) + +``` +安装前准备参考https://www.zutuanxue.com/home/4/52_138 +本文通过自定义脚本init_linux_os.sh脚本来完成 + +# cat init_linux_os.sh +#!/bin/bash +#Description: initialize linux OS from ZUTUANXUE(http://www.zutuanxue.com) +#Release: 1.0 +#Auther: www.zutuanxue.com +#Email: +#OS: Centos 8.X +################ +hosts() { + echo "" > /etc/hosts + cat >> /etc/hosts<> /etc/chrony.conf < "/var/log/messages" #日志文件路径 + start_position => "beginning" #收集日志开始的位置点 + } +} + +#输出给ES +output { + elasticsearch{ + hosts => ["192.168.98.201:9200"] #ES地址 + #数据保存的索引名字 test-YYYY-MM-DD 按日期生成索引 + index => "test-%{+YYYY.MM.dd}" + } + +#输出到屏幕一份,dubug使用,前台启动Logstash排错有用 +#stdout { +# codec => rubydebug +# } +} +``` + +注意问题 + +设置/var/log/messages文件权限,让logstash能读取 + +logstash进程管理用户 logstash + +/var/log/messages文件权限400 + +``` +[root@node3 logstash]# ls /var/log/messages -l +-rw------- 1 root root 374743 2月 15 05:08 /var/log/messages +[root@node3 logstash]# chmod 644 /var/log/messages +``` + +启动logstash生效设置 + +``` +[root@node3 logstash]# systemctl restart logstash +``` + +查看启动日志 + +``` +[root@node3 ~]# tail -f /var/log/logstash/logstash-plain.log +``` + +![26_logstash启动日志.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601976984569.png) + + 看到上图选择的内容就说明成功了。 + +验证监听地址 + +``` +[root@node3 ~]# netstat -ntpl +``` + +![27_logstash监听IP启动查看.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601976999108.png) + +验证ES数据,通过ES-head查看数据情况 + +通过浏览器登陆:http://192.168.98.201:9100 + +![28_messages日志收集ES验证.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601977015184.png) + +看到数据索引,成功了。 + +## 五、logstash多日志收集 + +实验注意: 清除上一个收集Messages的业务配置文件 + + 清除ES的索引,方便查看,此条不是必须 + +**案例:**实验日志文件收集 + + /var/log/messages 索引 message-%{+YYYY.MM.dd} + + /var/log/dnf.rpm.log 索引 dnf-%{+YYYY.MM.dd} + +**思路** + +1、(input)收集日志同时给不同的日志打标签区别 + +2、(output)根据不同的数据标签将不同数据输出到ES不同索引 + +``` +[root@node3 ~]# cat /etc/logstash/conf.d/logstash_to_es_mutl_log.conf +input { + file { + path => "/var/log/messages" + start_position => "beginning" + type => "messages" #给每条数据打标签 + } + + + file { + path => "/var/log/dnf.rpm.log" + start_position => "beginning" + type => "dnf" + } +} + +output { + + if [type] == "messages" { + elasticsearch { + hosts => ["192.168.98.201:9200"] + index => "message-%{+YYYY.MM.dd}" + } + } + + if [type] == "dnf" { + elasticsearch { + hosts => ["192.168.98.201:9200"] + index => "dnf-%{+YYYY.MM.dd}" + } + } + +} +``` + +重启logstash验证ES数据 + +``` +[root@node3 logstash]# systemctl restart logstash +``` + +查看ES-head web页面概览标签,查看数据索引 + +![29_多日志收集ES展示.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601977041244.png) + +通过数据浏览标签,查看原始数据我们自定义的标签。 + +![30_查看数据定义的标签.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601977059027.png) + +完美,多日志收集成功。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-beats\346\225\260\346\215\256\351\207\207\351\233\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-beats\346\225\260\346\215\256\351\207\207\351\233\206.md" new file mode 100644 index 0000000..0006952 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-beats\346\225\260\346\215\256\351\207\207\351\233\206.md" @@ -0,0 +1,258 @@ +## 一、beats介绍 + +因为**logstash太费内存**了,如果在要采集的服务上都安装logstash,你可以想象这样这样资源消耗多高。所以我们要用**轻量级**的采集工具才更高效,更省资源。 + +![ELKfilebeat架构.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601977321444.png) + +beats是轻量级的日志收集处理工具,Beats占用资源少 + +- Packetbeat: 网络数据(收集网络流量数据) +- Metricbeat: 指标 (收集系统、进程和文件系统级别的 CPU 和内存使用情况等数据) +- Filebeat: 文件(收集日志文件数据) +- Winlogbeat: windows事件日志(收集 Windows 事件日志数据) +- Auditbeat:审计数据 (收集审计日志) +- Heartbeat:运行时间监控 (收集系统运行时的数据) + +我们这里主要是收集日志信息, 所以只讨论filebeat。 + +filebeat可以直接将采集的日志数据传输给ES集群(EFK), 也可以给logstash(**5044**端口接收)。 + +## 二、 filebeat + +**准备工作** + +机器:node4(192.168.98.204) + +``` +部署前准备参考https://www.zutuanxue.com/home/4/52_138 +``` + +**filebeat安装** + +a、yum安装 + +b、rpm安装 + +c、源码安装 + +a、yum安装 + +如果你安装ES的时候设置过yum源可以直接使用yum命令: + +``` + # yum -y install filebeat +``` + +b、rpm安装 + +``` +[root@node4 ~]# rpm -i filebeat-7.6.0-x86_64.rpm +警告:filebeat-7.6.0-x86_64.rpm: 头V4 RSA/SHA512 Signature, 密钥 ID d88e42b4: NOKEY + +-i install +``` + +c、源码安装 + +``` +参考官方手册 +``` + +**相关文件及目录** + +安装目录: /usr/share/filebeat + +配置文件目录: /etc/filebeat + +配置文件:/etc/filebeat/filebeat.yml + +服务启动管理 + +``` +[root@node4 ~]# systemctl enable filebeat +Synchronizing state of filebeat.service with SysV service script with /usr/lib/systemd/systemd-sysv-install. +Executing: /usr/lib/systemd/systemd-sysv-install enable filebeat +Created symlink /etc/systemd/system/multi-user.target.wants/filebeat.service → /usr/lib/systemd/system/filebeat.service. + +#没有修改配置文件,起不来 +[root@node4 ~]# systemctl start filebeat +``` + +## 三、filebeat配置文件 + +``` +[root@node4 ~]# cat /etc/filebeat/filebeat.yml |grep -v '#' |grep -v '^$' +filebeat.inputs: +- type: log + enabled: false #默认false,修改为true + paths: + - /var/log/*.log #收集日志的路径 +filebeat.config.modules: + path: ${path.config}/modules.d/*.yml + reload.enabled: false +setup.template.settings: + index.number_of_shards: 1 +#定义kibana地址 +setup.kibana: +#定义ES地址接收数据 +output.elasticsearch: + hosts: ["192.168.98.201:9200"] +processors: + - add_host_metadata: ~ + - add_cloud_metadata: ~ + - add_docker_metadata: ~ + - add_kubernetes_metadata: ~ +``` + +## 四、收集日志给ES集群 + +**案例:filebeat收集本机messages日志到ES,通过ES-head查看** + +**业务拓扑** + +![FEK.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601977445213.png) + +``` +注意:每做下一个实验前,建议大家把之前的索引数据清除,通过es-head,这样没有干扰,也好验证效果。否则那么多索引信息,对前期学习的你来说,干扰太多了。 +``` + +a、设置filebeat配置文件 + +``` +[root@node4 ~]# cat /etc/filebeat/filebeat.yml |grep -v '#' |grep -v '^$' +filebeat.inputs: +- type: log + enabled: true #默认false,修改为true + paths: + - /var/log/messages #收集日志的路径 +filebeat.config.modules: + path: ${path.config}/modules.d/*.yml + reload.enabled: false +setup.template.settings: + index.number_of_shards: 1 +#定义kibana地址 +setup.kibana: +#定义ES地址接收数据 +output.elasticsearch: + hosts: ["192.168.98.201:9200"] +processors: + - add_host_metadata: ~ + - add_cloud_metadata: ~ + - add_docker_metadata: ~ + - add_kubernetes_metadata: ~ +``` + +b、重启filebeat服务,生效配置 + +``` +[root@node4 ~]# systemctl restart filebeat +``` + +c、通过ES-head验证日志收集 + +![31_es-filebeat验证](https://www.zutuanxue.com:8000%E6%9E%84%E5%BB%BA%E5%8F%AF%E8%A7%86%E5%8C%96%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90%E7%B3%BB%E7%BB%9F.assets/31_es-filebeat%E9%AA%8C%E8%AF%81.png) + +**拓展:关于filebeat设置数据索引** + +``` +[root@node4 ~]# cat /etc/filebeat/filebeat.yml |grep -v '#' |grep -v '^$' +filebeat.inputs: +- type: log + enabled: true + paths: + - /var/log/messages +filebeat.config.modules: + path: ${path.config}/modules.d/*.yml + reload.enabled: false +setup.template.settings: + index.number_of_shards: 1 +setup.kibana: +#在output.*输出全局中插入这行插入,下面三行 +#禁用ilm +setup.ilm.enabled: false +#设置索引模板名 +setup.template.name: "node4_messages" +#索引前缀 +setup.template.pattern: "node4_messages-*" +output.elasticsearch: + hosts: ["192.168.98.201:9200"] + #定义索引 + index: "node4_messages-%{+yyyy.MM.dd}" +processors: + - add_host_metadata: ~ + - add_cloud_metadata: ~ + - add_docker_metadata: ~ + - add_kubernetes_metadata: ~ +``` + +## 五、收集日志给logstash + +**案例:收集本机messages日志到logstash,通过ES-head查看,要求索引为zutuanxue_node4_messages** + +**业务拓扑:** + +![elk部署图3933846.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601977492712.png) + +**案例分析:** + +a、设置filebeat配置文件,将采集的日志发送给logstash + +b、logstash收到日志添加索引后给ES + +c、ES-head验证 + +a、设置filebeat配置文件,将采集的日志发送给logstash + +``` +[root@node4 ~]# cat /etc/filebeat/filebeat.yml |grep -v '#' |grep -v '^$' +filebeat.inputs: +- type: log + enabled: true + paths: + - /var/log/messages +filebeat.config.modules: + path: ${path.config}/modules.d/*.yml + reload.enabled: false +setup.template.settings: + index.number_of_shards: 1 +setup.kibana: +#定义输出到logstash +output.logstash: + hosts: ["192.168.98.203:5044"] +processors: + - add_host_metadata: ~ + - add_cloud_metadata: ~ + - add_docker_metadata: ~ + - add_kubernetes_metadata: ~ +``` + +b、logstash收到日志添加索引后给ES + +``` +[root@node3 conf.d]# cat filebeat_to_logstash_es.conf +input { + beats { + port => 5044 + } +} + +output { + elasticsearch { + hosts => ["192.168.98.201:9200"] + index => "zutuanxue_node4-%{+YYYY.MM.dd}" #定义索引 + } +} +``` + +重启filebeat、logstash服务生效配置 + +``` +[root@node4 ~]# systemctl restart filebeat +[root@node3 ~]# systemctl restart logstash +``` + +c、ES-head验证 + +![32_esheadfilebeat_logstat验证.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601977514250.png) + +完美,实验完成 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-kibana\346\225\260\346\215\256\345\261\225\347\244\272.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-kibana\346\225\260\346\215\256\345\261\225\347\244\272.md" new file mode 100644 index 0000000..8f153b9 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-kibana\346\225\260\346\215\256\345\261\225\347\244\272.md" @@ -0,0 +1,213 @@ +学习数据采集、数据分析的时候,我们一般验证都是通过ES-head来查看的,虽然解决了验证问题,但是界面友好度还是比较差,为了解决这个问题,我们可以通过学习kibana之后,通过kibana进行数据展示。 + +## 一、kibana部署 + +### 1.1、kibana介绍 + +Kibana是一个开源的可视化web平台,【是什么】 + +可以为ElasticSearch集群的管理提供友好的Web界面,帮助汇总,分析和搜索重要的日志数据。【干什么】 + +文档路径: https://www.elastic.co/guide/en/kibana/current/setup.html + +### 1.2、kibana安装部署 + +**部署前准备** + +- 机器准备 +- 初始化设置【参考4.2】 + +**安装方法** + +- yum +- rpm +- 源码包 + +**kibana安装** + +``` +[root@manage01 elk_7.6_soft]# rpm -ivh kibana-7.6.0-x86_64.rpm +警告:kibana-7.6.0-x86_64.rpm: 头V4 RSA/SHA512 Signature, 密钥 ID d88e42b4: NOKEY +Verifying... ################################# [100%] +准备中... ################################# [100%] +正在升级/安装... + 1:kibana-7.6.0-1 ################################# [100%] +``` + +**相关目录** + +``` +安装目录:/usr/share/kibana +配置文件目录:/etc/kibana +配置文件:/etc/kibana/kibana.yml +``` + +### 1.3、kibana数据导入 + +``` +[root@manage01 ~]# egrep -v "^#|^$" /etc/kibana/kibana.yml +#kibana监听端口 +server.port: 5601 +#kibana监听地址 +server.host: "0.0.0.0" +#ES主机地址,用于取数据 +elasticsearch.hosts: ["http://192.168.98.201:9200"] +#PID文件 +pid.file: /tmp/kibana.pid +#日志文件路径 +logging.dest: /var/log/kibana.log +#汉化中文 +i18n.locale: "zh-CN" +``` + +**创建日志文件** + +``` +注意:日志文件kibana不会自己创建的,必须手动创建 +[root@manage01 ~]# touch /var/log/kibana.log +[root@manage01 ~]# chown kibana.kibana /var/log/kibana.log +``` + +**kibana启动** + +``` +[root@manage01 ~]# systemctl enable kibana +Synchronizing state of kibana.service with SysV service script with /usr/lib/systemd/systemd-sysv-install. +Executing: /usr/lib/systemd/systemd-sysv-install enable kibana +Created symlink /etc/systemd/system/multi-user.target.wants/kibana.service → /etc/systemd/system/kibana.service. + +[root@manage01 ~]# systemctl start kibana +``` + +**启动验证** + +``` +[root@manage01 ~]# netstat -ntpl +tcp 0 0 0.0.0.0:5601 0.0.0.0:* LISTEN 2351/node +``` + +### 1.4、kibana web界面 + +**项目案例:** + +收集业务机器的messages日志,通过kibana数据分析,实时查看的数据增长量。 + +数据索引为zutuanxue-主机名-messages-YYYY-MM-DD.以node4为例。 + +**实验架构** + +![FEK1986104.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601977772335.png) + +1、filebeat设置,收集日志给ES + +2、索引管理-通过鼠标流展示 + +登陆kibana:http://192.168.98.200:5601 + +索引添加 + + 1、输入索引名称:xxxx-* + + 2、输入索引中筛选字段名 + +``` +注意:第一次登陆,必须设置索引数据后才能使用web工具栏上的工具 +``` + +WEB界面介绍 + +![33kibanaweb_ui.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601977849838.png) + +索引查看 + +![34kibanaindex1992790.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601977822314.png) + +索引管理 + +![35kibanaindex管理.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601977868506.png) + +### 1.5、kibana图表 + +参考文档:https://www.elastic.co/guide/cn/kibana/current/createvis.html + +发现工具:可以展示索引中的数据,以及按时间统计增长数量 + +![36发现.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601977919596.png) + +**图表管理** + +创建图表 + +![37创建图表.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601977930781.png) + +选择图表样式(柱形图) + +![36创建图表1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601977947668.png) + +选择索引数据 + +![38创建图表索引选择.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601977963135.png) + +设置图形数据x-y轴 + +![39创建图表xy轴1.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601977980097.png) + +x轴添加及设置 + +![40创建图表x轴.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601977994112.png) + +图形保存 + +![41创建图形图形保存.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601978008221.png) + +可视化图表管理 + +![42可视化管理图形.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601978021588.png) + +在可视化中可以对图表进行查看、修改、删除 + +我们再练习一个图表创建,说一下图表的选项设置。 + +仪表盘图形设置—创建仪表盘图形 + +![43仪表盘图形创建.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601978043013.png) + +仪表盘图形索引选择 + +![44仪表盘索引选择1995682.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601978059245.png) + +图形选项设置 + +![46仪表盘图形选项设置.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601978089815.png) + +保存仪表盘图形 + +![47仪表盘保存.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601978104853.png) + +**仪表盘管理** + +将多个图表放在一个页面展示给用户 + +仪表盘-创建仪表盘 + +![48仪表盘创建.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601978120788.png) + +添加图形 + +![49添加图形到仪表盘.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601978134035.png) + +选择图形的同时,图表就会展示出来,选择完毕,点右上角叉号关闭即可 + +仪表盘内容查看 + +![仪表盘查看.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601978150997.png) + +保存仪表盘 + +![50仪表盘保存.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601978164600.png) + +仪表盘管理 + +![51仪表盘管理.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601978179720.png) + +在本页面可以对仪表盘进行查看,修改,删除。 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-\345\215\225\346\234\272\351\203\250\347\275\262Elasticsearch.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-\345\215\225\346\234\272\351\203\250\347\275\262Elasticsearch.md" new file mode 100644 index 0000000..0c75598 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-\345\215\225\346\234\272\351\203\250\347\275\262Elasticsearch.md" @@ -0,0 +1,317 @@ +### 一、Elasticsearch简介 + +Elasticsearch(简称ES)是一个**开源的分布式搜索引擎**,Elasticsearch还是一个**分布式文档数据库**。所以它提供了大量数据的**存储**功能,快速的**搜索**与**分析**功能。 + +提到搜索,大家肯定就想到了百度,谷歌,必应等。当然也有如下的搜索场景。 + +![github搜索界面.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601974609952.png) + +## 二、Elasticsearch部署方法 + +1. JDK安装并设置为默认java环境 +2. Elasticsearch安装 +3. 配置elasticsearch监听ip地址 +4. 测试 + +``` +关于软件获得 +1、JDK 注意:下载页面,需要接受下载协议才能下载 +jdk13 https://download.oracle.com/otn-pub/java/jdk/13.0.2+8/d4173c853231432d94f001e99d882ca7/jdk-13.0.2_linux-x64_bin.rpm + +2、Elasticsearch https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.6.0-x86_64.rpm + +3、logstash https://artifacts.elastic.co/downloads/logstash/logstash-7.6.0.rpm + +4、kibana https://artifacts.elastic.co/downloads/kibana/kibana-7.6.0-x86_64.rpm + +5、filebeat https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.6.0-x86_64.rpm +``` + +### 2.1、JDK安装 + +#### JDK介绍 + +JDK的全称是Java Development Kit,是Sun公司免费提供的Java语言的软件开发工具包,其中包含Java虚拟机(JVM),java运行环境(JRE)。编写好的Java源程序经过编译可形成Java字节码,只要安装了JDK,就可以利用JVM解释这些字节码文件,从而保证了Java的跨平台性。 + +##### JDK安装方法 + +1. 软件安装[本次安装jdk13.0.2] +2. 设置环境变量,默认java环境为新安装环境 + +``` +#1、软件安装 +#默认安装路径/usr/java/jdk-13.0.2 +[root@node1 ~]# rpm -ivh jdk-13.0.2_linux-x64_bin.rpm +警告:jdk-13.0.2_linux-x64_bin.rpm: 头V3 RSA/SHA256 Signature, 密钥 ID ec551f03: NOKEY +Verifying... ################################# [100%] +准备中... ################################# [100%] +正在升级/安装... + 1:jdk-13.0.2-2000:13.0.2-ga ################################ [100%] + +or +如果有依赖,可以通过yum解决依赖 +[root@node1 elk_7.6_soft]# yum -y localinstall jdk-13.0.2_linux-x64_bin.rpm + + +#2、设置环境变量,默认java环境为新安装环境 +#注意 java环境给谁用 +#/etc/profile +#~/.bash_profile +#在/etc/profile文件中追加以下环境变量,并导出为全局变量 +[root@node1 ~]# tail -4 /etc/profile +#JAVA安装路径 +JAVA_HOME=/usr/java/jdk-13.0.2/ +#JAVA命令输出 +PATH=$JAVA_HOME/bin:$PATH:$HOME/bin +#JAVA库文件 +CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar +#导出全局 +export PATH JAVA_HOME CLASSPATH CATALINA_HOME + +#重载/etc/profile文件到内存,生效变量 +[root@node1 ~]# source /etc/profile + +#3、测试java默认环境 +[root@node1 ~]# java --version +java 13.0.2 2020-01-14 #看这里,看这里,完美! +Java(TM) SE Runtime Environment (build 13.0.2+8) +Java HotSpot(TM) 64-Bit Server VM (build 13.0.2+8, mixed mode, sharing) +``` + +#### 2.2 Elasticsearch安装 + +##### Elasticsearch安装方法 + +- Elasticsearch RPM安装 +- yum源安装 +- 源码安装 + +**Elasticsearch安装方法对比** + +Elasticsearch RPM安装: + + 需要提前下好安装包,如果有依赖需要手动解决依赖,压力山大! + +yum源安装 + + 傻瓜式安装,做好yum源即可,网络很重要。 + +源码安装 + + 源码自定义安装,可以优化软件功能,删减功能,高手的选择。 + +RPM安装方法 + +a、下载elasticsearch RPM包 + +b、安装elasticsearch + +``` +a、下载elasticsearch RPM包 +[root@node1 ~]# wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.6.0-x86_64.rpm + +b、安装elasticsearch +[root@node1 ~]# rpm -ivh elasticsearch-7.6.0-x86_64.rpm +警告:elasticsearch-7.6.0-x86_64.rpm: 头V4 RSA/SHA512 Signature, 密钥 ID d88e42b4: NOKEY +Verifying... ################################# [100%] +准备中... ################################# [100%] +Creating elasticsearch group... OK +Creating elasticsearch user... OK +正在升级/安装... + 1:elasticsearch-0:7.6.0-1 ################################# [100%] +### NOT starting on installation, please execute the following statements to configure elasticsearch service to start automatically using systemd 安装服务到systemd服务,方便使用systemctl管理服务 + sudo systemctl daemon-reload + sudo systemctl enable elasticsearch.service +### You can start elasticsearch service by executing + sudo systemctl start elasticsearch.service 服务启动方法 +Created elasticsearch keystore in /etc/elasticsearch +[/usr/lib/tmpfiles.d/elasticsearch.conf:1] Line references path below legacy directory /var/run/, updating /var/run/elasticsearch → /run/elasticsearch; please update the tmpfiles.d/ drop-in file accordingly. +[/usr/lib/tmpfiles.d/libstoragemgmt.conf:1] Line references path below legacy directory /var/run/, updating /var/run/lsm → /run/lsm; please update the tmpfiles.d/ drop-in file accordingly. +[/usr/lib/tmpfiles.d/libstoragemgmt.conf:2] Line references path below legacy directory /var/run/, updating /var/run/lsm/ipc → /run/lsm/ipc; please update the tmpfiles.d/ drop-in file accordingly. +[/usr/lib/tmpfiles.d/mdadm.conf:1] Line references path below legacy directory /var/run/, updating /var/run/mdadm → /run/mdadm; please update the tmpfiles.d/ drop-in file accordingly. +[/usr/lib/tmpfiles.d/radvd.conf:1] Line references path below legacy directory /var/run/, updating /var/run/radvd → /run/radvd; please update the tmpfiles.d/ drop-in file accordingly. +[/usr/lib/tmpfiles.d/spice-vdagentd.conf:2] Line references path below legacy directory /var/run/, updating /var/run/spice-vdagentd → /run/spice-vdagentd; please update the tmpfiles.d/ drop-in file accordingly. + + +安装路径 /usr/share/elasticsearch/ +``` + +yum源安装 + +a、安装elasticsearch gpg key + +b、设置yum源 + +c、安装elasticsearch + +``` +a、=================安装elasticsearch key================= +[root@node1 ~]# rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch + +b、=================设置yum源================= +[root@node1 ~]# cat >>/etc/yum.repos.d/elk.repo < [elasticsearch-7.x] +> name=Elasticsearch repository for 7.x packages +> baseurl=https://artifacts.elastic.co/packages/7.x/yum +> gpgcheck=1 +> gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch +> enabled=1 +> autorefresh=1 +> type=rpm-md +> EOF + +c、=================安装elasticsearch================= +[root@node1 ~]# yum install elasticsearch +``` + +源码安装 + +a、下载源码包 + +b、解压安装 + +c、启动测试 + +``` +挑战自我,超越自我,you can you do! + +参考官方手册 +https://www.elastic.co/guide/en/elasticsearch/reference/7.6/targz.html +``` + +**Elasticsearch配置文件目录结构** + +``` +elasticsearch安装目录:/usr/share/elasticsearch/ +elasticsearch配置文件目录:/etc/elasticsearch/ +[root@node1 ~]# cd /etc/elasticsearch/ + +[root@node1 elasticsearch]# tree +. +├── elasticsearch.keystore #key存储 +├── elasticsearch.yml #主配置文件 +├── jvm.options #JVM虚拟机参数配置文件 +├── log4j2.properties #记录日志 +├── role_mapping.yml #空文件 +├── roles.yml #空文件,定义权限文件 +├── users #空文件,定义用户文件 +└── users_roles #空文件 + +四个空文件是ES权限控制文件 +``` + +Elasticsearch设置[拓展] + +``` +#堆内存设置 +jvm将内存逻辑分区,主要分为堆、栈、方法区 +java创建的对象放在堆内存中 +java创建的方法是放在栈内存执行,包括局部变量 +java源码编译后二进制文件执行要加载到方法区,常量池也存在方法区 + +#详情可参考天易IT学院java课程 +数据结构 +JVM课程 + +Elasticsearch 默认安装后设置的堆内存是 1 GB。对于任何一个业务部署来说, 这个设置都太小了。如果你正在使用这些默认堆内存配置,您的集群可能会出现问题。 + +#建议不要超过32G + +官方解释 +在 Java 中,所有的对象都分配在堆上,并通过一个指针进行引用。 普通对象指针(OOP)指向这些对象,通常为 CPU 字长 的大小:32 位或 64 位,取决于你的处理器。指针引用的就是这个 OOP 值的字节位置。 + +对于 32 位的系统,意味着堆内存大小最大为 4 GB。对于 64 位的系统, 可以使用更大的内存,但是 64 位的指针意味着更大的浪费,因为你的指针本身大了。更糟糕的是, 更大的指针在主内存和各级缓存(例如 LLC,L1 等)之间移动数据的时候,会占用更多的带宽。 + +Java 使用一个叫作 内存指针压缩(compressed oops)的技术来解决这个问题。 它的指针不再表示对象在内存中的精确位置,而是表示 偏移量 。这意味着 32 位的指针可以引用 40 亿个 对象 , 而不是 40 亿个字节。最终, 也就是说堆内存增长到 32 GB 的物理内存,也可以用 32 位的指针表示。 + +一旦你越过那个神奇的 ~32 GB 的边界,指针就会切回普通对象的指针。 每个对象的指针都变长了,就会使用更多的 CPU 内存带宽,也就是说你实际上失去了更多的内存。事实上,当内存到达 40–50 GB 的时候,有效内存才相当于使用内存对象指针压缩技术时候的 32 GB 内存。 + +这段描述的意思就是说:即便你有足够的内存,也尽量不要 超过 32 GB。因为它浪费了内存,降低了 CPU 的性能,还要让 GC 应对大内存。 + +#GC,全称是 Garbage Collection (垃圾收集)或者 Garbage Collector(垃圾收集器) + +#参考文档 +https://www.elastic.co/guide/cn/elasticsearch/guide/current/heap-sizing.html + +#设置方法 +[root@node1 ~]#vim /etc/elasticsearch/jvm.options +# Xms represents the initial size of total heap space +# Xmx represents the maximum size of total heap space + +-Xms1g +-Xmx1g +``` + +**Elasticsearch服务管理方法** + +a、开机启动服务 + +b、服务启动管理 + +``` +a、开机启动服务 +[root@node1 ~]# systemctl enable elasticsearch.service +Synchronizing state of elasticsearch.service with SysV service script with /usr/lib/systemd/systemd-sysv-install. +Executing: /usr/lib/systemd/systemd-sysv-install enable elasticsearch +Created symlink /etc/systemd/system/multi-user.target.wants/elasticsearch.service → /usr/lib/systemd/system/elasticsearch.service. + +b、服务启动管理 +[root@node1 ~]# systemctl start elasticsearch.service + +c、启动测试 +[root@node1 ~]# netstat -ntpl +..... +tcp6 0 0 127.0.0.1:9200 :::* LISTEN 2698/java +tcp6 0 0 ::1:9200 :::* LISTEN 2698/java +tcp6 0 0 127.0.0.1:9300 :::* LISTEN 2698/java +tcp6 0 0 ::1:9300 :::* LISTEN 2698/java +``` + +#### 2.3、配置Elasticsearch监听本地外网地址 + +绑定ES监听地址为:192.168.98.201 + +``` +[root@node1 ~]# vim /etc/elasticsearch/elasticsearch.yml +# ---------------------------------- Network -------------------------- +# +# Set the bind address to a specific IP (IPv4 or IPv6): +# +network.host: 192.168.98.201 #删除#号,设置本机某个公网地址或0.0.0.0 +# +# Set a custom port for HTTP: +# +#http.port: 9200 +# +# For more information, consult the network module documentation. +# +# --------------------------------- Discovery ------------------------- +# +# Pass an initial list of hosts to perform discovery when this node is started: +# The default list of hosts is ["127.0.0.1", "[::1]"] +# +#discovery.seed_hosts: ["host1", "host2"] +# +# Bootstrap the cluster using an initial set of master-eligible nodes: +#如果ES设置公网地址,非localhost,那么它就会认为这是一个es集群,必须有一个master +#所有开启下面这行,指定master可以是哪个node。 +cluster.initial_master_nodes: ["192.168.98.201"] #删除#号,写上自己本地地址 +# +# For more information, consult the discovery and cluster formation module documentation. +``` + +重启服务生效 + +``` +[root@node1 ~]# systemctl restart elasticsearch.service +``` + +#### 2.4、测试 + +验证端口及监听地址 + +![02_elasticsearch_启动验证.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601974762675.png) + +通过浏览器访问ES + +![03_elasticsearch_web_启动验证.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601974776768.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-\346\224\266\351\233\206mysql slow \346\227\245\345\277\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-\346\224\266\351\233\206mysql slow \346\227\245\345\277\227.md" new file mode 100644 index 0000000..bac0d3b --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-\346\224\266\351\233\206mysql slow \346\227\245\345\277\227.md" @@ -0,0 +1,546 @@ +## 案例分析 + +开发和DBA为了能够实时掌握mysql的运行情况,需要对mysql中执行的sql指令大于1秒的统计出来,并且通过ELK分析,统计,实时查看。通过分析可以让DBA能够优化数据库,能够提升运行速度。 + +## 一、MySQL设置 + +**a、mysql安装** + +``` +安装脚本 +``` + +mysql默认root密码更改 + +``` +[root@node4 mysql]# mysql_secure_installation +``` + +**b、mysql slow日志开启** + +``` +#开启slow log +slow_query_log=1 +slow_query_log_file=/usr/local/mysql/mysql-slow.log +long-query-time=1 + +#允许使用Load data命令 +secure_file_priv='' +``` + +重启mysql生效 + +``` +[root@node4 mysql]# /etc/init.d/mysql.server restart +Shutting down MySQL.. SUCCESS! +Starting MySQL. SUCCESS! +``` + +**c、生成测试数据** + +``` +[root@node4 mysql]# seq 1 10000000 > /tmp/big +``` + +导入数据 + +``` +mysql> create table db1.t1(id int(11)); +mysql> load data infile '/tmp/big' into table db1.t1; +Query OK, 10000000 rows affected (21.73 sec) +Records: 10000000 Deleted: 0 Skipped: 0 Warnings: 0 +``` + +生成slow日志 + +``` +mysql> select * from db1.t1 where id=8; ++------+ +| id | ++------+ +| 8 | ++------+ +1 row in set (3.46 sec) +``` + +查看slow 日志 + +``` +[root@node4 mysql]# cat mysql-slow.log +/usr/local/mysql/bin/mysqld, Version: 5.7.28-log (MySQL Community Server (GPL)). started with: +Tcp port: 0 Unix socket: /tmp/mysql.sock +Time Id Command Argument +/usr/local/mysql/bin/mysqld, Version: 5.7.28-log (MySQL Community Server (GPL)). started with: +Tcp port: 0 Unix socket: /tmp/mysql.sock +Time Id Command Argument +# Time: 2020-02-18T13:15:34.406907Z +# User@Host: root[root] @ localhost [] Id: 2 +# Query_time: 21.729690 Lock_time: 0.005813 Rows_sent: 0 Rows_examined: 0 +SET timestamp=1582031734; +load data infile '/tmp/big' into table db1.t1; +# Time: 2020-02-18T13:16:03.022224Z +# User@Host: root[root] @ localhost [] Id: 2 +# Query_time: 3.458640 Lock_time: 0.004334 Rows_sent: 1 Rows_examined: 10000000 +SET timestamp=1582031763; +select * from db1.t1 where id=8; +# Time: 2020-02-18T13:23:11.893639Z +# User@Host: root[root] @ localhost [] Id: 3 +# Query_time: 3.583976 Lock_time: 0.000412 Rows_sent: 1 Rows_examined: 10000000 +SET timestamp=1582032191; +select * from db1.t1 where id=88; +# Time: 2020-02-18T13:23:17.347380Z +# User@Host: root[root] @ localhost [] Id: 3 +# Query_time: 3.557843 Lock_time: 0.000113 Rows_sent: 1 Rows_examined: 10000000 +SET timestamp=1582032197; +select * from db1.t1 where id=888; +# Time: 2020-02-18T13:23:22.470483Z +# User@Host: root[root] @ localhost [] Id: 3 +# Query_time: 3.498105 Lock_time: 0.000173 Rows_sent: 1 Rows_examined: 10000000 +SET timestamp=1582032202; +select * from db1.t1 where id=8888; +``` + +## 二、数据收集 + +\###a、mysql slow日志格式整理收集 + +通过filebeat多行模式收集mysql slow日志 + +``` +[root@node4 ~]# egrep -v "^#|^$| #" /etc/filebeat/filebeat.yml +filebeat.inputs: +- type: log + enabled: true + paths: + - /usr/local/mysql/mysql-slow.log + #开启多行收集 + multiline.pattern: "^# User@Host:" + multiline.negate: true + multiline.match: after + +filebeat.config.modules: + path: ${path.config}/modules.d/*.yml + reload.enabled: false +setup.template.settings: + index.number_of_shards: 1 +setup.kibana: +output.logstash: + hosts: ["192.168.98.203:5044"] +processors: + - add_host_metadata: ~ + - add_cloud_metadata: ~ + - add_docker_metadata: ~ + - add_kubernetes_metadata: ~ + +参数说明 +multiline.pattern:正则表达式,去匹配指定的一行,这里去匹配的以“# User@Host:”开头的那一行; +multiline.negate:取值true 或 false; +默认是false,就是将multiline.pattern匹配到的那一行合并到上一行; +如果配置是true,就是将除了multiline.pattern匹的那一行的其他所有行合并到其上一行; +multiline.match:after 或 before,就是指定将要合并到上一行的内容,合并到上一行的末尾或开头; +``` + +logstash中的数据是这样存储的 + +``` +{ + "host" => { + "hostname" => "node4", + "name" => "node4", + "os" => { + "family" => "redhat", + "name" => "CentOS Linux", + "kernel" => "4.18.0-80.el8.x86_64", + "codename" => "Core", + "version" => "8 (Core)", + "platform" => "centos" + }, + "containerized" => false, + "id" => "d8100d9fc21041ae9364bbb1ca84da02", + "architecture" => "x86_64" + }, + "log" => { + "offset" => 4629, + "file" => { + "path" => "/usr/local/mysql/mysql-slow.log" + } + }, + "tags" => [ + [0] "beats_input_codec_plain_applied" + ], + "@timestamp" => 2020-02-19T02:50:06.763Z, + "input" => { + "type" => "log" + }, + #这里有一个message行,记录了时间 + "message" => "# Time: 2020-02-19T02:50:05.740090Z", + "ecs" => { + "version" => "1.4.0" + }, + "agent" => { + "hostname" => "node4", + "type" => "filebeat", + "ephemeral_id" => "3736821d-5c17-429a-a8af-0a9b28ba87b7", + "version" => "7.6.0", + "id" => "060fdb52-cc79-463e-9cbf-f7d8fee5db89" + }, + "@version" => "1" +} +{ + "log" => { + "file" => { + "path" => "/usr/local/mysql/mysql-slow.log" + }, + "offset" => 4665, + "flags" => [ + [0] "multiline" + ] + }, + "host" => { + "hostname" => "node4", + "name" => "node4", + "os" => { + "family" => "redhat", + "name" => "CentOS Linux", + "kernel" => "4.18.0-80.el8.x86_64", + "codename" => "Core", + "version" => "8 (Core)", + "platform" => "centos" + }, + "containerized" => false, + "id" => "d8100d9fc21041ae9364bbb1ca84da02", + "architecture" => "x86_64" + }, + "tags" => [ + [0] "beats_input_codec_plain_applied" + ], + "@timestamp" => 2020-02-19T02:50:06.763Z, + "input" => { + "type" => "log" + }, + ####看这里message!mysql slow日志这样才的 + "message" => "# User@Host: root[root] @ localhost [] Id: 2\n# Query_time: 4.764090 Lock_time: 0.001112 Rows_sent: 1 Rows_examined: 10000000\nSET timestamp=1582080605;\nselect * from db1.t1 where id=1;", + "ecs" => { + "version" => "1.4.0" + }, + "agent" => { + "hostname" => "node4", + "type" => "filebeat", + "version" => "7.6.0", + "ephemeral_id" => "3736821d-5c17-429a-a8af-0a9b28ba87b7", + "id" => "060fdb52-cc79-463e-9cbf-f7d8fee5db89" + }, + "@version" => "1" +} +``` + +**b、使用grok插件格式化数据** + +**grok**是一种采用组合多个预定义的正则表达式,用来匹配分割文本并映射到关键字的工具。通常用来对日志数据进行预处理。logstash的filter模块中grok插件是其实现之一。 + +处理思路: + +``` +1、第一个message数据行,没有用到,删除; +2、第二个message数据行的数据做json格式; +3、时间根据第二个message数据行中的时间戳转换; +4、数据已经做成json格式了,自然第二个message也没用了,删除第二个message行; +``` + +**通过不断测试,查看Logstash中的数据存储** + +1、第一个message数据行,没有用到,删除; + +2、第二个message数据行的数据做json格式; + +3、时间根据第二个message数据行中的时间戳转换; + +``` +filter { +#2、将第二个message数据格式化为json格斯 +grok { + match => [ "message", "(?m)^# User@Host: %{USER:query_user}\[[^\]]+\] @ (?:(?\S*) )?\[(?:%{IP:query_ip})?\]\s+Id:\s+%{NUMBER:row_id:int}\s*# Query_time: %{NUMBER:query_time:float}\s+Lock_time: %{NUMBER:lock_time:float}\s+Rows_sent: %{NUMBER:rows_sent:int}\s+Rows_examined: %{NUMBER:rows_examined:int}\s*(?:use %{DATA:database};\s*)?SET timestamp=%{NUMBER:timestamp};\s*(?(?\w+)\s+.*)" ] + } + +#1、匹配"message" => "# Time: "数据行[第一个message],添加一个标签 drop +grok { + match => { "message" => "# Time: " } + add_tag => [ "drop" ] + tag_on_failure => [] + } + +#1、删除标签为drop的数据行 + if "drop" in [tags] { + drop {} + } + +#3、匹配message中的时间戳,根据亚洲/上海的格式生成本地时间 + date { + match => ["mysql.slowlog.timestamp", "UNIX", "YYYY-MM-dd HH:mm:ss"] + target => "@timestamp" + timezone => "Asia/Shanghai" + } + ruby { + code => "event.set('[@metadata][today]', Time.at(event.get('@timestamp').to_i).localtime.strftime('%Y.%m.%d'))" + } + + + +} +``` + +**logstash中数据存储** + +``` +{ + "agent" => { + "ephemeral_id" => "3736821d-5c17-429a-a8af-0a9b28ba87b7", + "type" => "filebeat", + "hostname" => "node4", + "version" => "7.6.0", + "id" => "060fdb52-cc79-463e-9cbf-f7d8fee5db89" + }, + #看这里,根据时间戳生成的时间 + "@timestamp" => 2020-02-19T03:01:46.833Z, + "input" => { + "type" => "log" + }, + "query_host" => "localhost", + "tags" => [ + [0] "beats_input_codec_plain_applied" + ], + "row_id" => 2, + ###看这里,第二个message数据 + "message" => "# User@Host: root[root] @ localhost [] Id: 2\n# Query_time: 4.448631 Lock_time: 0.000213 Rows_sent: 1 Rows_examined: 10000000\nSET timestamp=1582081300;\nselect * from db1.t1 where id=1;", + "@version" => "1", + ###从这往下看,能看到这里面夹杂这生成的json数据 + #row_id query_time lock_time rows_examined query query_user等都是 + "query_time" => 4.448631, + "lock_time" => 0.000213, + "ecs" => { + "version" => "1.4.0" + }, + "rows_examined" => 10000000, + "query" => "select * from db1.t1 where id=1;", + "log" => { + "flags" => [ + [0] "multiline" + ], + "offset" => 5346, + "file" => { + "path" => "/usr/local/mysql/mysql-slow.log" + } + }, + "host" => { + "name" => "node4", + "os" => { + "codename" => "Core", + "name" => "CentOS Linux", + "family" => "redhat", + "version" => "8 (Core)", + "kernel" => "4.18.0-80.el8.x86_64", + "platform" => "centos" + }, + "hostname" => "node4", + "architecture" => "x86_64", + "id" => "d8100d9fc21041ae9364bbb1ca84da02", + "containerized" => false + }, + "action" => "select", + "rows_sent" => 1, + "timestamp" => "1582081300", + "query_user" => "root" +} +``` + +**通过grok插件,实现日志过滤** + +关于正则表达式内容,参考shell脚本中的正则表达式一章 + +``` +补充知识点 +空格匹配 \s +回车匹配 \s* +非空格匹配 \S [大写] +``` + +grok中的语法 + +``` +grok匹配规则 +%{数据类型:变量名} +例如 5.12 可能是一个事件的持续时间,192.168.98.200可能是请求的client地址。所以这两个值可以用 %{NUMBER:duration} %{IP:client} 来匹配。 + +自定义数据类型 +(?<字段名>表达式) + +例如,日志有一个student_id 为一个长度为10或11个字符的十六进制值。使用下列语法可以获取该片段,并把值赋予student_id +(?[0-9A-F]{10,11}) + +具体参考 +https://www.elastic.co/guide/en/logstash/current/plugins-filters-grok.html +``` + +删除第二个message数据 + +``` +filter { +#1、将第二个message数据格式化为json格斯 +grok { + match => [ "message", "(?m)^# User@Host: %{USER:query_user}\[[^\]]+\] @ (?:(?\S*) )?\[(?:%{IP:query_ip})?\]\s+Id:\s+%{NUMBER:row_id:int}\s*# Query_time: %{NUMBER:query_time:float}\s+Lock_time: %{NUMBER:lock_time:float}\s+Rows_sent: %{NUMBER:rows_sent:int}\s+Rows_examined: %{NUMBER:rows_examined:int}\s*(?:use %{DATA:database};\s*)?SET timestamp=%{NUMBER:timestamp};\s*(?(?\w+)\s+.*)" ] + } + +#匹配"message" => "# Time: "数据行[第一个message],添加一个标签 drop +grok { + match => { "message" => "# Time: " } + add_tag => [ "drop" ] + tag_on_failure => [] + } + +#删除标签为drop的数据行 + if "drop" in [tags] { + drop {} + } + +#匹配message中的时间戳,根据亚洲/上海的格式生成本地时间 + date { + match => ["mysql.slowlog.timestamp", "UNIX", "YYYY-MM-dd HH:mm:ss"] + target => "@timestamp" + timezone => "Asia/Shanghai" + } + ruby { + code => "event.set('[@metadata][today]', Time.at(event.get('@timestamp').to_i).localtime.strftime('%Y.%m.%d'))" + } + +#删除message字段 + mutate { + remove_field => [ "message" ] + } + + +} +``` + +**实现过滤后,logstash数据存储状态** + +``` +{ + "lock_time" => 0.000226, + "host" => { + "name" => "node4", + "architecture" => "x86_64", + "os" => { + "name" => "CentOS Linux", + "family" => "redhat", + "platform" => "centos", + "kernel" => "4.18.0-80.el8.x86_64", + "version" => "8 (Core)", + "codename" => "Core" + }, + "hostname" => "node4", + "id" => "d8100d9fc21041ae9364bbb1ca84da02", + "containerized" => false + }, + "rows_examined" => 10000000, + "action" => "select", + "rows_sent" => 1, + "tags" => [ + [0] "beats_input_codec_plain_applied" + ], + "row_id" => 2, + "log" => { + "file" => { + "path" => "/usr/local/mysql/mysql-slow.log" + }, + "flags" => [ + [0] "multiline" + ], + "offset" => 5119 + }, + "@version" => "1", + "ecs" => { + "version" => "1.4.0" + }, + "input" => { + "type" => "log" + }, + ###看这里下面数据,数据已经被定义为json格式了, + "query_host" => "localhost", + "@timestamp" => 2020-02-19T02:57:11.812Z, + "query_time" => 4.377673, + "query_user" => "root", + "query" => "select * from db1.t1 where id=1;", + "timestamp" => "1582081027", + "agent" => { + "type" => "filebeat", + "version" => "7.6.0", + "hostname" => "node4", + "id" => "060fdb52-cc79-463e-9cbf-f7d8fee5db89", + "ephemeral_id" => "3736821d-5c17-429a-a8af-0a9b28ba87b7" + } +} +``` + +**c、logstash将数据交给elasticsearch** + +``` +[root@node3 conf.d]# cat mysql_logstash_es.conf +#采集数据 +input { + beats { + port => 5044 + } +} + +#过滤 +filter { +grok { + match => [ "message", "(?m)^# User@Host: %{USER:query_user}\[[^\]]+\] @ (?:(?\S*) )?\[(?:%{IP:query_ip})?\]\s+Id:\s+%{NUMBER:row_id:int}\s*# Query_time: %{NUMBER:query_time:float}\s+Lock_time: %{NUMBER:lock_time:float}\s+Rows_sent: %{NUMBER:rows_sent:int}\s+Rows_examined: %{NUMBER:rows_examined:int}\s*(?:use %{DATA:database};\s*)?SET timestamp=%{NUMBER:timestamp};\s*(?(?\w+)\s+.*)" ] + } + + grok { + match => { "message" => "# Time: " } + add_tag => [ "drop" ] + tag_on_failure => [] + } + + if "drop" in [tags] { + drop {} + } + + date { + match => ["mysql.slowlog.timestamp", "UNIX", "YYYY-MM-dd HH:mm:ss"] + target => "@timestamp" + timezone => "Asia/Shanghai" + } + ruby { + code => "event.set('[@metadata][today]', Time.at(event.get('@timestamp').to_i).localtime.strftime('%Y.%m.%d'))" + } + + mutate { + remove_field => [ "message" ] + } + + +} + + +#输出到es +output { + elasticsearch{ + hosts => ["192.168.98.201:9200"] + index => "zutuanxue_node4_mysql-%{+YYYY.MM.dd}" + } + +stdout { + codec => rubydebug + } +} +``` + +## 三、kibana展示 + +绘制图表 + +- query_time分布 +- 统计slow日志数量 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-\346\225\260\346\215\256\347\256\241\347\220\206.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-\346\225\260\346\215\256\347\256\241\347\220\206.md" new file mode 100644 index 0000000..7f14645 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-\346\225\260\346\215\256\347\256\241\347\220\206.md" @@ -0,0 +1,105 @@ +## 一、elasticsearch基础概念 + +主要的基础概念有: Index,Type,Document,Field,shard和replicas. + +Index(索引): 是具有相似特性的文档集合。 + +Type(类型): 在一个索引中可以定义一个或多个类型。 + +Documenet(文档): 索引信息的基本单位。 + +Field(字段): ES里更小的信息单位。 + +shard(分片): 数据存储的方式 + +replicas(副本):副本 数据备份 + +为了便于理解,我们和mysql这种关系型数据库做一个对比: + +| 关系型数据库(如mysql,oracle等) | elasticsearch | +| :----------------------------- | :------------ | +| database | index | +| table | type | +| row | document | +| column | field | + +ES是分布式搜索引擎,每个索引有一个或多个分片(shard),索引的数据被分配到各个分片上。你可以看作是一份数据分成了多份给不同的节点。 + +## 二、elaticsearch基础API操作 + +**如果有ES集群,则为ES任意节点IP都可以** + +前面我们通过http://192.168.98.201:9200/_cluster/health?pretty查看ES集群状态,其实就是它的一种API操作。 + +``` +什么是API? +API(Application Programming Interface)应用程序编程接口,就是无需访问程序源码或理解内部工作机制就能实现一些相关功能的接口。 +``` + +elasticseearch的API很多, 我们运维人员主要用到以下几个要介绍的较简单的API。 + +更多API参考: https://www.elastic.co/guide/en/elasticsearch/reference/6.2/index.html + +##### **查看节点信息** + +通过curl或浏览器访问http://192.168.98.202:9200/_cat/nodes?v ip为ES节点IP,如果有ES集群,则为ES任意节点IP都可以) + +``` +[root@node1 ~]# curl http://192.168.98.202:9200/_cat/nodes?v +ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name +192.168.98.201 9 94 0 0.09 0.06 0.06 dilm * node1 +192.168.98.202 15 92 4 0.12 0.14 0.11 dilm - node2 +``` + +使用浏览器访问 + +![05_api_查看节点信息.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601975332241.png) + +## 三、索引管理 + +- 文本界面API管理索引 +- web图形ES-head管理索引 + +### 文本界面管理索引 + +- 查看索引信息 + +通过curl或浏览器访问http://192.168.98.201:9200/_cat/indices?v + +``` +[root@node1 ~]# curl http://192.168.98.201:9200/_cat/indices?v +health status index uuid pri rep docs.count docs.deleted store.size pri.store.size +默认现在没有任何索引 +``` + +- 新增索引 + +``` +[root@node1 ~]# curl -X PUT http://192.168.98.201:9200/zutuanxue_com_access_log +[root@node1 ~]# + + +输出信息 +{"acknowledged":true,"shards_acknowledged":true,"index":"zutuanxue_com_access_log"} + +[root@node1 ~]# curl http://192.168.98.201:9200/_cat/indices?v +health status index uuid pri rep docs.count docs.deleted store.size pri.store.size +green open zutuanxue_com_access_log A_keWJh4RSOUS3gKCX2AwA 1 1 0 0 460b 230b +``` + +![06_api_查看索引.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601975369276.png) + +green:表示每个index的shard和replica都是活跃状态的。 + +yellow:表示每个index的shard是活跃状态的,replica是不可用状态的。 + +red:表示索引中有些shard是不可用状态,导致数据丢失。 + +- 删除索引 + +``` +[root@node1 ~]# curl -X DELETE http://192.168.98.201:9200/zutuanxue_com_access_log +{"acknowledged":true} +``` + +当ES集群增加或删除节点时,shard会在多个节点中均衡分配。7.0之前,默认是5个primary shard(主分片)和1个replica shard(副本,用于容错)。7.x之后是1个主分片 1个副本分片 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-\351\203\250\347\275\262Elasticsearch\351\233\206\347\276\244.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-\351\203\250\347\275\262Elasticsearch\351\233\206\347\276\244.md" new file mode 100644 index 0000000..7c21acd --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK-\351\203\250\347\275\262Elasticsearch\351\233\206\347\276\244.md" @@ -0,0 +1,117 @@ +单节点的ES需要在处理大量数据的时候需要消耗大量内存和CPU资源,数据量大到一定程度就会产生处理瓶颈,甚至会出现宕机。为了解决单节点ES的处理能力的瓶颈及单节点故障问题,我们考虑使用ES集群。 + +## 一、ES集群的优点: + +优化数据处理能力:通过多台ES共同处理数据,提升处理能力,节省时间。 + +容错能力增强:解决了ES单点故障问题,让架构更稳定。 + +数据安全:分布式数据存储,数据更安全 + +**实验部署准备** + +两台ES机器:node1、node2 + +同步时间:chrony + +静态IP:192.168.98.201 192.168.98.202 + +关闭防火墙、selinux + +配置ES yum源 + +``` +准备工作参考https://www.zutuanxue.com/home/4/52_138 + - ELK学习准备 +``` + +## 二、集群部署 + +部署步骤: + +1. node1、node2安装jdk、Elasticsearch软件包 +2. node1、node2设置配置文件配置集群 +3. 启动ES验证集群 + +### 2.1、软件包安装 + +``` +软件包安装,机器node1 node2 + +以node1为例 +jdk安装通过rpm软件包 +[root@node1 ~]# rpm -ivh jdk-13.0.2_linux-x64_bin.rpm + +Elasticsearch安装通过rpm软件包 +[root@node1 ~]# rpm -ivh elasticsearch-7.6.0-x86_64.rpm +``` + +### 2.2、node1、node2设置配置文件配置集群 + +``` +配置文件修改 +[root@node1 ~]# egrep -v "(^#|^$)" /etc/elasticsearch/elasticsearch.yml +cluster.name: zutuanxue_elk 集群名称,所有节点必须一样 +node.name: node1 节点名称 +#node.master: true 定义为主 +path.data: /var/lib/elasticsearch 数据路径 +path.logs: /var/log/elasticsearch 日志路径 +network.host: 0.0.0.0 监听地址 +http.port: 9200 监听端口 +discovery.seed_hosts: ["node1", "node2"] 可扫描监控的主机 +cluster.initial_master_nodes: ["node1", "node2"] 开启服务的时候谁可以竞选为主[第一次启动集群] + +node2配置文件 +[root@node2 elasticsearch]# egrep -v "(^#|^$)" /etc/elasticsearch/elasticsearch.yml +cluster.name: zutuanxue_elk +node.name: node2 +path.data: /var/lib/elasticsearch +path.logs: /var/log/elasticsearch +network.host: 192.168.98.202 +discovery.seed_hosts: ["node1", "node2"] +cluster.initial_master_nodes: ["node1", "node2"] + +拓展 +当您想要与其他主机上的节点组成群集时,你必须使用 discovery.seed_hosts 来提供群集中可以成为master ,可能存在并且可以连接到的其他节点的列表,使得 discovery process 能够发现节点)。此设置通常应包含群集中所有可以成为master节点的地址。需要注意的是,IPv6主机必须放在括号内。此设置的默认值为127.0.0.1,[::1]。 + + +cluster.initial_master_nodes +当你第一次启动全新的Elasticsearch集群时,会有一个集群引导(cluster bootstrapping)步骤,这个步骤会确定一个在第一次选举中投票被计数的、并且可以成为master节点的集合。 +cluster.initial_master_nodes参数说明:es7 引用了 [Bootstrapping a cluster](https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-discovery-bootstrap-cluster.html) 后,首次启动Elasticsearch集群需要在集群中的一个或多个符合主节点的节点上显式定义初始的符合主节点的节点集。这称为群集自举,这仅在群集首次启动时才需要。 +``` + +### 2.3 启动ES验证集群 + +``` +启动ES +[root@node1 ~]# systemctl restart elasticsearch +[root@node2 ~]# systemctl restart elasticsearch +确保服务正常启动:端口正常打开 +``` + +### 2.4 集群测试 + +web站点测试方法:http://192.168.98.201:9200/_cluster/health?pretty + +![04_es_cluster.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601974986968.png) + +``` +页面输出介绍 +{ + "cluster_name" : "zutuanxue_elk", #集群名称 + "status" : "green", #集群状态 + "timed_out" : false, #超时设置 + "number_of_nodes" : 2, #集群节点数量 + "number_of_data_nodes" : 2, #集群数据节点数量 + "active_primary_shards" : 0, + "active_shards" : 0, + "relocating_shards" : 0, + "initializing_shards" : 0, + "unassigned_shards" : 0, + "delayed_unassigned_shards" : 0, + "number_of_pending_tasks" : 0, + "number_of_in_flight_fetch" : 0, + "task_max_waiting_in_queue_millis" : 0, + "active_shards_percent_as_number" : 100.0 +} +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK\344\273\213\347\273\215.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK\344\273\213\347\273\215.md" new file mode 100644 index 0000000..86302e2 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK\344\273\213\347\273\215.md" @@ -0,0 +1,165 @@ +## 一、项目背景 + +运维人员需要对系统和业务日志进行精准把控,便于分析系统和业务状态。日志分布在不同的服务器上,传统的使用传统的方法依次登录每台服务器查看日志,既繁琐又效率低下。所以我们需要**集中化**的日志管理工具将**位于不同服务器上的日志收集到一起, 然后进行分析,展示**。 + +前面我们学习过rsyslog,它就可以实现集中化的日志管理,可是rsyslog集中后的日志实现统计与检索又成了一个问题。使用wc, grep, awk等相关命令可以实现统计与检索,但如果要求更高的场景,这些命令也会力不从心。所以我们需要一套专业的日志收集分析展示系统。 + +## 二、项目分析 + +### 2.1、数据分析流程 + +1. 数据收集 +2. 数据分析 +3. 数据展示 + +明确数据分析流程后,我们来看一下能够进行数据处理的软件-ELK + +ELK是一套开源的日志分析系统,由elasticsearch+logstash+Kibana组成。它可以实时的收集、处理、展示分析数据,可以让人通过图表直观的看到数据分析结果。 + +ELK一般应用数据分析领域比如: + + 日志分析处理 + + 结合Hadoop实现大数据分析处理和展示 + + 数据搜索 + +## 三、认识ELK + +**ELK介绍** + +ELK是一套开源的日志分析系统,由elasticsearch+logstash+Kibana组成。 + +官网说明:https://www.elastic.co/cn/products + +首先: 先一句话简单了解E,L,K这三个软件 + +Elasticsearch 垃圾处理厂 +Elasticsearch 是基于 JSON 的分布式搜索和分析引擎,专为实现水平扩展、高可靠性和管理便捷性而设计 + +Elasticsearch 是一个分布式的 RESTful 风格的搜索和数据分析引擎,能够解决不断涌现出的各种用例。作为 Elastic Stack 的核心,它集中存储您的数据,帮助您发现意料之中以及意料之外的情况。 + +Logstash 垃圾中转站 + +Logstash 是动态数据收集管道,拥有可扩展的插件生态系统,能够与 Elasticsearch 产生强大的协同作用。 +Logstash 是开源的服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到您最喜欢的 “存储库” 中。(我们的存储库当然是 Elasticsearch) + +Kibana 垃圾处理报表 +Kibana 能够以图表的形式呈现数据,并且具有可扩展的用户界面,供您全方位配置和管理 Elastic Stack。 + +Kibana 让您能够自由地选择如何呈现您的数据。或许您一开始并不知道自己想要什么。不过借助 Kibana 的交互式可视化,您可以先从一个问题出发,看看能够从中发现些什么。 +一张图片胜过千万行日志 + +Beats 垃圾桶 垃圾回收车 +Beats 是轻量型采集器的平台,从边缘机器向 Logstash 和 Elasticsearch 发送数据。 + +Beats 是数据采集的得力工具。将这些采集器安装在您的服务器中,它们就会把数据汇总到 Elasticsearch。如果需要更加强大的处理性能,Beats 还能将数据输送到 Logstash 进行转换和解析。 + +![elk架构图.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601974367132.png) + +ELK下载地址:https://www.elastic.co/cn/downloads + +![elk_download_page.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601974302132.png) + +## 四、ELK学习准备 + +### 4.1、实验拓扑图: + +![elk部署图3933846.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601974397761.png) + +- 收集系统日志 + + F-E-K + + L-E-K + + F-L-E-K + +- 收集web服务器access.log日志 + +- 收集mysql slow日志 + +### 4.2、部署前准备 + +- 静态IP(要求能上公网,最好用虚拟机的NAT网络类型上网) +- 主机名及IP绑定 +- 关闭防火墙和selinux +- 时间同步 chrony +- yum源(centos安装完系统后的默认yum源就OK) + +1. 所有服务器全部采用静态ip + + | 主机名称 | IP地址 | 角色 | + | -------- | ----------------- | -------------------- | + | manage01 | 192.168.98.200/24 | kibana数据展示 | + | node1 | 192.168.98.201/24 | ES1 | + | node2 | 192.168.98.202/24 | ES2 | + | node3 | 192.168.98.203/24 | logstash或(业务机器) | + | node4 | 192.168.98.204/24 | filebeat-业务机器 | + +2. 主机名及IP互相绑定 + + ``` + [root@manage01 ~]# cat /etc/hosts + 127.0.0.1 localhost + ::1 localhost + 192.168.98.200 manage01 + 192.168.98.201 node1 + 192.168.98.202 node2 + 192.168.98.203 node3 + 192.168.98.204 node4 + + 其他机器同理 + ``` + +3. 关闭防火墙, selinux + + ``` + [root@manage01 ~]# systemctl disable firewalld + [root@manage01 ~]# iptables -F + [root@manage01 ~]# iptables -t nat -F + [root@manage01 ~]# sed -i -r '/SELINUX=/c\SELINUX=disabled' /etc/selinux/config + [root@manage01 ~]# reboot + + + 其他机器同理 + ``` + +4. 采用时间服务器,时间同步 + + ``` + 1、修改配置文件,配置时间服务器为阿里云的时间服务器 + [root@manage01 ~]# egrep "^server" /etc/chrony.conf + server ntp1.aliyun.com + server ntp2.aliyun.com + server ntp3.aliyun.com + server ntp4.aliyun.com + + #注释 + # pool 2.centos.pool.ntp.org iburst + + 2、重启服务chronyd + [root@manage01 ~]# systemctl restart chronyd.service + + 3、查看源信息 + #chronyc chrony的命令行客户端 + [root@manage01 ~]# chronyc sources -v + 210 Number of sources = 2 + + .-- Source mode '^' = server, '=' = peer, '#' = local clock. + / .- Source state '*' = current synced, '+' = combined , '-' = not combined, + | / '?' = unreachable, 'x' = time may be in error, '~' = time too variable. + || .- xxxx [ yyyy ] +/- zzzz + || Reachability register (octal) -. | xxxx = adjusted offset, + || Log2(Polling interval) --. | | yyyy = measured offset, + || \ | | zzzz = estimated error. + || | | \ + MS Name/IP address Stratum Poll Reach LastRx Last sample + =============================================================================== + ^? 120.25.115.20 2 6 1 3 +663us[ +663us] +/- 23ms + ^? 203.107.6.88 2 6 1 2 -1326us[-1326us] +/- 17ms + ``` + +5. yum源设置 + + 建议采用默认yum源就可以 \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK\346\224\266\351\233\206nginx access_log\346\227\245\345\277\227.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK\346\224\266\351\233\206nginx access_log\346\227\245\345\277\227.md" new file mode 100644 index 0000000..bb21bba --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK\346\224\266\351\233\206nginx access_log\346\227\245\345\277\227.md" @@ -0,0 +1,110 @@ +## 一、案例分析 + +公司为了每天都能够随时看到公司WEB业务的实时运行情况,希望运维通过分析access.log日志信息,实时展示一下数据给公司的运营部门: + +- 统计不同返回值的数量 +- 统计访问前5名的IP地址 +- 统计每日PV +- 统计每日UV +- ……. + +## 二、nginx access_log定义json格式日志 + +- 部署nginx +- 设置nginx 访问日志为json格式 + +a、部署nginx服务 + +``` +[root@node4 ~]# tar xf nginx-*.rpm +[root@node4 ~]# cd nginx-*.rpm +[root@node4 ~]# yum -y install pcre-devel zlib-devel gcc-* +[root@node4 ~]# ./configure --prefix=/usr/local +[root@node4 ~]# make +[root@node4 ~]# make install +``` + +b、设置nginx 访问日志为json格式 + +由于ES是基于json来处理数据的,所以给ES的数据就必须是JSON数据,只有这样才能通过json将数据进行分析、统计。为了能让ES能分析access.log日志,我们让nginx直接将该日志的格式设置为json格式。 + +``` +[root@node4 ~]# vim /usr/local/nginx/conf/nginx.conf + +log_format main_json '{"@timestamp":"$time_local",' +'"N_client_ip": "$remote_addr",' +'"N_request": "$request",' +'"N_request_time": "$request_time",' +'"N_status": "$status",' +'"N_bytes": "$body_bytes_sent",' +'"N_user_agent": "$http_user_agent",' +'"N_x_forwarded": "$http_x_forwarded_for",' +'"N_referer": "$http_referer"' +'}'; + + access_log logs/access.log main_json; +``` + +## 三、日志收集 + +filebeat设置-修改配置文件定义日志收集 + +``` +[root@node4 ~]# egrep -v "(#|^$)" /etc/filebeat/filebeat.yml +filebeat.inputs: +- type: log + enabled: true + paths: + - /usr/local/nginx/logs/access.log + #添加以下两行,定义收集的是json日志 + json.keys_under_root: true + json.overwrite_keys: true +filebeat.config.modules: + path: ${path.config}/modules.d/*.yml + reload.enabled: false +setup.template.settings: + index.number_of_shards: 1 +setup.kibana: + host: "192.168.98.200:5601" +output.logstash: + hosts: ["192.168.98.203:5044"] +processors: + - add_host_metadata: ~ + - add_cloud_metadata: ~ +``` + +logstash设置-配置业务文件,接收Filebeat发送的数据,然后将数据发送给ES + +``` +[root@node3 conf.d]# cat f_to_e.conf +input { + beats { + port => 5044 + } +} + +output { + elasticsearch { + hosts => ["192.168.98.202:9200"] + index => "nginx-%{+YYYY.MM.dd}" + } + stdout { + codec => rubydebug + } +} +``` + +#### kibana + +创建索引,添加nginx数据 + +## 四、kibana展示 + +统计不同返回值的数量 饼图 + +统计访问前5名的IP地址 柱形图 + +统计每日PV 仪表盘 + +统计每日UV 计数 +![52nginx_access.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601978343835.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK\346\225\260\346\215\256\347\256\241\347\220\206\345\267\245\345\205\267ES-Head\345\272\224\347\224\250.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK\346\225\260\346\215\256\347\256\241\347\220\206\345\267\245\345\205\267ES-Head\345\272\224\347\224\250.md" new file mode 100644 index 0000000..34c2f61 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK\346\225\260\346\215\256\347\256\241\347\220\206\345\267\245\345\205\267ES-Head\345\272\224\347\224\250.md" @@ -0,0 +1,124 @@ +## 一、ES-head web UI界面 + +##### **ES-head web UI界面介绍** + +http://ES-head_ip:9100 + +![10_eshead_webUI.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601976096817.png) + +``` +概览:显示ES集群及节点状态 +索引:索引管理 +数据浏览:查看某个索引中的数据 +基本查询:查询索引中的所有数据 +复合查询:数据管理[上传数据、查看数据、删除数据 doc] +``` + +##### **索引管理** + +- 创建索引 +- 管理索引 +- 删除索引 + +a、创建索引 + +![11_eshead_index创建1729565.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601976114109.png) + +选择索引标签–新建索引 + +![12_eshead_index创建.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601976152442.png) + +``` +索引名称:根据业务起名字 +分片数:创建多少个shard分片 +副本数:需要多少个ES集群节点存储 +``` + +b、查看索引 + +![13_eshead_index创建.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601976222734.png) + +可以看到新创建的索引 zutuanxue_com_log 以及大小和文档数 + +也可以通过概述查看索引分片情况 + +![14_eshead_index查看.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601976236172.png) + +主从分片有区分的,加粗的是主分片 + +c、索引管理 + +![15_eshead_index管理.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601976261727.png) + +d、索引删除 + +![16_eshead_index删除.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601976285003.png) + +##### **数据查询** + +- 符合查询 +- 基本查询 + +a、复合查询 + + 1)存储数据 + + 2)查询数据 + + 3)删除某条数据 + +1)存储数据 + +上传数据[提前创建好存储索引] + +指定索引和type:zutuanxue_com_log/test + +``` +type是一个index中用来区分类似的数据的,但是可能有不同的fields,而且有不同的属性来控制索引建立、分词器。 +``` + +![17_eshead_复合查询_提交数据.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601976302432.png) + +key是列Field(字段)的名字 + +2)查询数据 + +查询方法:index/type/id + +``` +id获得方法: +1)基本查询 +2)数据浏览 +``` + +![18_eshead_复合查询_查询数据.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601976323265.png) + +**数据删除** + +通过复合查询删除指定数据 + +删除方法:删除数据的 索引/类型/id 删除方法:DELETE + +![21_eshead_复合查询_删除数据.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601976342235.png) + +查询结果 + +![22_eshead_复合查询_删除数据1830276.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601976392933.png) + +**基本查询** + +查询索引中的数据 + +![19_eshead_基本查询_查询数据.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601976411566.png) + +显示数据 + + + +![20_eshead_基本查询_数据显示.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601976431959.png) + +**数据浏览** + +浏览索引中的所有数据 + +![23_eshead数据浏览.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601976447902.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK\346\225\260\346\215\256\347\256\241\347\220\206\345\267\245\345\205\267ES-Head\351\203\250\347\275\262.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK\346\225\260\346\215\256\347\256\241\347\220\206\345\267\245\345\205\267ES-Head\351\203\250\347\275\262.md" new file mode 100644 index 0000000..011c39f --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\346\236\204\345\273\272\345\217\257\350\247\206\345\214\226\346\225\260\346\215\256\345\210\206\346\236\220\347\263\273\347\273\237-ELK/ELK\346\225\260\346\215\256\347\256\241\347\220\206\345\267\245\345\205\267ES-Head\351\203\250\347\275\262.md" @@ -0,0 +1,359 @@ +## 一、elasticsearch-head介绍 + +elasticsearch-head是 ES集群管理、索引数据可视化、增删改查、查询语句可视化 工具。 + +ES集群管理 ES集群上的数据索引管理和查询 查看索引中的某条数据 + +从ES5版本后安装方式和ES2以上的版本有很大的不同,在ES2中可以直接在bin目录下执行plugin install xxxx 来进行安装,但是在ES5中这种安装方式变了,要想在ES5中安装Elasticsearch Head必须要安装NodeJs,然后通过NodeJS来启动Head。 + +**官网下载地址**:https://github.com/mobz/elasticsearch-head + +**安装机器**:node1 集群机器,生产环境下建议两台或多天进行容灾 + +安装方法: + +- nodejs +- es-head + +## 二、elasticsearch-head部署 + +### 2.1、安装依赖包-node.js + +a、下载软件包 + +``` +[root@node1 ~]# wget https://nodejs.org/dist/v13.8.0/node-v13.8.0-linux-x64.tar.xz +``` + +b、安装node.js + +``` +[root@node1 ~]# tar xf node-v13.8.0-linux-x64.tar.xz +[root@node1 ~]# mv node-v13.8.0-linux-x64 /usr/local/nodejs + +#可以看出是免安装版的软件 +[root@node1 ~]# cd /usr/local/nodejs/ +[root@node1 nodejs]# ls +bin CHANGELOG.md include lib LICENSE README.md share + +#链接命令 +[root@node1 nodejs]# ln -sf /usr/local/nodejs/bin/* /usr/local/bin/ + +#验证链接,确保正确 +[root@node1 nodejs]# ll /usr/local/bin/node +lrwxrwxrwx 1 root root 26 2月 14 12:01 /usr/local/bin/node -> /usr/local/nodejs/bin/node +[root@node1 nodejs]# ll /usr/local/bin/npm +lrwxrwxrwx 1 root root 25 2月 14 12:01 /usr/local/bin/npm -> /usr/local/nodejs/bin/npm + +#验证node版本 +[root@node1 nodejs]# node -v +v13.8.0 + +#升级npm为最新,npm是 Node.js 的包管理器,类似于yum +[root@node1 nodejs]# npm update -g npm +/usr/local/nodejs/bin/npm -> /usr/local/nodejs/lib/node_modules/npm/bin/npm-cli.js +/usr/local/nodejs/bin/npx -> /usr/local/nodejs/lib/node_modules/npm/bin/npx-cli.js ++ npm@6.13.7 +added 7 packages from 3 contributors, removed 3 packages and updated 11 packages in 7.6s +``` + +### 2.2、elasticsearch-head部署 + +es-head是基于nodejs开发的一个前端网站 + +官网有安装说明,可以通过git安装,也可以下载zip包解压安装 + +这里去下载相应的软件包,并拷贝到ES集群的一个节点上(我这里拷贝到192.168.98.202这台,也就是node2上) + +a、下载ES-head + +``` +[root@node1 ~]# git clone git://github.com/mobz/elasticsearch-head.git +正克隆到 'elasticsearch-head'... +remote: Enumerating objects: 77, done. +remote: Counting objects: 100% (77/77), done. +remote: Compressing objects: 100% (57/57), done. +remote: Total 4337 (delta 38), reused 46 (delta 17), pack-reused 4260 +接收对象中: 100% (4337/4337), 2.51 MiB | 26.00 KiB/s, 完成. +处理 delta 中: 100% (2411/2411), 完成. +``` + +b、安装es-head + +``` +安装grunt服务 +#grunt作为一个前端构建工具,有资源压缩,代码检查,文件合并等功能。 +#构建nodejs代码 es-head并发布代码 +[root@node1 ~]# cd elasticsearch-head/ +[root@node1 elasticsearch-head]# npm install -g grunt-cli +/usr/local/nodejs/bin/grunt -> /usr/local/nodejs/lib/node_modules/grunt-cli/bin/grunt ++ grunt-cli@1.3.2 +added 150 packages from 121 contributors in 32.255s +``` + +c、安装插件 + +``` +[root@node1 elasticsearch-head]# npm install +#安装不成功的插件,手动在单独安装一下,依赖存在源码根目录package.json文件中 +npm WARN deprecated http2@3.3.7: Use the built-in module in node 9.0.0 or newer, instead +npm WARN deprecated coffee-script@1.10.0: CoffeeScript on NPM has moved to "coffeescript" (no hyphen) +npm WARN deprecated core-js@2.6.11: core-js@<3 is no longer maintained and not recommended for usage due to the number of issues. Please, upgrade your dependencies to the actual version of core-js@3. +npm WARN deprecated phantomjs-prebuilt@2.1.16: this package is now deprecated +npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142 +npm WARN deprecated json3@3.3.2: Please use the native JSON object instead of JSON 3 +npm WARN deprecated json3@3.2.6: Please use the native JSON object instead of JSON 3 + +> phantomjs-prebuilt@2.1.16 install /root/elasticsearch-head/node_modules/phantomjs-prebuilt +> node install.js + +PhantomJS not found on PATH +Downloading https://github.com/Medium/phantomjs/releases/download/v2.1.1/phantomjs-2.1.1-linux-x86_64.tar.bz2 +Saving to /tmp/phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2 +Receiving... + [==================================------] 84% +Received 22866K total. +Extracting tar contents (via spawned process) +Removing /root/elasticsearch-head/node_modules/phantomjs-prebuilt/lib/phantom +Copying extracted folder /tmp/phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2-extract-1581725015606/phantomjs-2.1.1-linux-x86_64 -> /root/elasticsearch-head/node_modules/phantomjs-prebuilt/lib/phantom +Phantom installation failed [Error: EACCES: permission denied, link '/tmp/phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2-extract-1581725015606/phantomjs-2.1.1-linux-x86_64' -> '/root/elasticsearch-head/node_modules/phantomjs-prebuilt/lib/phantom'] { + errno: -13, + code: 'EACCES', + syscall: 'link', + path: '/tmp/phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2-extract-1581725015606/phantomjs-2.1.1-linux-x86_64', + dest: '/root/elasticsearch-head/node_modules/phantomjs-prebuilt/lib/phantom' +} Error: EACCES: permission denied, link '/tmp/phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2-extract-1581725015606/phantomjs-2.1.1-linux-x86_64' -> '/root/elasticsearch-head/node_modules/phantomjs-prebuilt/lib/phantom' +npm WARN notsup Unsupported engine for karma@1.3.0: wanted: {"node":"0.10 || 0.12 || 4 || 5 || 6"} (current: {"node":"13.8.0","npm":"6.13.6"}) +npm WARN notsup Not compatible with your version of node/npm: karma@1.3.0 +npm WARN notsup Unsupported engine for http2@3.3.7: wanted: {"node":">=0.12.0 <9.0.0"} (current: {"node":"13.8.0","npm":"6.13.6"}) +npm WARN notsup Not compatible with your version of node/npm: http2@3.3.7 +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.0.0 (node_modules/chokidar/node_modules/fsevents): +npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.11: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"}) +npm WARN elasticsearch-head@0.0.0 license should be a valid SPDX license expression +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: abbrev@1.1.1 (node_modules/fsevents/node_modules/abbrev): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/abbrev' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.abbrev.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ansi-regex@2.1.1 (node_modules/fsevents/node_modules/ansi-regex): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/ansi-regex' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.ansi-regex.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: aproba@1.2.0 (node_modules/fsevents/node_modules/aproba): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/aproba' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.aproba.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: balanced-match@1.0.0 (node_modules/fsevents/node_modules/balanced-match): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/balanced-match' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.balanced-match.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: chownr@1.1.3 (node_modules/fsevents/node_modules/chownr): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/chownr' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.chownr.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: code-point-at@1.1.0 (node_modules/fsevents/node_modules/code-point-at): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/code-point-at' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.code-point-at.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: concat-map@0.0.1 (node_modules/fsevents/node_modules/concat-map): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/concat-map' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.concat-map.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: console-control-strings@1.1.0 (node_modules/fsevents/node_modules/console-control-strings): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/console-control-strings' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.console-control-strings.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: core-util-is@1.0.2 (node_modules/fsevents/node_modules/core-util-is): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/core-util-is' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.core-util-is.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: deep-extend@0.6.0 (node_modules/fsevents/node_modules/deep-extend): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/deep-extend' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.deep-extend.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: delegates@1.0.0 (node_modules/fsevents/node_modules/delegates): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/delegates' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.delegates.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: detect-libc@1.0.3 (node_modules/fsevents/node_modules/detect-libc): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/detect-libc' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.detect-libc.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fs.realpath@1.0.0 (node_modules/fsevents/node_modules/fs.realpath): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/fs.realpath' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.fs.realpath.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: has-unicode@2.0.1 (node_modules/fsevents/node_modules/has-unicode): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/has-unicode' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.has-unicode.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: inherits@2.0.4 (node_modules/fsevents/node_modules/inherits): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/inherits' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.inherits.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ini@1.3.5 (node_modules/fsevents/node_modules/ini): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/ini' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.ini.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: isarray@1.0.0 (node_modules/fsevents/node_modules/isarray): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/isarray' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.isarray.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: minimist@0.0.8 (node_modules/fsevents/node_modules/minimist): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/minimist' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.minimist.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ms@2.1.2 (node_modules/fsevents/node_modules/ms): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/ms' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.ms.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: npm-normalize-package-bin@1.0.1 (node_modules/fsevents/node_modules/npm-normalize-package-bin): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/npm-normalize-package-bin' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.npm-normalize-package-bin.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: number-is-nan@1.0.1 (node_modules/fsevents/node_modules/number-is-nan): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/number-is-nan' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.number-is-nan.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: object-assign@4.1.1 (node_modules/fsevents/node_modules/object-assign): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/object-assign' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.object-assign.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: os-homedir@1.0.2 (node_modules/fsevents/node_modules/os-homedir): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/os-homedir' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.os-homedir.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: os-tmpdir@1.0.2 (node_modules/fsevents/node_modules/os-tmpdir): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/os-tmpdir' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.os-tmpdir.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: path-is-absolute@1.0.1 (node_modules/fsevents/node_modules/path-is-absolute): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/path-is-absolute' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.path-is-absolute.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: process-nextick-args@2.0.1 (node_modules/fsevents/node_modules/process-nextick-args): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/process-nextick-args' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.process-nextick-args.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: minimist@1.2.0 (node_modules/fsevents/node_modules/rc/node_modules/minimist): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/rc/node_modules/minimist' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/rc/node_modules/.minimist.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: safe-buffer@5.1.2 (node_modules/fsevents/node_modules/safe-buffer): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/safe-buffer' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.safe-buffer.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: safer-buffer@2.1.2 (node_modules/fsevents/node_modules/safer-buffer): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/safer-buffer' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.safer-buffer.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: sax@1.2.4 (node_modules/fsevents/node_modules/sax): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/sax' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.sax.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: semver@5.7.1 (node_modules/fsevents/node_modules/semver): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/semver' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.semver.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: set-blocking@2.0.0 (node_modules/fsevents/node_modules/set-blocking): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/set-blocking' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.set-blocking.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: signal-exit@3.0.2 (node_modules/fsevents/node_modules/signal-exit): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/signal-exit' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.signal-exit.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: strip-json-comments@2.0.1 (node_modules/fsevents/node_modules/strip-json-comments): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/strip-json-comments' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.strip-json-comments.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: util-deprecate@1.0.2 (node_modules/fsevents/node_modules/util-deprecate): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/util-deprecate' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.util-deprecate.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: wrappy@1.0.2 (node_modules/fsevents/node_modules/wrappy): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/wrappy' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.wrappy.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: yallist@3.1.1 (node_modules/fsevents/node_modules/yallist): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/root/elasticsearch-head/node_modules/fsevents/node_modules/yallist' -> '/root/elasticsearch-head/node_modules/fsevents/node_modules/.yallist.DELETE' + +#报错 +npm ERR! code ELIFECYCLE +npm ERR! errno 1 +npm ERR! phantomjs-prebuilt@2.1.16 install: `node install.js` +npm ERR! Exit status 1 +npm ERR! #phantomjs-prebuilt@2.1.16 install script 安装脚本失败 +npm ERR! Failed at the phantomjs-prebuilt@2.1.16 install script. +npm ERR! This is probably not a problem with npm. There is likely additional logging output above. + +npm ERR! A complete log of this run can be found in: +npm ERR! /root/.npm/_logs/2020-02-14T23_45_53_948Z-debug.log + +#收到安装一下,忽略脚本 +[root@node1 elasticsearch-head]# npm install phantomjs-prebuilt@2.1.16 --ignore-script +npm WARN deprecated phantomjs-prebuilt@2.1.16: this package is now deprecated +npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142 +npm notice created a lockfile as package-lock.json. You should commit this file. +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.0.0 (node_modules/chokidar/node_modules/fsevents): +npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.11: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"}) +npm WARN elasticsearch-head@0.0.0 license should be a valid SPDX license expression +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: abbrev@1.1.1 (node_modules/chokidar/node_modules/fsevents/node_modules/abbrev): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/abbrev' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.abbrev.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ansi-regex@2.1.1 (node_modules/chokidar/node_modules/fsevents/node_modules/ansi-regex): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/ansi-regex' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.ansi-regex.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: aproba@1.2.0 (node_modules/chokidar/node_modules/fsevents/node_modules/aproba): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/aproba' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.aproba.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: balanced-match@1.0.0 (node_modules/chokidar/node_modules/fsevents/node_modules/balanced-match): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/balanced-match' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.balanced-match.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: chownr@1.1.3 (node_modules/chokidar/node_modules/fsevents/node_modules/chownr): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/chownr' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.chownr.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: code-point-at@1.1.0 (node_modules/chokidar/node_modules/fsevents/node_modules/code-point-at): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/code-point-at' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.code-point-at.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: concat-map@0.0.1 (node_modules/chokidar/node_modules/fsevents/node_modules/concat-map): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/concat-map' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.concat-map.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: console-control-strings@1.1.0 (node_modules/chokidar/node_modules/fsevents/node_modules/console-control-strings): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/console-control-strings' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.console-control-strings.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: core-util-is@1.0.2 (node_modules/chokidar/node_modules/fsevents/node_modules/core-util-is): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/core-util-is' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.core-util-is.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: deep-extend@0.6.0 (node_modules/chokidar/node_modules/fsevents/node_modules/deep-extend): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/deep-extend' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.deep-extend.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: delegates@1.0.0 (node_modules/chokidar/node_modules/fsevents/node_modules/delegates): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/delegates' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.delegates.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: detect-libc@1.0.3 (node_modules/chokidar/node_modules/fsevents/node_modules/detect-libc): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/detect-libc' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.detect-libc.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fs.realpath@1.0.0 (node_modules/chokidar/node_modules/fsevents/node_modules/fs.realpath): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/fs.realpath' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.fs.realpath.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: has-unicode@2.0.1 (node_modules/chokidar/node_modules/fsevents/node_modules/has-unicode): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/has-unicode' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.has-unicode.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: inherits@2.0.4 (node_modules/chokidar/node_modules/fsevents/node_modules/inherits): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/inherits' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.inherits.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ini@1.3.5 (node_modules/chokidar/node_modules/fsevents/node_modules/ini): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/ini' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.ini.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: isarray@1.0.0 (node_modules/chokidar/node_modules/fsevents/node_modules/isarray): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/isarray' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.isarray.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: minimist@0.0.8 (node_modules/chokidar/node_modules/fsevents/node_modules/minimist): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/minimist' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.minimist.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ms@2.1.2 (node_modules/chokidar/node_modules/fsevents/node_modules/ms): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/ms' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.ms.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: npm-normalize-package-bin@1.0.1 (node_modules/chokidar/node_modules/fsevents/node_modules/npm-normalize-package-bin): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/npm-normalize-package-bin' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.npm-normalize-package-bin.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: number-is-nan@1.0.1 (node_modules/chokidar/node_modules/fsevents/node_modules/number-is-nan): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/number-is-nan' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.number-is-nan.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: object-assign@4.1.1 (node_modules/chokidar/node_modules/fsevents/node_modules/object-assign): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/object-assign' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.object-assign.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: os-homedir@1.0.2 (node_modules/chokidar/node_modules/fsevents/node_modules/os-homedir): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/os-homedir' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.os-homedir.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: os-tmpdir@1.0.2 (node_modules/chokidar/node_modules/fsevents/node_modules/os-tmpdir): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/os-tmpdir' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.os-tmpdir.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: path-is-absolute@1.0.1 (node_modules/chokidar/node_modules/fsevents/node_modules/path-is-absolute): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/path-is-absolute' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.path-is-absolute.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: process-nextick-args@2.0.1 (node_modules/chokidar/node_modules/fsevents/node_modules/process-nextick-args): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/process-nextick-args' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.process-nextick-args.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: minimist@1.2.0 (node_modules/chokidar/node_modules/fsevents/node_modules/rc/node_modules/minimist): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/rc/node_modules/minimist' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/rc/node_modules/.minimist.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: safe-buffer@5.1.2 (node_modules/chokidar/node_modules/fsevents/node_modules/safe-buffer): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/safe-buffer' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.safe-buffer.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: safer-buffer@2.1.2 (node_modules/chokidar/node_modules/fsevents/node_modules/safer-buffer): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/safer-buffer' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.safer-buffer.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: sax@1.2.4 (node_modules/chokidar/node_modules/fsevents/node_modules/sax): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/sax' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.sax.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: semver@5.7.1 (node_modules/chokidar/node_modules/fsevents/node_modules/semver): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/semver' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.semver.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: set-blocking@2.0.0 (node_modules/chokidar/node_modules/fsevents/node_modules/set-blocking): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/set-blocking' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.set-blocking.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: signal-exit@3.0.2 (node_modules/chokidar/node_modules/fsevents/node_modules/signal-exit): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/signal-exit' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.signal-exit.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: strip-json-comments@2.0.1 (node_modules/chokidar/node_modules/fsevents/node_modules/strip-json-comments): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/strip-json-comments' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.strip-json-comments.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: util-deprecate@1.0.2 (node_modules/chokidar/node_modules/fsevents/node_modules/util-deprecate): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/util-deprecate' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.util-deprecate.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: wrappy@1.0.2 (node_modules/chokidar/node_modules/fsevents/node_modules/wrappy): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/wrappy' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.wrappy.DELETE' +npm WARN optional SKIPPING OPTIONAL DEPENDENCY: yallist@3.1.1 (node_modules/chokidar/node_modules/fsevents/node_modules/yallist): +npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/yallist' -> '/usr/local/elasticsearch-head/node_modules/chokidar/node_modules/fsevents/node_modules/.yallist.DELETE' + ++ phantomjs-prebuilt@2.1.16 +added 61 packages from 63 contributors, removed 6 packages and audited 1736 packages in 10.371s + +3 packages are looking for funding + run `npm fund` for details + +found 40 vulnerabilities (18 low, 2 moderate, 20 high) + run `npm audit fix` to fix them, or `npm audit` for details + +#安装完成,后台grunt启动,发布ES-head 前端web +[root@node1 elasticsearch-head]# nohup npm run start & +[1] 38691 +[root@node1 elasticsearch-head]# nohup: 忽略输入并把输出追加到'nohup.out' + +[root@node1 elasticsearch-head]# jobs +[1]+ 运行中 nohup npm run start & +``` + +**测试es-head发布** + +``` +[root@node1 ~]# netstat -ntpl +``` + +![07_grunt_启动验证.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601975985832.png) + +web测试 + +``` +浏览器中输入:http://192.168.98.201:9100/ +``` + +![08_grunt_web启动验证.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601975973100.png) + +**FAQ:连接失败解决方法** + +ES安装成功后,从另外一个域的浏览器访问ES服务器数据,会出现跨域的问题。 + +**解决方案** + +1)修改elasticsearch.yml末尾添加:跨域访问 + +``` +跨域访问 +http.cors.enabled: true +http.cors.allow-origin: "*" +``` + +2)重启elasticsearch服务 + +``` +[root@node1 ~]# systemctl restart elasticsearch +``` + +再次测试 + +![09_grunt_web启动验证成功.png](https://www.zutuanxue.com:8000/static/media/images/2020/10/6/1601976000242.png) \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\231\232\346\213\237\345\214\226\344\271\213KVM/CentOS 8 VNC\350\277\234\347\250\213\346\241\214\351\235\242.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\231\232\346\213\237\345\214\226\344\271\213KVM/CentOS 8 VNC\350\277\234\347\250\213\346\241\214\351\235\242.md" new file mode 100644 index 0000000..dccb780 --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\231\232\346\213\237\345\214\226\344\271\213KVM/CentOS 8 VNC\350\277\234\347\250\213\346\241\214\351\235\242.md" @@ -0,0 +1,89 @@ +## 一、VNC介绍 + +VNC (Virtual Network Console)是虚拟网络控制台的缩写。它 是一款优秀的远程控制工具软件,由著名的 AT&T 的欧洲研究实验室开发的。VNC 是在基于 UNIX和 Linux操作系统的免费的开源软件,远程控制能力强大,高效实用,其性能可以和 Windows和 MAC中的任何远程控制软件媲美。 + +平行软件:向日葵 teamview 远程桌面 + +C/S: client/server模式 + +## 二、VNC部署 + +**部署步骤:** + +- 软件安装 +- 连接验证配置 +- VNC连接管理 + +#### 2.1、安装VNC + +``` +[root@zutuanxue ~]# yum -y install tigervnc-server tigervnc-server-module +``` + +#### 2.2、配置连接密码 + +``` +[root@zutuanxue ~]# vncpasswd $USERNAME +Password: +Verify: +Would you like to enter a view-only password (y/n)? n +A view-only password is not used +``` + +#### 2.3、关闭Wayland + +Wayland 是 GNOME 中的默认显示管理器 (GDM),并且未配置用于处理 Xorg 等远程渲染的 API。取消注释 `/etc/gdm/custom.conf` 中的 `WaylandEnable=false`,以使通过 vnc 进行的远程桌面会话请求由 GNOME 桌面的 xorg 处理,来代替 Wayland 显示管理器。 + +``` + [root@zutuanxue ~]# sed -i '/^#WaylandEnable=/cWaylandEnable=false' /etc/gdm/custom.conf +``` + +#### 2.4、VNC管理 + +**a、启动VNC** + +``` +[root@zutuanxue ~]# vncserver -autokill :1 + +New 'zutuanxue:1 (root)' desktop is zutuanxue:1 + +Starting applications specified in /root/.vnc/xstartup +Log file is /root/.vnc/zutuanxue:1.log + +查看启动 +[root@zutuanxue ~]# netstat -ntpl +Active Internet connections (only servers) +Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name +tcp 0 0 192.168.122.1:53 0.0.0.0:* LISTEN 1310/dnsmasq +tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 918/sshd +tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 917/cupsd +tcp 0 0 0.0.0.0:5601 0.0.0.0:* LISTEN 839/node +tcp 0 0 0.0.0.0:5901 0.0.0.0:* LISTEN 4848/Xvnc +tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 1/systemd +tcp6 0 0 :::22 :::* LISTEN 918/sshd +tcp6 0 0 ::1:631 :::* LISTEN 917/cupsd +tcp6 0 0 :::5901 :::* LISTEN 4848/Xvnc +tcp6 0 0 :::111 + +-autokill +退出图形桌面终止VNC +用户从图形环境注销 终止VNC +每当xstartup脚本退出时自动终止Xvnc。在大多数情况下,这具有终止当用户从窗口管理器注销时使用Xvnc。 +``` + +**b、VNC管理-查看VNC** + +``` +[root@zutuanxue ~]# vncserver -list + +TigerVNC server sessions: + +X DISPLAY # PROCESS ID +:1 2621 +``` + +**c、VNC管理-关闭VNC** + +``` +[root@zutuanxue ~]# vncserver -kill :1 +``` \ No newline at end of file diff --git "a/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\231\232\346\213\237\345\214\226\344\271\213KVM/KVM \345\272\224\347\224\250-\345\210\233\345\273\272\350\231\232\346\213\237\346\234\272.md" "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\231\232\346\213\237\345\214\226\344\271\213KVM/KVM \345\272\224\347\224\250-\345\210\233\345\273\272\350\231\232\346\213\237\346\234\272.md" new file mode 100644 index 0000000..3ecffcd --- /dev/null +++ "b/Linux/1--Linux\344\272\221\350\256\241\347\256\227\350\277\220\347\273\264/\350\231\232\346\213\237\345\214\226\344\271\213KVM/KVM \345\272\224\347\224\250-\345\210\233\345\273\272\350\231\232\346\213\237\346\234\272.md" @@ -0,0 +1,754 @@ +KVM虚拟化部署完成了,接下来我们要做的就是创建一个KVM虚拟机,如何创建呢?本节课程主要讨论。 + +## 一、创建虚拟机方法 + +1. 通过virt-manager虚拟机管理工具创建 +2. 通过web控制台创建虚拟机 +3. 使用virt-install命令创建 + +### 1.1、通过virt-manager虚拟机管理工具创建 + +a、打开虚拟机管理工具(virt-manager),新建一个虚拟机 + +![virtmanager01.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/25/1601029281905.png) + +b、设置虚拟机的安装方法 + +![virtmanager02.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/25/1601029292676.png) + +c、设置虚拟机的安装光盘与安装系统类型 + +![virtmanager03.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/25/1601029304562.png) + +d、设置虚拟机的内存与CPU + +![virtmanager04.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/25/1601029318016.png) + +e、设置虚拟机的磁盘 + +![virtmanager05.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/25/1601029329814.png) + +f、设置虚拟机的名称及网络 + +![virtmanager06.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/25/1601029343926.png) + +h、创建成功 + +![virtmanager07.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/25/1601029354805.png) + +### 1.2、使用web 控制台创建一个虚拟机 + +a、登陆cockpit web控制台 + +![cockpit_web登陆1.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/25/1601029371661.png) + +b、创建虚拟机 + +![cockpit_web创建虚拟机01.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/25/1601029386547.png) + +c、设置虚拟机硬件 + +![cockpit_web创建虚拟机02.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/25/1601029401551.png) + +d、创建成功 + +![cockpit_web创建虚拟机03.png](https://www.zutuanxue.com:8000/static/media/images/2020/9/25/1601029412949.png) + +### 1.3、使用virt-install创建一个虚拟机 + +virt-install是一个命令行工具,用于使用“libvirt”创建新的KVM、Xen或Linux容器guest + +管理程序管理库。 + +virt-install命令是用来让用户可以通过shell命令行创建KVM虚拟机。 + +**创建虚拟机使用virt-install命令** + +``` +[root@zutuanxue ~]# virt-install --name tyschool_web1 --memory 2048 --vcpus 2 \ +--disk size=10 --os-variant rhel8.0 --cdrom /cache/iso/CentOS-8-x86_64-1905-dvd1.iso \ +--graphics vnc,port=5980,listen=192.168.1.200,password=123456 --network \ +network=default,mac=52:54:00:A7:9C:01 + +--name 指定虚拟机名称 +--memory 内存容量 默认单位为MB +--vcpus 虚拟机CPU的数量,不要超过真机的核数 +--disk size= 虚拟机磁盘容量 默认单位GB +--os-variant 虚拟机系统版本 +--cdrom 指定光驱中的光盘 +--graphics vnc,port=5980,listen=192.168.1.200,password=123456 VNC设置 +--network network=default,mac=52:54:00:A7:9C:01 网络设置 +``` + +**virt-install命令的用法** + +``` +virt-install {Options} + +1、通用命令Options: +-n NAME, --name=NAME +新客户虚拟机实例名字,在连接的hypervisor已知的所有虚拟机中必须唯一,包括那些当前未活动的虚拟机。想要重新定义一个已存在的虚拟机,在运行‘virt-install’之前 +使用virsh工具关闭(‘virsh shutdown’)和删除(‘virsh undefine’)此虚拟机。 + +-r MEMORY, --ram=MEMORY +以M为单位指定分配给虚拟机的内存大小,如果hypervisor没有足够的可用内存,它通常自动从主机操作系统使用的内存中获取,以满足此操作分配需要。 + +2、cpu设置 +--arch=ARCH +为虚拟机请求一个非本地CPU架构,这个选项当前只对qemu客户机有效,但是不能够使用加速机制。如果忽略,在虚拟机中将使用主机CPU架构。 + +--vcpus=VCPUS +虚拟机的虚拟CPU数。不是所有hypervisor都支持SMP虚拟机,在这种情况下这个变量将被忽略。 + +--cpuset=CPUSET +设置哪个物理CPU能够被虚拟机使用。“CPUSET”是一个逗号分隔数字列表,也可以指定范围,例如: + +0,2,3,5 : Use processors 0,2,3 and 5 --使用0,2,3 和5 处理器 +1-3,5,6-8 : Use processors 1,2,3,5,6,7 and 8 --使用1,2,3,5,6,7,8 +1-5,^3,8 : 使用处理器1、2、4、5和8 +处理器 +如果此参数值为‘auto’,virt-install将使用NUMA(非一致性内存访问)数据试图自动确定一个优化的CPU定位。 + +3、系统类型指定 +--os-type=OS_TYPE +针对一类操作系统优化虚拟机配置(例如:‘linux’,‘windows’),这将试图选择最适合的ACPI与APIC设置,支持优化鼠标驱动,virtio以及通常适应其他操作系统特性。 +参见"--os-variant" 选项 + +--os-variant=OS_VARIANT +针对特定操作系统变体(例如’fedora8’, ’winxp’)进一步优化虚拟机配置,这个参数是可选的并且不需要与 "--os-type"选项并用,有效值包括: + linux + debianetch + Debian Etch + + debianlenny + Debian Lenny + + fedora5 + Fedora Core 5 + + fedora6 + Fedora Core 6 + + fedora7 + Fedora 7 + + fedora8 + Fedora 8 + + fedora9 + Fedora 9 + + fedora10 + Fedora 10 + + fedora11 + Fedora 11 + + fedora12 + Fedora 12 + + generic24 + Generic 2.4.x kernel + + generic26 + Generic 2.6.x kernel + + virtio26 + Generic 2.6.25 or later kernel with virtio + + rhel2.1 + Red Hat Enterprise Linux 2.1 + + rhel3 + Red Hat Enterprise Linux 3 + + rhel4 + Red Hat Enterprise Linux 4 + + rhel5 + Red Hat Enterprise Linux 5 + + rhel5.4 + Red Hat Enterprise Linux 5.4 or later + + rhel6 + Red Hat Enterprise Linux 6 + + sles10 + Suse Linux Enterprise Server + + ubuntuhardy + Ubuntu 8.04 LTS (Hardy Heron) + + ubuntuintrepid + Ubuntu 8.10 (Intrepid Ibex) + + ubuntujaunty + Ubuntu 9.04 (Jaunty Jackalope) + + other + generic + Generic + + msdos + MS-DOS + + netware4 + Novell Netware 4 + + netware5 + Novell Netware 5 + + netware6 + Novell Netware 6 + + solaris + opensolaris + Sun OpenSolaris + + solaris10 + Sun Solaris 10 + + solaris9 + Sun Solaris 9 + + unix + freebsd6 + Free BSD 6.x + + freebsd7 + Free BSD 7.x + + openbsd4 + Open BSD 4.x + + windows + vista + Microsoft Windows Vista + + win2k + Microsoft Windows 2000 + + win2k3 + Microsoft Windows 2003 + + win2k8 + Microsoft Windows 2008 + + winxp + Microsoft Windows XP (x86) + + winxp64 + Microsoft Windows XP (x86_64) + +--host-device=HOSTDEV +附加一个物理主机设备到客户机。HOSTDEV是随着libvirt使用的一个节点设备名(具体设备如’virsh nodedev-list’的显示的结果) + +4、完全虚拟化特定选项(Full Virtualization specific options) + 在完全虚拟化客户机安装时的特定参数。 + --sound + 附加一个虚拟音频设备到客户机 + + --noapic + 覆盖操作系统类型/变体使APIC(Advanced Programmable Interrupt Controller)设置对全虚拟化无效。 + + --noacpi + 覆盖操作系统类型/变体使ACPI(Advanced Configuration and Power Interface)设置对全虚拟化无效。 + + +5、虚拟化类型选项(Virtualization Type options) + 这些选项覆盖默认虚拟化类型选择。 + -v, --hvm + 如果在主机上全虚拟化和para 虚拟化(para-irtualization如何解释还没有定论,有人称之为半虚拟化),请求使用全虚拟化(full virtualization)。如果在 + 一个没有硬件虚拟化支持的机器上连接Xen hypervisor,这个参数不可用,这个参数意指连接到一个基于qemu的hypervisor。 + + -p, --paravirt + 这个参数意指构建一个paravirtualized客户机。如何主机既支持para又支持 full虚拟化,并且既没有指定本选项也没有指定"--hvm"选项,这个选项是假定选项。 + + --accelerate + 当安装QEMU客户机时,如果支持可用KVM或KQEMU内核加速能力。除非一个客户机操作系统不兼容加速,这个选项是推荐最好加上。如果KVM和KQEMU都支持,KVM加速器优先使用。 + +6、安装方法选项(Installation Method options) + + -c CDROM, --cdrom=CDROM + 对应全虚拟化客户机,文件或设备作为一个虚拟化CD-ROM设备使用,可以是ISO映像路径或者一个CDROM设备,它也可以是一个能够提取/访问最小引导ISO映像的URL, + URL使用与在 "--location" 选项中说明的相同的格式。如果一个CDROM已经通过 "--disk"选项指定,并且 "--cdrom"和其他任何选项都没有指定,"--disk" cdrom将作为安装媒介使用。 + + -l LOCATION, --location=LOCATION + 客户虚拟机kernel+initrd 安装源。LOCATION使用以下格式: + + DIRECTORY + 指向一个包含可安装发行版映像的目录。 + + nfs:host:/path or nfs://host/path + 指向包含可安装发行版映像的NFS服务器位置。 + + http://host/path + 指向包含可安装发行版映像的http服务器位置。 + + ftp://host/path + 指向包含可安装发行版映像的FTP服务器位置。 + + 下面是指定几个特定发行版url的例子: +Fedora/Red Hat Based: https://download.fedoraproject.org/pub/fedora/linux/releases/29/Server/x86_64/os +Debian: https://ftp.us.debian.org/debian/dists/stable/main/installer-amd64/ +Ubuntu: https://us.archive.ubuntu.com/ubuntu/dists/wily/main/installer-amd64/ +Suse: https://download.opensuse.org/pub/opensuse/distribution/leap/42.3/repo/oss/ + + --pxe + 使用PXE(preboot execute environment)加载初始ramdisk 和 kernel,从而起动客户机安装过程。 + + --import + 跳过操作系统安装过程,围绕一个存在的磁盘映像建立客户机。引导使用的设备是通过"--disk" or "--file"指定的第一个设备。 + + --livecd + 指定安装媒介是一个可引导操作系统CD,因此需要将虚拟机配置成永不从CDROM引导。这也许需要与"--nodisks" 标准组合使用。 + + -x EXTRA, --extra-args=EXTRA + 当执行从"--location"选项指定位置的客户机安装时,附加内核命令行参数到安装程序。 + +7、存储配置选项(Storage Configuration) + + --disk=DISKOPTS + 用不同的选项,指定作为客户机存储的媒介。通常的磁盘串格式是: + --disk opt1=val1,opt2=val2,... + + 要知道媒介,必须提供下面选项其中之一: + + path + 要使用的一个指向某些存在后不存在存储媒介的路径。存在的媒介可以是文件或块设备。如在远程主机安装,存在的媒介必须被共享为一个libvirt存储卷。 + + 指定一个不存在的路径意指试图建立一个新的存储,并且需要知道一个‘size’值。如果路径的基目录是一个在主机上的libvirt存储池,新存储将被建立为一个 + libvirt存储卷。对于远程主机,如果使用此方法,基目录需要是一个存储池。 + + pool + 一个要在其上建立新存储的已有的libvirt存储池名,需要指定一个‘size’值。 + + vol + 要使用的一个已有的libvirt存储卷,指定格式类似’poolname/volname’ + +8、其他可用选项(Other available options) + + device + 磁盘设备类型。取值是’cdrom’, ’disk’, or ’floppy’,默认为 ’disk’。如果’cdrom’作为指定值并且没有选择安装方法,cdrom将被作为安装媒介。 + + bus + 磁盘总线类型,取值是’ide’, ’scsi’,’usb’, ’virtio’ 或 ’xen’,由于不是所有的hypervisor对所有总线类型都支持,因此默认值为依赖于所使用的hypervisor。 + + perms + 磁盘权限,取值为’rw’ (读/写), ’ro’ (只读), or ’sh’ (共享 读/写),默认值为’rw' + + size + 以GB为单位的新建存储大小。 + + sparse + 指定建立的存储是否跳过完全分配。取值为 ’true’ 或 ’false’。 + --所谓的完全分配是指在建立文件后即分配给其规定的所有空间,所谓的sparse是指根据使用情况逐渐增加空间。 + 初始时对客户机虚拟磁盘采用全分配策略(sparse=false)通常在客户机内部通过提供更快的安装时间获得平衡。因此在主机文件系统可能被填满时推荐使用 + 此选项以确保高性能和避免I/O错误。 + + cache + 使用缓存模式,,主机页面缓存提供内存缓存。此选项取值包括’none’, ’writethrough’, 或 ’writeback’, ’writethrough’提供读缓存,’writeback’提供 + 读和写缓存。 + + 参加例子一节中的一些使用。这个选项屏蔽 "--file", "--file-size"和 "--nonsparse"选项。 + + -f DISKFILE, --file=DISKFILE + 指向作为客户机虚拟磁盘后台存储的文件、磁盘分区或逻辑卷。这个选项与"--disk"选项指定一个即可。 + + favor of "--disk". + + -s DISKSIZE, --file-size=DISKSIZE + 作为客户机虚拟磁盘的文件大小。这个选项不能与"--disk"选项同时使用。 + + --nonsparse + 指定在建立存储时机分配全部空间。这个选项不能与"--disk"选项同时使用。 + + --nodisks + 请求一个没有任何本地磁盘存储的虚拟机,典型应用在运行’Live CD’映像或安装到网络存储(iSCSI或NFS root)时。 + +9、网络配置选项(Networking Configuration) + + -w NETWORK, --network=NETWORK + 连接客户机到主机网络。"NETWORK"可采用一下任何一种值: + + bridge:BRIDGE + 连接到主机上名称为"BRIDGE"的桥接设备。如果主机具有静态网络配置和客户机需要与局域网进行全面的入站出站连接时使用此选项。在客户机使用在线迁移时也使用此选项。 + + network:NAME + 连接到主机上名称为"NAME"的虚拟网络。虚拟网络可以使用"virsh"命令行工具列出、建立和删除。未经修改的“libvirt”安装通常有一个名字为“default”的虚拟 + 网络。在主机使用动态网络或无线网时使用虚拟网络。任何一个连接活动时客户机将通过地址转换将连接请求转到局域网。 + + user + 使用SLIRP连接到局域网。只有没有特权的用户运行一个QEMU客户机时才使用本选项。这种方法从网络地址转换(NAT)提供了非常有限的方式。 + + 如果忽略此选项,将在客户机中建立一个单网络接口卡(NIC),如果在主机中有一个与物理网卡绑定的桥接设备,将用此设备进行网络连接。做不到这一点,被成之为 + "default"的虚拟网络将被使用。这个选项可以被指定多次从而设置多个网卡。 + + -b BRIDGE, --bridge=BRIDGE + 指定连接客户机网卡的桥接设备。这个参数不能与 "--network"选项共同使用。指定 + + -m MAC, --mac=MAC + 指定客户机网卡物理地址;如果忽略这个参数或者指定了值"RANDOM",将随机产生一个适当的地址。对应基于Xen的虚拟机,物理地址中最先的3对必须是’00:16:3e’, + 而QEMU或KVM虚拟机必须是’54:52:00’。 + + --nonetworks + 请求一个没有任何网卡的虚拟机。 + +10、图形化配置(Graphics Configuration) + + 如果没有指定图形选项,在DISPLAY环境变量已经设置的情况下,"virt-install" 将默认使用--vnc选项,否则将使用--nographics选项。 + + --vnc + 在客户机中设置一个虚拟控制台并且将其导出为一个VNC服务。除非"--vncport" 参数也已提供,VNC服务将运行在5900或其之上第一个未用的端口号。实际的VNC显示 + 可以使用"virsh"的"vncdisplay"命令(或者使用virt-viewer处理这个细节)。 + + --vncport=VNCPORT + 为客户机VNC控制台请求一个永久、静态的指定端口号。当其他客户机自动选择端口号时不鼓励使用此选项,因为可能产生冲突。 + + --sdl + 在客户机中设置一个虚拟控制台并且在主机中显示一个SDL窗口来呈现输出。如果SDL窗口被关闭,客户机将被无条件终止。 + + --nographics + 指定没有控制台被分配给客户机。全虚拟化客户机(Xen FV或者QEMU/KVM)将需要在客户机第一个串口有一个文本控制台配置(这可以通过--extra-args选项实现)。 + Xen PV将自动进行设置。命令’virsh console NAME’被用来连接串行设备。 + + --noautoconsole + 使用本选项指定不自动试图连接到客户机控制台。默认行为是调用一个VNC客户端显示图形控制台,或者运行 "virsh" "console"命令显示文本控制台。 + + -k KEYMAP, --keymap=KEYMAP + 请求将虚拟VNC控制台配置为非英语键盘布局。 + +11、Miscellaneous Options + + -d, --debug + 在安装过程中,打印调试信息到终端。即使忽略此选项,调试信息也保存在当前用户home目录下的.virtinst/virt-install.log文件中。 + + --noreboot + 防止域(虚拟机)在安装完成后自动重启。 + + --wait=WAIT + 设置以分钟为单位的等待虚拟机完成其安装的时间。没有这个的选项,virt-install将等待控制台关闭(不必要指示客户机已经关闭),或者在--noautoconsole选项 + 指定的情况下,简单地开始安装并退出。任何负值将使virt-install无限等待,0值将触发与--noauotoconsole选项相同的结果。如果超出时间限制,virt-install只是简单的退出,保留虚拟机在其当前状态。 + + --force + 防止交互式提示。如果预期的提示为是/否,总是回答是。对应任何其他提示,应用将退出。 + + --prompt + 提供交互模式,提示选择和输入建立虚拟机必要的信息。默认情况下提示功能是关闭的。 + +12、例子(EXAMPLES) +virt-install --name rhel9 \ +--vcpus 2 \ +--ram 1024 \ +--disk /var/lib/libvirt/images/rhel8.img --import \ +--graphics vnc,port=5909,listen=192.168.19.254 \ +--os-variant rhel6 \ +--virt-type kvm \ +--network brIdge="br0",mac=52:54:00:A7:9C:09 + + + +--network network=defalut + + +#从物理机的光驱开始安装 +virt-install --name rhel9 \ +--vcpus 2 \ +--ram 1024 \ +--disk /var/lib/libvirt/images/rhel8.img +--graphics vnc,port=5909,listen=192.168.19.254 \ +--os-variant rhel6 \ +--virt-type kvm \ +--network network=default +--cdrom /dev/cdrom + +##使用镜像安装 +virt-install --name rhel9 \ +--vcpus 2 \ +--ram 1024 \ +--disk /var/lib/libvirt/images/rhel8.img +--graphics vnc,port=5909,listen=192.168.19.254 \ +--os-variant rhel6 \ +--virt-type kvm \ +--network network=default +--cdrom /tmp/rhel6.iso + + +##使用PXE安装 + +virt-install --name rhel9 \ +--vcpus 2 \ +--ram 1024 \ +--disk /var/lib/libvirt/images/rhel8.img,size=10,format=raw \ +--graphics vnc,port=5909,listen=192.168.19.254 \ +--os-variant rhel6 \ +--virt-type kvm \ +--network network=default +--location ftp://192.168.122.1/pub +``` + +## 二、KVM相关目录及虚拟机配置文件 + +### 2.1、相关目录及文件 + +KVM虚拟机目录: /var/lib/libvirt/ + +镜像及磁盘目录: /var/lib/libvirt/images + +libvirt目录:/etc/libvirt + +``` +[root@zutuanxue libvirt]# tree +. +├── libvirt-admin.conf +├── libvirt.conf 针对virsh命令主要是关于客户端的配置文件,一般默认的就满足要求了 +├── libvirtd.conf 主要是针对服务器端的配置文件,它提供了不同的安全选项,请求限制和日志选项。 +├── nwfilter 网络管理 +│ ├── allow-arp.xml +│ ├── allow-dhcp-server.xml +│ ├── allow-dhcp.xml +│ ├── allow-incoming-ipv4.xml +│ ├── allow-ipv4.xml +│ ├── clean-traffic-gateway.xml +│ ├── clean-traffic.xml +│ ├── no-arp-ip-spoofing.xml +│ ├── no-arp-mac-spoofing.xml +│ ├── no-arp-spoofing.xml +│ ├── no-ip-multicast.xml +│ ├── no-ip-spoofing.xml +│ ├── no-mac-broadcast.xml +│ ├── no-mac-spoofing.xml +│ ├── no-other-l2-traffic.xml +│ ├── no-other-rarp-traffic.xml +│ ├── qemu-announce-self-rarp.xml +│ └── qemu-announce-self.xml +├── qemu +│ ├── networks 虚拟机网络相关配置文件 +│ │ ├── autostart +│ │ │ └── default.xml -> ../default.xml +│ │ └── default.xml +│ └── tyschool_web1.xml 虚拟机配置文件 +├── qemu.conf qemu配置文件 +├── qemu-lockd.conf +├── secrets +├── storage 虚拟机存储域 +│ ├── autostart +│ │ ├── default.xml -> /etc/libvirt/storage/default.xml +│ │ └── ISO.xml -> /etc/libvirt/storage/ISO.xml +│ ├── default.xml +│ └── ISO.xml +├── virtlockd.conf +└── virtlogd.conf +``` + +### 2.2、虚拟机配置文件 + +[root@zutuanxue ~]# cat /etc/libvirt/qemu/tyschool_web1.xml + +``` +[root@zutuanxue ~]# cat /etc/libvirt/qemu/tyschool_web1.xml + +虚拟化类型 kvm + + 虚拟机名字 + tyschool_web1 + 虚拟机UUID + 78d9ca74-3ab3-44b3-99f6-12ca3e315fab + + + + + + + 内存单位 最大分配内存数量 + 2097152 + 当前内存 + 2097152 + CPU数量 + 2 + + /machine + + + + 虚拟机架构 + hvm + 引导方式启动设备 + + + + + + + + CPU功能 + + Haswell-noTSX-IBRS + Intel + + + + + + + + + + + + + + + + + + + + 时钟设置 + + + + + + + 面板按钮 + destroy + restart + destroy + + + + + + 虚拟机设备 + + /usr/libexec/qemu-kvm 仿真 + + 磁盘来自系统文件 + + 磁盘类型为qcow2 + + 磁盘文件的位置 + + 磁盘总线使用的是virtio + +
+ + + 光驱设置 + + + + +
+ + + 接口设置 + usb总线 + +
+ + + sata总线 + +
+ + + + + + +
+ + + + +
第一个PCI接口 + + + + +
第二个PCI接口 + + + + +
第三个PCI接口 + + + + +
第四个PCI接口 + + + + +
第五个PCI接口 + + + + +
第六个PCI接口 + + +
+ + + 网卡设置 + + MAC地址 + 网络连接方式 + 网卡总线 +
+ + + 串口设置 + + + + + + + + + 信道qemu-ga + + +
+ + USB设置 + +
+ + + 鼠标 + 键盘 + + 图形设置 + 图形VNC设置 + + + +