├── .gitignore ├── LICENSE ├── README.md ├── docker ├── docker创建kafka和zk的网络群.md ├── mac安装docker.md ├── ubuntu │ ├── 安装jdk8.md │ └── 安装ping.md ├── win10安装虚拟机跑centos6.5.md ├── 从零开始搭建服务器集群.md └── 获取docker某个镜像全部tags.md ├── es ├── es7.8常见命令 │ ├── es 保证单词间顺序.md │ ├── 删除某个索引的某些 doc.md │ ├── 搜索某个关键词.md │ ├── 查看es所有索引.md │ ├── 查看某个字段不存在的门店.md │ ├── 查看某个字段存在的门店.md │ ├── 查看某个索引size.md │ └── 查看某个索引的mappings.md ├── es入门 │ ├── es 开启 auth 验证.md │ ├── es副本和节点.png │ ├── step1-安装es.md │ ├── step2-创建索引.md │ ├── step3-修改索引.md │ └── step4-分区和副本的概念.md ├── multi_search │ └── multi_match的六种类型.md ├── 底层原理 │ ├── 合并1-索引合并的底层逻辑.md │ ├── 合并2-合并中性能的时间空间考量.md │ └── 建索引的底层逻辑.md └── 相关性分数 │ ├── TF&IDF.md │ ├── function_scope入门.md │ ├── score_mode和 boost_mode.md │ ├── 为什么es的分数总是不准.md │ ├── 相关性分数调优.md │ └── 衰减函数.png ├── git ├── git放弃更改.md └── 仓库链接到远程.md ├── leetcode ├── 前缀和 │ ├── 1423.可获得的最大点数.md │ └── 560.和为K的子数组.md └── 滑动窗口 │ └── 3.无重复字符的最长子串.md ├── linux ├── 100个高频linux命令 │ ├── 001_cat.md │ ├── 002_echo.md │ ├── 003_clear.md │ ├── 004_pwd.md │ ├── 005_cd.md │ ├── 006_tree.md │ ├── 007_ls.md │ ├── 008_history.md │ ├── 009_ps.md │ ├── 010_grep.md │ ├── 011_date.md │ ├── 012_top.md │ ├── 013_head.md │ ├── 014_tail.md │ ├── 015_ping.md │ ├── 016_rm.md │ ├── 017_mkdir.md │ ├── 018_ifconfig.md │ ├── 019_touch.md │ ├── 020_vi.md │ ├── 021_cp.md │ ├── 022_scp.md │ ├── 023_awk_1.md │ ├── 024_more.md │ ├── 025_less.md │ ├── 026_most.md │ ├── 027_sort.md │ ├── 028_sed_1_插入一行.md │ ├── 029_sed_2_在某行处替换一行.md │ ├── 030_sed_3_删除一行.md │ ├── 031_nl.md │ └── 032_mtr.md ├── cd跳最新文件夹.md ├── centos下查看网络流量.md ├── nc做端口转发.md ├── nfs │ └── ubuntu18.04创建nfs.md ├── portmap端口转发.md ├── python3 │ ├── logger怎么玩.md │ ├── ubuntu18.04下pip3安装失败合集.md │ ├── ubuntu18.04安装gevent失败的解决方案.md │ └── 替换敏感词.md ├── shell │ ├── awk │ │ ├── 求和求均最大最小.md │ │ └── 统计nginx超时请求.md │ ├── rsync同步文件.md │ ├── xargs和sed批量重命名.md │ ├── zip排除目录后的打包.md │ ├── zsh │ │ ├── 一键初始化zsh.md │ │ ├── 一键初始化zsh下的diff环境.md │ │ └── 调整命令行的prompt.md │ └── 遍历日期然后执行命令.md ├── ssh │ └── 端口转发.md ├── 修改命令行显示的用户名.md ├── 加固 │ ├── firewall-cmd防火墙.md │ ├── ssh 禁止密码登录.md │ ├── ubuntu18.04使用fail2ban加固服务器.md │ └── ubuntu18.04搞ufw.md ├── 开机启动 │ └── ubuntu18.04新增supervisor开机自启动.md ├── 查看上次开机时间.md └── 查看网络质量.md ├── mysql ├── 5.7创建新用户.md ├── mysqldump导数据.md ├── ubuntu18.04下安装mysql5.6.md └── 连接数过大.md ├── nginx ├── ubuntu18.04新增 geoip 控制.md ├── 简单的配置.md └── 配置实战&https证书配置.md ├── ssl ├── CA机构在干嘛.md ├── acme.sh创建ssl证书.md ├── openssl入门.md ├── openssl生成证书.md └── ssl入门.md ├── zk └── ubuntu安装zk3.4.13.md ├── 乱码 ├── ubuntu18.04vim中文乱码.md ├── ubuntu18.04vim中文乱码解决.md ├── ubuntu18.04修改python3默认编码为utf8.md └── ubuntu18.04设置vim中文编码.md ├── 奇技淫巧 ├── 切割文件.md └── 生成大文件.md ├── 服务排查.png └── 服务访问不了怎么办.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | 3 | 4 | *.orig.* 5 | *.toc.* 6 | 7 | 8 | # Byte-compiled / optimized / DLL files 9 | __pycache__/ 10 | *.py[cod] 11 | *$py.class 12 | 13 | # C extensions 14 | *.so 15 | 16 | # Distribution / packaging 17 | .Python 18 | env/ 19 | build/ 20 | develop-eggs/ 21 | dist/ 22 | downloads/ 23 | eggs/ 24 | .eggs/ 25 | lib/ 26 | lib64/ 27 | parts/ 28 | sdist/ 29 | var/ 30 | wheels/ 31 | *.egg-info/ 32 | .installed.cfg 33 | *.egg 34 | 35 | # PyInstaller 36 | # Usually these files are written by a python script from a template 37 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 38 | *.manifest 39 | *.spec 40 | 41 | # Installer logs 42 | pip-log.txt 43 | pip-delete-this-directory.txt 44 | 45 | # Unit test / coverage reports 46 | htmlcov/ 47 | .tox/ 48 | .coverage 49 | .coverage.* 50 | .cache 51 | nosetests.xml 52 | coverage.xml 53 | *.cover 54 | .hypothesis/ 55 | 56 | # Translations 57 | *.mo 58 | *.pot 59 | 60 | # Django stuff: 61 | *.log 62 | local_settings.py 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # pyenv 81 | .python-version 82 | 83 | # celery beat schedule file 84 | celerybeat-schedule 85 | 86 | # SageMath parsed files 87 | *.sage.py 88 | 89 | # dotenv 90 | .env 91 | 92 | # virtualenv 93 | .venv 94 | venv/ 95 | ENV/ 96 | 97 | # Spyder project settings 98 | .spyderproject 99 | .spyproject 100 | 101 | # Rope project settings 102 | .ropeproject 103 | 104 | # mkdocs documentation 105 | /site 106 | 107 | # mypy 108 | .mypy_cache/ 109 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 ouyangbro 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | * [服务访问不了或异常慢卡](#服务访问不了或异常慢卡) 2 | * [正在运行的业务进程CPU调优](#服务访问不了或异常慢卡) 3 | * [Java调优](#java调优) 4 | * [Python调优](#python调优) 5 | * [Mysql日常优化](#mysql日常优化) 6 | * [Mysql查看慢查询日志](#mysql查看慢查询日志) 7 | * [Mysql查看正在执行的sql](#mysql查看正在执行的sql) 8 | * [Nginx查看访问最频繁的IP并禁止某个异常IP](#nginx查看访问最频繁的ip并禁止某个异常ip) 9 | * [firewall-cmd](#firewall-cmd) 10 | * [iptables](#iptables) 11 | * [监控硬盘并邮件报警](#监控硬盘并邮件报警) 12 | 13 | 14 | 15 | # 服务访问不了或异常慢卡 16 | ![Alt text](https://github.com/emaste-r/backend_note/blob/master/%E6%9C%8D%E5%8A%A1%E8%AE%BF%E9%97%AE%E4%B8%8D%E4%BA%86%E6%80%8E%E4%B9%88%E5%8A%9E.jpg) 17 | 18 | 19 | # 正在运行的业务进程CPU调优 20 | 21 | ## Java调优 22 | 先找到CPU异常的PID: 23 | ``` 24 | [root@iZ9458z0ss9Z ~]# top -c 25 | ``` 26 | 然后查看该进程下的线程: 27 | ``` 28 | [root@iZ9458z0ss9Z ~]# top -Hp YOUR_PID 29 | ``` 30 | 然后查看异常的线程: 31 | ``` 32 | [root@iZ9458z0ss9Z ~]# jstack YOUR_THREAD_PID 33 | ``` 34 | 如此,便能查看该线程到底在执行到哪一段代码会导致CPU异常: 35 | ``` 36 | [root@iZ94won0vbvZ ~]# printf '%x\n' 15589 37 | 3ce5 38 | [root@iZ94won0vbvZ ~]# jstack 15589 | grep "3ce" -C 5 39 | 40 | "qtp540159270-15" #15 prio=5 os_prio=0 tid=0x00007f312878e000 nid=0x3cfd waiting on condition [0x00007f311115f000] 41 | java.lang.Thread.State: TIMED_WAITING (parking) 42 | at sun.misc.Unsafe.park(Native Method) 43 | - parking to wait for <0x00000000e002b348> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) 44 | at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215) 45 | at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078) 46 | -- 47 | at org.eclipse.jetty.util.thread.QueuedThreadPool.idleJobPoll(QueuedThreadPool.java:531) 48 | at org.eclipse.jetty.util.thread.QueuedThreadPool.access$700(QueuedThreadPool.java:47) 49 | at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:590) 50 | at java.lang.Thread.run(Thread.java:745) 51 | ``` 52 | 53 | 可能会出现如下错误: 54 | ``` 55 | Unable to open socket file: target process not responding or HotSpot VM not loaded 56 | ``` 57 | 原因: 58 | ``` 59 | jstack找不到pid文件。 60 | ``` 61 | 解决方案: 62 | ``` 63 | 1、要么是因为pid文件放在/tmp文件夹下,然而tmpwatch策略导致系统定时清理掉/tmp文件夹下的长时间无访问的文件... 64 | 只能重启才能重新生成pid; 65 | 2、也有可能pid文件被自定义设置到别处,那么jstack /data/you/path/your.pid即可。 66 | ``` 67 | 68 | ## Python调优 69 | 70 | 本人版本: 71 | ``` 72 | centos7+python2.7.5 73 | ``` 74 | 安装gdb: 75 | ``` 76 | [root@iZ9458z0ss9Z ~]# sudo yum install gdb 77 | ``` 78 | 出现如下信息说明安装成功: 79 | ``` 80 | [root@ouyang ~]# gdb 81 | GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7_4.1 82 | Copyright (C) 2013 Free Software Foundation, Inc. 83 | License GPLv3+: GNU GPL version 3 or later 84 | This is free software: you are free to change and redistribute it. 85 | There is NO WARRANTY, to the extent permitted by law. Type "show copying" 86 | and "show warranty" for details. 87 | This GDB was configured as "x86_64-redhat-linux-gnu". 88 | For bug reporting instructions, please see: 89 | . 90 | (gdb) 91 | ``` 92 | 安装python包(才能使用py-list、py-bt等操作): 93 | ``` 94 | wget http://debuginfo.centos.org/6/x86_64/python27-python-debuginfo-2.7.5-10.el6.centos.alt.x86_64.rpm 95 | rpm -ivh python27-python-debuginfo-2.7.5-10.el6.centos.alt.x86_64.rpm 96 | ``` 97 | 出现如下信息说明python-debuginfo包安装成功: 98 | ``` 99 | [root@iZ94won0vbvZ ~]# gdb -p 31618 # 31618 是某个python进程的PID 100 | 101 | (gdb) py 102 | py-bt py-down py-list py-locals py-print py-up python python-interactive 103 | ``` 104 | 开始调试,查看当前线程运行的代码: 105 | ``` 106 | (gdb) py-list 107 | 858 # clear alarm so it doesn't fire while poll is waiting for 108 | 859 # events. 109 | 860 signal.setitimer(signal.ITIMER_REAL, 0, 0) 110 | 861 111 | 862 try: 112 | >863 event_pairs = self._impl.poll(poll_timeout) 113 | 864 except Exception as e: 114 | 865 # Depending on python version and IOLoop implementation, 115 | 866 # different exception types may be thrown and there are 116 | 867 # two ways EINTR might be signaled: 117 | 868 # * e.errno == errno.EINTR 118 | (gdb) 119 | ``` 120 | 121 | # Mysql日常优化 122 | 123 | ## Mysql查看慢查询日志 124 | 首先要判断mysql是否开启慢查询、慢查询日志存放位置: 125 | ``` 126 | [root@iZ9458z0ss9Z ~]# cat /etc/my.cnf| grep slow 127 | slow_launch_time=2 # 表示如果建立线程花费了比这个值更长的时间,slow_launch_threads 计数器将增加 128 | slow_query_log=on   # 开启 慢查询 129 | slow_query_log_file=/data/log/your_slow_query.log # log文件存放位置 130 | ``` 131 | 万一没开启,怎么开启呢? 132 | ``` 133 | mysql> set global slow_query_log='ON'; 134 | mysql> set global slow_query_log_file='/usr/local/mysql/data/slow.log'; 135 | mysql> set global long_query_time=1; # 超过一秒的查询会被记录 136 | ``` 137 | 查看慢查询日志,主要关心参数: 138 | Query_time = 查询耗费多少秒 = 3.088468 139 | Rows_examined = 影响的行数 = 43817   140 | ``` 141 | [root@iZ9458z0ss9Z ~]# tail -f /data/log/your_slow_query.log 142 | # Time: 180301 16:17:20 143 | # User@Host: root[root] @ iZ9458z0ss9Z [10.24.245.83] 144 | # Thread_id: 9601563 Schema: miaoyan QC_hit: No 145 | # Query_time: 3.088468 Lock_time: 0.000084 Rows_sent: 1 Rows_examined: 43817 146 | # Rows_affected: 0 147 | SET timestamp=1519892240; 148 | select count(id) as cnt from `your_table` where com_id = 1867 and ptype = 1; 149 | ``` 150 | 151 | ## Mysql查看正在执行的sql 152 | 查看当前的sql执行情况: 153 | ``` 154 | mysql> show processlist; 155 | +----------+---------+----------------------+----------------------+---------+-------+----------+------------------+ 156 | | Id | User | Host | db | Command | Time | State | Info | 157 | +----------+---------+----------------------+----------------------+---------+-------+----------+------------------+ 158 | | 15490667 | seafile | localhost:45682 | ccnet-db | Sleep | 23 | | NULL | 159 | | 15490668 | seafile | localhost:45684 | seafile-db | Sleep | 3 | | NULL | 160 | | 15496875 | seafile | localhost:60158 | ccnet-db | Sleep | 1530 | | NULL | 161 | | 15498263 | seafile | localhost:35184 | seafile-db | Sleep | 630 | | NULL | 162 | | 9604402 | root   | iZ9458z0ss9Z:22193   | your_db             | Query   |     1 | Sending data                                                                 | select count(id) as cnt from `your_table` where com_id = 1769 and ptype=1 | 163 | ``` 164 | Sleep状态的项不需要管,如果看到一个Query状态的sql,Time(秒)还很大,可能卡住了,个人感觉select的sql如果卡住了,可以先kill掉: 165 | ``` 166 | kill 9604402 167 | ``` 168 | 再慢慢分析是否有索引: 169 | ``` 170 | explain select count(id) as cnt from `your_table` where com_id = 1769 and ptype=1; 171 | ``` 172 | 如果是Update的sql,那就还是慢慢等执行完毕吧,一般不会耗费太多时间,除非你全表update。 173 | 174 | 175 | # Nginx查看访问最频繁的IP并禁止某个异常IP 176 | 177 | 查看排名前10个访问最频繁的IP: 178 | ``` 179 | [root@iZ9458z0ss9Z ~]# awk '{a[$1]+=1;}END{for(i in a){print a[i] " " i;}}' /var/log/nginx/access.log |sort -gr | head -10 180 | 11929 123.44.55.66 181 | 9727 119.137.52.231 182 | 8132 111.18.73.48 183 | 2926 115.191.176.18 184 | 2407 183.198.212.108 185 | 2322 218.11.141.142 186 | 2257 183.225.60.104 187 | 2229 183.40.130.198 188 | 1990 115.207.217.131 189 | 1965 221.180.236.146 190 | [root@iZ9458z0ss9Z ~]# 191 | ``` 192 | 193 | ## firewall-cmd 194 | 假设我们感觉这个123.44.55.66太可疑了,如何用firewall禁用: 195 | 先查看firewall是否开启: 196 | ``` 197 | [root@iZ9458z0ss9Z ~]# firewall-cmd --state 198 | running 199 | ``` 200 | 禁用123.44.55.66: 201 | ``` 202 | [root@iZ9458z0ss9Z ~]# firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='123.44.55.66' reject" 203 | success 204 | ``` 205 | 重启生效: 206 | ``` 207 | [root@iZ9458z0ss9Z ~]# firewall-cmd --reload 208 | success 209 | [root@iZ9458z0ss9Z ~]# iptables -L | grep '123' 210 | REJECT all -- 123.44.55.66 anywhere reject-with icmp-port-unreachable 211 | ``` 212 | 解封IP,把--add-rich-rule改成--remove-rich-rule: 213 | ``` 214 | [root@iZ9458z0ss9Z ~]# firewall-cmd --permanent --remove-rich-rule="rule family='ipv4' source address='123.44.55.66' reject" 215 | ``` 216 | 217 | ## iptables 218 | 如果未安装firewall-cmd,那么可以试试iptables,先看iptables服务跑起来没: 219 | ``` 220 | [root@iZ94won0vbvZ ~]# service iptables status 221 | ``` 222 | 如果没有跑起来: 223 | ``` 224 | 重启后生效 225 | 开启: chkconfig iptables on 226 | 关闭: chkconfig iptables off 227 | 即时生效,重启后失效 228 | 开启: service iptables start 229 | 关闭: service iptables stop 230 | ``` 231 | 添加拒绝ip的规则: 232 | ``` 233 | [root@iZ9458z0ss9Z ~]# cp /etc/sysconfig/iptables-config /var/tmp   //先保存原先配置 234 | [root@iZ9458z0ss9Z ~]# iptables -I INPUT -s 123.44.55.66 -j DROP //添加拒绝的ip 235 | [root@iZ9458z0ss9Z ~]# service iptables save //保存配置 236 | [root@iZ9458z0ss9Z ~]# service iptables restart //重启防火墙 237 | ``` 238 | 查看下添加成功否: 239 | ``` 240 | [root@iZ94won0vbvZ ~]# iptables -L //查看iptables 241 | Chain INPUT (policy ACCEPT) 242 | target prot opt source destination 243 | DROP all -- 123.44.55.66 anywhere 244 | ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED 245 | ``` 246 | 如果发现是个误会,想解封123.44.55.66: 247 | ``` 248 | [root@iZ94won0vbvZ ~]# iptables -D INPUT -s 123.44.55.66 -j DROP 249 | [root@iZ94won0vbvZ ~]# iptables -L | grep 123.44.55   //发现找不到和123.44.55.66相关的规则了,解封成功! 250 | [root@iZ94won0vbvZ ~]# 251 | ``` 252 | 253 | # 监控硬盘并邮件报警 254 | 255 | 我们查看硬盘使用率 df -h: 256 | ``` 257 | [root@iZ9458z0ss9Z script]# df -h 258 | Filesystem Size Used Avail Use% Mounted on 259 | /dev/vda1 40G 14G 24G 36% / 260 | devtmpfs 3.9G 0 3.9G 0% /dev 261 | tmpfs 3.9G 28K 3.9G 1% /dev/shm 262 | tmpfs 3.9G 408M 3.5G 11% /run 263 | tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup 264 | /dev/vdb 197G 124G 64G 66% /data 265 | tmpfs 783M 0 783M 0% /run/user/0 266 | ``` 267 | 268 | 如果从未配置过mail: 269 | ``` 270 | [root@001 ~]# vim /etc/mail.rc #添加如下内容 271 | set from=xxxx@126.com # from:对方收到邮件时显示的发件人 272 | set smtp=smtp.126.com # smtp:指定第三方发邮件的smtp服务器地址 273 | set smtp-auth-user=xx@126.com # set smtp-auth-user:第三方发邮件的用户名 274 | set smtp-auth-password=xxx # set smtp-auth-password:用户名对应的密码,有些邮箱填的是授权码 275 | set smtp-auth=login # smtp-auth:SMTP的认证方式,默认是login,也可以改成CRAM-MD5或PLAIN方式 276 | ``` 277 | 测试下: 278 | ``` 279 | [root@iZ9458z0ss9Z script]# echo "测试邮件" | mail -s "测试主题" xihuanjianguo@163.com 280 | ``` 281 | 282 | 写发送邮件的脚本: 283 | ``` 284 | [root@iZ9458z0ss9Z script]# cat sendmail.sh 285 | #!/bin/bash 286 | # by kin 287 | source /etc/profile 288 | content=$1 289 | address=$2 290 | echo ${content} | mail -s ${content} ${address} 291 | ``` 292 | 293 | 写监控硬盘脚本: 294 | ``` 295 | [root@iZ9458z0ss9Z ~]# cat /data/your_script_path/hdd_alarm.sh 296 | #!/bin/sh 297 | # by kin 298 | source /etc/profile; 299 | runpath='/data/your_script_path' 300 | 301 | # 定义send函数来调用我们的sendmail.sh脚本 302 | send() 303 | { 304 | ./sendmail.sh $1 your_email_1@163.com 305 | ./sendmail.sh $1 your_email_2@163.com 306 | } 307 | 308 | # 如果不存在hdd_alarm文件夹则创建之 309 | if [ ! -d $runpath/hdd_alarm ] 310 | then 311 | mkdir $runpath/hdd_alarm 312 | fi 313 | 314 | # 获取本机的IP地址 315 | Host_IP=`ifconfig |grep "inet "|grep -v 127.0.0.1|grep -v 'inet 10.'|grep -v '192.168'|awk '{print $2}'` 316 | 317 | 318 | # 获取df硬盘容量参数的后两列使用率a和路径b,遍历a和b 319 | df -h | awk '{print $(NF-1),$NF}'|awk '{if($NF!=$1){print $0}}'|sed 's/\%//g'|sed '1d'|while read a b; 320 | do 321 | 322 | # 如果a和b有一个是空字符串则跳过 323 | if [ -z $a ] || [ -z $b ] 324 | then 325 | : 326 | else 327 |        # 从日志中获取上一次报警的使用率 328 |        old_used=`cat $runpath/hdd_alarm/hdd_tmp.log 2>/dev/null|grep "$b$"|awk '{print $(NF-1)}'|sed 's/\%//g'` 329 | 330 |        # 如果使用率不超过80 或者 相比上一次没有增加,则跳过 331 |        if [ ! -z $old_used ] && [ $old_used -eq $a ] && [ $a -le 80 ] 332 | then 333 | continue; 334 | fi 335 | 336 |        # 如果使用率确实>=80,则调用send()发送邮件... 337 |        if [ $a -gt 80 ] ; 338 | then 339 | msg="Hdd_alarm:$Host_IP-$b-Reach-$a-precent" 340 | echo "$msg" #>>./Hdd_alarm.log 341 | send "$msg" 342 | 343 |                # 如果调用send()的返回值不是0,说明有错误 344 |                if [ $? -ne 0 ]; 345 | then 346 | echo -e "############Send Fail#############" 347 | fi 348 | fi 349 | 350 | 351 | fi 352 | done 353 | 354 | # 把df信息存入到日志中,方便下一次对比 355 | df -h >$runpath/hdd_alarm/hdd_tmp.log 356 | 357 | ``` 358 | 放到定时任务,每15分钟跑一次: 359 | ``` 360 | [root@iZ9458z0ss9Z script]# crontab -l 361 | */15 * * * * cd /data/your_script_path/;./hdd_alarm.sh >/dev/null 2>&1 362 | ``` 363 | 364 | -------------------------------------------------------------------------------- /docker/docker创建kafka和zk的网络群.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 搭建 zk 集群 4 | vi docker-compose-zk.yml: 5 | ``` 6 | version: '3.1' 7 | 8 | services: 9 | zoo1: 10 | image: zookeeper 11 | restart: always 12 | privileged: true 13 | hostname: zoo1 14 | ports: 15 | - 2181:2181 16 | volumes: # 挂载数据 17 | - /Users/apple/dockerdata/zookeeper_home/node1/data:/data 18 | - /Users/apple/dockerdata/zookeeper_home/node1/datalog:/datalog 19 | - /Users/apple/dockerdata/zookeeper_home/node1/logs:/logs 20 | environment: 21 | ZOO_MY_ID: 1 22 | ZOO_SERVERS: server.1=0.0.0.0:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181 23 | networks: 24 | default: 25 | ipv4_address: 172.19.0.11 26 | 27 | zoo2: 28 | image: zookeeper 29 | restart: always 30 | privileged: true 31 | hostname: zoo2 32 | ports: 33 | - 2182:2181 34 | volumes: # 挂载数据 35 | - /Users/apple/dockerdata/zookeeper_home/node2/data:/data 36 | - /Users/apple/dockerdata/zookeeper_home/node2/datalog:/datalog 37 | - /Users/apple/dockerdata/zookeeper_home/node2/logs:/logs 38 | environment: 39 | ZOO_MY_ID: 2 40 | ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=0.0.0.0:2888:3888;2181 server.3=zoo3:2888:3888;2181 41 | networks: 42 | default: 43 | ipv4_address: 172.19.0.12 44 | 45 | zoo3: 46 | image: zookeeper 47 | restart: always 48 | privileged: true 49 | hostname: zoo3 50 | ports: 51 | - 2183:2181 52 | volumes: # 挂载数据 53 | - /Users/apple/dockerdata/zookeeper_home/node3/data:/data 54 | - /Users/apple/dockerdata/zookeeper_home/node3/datalog:/datalog 55 | - /Users/apple/dockerdata/zookeeper_home/node3/logs:/logs 56 | environment: 57 | ZOO_MY_ID: 3 58 | ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=0.0.0.0:2888:3888;2181 59 | networks: 60 | default: 61 | ipv4_address: 172.19.0.13 62 | 63 | networks: # 自定义网络 64 | default: 65 | external: 66 | name: zoonet 67 | ``` 68 | 69 | 70 | 创建网络: 71 | ``` 72 | docker network create --driver bridge --subnet=172.19.0.0/16 --gateway=172.19.0.1 zoonet 73 | ``` 74 | 75 | 创建挂载目录: 76 | ``` 77 | mkdir -p /Users/apple/dockerdata/zookeeper_home/node1 78 | mkdir -p /Users/apple/dockerdata/zookeeper_home/node2 79 | mkdir -p /Users/apple/dockerdata/zookeeper_home/node3 80 | ``` 81 | 启动: 82 | ``` 83 | docker-compose -f docker-compose-zk.yml up -d 84 | ``` 85 | ``` 86 | Creating zookeeper_zoo3_1 ... done 87 | Creating zookeeper_zoo1_1 ... done 88 | Creating zookeeper_zoo2_1 ... done 89 | ``` 90 | 暂停: 91 | ``` 92 | docker-compose -f docker-compose.yml stop 93 | ``` 94 | ``` 95 | Stopping zookeeper_zoo1_1 ... done 96 | Stopping zookeeper_zoo3_1 ... done 97 | Stopping zookeeper_zoo2_1 ... done 98 | ``` 99 | 删除: 100 | ``` 101 | docker-compose -f docker-compose.yml rm 102 | ``` 103 | ``` 104 | Going to remove zookeeper_zoo1_1, zookeeper_zoo3_1, zookeeper_zoo2_1 105 | Are you sure? [yN] y 106 | Removing zookeeper_zoo1_1 ... done 107 | Removing zookeeper_zoo3_1 ... done 108 | Removing zookeeper_zoo2_1 ... done 109 | ``` 110 | 111 | ## 搭建 kafka 集群 112 | vi docker-compose-kafka.yml: 113 | ``` 114 | version: '3.4' 115 | services: 116 | kafka1: 117 | image: wurstmeister/kafka 118 | restart: always 119 | hostname: kafka1 120 | container_name: kafka1 121 | privileged: true 122 | ports: 123 | - 9092:9092 124 | environment: 125 | KAFKA_ADVERTISED_HOST_NAME: kafka1 126 | KAFKA_LISTENERS: PLAINTEXT://kafka1:9092 127 | KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka1:9092 128 | KAFKA_ADVERTISED_PORT: 9092 129 | KAFKA_ZOOKEEPER_CONNECT: zoo1:2181,zoo2:2181,zoo3:2181 130 | volumes: 131 | - /Users/apple/dockerdata/kafka_home/kafka1/logs:/kafka 132 | networks: 133 | kafka: 134 | ipv4_address: 172.19.1.11 135 | extra_hosts: 136 | zoo1: 172.19.0.11 137 | zoo2: 172.19.0.12 138 | zoo3: 172.19.0.13 139 | kafka2: 140 | image: wurstmeister/kafka 141 | restart: always 142 | hostname: kafka2 143 | container_name: kafka2 144 | privileged: true 145 | ports: 146 | - 9093:9093 147 | environment: 148 | KAFKA_ADVERTISED_HOST_NAME: kafka2 149 | KAFKA_LISTENERS: PLAINTEXT://kafka2:9093 150 | KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka2:9093 151 | KAFKA_ADVERTISED_PORT: 9093 152 | KAFKA_ZOOKEEPER_CONNECT: zoo1:2181,zoo2:2181,zoo3:2181 153 | volumes: 154 | - /Users/apple/dockerdata/kafka_home/kafka2/logs:/kafka 155 | networks: 156 | kafka: 157 | ipv4_address: 172.19.1.12 158 | extra_hosts: 159 | zoo1: 172.19.0.11 160 | zoo2: 172.19.0.12 161 | zoo3: 172.19.0.13 162 | kafka3: 163 | image: wurstmeister/kafka 164 | restart: always 165 | hostname: kafka3 166 | container_name: kafka3 167 | privileged: true 168 | ports: 169 | - 9094:9094 170 | environment: 171 | KAFKA_ADVERTISED_HOST_NAME: kafka3 172 | KAFKA_LISTENERS: PLAINTEXT://kafka3:9094 173 | KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka3:9094 174 | KAFKA_ADVERTISED_PORT: 9094 175 | KAFKA_ZOOKEEPER_CONNECT: zoo1:2181,zoo2:2181,zoo3:2181 176 | volumes: 177 | - /Users/apple/dockerdata/kafka_home/kafka3/logs:/kafka 178 | networks: 179 | kafka: 180 | ipv4_address: 172.19.1.13 181 | extra_hosts: 182 | zoo1: 172.19.0.11 183 | zoo2: 172.19.0.12 184 | zoo3: 172.19.0.13 185 | networks: 186 | kafka: 187 | external: 188 | name: kafka 189 | ``` 190 | 191 | 创建网络: 192 | ``` 193 | docker network create --driver bridge --subnet=172.19.1.0/16 --gateway=172.19.1.1 kafka 194 | ``` 195 | 196 | 创建挂载目录: 197 | ``` 198 | mkdir -p /Users/apple/dockerdata/kafka_home/kafka1/logs 199 | mkdir -p /Users/apple/dockerdata/kafka_home/kafka2/logs 200 | mkdir -p /Users/apple/dockerdata/kafka_home/kafka3/logs 201 | ``` 202 | 启动: 203 | ``` 204 | docker-compose -f docker-compose-kafka.yml up -d 205 | ``` 206 | 暂停: 207 | ``` 208 | docker-compose -f docker-compose-kafka.yml stop 209 | ``` 210 | 211 | 删除: 212 | ``` 213 | docker-compose -f docker-compose-kafka.yml rm 214 | ``` 215 | 216 | 217 | -------------------------------------------------------------------------------- /docker/mac安装docker.md: -------------------------------------------------------------------------------- 1 | ``` 2 | brew install --cask docker 3 | ``` 4 | -------------------------------------------------------------------------------- /docker/ubuntu/安装jdk8.md: -------------------------------------------------------------------------------- 1 | 有效版本:18.04,其他版本暂未尝试: 2 | ``` 3 | apt install openjdk-8-jdk 4 | ``` 5 | 可以安装jdk11: 6 | ``` 7 | apt install openjdk-11-jdk 8 | ``` 9 | -------------------------------------------------------------------------------- /docker/ubuntu/安装ping.md: -------------------------------------------------------------------------------- 1 | 有效版本:18.04,其他版本暂未尝试: 2 | ``` 3 | apt-get install iputils-ping 4 | ``` 5 | -------------------------------------------------------------------------------- /docker/win10安装虚拟机跑centos6.5.md: -------------------------------------------------------------------------------- 1 | ## 下载ISO镜像 2 | ``` 3 | http://ftp.jaist.ac.jp/pub/Linux/CentOS-vault/6.5/isos/x86_64/ 4 | ``` 5 | 6 | 当然也有别的版本: 7 | ``` 8 | http://ftp.jaist.ac.jp/pub/Linux/CentOS-vault/ 9 | ``` 10 | 11 | ## 打开windows的Hyper-V 12 | 自带的,只要打开服务,就好。 13 | 14 | 15 | 第一步: 16 | ``` 17 | 在 Windows 上,从桌面开始键入程序,单击 "程序和功能" (控制面板 ") Windows 打开或关闭 "hyper-vhyper-v 管理工具"。 然后,单击“确定”。 18 | ``` 19 | 20 | 第二步: 21 | ``` 22 | 将服务重新配置为使用 "服务" 桌面应用程序自动启动 23 | 打开 "服务" 桌面应用。 (单击 " 开始",在搜索框中单击,开始键入 " 服务",然后在结果列表中单击 "服务"。 24 | 25 | 在详细信息窗格中,右键单击 " Hyper-v 虚拟机管理",然后单击 " 属性"。 26 | 27 | 在 " 常规 " 选项卡上,在 " 启动 类型" 中单击 " 自动"。 28 | ``` 29 | 30 | 教程: 31 | ``` 32 | https://docs.microsoft.com/zh-cn/windows-server/virtualization/hyper-v/best-practices-analyzer/The-Hyper-V-Virtual-Machine-Management-service-should-be-configured-to-start 33 | ``` 34 | 35 | ## 创建VM 36 | 啊,就是傻瓜化,有个快速创建,也有自己创建,可以配置文件夹什么的,点下一步即可。 37 | 38 | 需要注意的是,我选择第一代就行,第二代就不行。 39 | 40 | 41 | ## 最终效果 42 | 43 | ![image](https://user-images.githubusercontent.com/6395350/187237156-c9a7d99c-375f-4f87-a93c-ff5bcf272c89.png) 44 | -------------------------------------------------------------------------------- /docker/从零开始搭建服务器集群.md: -------------------------------------------------------------------------------- 1 | ## 目标 2 | ``` 3 | 内网【server(centos7.9) <----> agent(centos6.5) 】 <------> web(ubuntu18.04) 4 | <------> data(ubuntu18.04) 5 | ``` 6 | 7 | ## 搭建 8 | 本来想拉 `centos:6.5` 但是失败了,最低 6.6,后来发现6.6跑不起来,改为6.7: 9 | ``` 10 | docker pull centos:6.7 11 | docker pull centos:7.9.2009 12 | ``` 13 | 跑 4 个服务: 14 | ``` 15 | docker run -itd --name rmdata-server -v $HOME/Desktop/tmp/all/:/data centos:7.9.2009 16 | docker run -itd --name rmdata-agent -v $HOME/Desktop/tmp/all/:/data centos:6.7 17 | docker run -itd --name rmdata-web -v $HOME/Desktop/tmp/all/:/data centos:7.9.2009 18 | docker run -itd --name rmdata-data -v $HOME/Desktop/tmp/all/:/data centos:7.9.2009 19 | ``` 20 | 看一下: 21 | ``` 22 | > docker ps 23 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 24 | 3eb3f7542893 centos:6.7 "/bin/bash" 8 seconds ago Up 7 seconds rmdata-agent 25 | 4d89f8622b3c centos:7.9.2009 "/bin/bash" 25 seconds ago Up 24 seconds rmdata-data 26 | 30d91cf1d39b centos:7.9.2009 "/bin/bash" 32 seconds ago Up 31 seconds rmdata-web 27 | 4206d8345bc0 centos:7.9.2009 "/bin/bash" 50 seconds ago Up 49 seconds rmdata-server 28 | ``` 29 | 30 | 31 | 安装一些必要的东西比如 openssl 和 gcc 等工具: 32 | ``` 33 | yum group install "Development Tools" 34 | yum install openssl -y 35 | ``` 36 | -------------------------------------------------------------------------------- /docker/获取docker某个镜像全部tags.md: -------------------------------------------------------------------------------- 1 | 创建一个dockerimage.sh 2 | ``` 3 | #!/bin/bash 4 | 5 | if [ $# -lt 1 ] 6 | then 7 | cat << HELP 8 | 9 | dockertags -- list all tags for a Docker image on a remote registry. 10 | 11 | EXAMPLE: 12 | - list all tags for ubuntu: 13 | dockertags ubuntu 14 | 15 | - list all php tags containing apache: 16 | dockertags php apache 17 | 18 | HELP 19 | fi 20 | 21 | image="$1" 22 | tags=`wget -q https://registry.hub.docker.com/v1/repositories/${image}/tags -O - | sed -e 's/[][]//g' -e 's/"//g' -e 's/ //g' | tr '}' '\n' | awk -F: '{print $3}'` 23 | 24 | if [ -n "$2" ] 25 | then 26 | tags=` echo "${tags}" | grep "$2" ` 27 | fi 28 | 29 | echo "${tags}" 30 | ``` 31 | 32 | 加上权限: 33 | ``` 34 | chmod +x dockersearch.sh 35 | ``` 36 | 37 | 实战: 38 | ``` 39 | ./dockersearch.sh centos 40 | latest 41 | 5 42 | 5.11 43 | 6 44 | 6.10 45 | 6.6 46 | 6.7 47 | 6.8 48 | 6.9 49 | 7 50 | 7.0.1406 51 | 7.1.1503 52 | 7.2.1511 53 | 7.3.1611 54 | 7.4.1708 55 | 7.5.1804 56 | 7.6.1810 57 | 7.7.1908 58 | 7.8.2003 59 | 7.9.2009 60 | 8 61 | 8.1.1911 62 | 8.2.2004 63 | 8.3.2011 64 | 8.4.2105 65 | centos5 66 | centos5.11 67 | centos6 68 | centos6.10 69 | centos6.6 70 | centos6.7 71 | centos6.8 72 | centos6.9 73 | centos7 74 | centos7.0.1406 75 | centos7.1.1503 76 | centos7.2.1511 77 | centos7.3.1611 78 | centos7.4.1708 79 | centos7.5.1804 80 | centos7.6.1810 81 | centos7.7.1908 82 | centos7.8.2003 83 | centos7.9.2009 84 | centos8 85 | centos8.1.1911 86 | centos8.2.2004 87 | centos8.3.2011 88 | centos8.4.2105 89 | ``` 90 | -------------------------------------------------------------------------------- /es/es7.8常见命令/es 保证单词间顺序.md: -------------------------------------------------------------------------------- 1 | ## interval 2 | 返回按照检索词的特定排列顺序排列的文档。这个查询比较复杂,这里只是简单的介绍,详细的介绍可以看官方文档 3 | 4 | 比如我们想查询同时包含raj和nayaka的字段并且ray正好在nayaka前面,查询语句如下: 5 | ``` 6 | POST /_search 7 | { 8 | "query": { 9 | "intervals": { 10 | "name": { 11 | "match": { 12 | "query": "raj nayaka", 13 | "max_gaps": 0, 14 | "ordered": true 15 | } 16 | } 17 | } 18 | } 19 | } 20 | 21 | ``` 22 | 上面的查询会匹配Raj Nayaka Acchu Valmiki和Yateesh Raj Nayaka。 23 | 24 | 如果把ordered:true去掉,就会匹配nayaka raj。 25 | 26 | 如果把max_gaps:0去掉,系统会用默认值-1也就是没有距离要求,就会匹配Raj Raja nayaka或者Raj Kumar Nayaka 27 | 28 | 其中有两个关键词ordered和max_gaps分别用来控制这个筛选条件是否需要排序以及两个token之间的最大间隔 29 | 30 | ## curl 31 | ``` 32 | curl -XGET 'http://127.0.0.1:9200/2022-10-26/_search?pretty' -H "Content-Type: application/json" --data \ 33 | ' 34 | { 35 | "query": { 36 | "intervals": { 37 | "content": { 38 | "match": { 39 | "query": "need service", 40 | "max_gaps": -1, 41 | "ordered": true 42 | } 43 | } 44 | } 45 | } 46 | } 47 | ' 48 | 49 | ``` 50 | 51 | ## 链接 52 | [十九种Elasticsearch字符串搜索方式终极介绍](https://zhuanlan.zhihu.com/p/137575167) 53 | -------------------------------------------------------------------------------- /es/es7.8常见命令/删除某个索引的某些 doc.md: -------------------------------------------------------------------------------- 1 | ## 根据用户 id 删除 doc 2 | ``` 3 | curl -XPOST http://127.0.0.1:9200/2022-10-16/_delete_by_query -H "Content-Type: application/json" -d' 4 | { 5 | "query":{ 6 | "term":{ 7 | "user_id": 123 8 | } 9 | } 10 | } 11 | ' 12 | ``` 13 | 14 | ## 同时删除多索引 15 | ``` 16 | curl -XPOST http://127.0.0.1:9200/2022-10-15,2022-10-16,2022-10-17/_delete_by_query -H "Content-Type: application/json" -d' 17 | { 18 | "query":{ 19 | "term":{ 20 | "user_id": 123 21 | } 22 | } 23 | } 24 | ' 25 | ``` 26 | 27 | ## 校验 28 | ``` 29 | curl -XPOST http://127.0.0.1:9200/2022-10-16,2022-10-17/_search?pretty -H "Content-Type: application/json" -d' 30 | { 31 | "query":{ 32 | "term":{ 33 | "user_id": 123 34 | } 35 | } 36 | } 37 | ' 38 | ``` 39 | -------------------------------------------------------------------------------- /es/es7.8常见命令/搜索某个关键词.md: -------------------------------------------------------------------------------- 1 | ## curl 2 | ``` 3 | curl -i -XPOST http://127.0.0.1:9200/2022-08-14/_search?pretty -H "Content-Type: application/json" --data \ 4 | '{ 5 | "query": { 6 | "match": { 7 | "content": "fatpo" 8 | } 9 | } 10 | }' 11 | 12 | ``` 13 | 14 | ## python3 15 | ``` 16 | import datetime 17 | 18 | from elasticsearch import Elasticsearch 19 | 20 | 21 | def main(): 22 | yesterday = datetime.datetime.today() + datetime.timedelta(days=-1) 23 | yesterday_str = yesterday.strftime('%Y-%m-%d') 24 | 25 | es = Elasticsearch( 26 | ['http://127.0.0.1:9200'] 27 | ) 28 | 29 | response = es.search( 30 | index=yesterday_str, # 索引名 31 | body={ # 请求体 32 | "query": { # 关键字,把查询语句给 query 33 | "bool": { # 关键字,表示使用 filter 查询,没有匹配度 34 | "should": [ # 表示里面的条件必须匹配,多个匹配元素可以放在列表里 35 | { 36 | "match": { # 关键字,表示需要匹配的元素 37 | "content": 'fatpo' # TransId 是字段名, 06100021650016153 是此字段需要匹配到的值 38 | } 39 | }, 40 | ], 41 | } 42 | }, 43 | 44 | # 下面是对返回的结果继续排序 45 | "sort": [{"created_at": {"order": "desc"}}], 46 | "from": 0, # 从匹配到的结果中的第几条数据开始返回,值是匹配到的数据的下标,从 0 开始 47 | "size": 500 # 返回多少条数据 48 | } 49 | ) 50 | # 命中几条 51 | print(response['hits']['total']['value']) 52 | # 每条内容 53 | print(response['hits']['hits']) 54 | 55 | 56 | if __name__ == '__main__': 57 | main() 58 | 59 | ``` 60 | -------------------------------------------------------------------------------- /es/es7.8常见命令/查看es所有索引.md: -------------------------------------------------------------------------------- 1 | 正常来说: 2 | ``` 3 | curl 'http://127.0.0.1:9200/_cat/indices' 4 | ``` 5 | 6 | 有些设置没开放本地地址访问,只能用IP访问: 7 | ``` 8 | curl 'http://66.1.2.3:9200/_cat/indices' 9 | ``` 10 | -------------------------------------------------------------------------------- /es/es7.8常见命令/查看某个字段不存在的门店.md: -------------------------------------------------------------------------------- 1 | # 查看tags为空的门店 2 | ``` 3 | curl --location --request GET 'http://1.2.3.4:9218/store_search_index/_search?pretty' \ 4 | --header 'Content-Type: application/json' \ 5 | --data-raw ' 6 | { 7 | "size": 10, 8 | "query": 9 | { 10 | "bool": 11 | { 12 | "must_not": 13 | [ 14 | { 15 | "exists": 16 | { 17 | "field": "tags" 18 | } 19 | } 20 | ] 21 | } 22 | } 23 | } 24 | ' 25 | ``` 26 | -------------------------------------------------------------------------------- /es/es7.8常见命令/查看某个字段存在的门店.md: -------------------------------------------------------------------------------- 1 | # 查看 tags 不为空的门店 2 | ``` 3 | curl --location --request GET 'http://1.2.3.4:9218/store_search_index/_search?pretty' \ 4 | --header 'Content-Type: application/json' \ 5 | --data-raw ' 6 | { 7 | "query" : { 8 | "constant_score" : { 9 | "filter" : { 10 | "exists" : { "field" : "tags" } 11 | } 12 | } 13 | } 14 | } 15 | ' 16 | ``` 17 | -------------------------------------------------------------------------------- /es/es7.8常见命令/查看某个索引size.md: -------------------------------------------------------------------------------- 1 | ``` 2 | curl http://127.0.0.1:9200/_cat/count/2022-08-14?pretty 3 | ``` 4 | -------------------------------------------------------------------------------- /es/es7.8常见命令/查看某个索引的mappings.md: -------------------------------------------------------------------------------- 1 | ``` 2 | curl 'http://127.0.0.1:9200/2022-08-26/_mappings?pretty' 3 | ``` 4 | -------------------------------------------------------------------------------- /es/es入门/es 开启 auth 验证.md: -------------------------------------------------------------------------------- 1 | 用`--header 'Authorization' `: 2 | ``` 3 | curl --header 'Authorization: Basic bzJvYWxnb19mb29kX3NlYXJjaDpw' -XPOST 'http://127.0.0.1:9201/fatpo_index/_search?pretty' -H "Content-Type: application/json" --data ' 4 | { 5 | "size" : 100, 6 | "query":{ 7 | "match": { 8 | "store_name": "test" 9 | } 10 | } 11 | } 12 | ' 13 | ``` 14 | 或者`--user username:password`: 15 | ``` 16 | curl --user username:password -XPOST 'http://127.0.0.1:9201/fatpo_index/_search?pretty' -H "Content-Type: application/json" --data ' 17 | { 18 | "size" : 100, 19 | "query":{ 20 | "match": { 21 | "store_name": "test" 22 | } 23 | } 24 | } 25 | ' 26 | ``` 27 | -------------------------------------------------------------------------------- /es/es入门/es副本和节点.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fatpo/backend_note/027983f71ae0b0ceacb11e0baf3430c80288196b/es/es入门/es副本和节点.png -------------------------------------------------------------------------------- /es/es入门/step1-安装es.md: -------------------------------------------------------------------------------- 1 | ## 安装 2 | ```text 3 | docker pull elasticsearch:7.16.2 4 | ``` 5 | 6 | ## 运行 7 | ```text 8 | docker run --name es -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -d elasticsearch:7.16.2 9 | ``` 10 | 11 | ## 验证 12 | ```text 13 | curl http://127.0.0.1:9200 14 | { 15 | "name" : "b870b26d1909", 16 | "cluster_name" : "docker-cluster", 17 | "cluster_uuid" : "eENZg2XtRtqTjTGRYvWxcw", 18 | "version" : { 19 | "number" : "7.16.2", 20 | "build_flavor" : "default", 21 | "build_type" : "docker", 22 | "build_hash" : "2b937c44140b6559905130a8650c64dbd0879cfb", 23 | "build_date" : "2021-12-18T19:42:46.604893745Z", 24 | "build_snapshot" : false, 25 | "lucene_version" : "8.10.1", 26 | "minimum_wire_compatibility_version" : "6.8.0", 27 | "minimum_index_compatibility_version" : "6.0.0-beta1" 28 | }, 29 | "tagline" : "You Know, for Search" 30 | } 31 | ``` -------------------------------------------------------------------------------- /es/es入门/step2-创建索引.md: -------------------------------------------------------------------------------- 1 | ## 创建索引 2 | ```text 3 | curl -XPUT http://127.0.0.1:9200/fatpo_index/?pretty 4 | ``` 5 | 创建成功: 6 | ```json 7 | { 8 | "acknowledged": true, 9 | "shards_acknowledged": true, 10 | "index": "fatpo_index" 11 | } 12 | ``` 13 | 14 | ## 创建带 settings 配置的索引 15 | 比如初始化索引的时候,指定好副本数和分区数。 16 | ```text 17 | curl -XPUT http://127.0.0.1:9200/fatpo_index/?pretty 18 | ``` 19 | body: 20 | ```json 21 | { 22 | "settings": { 23 | "number_of_shards": 3, 24 | "number_of_replicas": 1 25 | } 26 | } 27 | ``` 28 | 创建成功: 29 | ```json 30 | { 31 | "acknowledged": true, 32 | "shards_acknowledged": true, 33 | "index": "fatpo_index" 34 | } 35 | ``` 36 | 37 | 38 | ## 查看整个索引结构 39 | ```text 40 | curl -XGET http://127.0.0.1:9200/fatpo_index/?pretty 41 | ``` 42 | 返回索引结构: 43 | ```json 44 | { 45 | "fatpo_index": { 46 | "aliases": {}, 47 | "mappings": {}, 48 | "settings": { 49 | "index": { 50 | "routing": { 51 | "allocation": { 52 | "include": { 53 | "_tier_preference": "data_content" 54 | } 55 | } 56 | }, 57 | "number_of_shards": "1", 58 | "provided_name": "fatpo_index", 59 | "creation_date": "1665643619571", 60 | "number_of_replicas": "1", 61 | "uuid": "05_-YbotQMiYnI1DqZTxFQ", 62 | "version": { 63 | "created": "7160299" 64 | } 65 | } 66 | } 67 | } 68 | } 69 | ``` 70 | 可以看到 es 的索引基本信息,默认副本 1,默认分区 1。 71 | 72 | ## 查看索引 mappings 73 | ```text 74 | curl -XGET http://127.0.0.1:9200/fatpo_index/_mappings?pretty 75 | ``` 76 | 结果可以看到,我们的索引 mappings 空空如也。 77 | ```json 78 | { 79 | "fatpo_index": { 80 | "mappings": {} 81 | } 82 | } 83 | ``` 84 | 85 | ## 查看索引 settings 86 | ```text 87 | curl -XGET http://127.0.0.1:9200/fatpo_index/_settings?pretty 88 | ``` 89 | 结果可以看到,我们的索引 _settings,默认分区是 1 个,副本是 1 个。 90 | ```json 91 | { 92 | "fatpo_index": { 93 | "settings": { 94 | "index": { 95 | "routing": { 96 | "allocation": { 97 | "include": { 98 | "_tier_preference": "data_content" 99 | } 100 | } 101 | }, 102 | "number_of_shards": "1", 103 | "provided_name": "fatpo_index", 104 | "creation_date": "1665643619571", 105 | "number_of_replicas": "1", 106 | "uuid": "05_-YbotQMiYnI1DqZTxFQ", 107 | "version": { 108 | "created": "7160299" 109 | } 110 | } 111 | } 112 | } 113 | } 114 | ``` 115 | -------------------------------------------------------------------------------- /es/es入门/step3-修改索引.md: -------------------------------------------------------------------------------- 1 | ## 修改副本数为 0 2 | ```text 3 | curl -XPUT http://127.0.0.1:9200/fatpo_index/_settings?pretty 4 | ``` 5 | body: 6 | ```json 7 | { 8 | "settings": { 9 | "index": { 10 | "number_of_replicas": "2" 11 | } 12 | } 13 | } 14 | ``` 15 | 修改成功: 16 | ```json 17 | { 18 | "acknowledged": true 19 | } 20 | ``` 21 | 查看下是否修改成功,可以看到 ` "number_of_replicas": "0",` : 22 | ```text 23 | curl -XGET http://127.0.0.1:9200/fatpo_index/_settings?pretty 24 | { 25 | "fatpo_index": { 26 | "settings": { 27 | "index": { 28 | "routing": { 29 | "allocation": { 30 | "include": { 31 | "_tier_preference": "data_content" 32 | } 33 | } 34 | }, 35 | "number_of_shards": "1", 36 | "provided_name": "fatpo_index", 37 | "creation_date": "1665643619571", 38 | "number_of_replicas": "0", 39 | "uuid": "05_-YbotQMiYnI1DqZTxFQ", 40 | "version": { 41 | "created": "7160299" 42 | } 43 | } 44 | } 45 | } 46 | } 47 | ``` 48 | 49 | 50 | ## 已经创建的索引不能修改分区数量 51 | 注意:已经创建的索引只能修改副本数,不能修改分区数!!! 52 | 53 | 唯一能够配置分区数量的时候,就是在创建的时候: 54 | ```text 55 | PUT /newindex 56 | { 57 | "settings" : { 58 | "number_of_shards" : 3, //分区数 59 | "number_of_replicas" : 1 //副本数 60 | } 61 | } 62 | ``` -------------------------------------------------------------------------------- /es/es入门/step4-分区和副本的概念.md: -------------------------------------------------------------------------------- 1 | ## 分区 2 | `分区是将数据切割`。 3 | 4 | es 是一个分布式系统,数据会被切割小片,放到不同的节点上。 5 | 6 | 查询时,es 将查询分配到每个相关的分片上,再把查询结果合并。 7 | 8 | 分区的目的是为了避免单分区时数据量过大,对节点的CPU、内存、磁盘产生压力过大,同时增加了集群的可扩展性。 9 | 10 | ## 副本 11 | `副本是将数据进行备份`, 副本目标是高可用性。 12 | 13 | 当主分配数据不可用时,副本分片会自动成为新的主分配,以保障数据的高可用性。 14 | 15 | ## 架构图 16 | 17 | ![imags/es副本和节点.png](es副本和节点.png) 18 | 19 | 20 | ## 如何分配 21 | -------------------------------------------------------------------------------- /es/multi_search/multi_match的六种类型.md: -------------------------------------------------------------------------------- 1 | 2 | ## multi_match 案例 3 | ```text 4 | GET /_search 5 | { 6 | "query": { 7 | "multi_match" : { 8 | "query": "kfc", 9 | "fields": [ "subject", "message" ] 10 | } 11 | } 12 | } 13 | ``` 14 | 解释: 15 | ```text 16 | 用"kfc"分别去搜索 subject和 message 字段。 17 | ``` 18 | 19 | ## multi_match 类型 20 | | 类型 | 解释 | 21 | |:--------------|:------------------------------------------------------------------------------------------------------------------------------------------------| 22 | | best_fields | (default) Finds documents which match any field, but uses the _score from the best field. .

默认项,匹配到多个 doc,会按照最佳分数去召回 doc。 | 23 | | most_fields | Finds documents which match any field and combines the _score from each field.

假设同时在subject和 message 命中 kfc,会把两个分数加起来。 | 24 | | cross_fields | Treats fields with the same analyzer as though they were one big field. Looks for each word in any field. | 25 | | phrase | Runs a match_phrase query on each field and uses the _score from the best field. | 26 | | phrase_prefix | Runs a match_phrase_prefix query on each field and uses the _score from the best field. | 27 | | bool_prefix | Creates a match_bool_prefix query on each field and combines the _score from each field. | -------------------------------------------------------------------------------- /es/底层原理/合并1-索引合并的底层逻辑.md: -------------------------------------------------------------------------------- 1 | 2 | * [es 怎么写数据的](#es-怎么写数据的) 3 | * [segment 长什么样子](#segment-长什么样子) 4 | * [segment 多会导致什么问题](#segment-多会导致什么问题) 5 | * [合并 segment 大致流程是什么](#合并-segment-大致流程是什么) 6 | * [原文搬运](#原文搬运) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 我们都知道 es 会自动或者可以手动 merge,但其实不是很清楚底层的原理如何。 14 | 15 | 了解底层的 merge 策略和底层原理,可以更好的帮助我们使用 es 和减轻日常 es 运维压力。 16 | 17 | 等等,又是运维,为什么开发面试问运维知识,运维面试问开发知识? 18 | 19 | # es 怎么写数据的 20 | 没看之前,盲猜就是: 21 | ``` 22 | 先写到一个内存的 buffer(主要是能利用顺序 IO + 批量的高效), 23 | 再有个参数配置,几秒刷到磁盘(一般是三个配置:always,one_second, os, 24 | 分别是一直刷、每秒刷、看操作系统file page cache满了刷)。 25 | ``` 26 | 以下是抄自文档(引用 1): 27 | ```text 28 | 当我们往 ElasticSearch 写入数据时,数据是先写入 memory buffer,然后定时(默认每隔1s)将 memory buffer 中的数据写入一个新的 segment 文件中, 29 | 并进入 Filesystem cache(同时清空 memory buffer),这个过程就叫做 refresh;每个 Segment 事实上是一些倒排索引的集合, 30 | 只有经历了 refresh 操作之后,数据才能变成可检索的。 31 | ``` 32 | 33 | 这里我们就引出一个概念,es 数据每秒都刷到磁盘的文件中,这个文件就是 segment。 34 | 35 | ## segment 长什么样子 36 | 37 | * 首先他是个文件,按照一定格式组织起来的文件。 38 | * 每个 segment 是一个包含正排(空间占比90,95%)+ 倒排(空间占比5,10%)的完整索引文件。 39 | * 每次搜索请求会把每个 segment 的倒排加载到内存空间,打分,再回流,将命中的文档号拿到正排中召回完整数据记录。 40 | 41 | ## segment 多会导致什么问题 42 | * 每秒 commit 一次,这么看来一天要产生 86400 个 segment,每个 segment 都是一个文件,进程每操作一个文件都要消耗一个 fd(我依稀记得默认情况下,linux 一个进程能操控的句柄是 1024个?),服务器的句柄经得住这么消耗吗? 43 | * 而且 es 在线服务会加载并搜索每一个 segment,segment 越多,搜索效率越低。 44 | 45 | 所以需要合并 segment。 46 | 47 | ## 合并 segment 大致流程是什么 48 | * 1、开一个后台进程,定期 merge(默认是每秒一次) 49 | * 2、将多个小 segment 合并到一个大的 segment,跳过那些被标记为删除的 segment,或者旧版本的 segment 50 | * 3、合并完成后,然后将新的 segment 文件 flush 写入磁盘 51 | * 4、然后创建一个新的 commit point 文件,标识所有新的 segment 文件,并排除掉旧的 segment 和已经被合并的小 segment 52 | * 5、然后打开新 segment 文件用于搜索使用,等所有的检索请求都从小的 segment 转到 大 segment 上以后,删除旧的 segment 文件,这时候,索引里 segment 数量就下降了 53 | 54 | 55 | # 原文搬运 56 | 57 | * [Elasticsearch搜索引擎:ES的segment段合并原理](https://blog.csdn.net/a745233700/article/details/117953198) 58 | * [Elasticsearch merge 你懂了吗?](https://cloud.tencent.com/developer/article/1846903) -------------------------------------------------------------------------------- /es/底层原理/合并2-合并中性能的时间空间考量.md: -------------------------------------------------------------------------------- 1 | 2 | * [写在前面](#写在前面) 3 | * [空间-合并策略](#空间-合并策略) 4 | * [调整空间策略的经验1:适当提高限速](#调整空间策略的经验1适当提高限速) 5 | * [调整空间策略的经验2:放弃不关键字段](#调整空间策略的经验2放弃不关键字段) 6 | * [时间-间隔策略](#时间-间隔策略) 7 | * [手动合并要警惕!](#手动合并要警惕) 8 | * [原文搬运](#原文搬运) 9 | 10 | 11 | 12 | 13 | 14 | 15 | ## 写在前面 16 | 按常理来说,合并多个 segments,多个小的合并成为一个大的。 17 | 18 | 一定有一堆的配置来限制,比如控制在 1000 个以下?比如控制大小 100MB 以内?总之一定有一些边界限制的。 19 | 20 | ## 空间-合并策略 21 | 22 | 合并线程是按照一定的运行策略来挑选 segment 进行归并的。主要有以下几条: 23 | 24 | * index.merge.policy.floor_segment:默认 2MB,小于该值的 segment 会优先被归并。 25 | * index.merge.policy.max_merge_at_once:默认一次最多归并 10 个 segment 26 | * index.merge.policy.max_merge_at_once_explicit:默认 forcemerge 时一次最多归并 30 个 segment 27 | * index.merge.policy.max_merged_segment:默认 5 GB,大于该值的 segment,不用参与归并,forcemerge 除外 28 | 29 | 30 | 查看 es 的策略: 31 | ```text 32 | curl -XGET 'http:///10.1.96.5:9200/2023-01-30/_settings?include_defaults&pretty' 33 | 34 | "policy" : { 35 | "floor_segment" : "2mb", 36 | "max_merge_at_once_explicit" : "30", 37 | "max_merge_at_once" : "10", 38 | "max_merged_segment" : "5gb", 39 | "expunge_deletes_allowed" : "10.0", 40 | "segments_per_tier" : "10.0", 41 | "deletes_pct_allowed" : "33.0" 42 | } 43 | 44 | 解释下: 45 | "policy": { 46 | "fool_segment": "2mb", 47 | "max_merge_at_once_explicit": "30", //显示调用optimize 操作或者 expungeDeletes时可以操作多少个segments,默认是30 48 | "max_merge_at_once": "10",//一次最多只操作多少个segments,默认是10. 49 | "max_merged_segment": "5gb",//超过多大size的segment不会再做merge,默认是5g 50 | "expunge_deletes_allowed": "10.0",//指删除了的文档数在一个segment里占的百分比,默认是10,大于这个值时,在执行expungeDeletes 操作时将会merge这些segments. 51 | "segments_per_tier": "10.0"//每个tier允许的segment 数,注意这个数要大于上面的at_once数,否则这个值会先于最大可操作数到达,就会立刻做merge,这样会造成频繁的访问操作 52 | } 53 | ``` 54 | 55 | ### 调整空间策略的经验1:适当提高限速 56 | 57 | 默认情况下,归并线程的限速配置 indices.store.throttle.max_bytes_per_sec 是 20MB。 58 | 59 | 对于写入量较大,磁盘转速较高,甚至使用 SSD 盘的服务器来说,这个限速是明显过低的。 60 | 61 | 对于 ELK Stack 应用,建议可以适当调大到 100MB或者更高。设置方式如下: 62 | ```text 63 | PUT /_cluster/settings 64 | { 65 | "persistent" : { 66 | "indices.store.throttle.max_bytes_per_sec" : "100mb" 67 | } 68 | } 69 | ``` 70 | 71 | 或者不限制: 72 | ```text 73 | PUT /_cluster/settings 74 | { 75 | "transient" : { 76 | "indices.store.throttle.type" : "none" 77 | } 78 | } 79 | ``` 80 | 81 | ### 调整空间策略的经验2:放弃不关键字段 82 | norms、doc_values 和 stored 字段的存储机制类似,每个 field 有一个全量的存储,对存储浪费很大。 83 | 84 | * norms: 如果一个 field 不需要考虑其相关度分数,那么可以禁用 norms,减少倒排索引内存占用量,字段粒度配置 omit_norms=true; norms记录了索引中index-time boost信息,但是当你进行搜索时可能会比较耗费内存。omit_norms = true则是忽略掉域加权信息,这样在搜索的时候就不会处理索引时刻的加权信息了。 85 | * doc_values: 如果不需要对 field 进行排序或者聚合,那么可以禁用 doc_values 字段; 86 | * store: 如果 field 只需要提供搜索,不需要返回则将 stored 设为 false; 域存储选项store,用来确定是否需要存储域的真实值,以便后续搜集时能恢复这个值。 87 | 88 | 这样子从根本上减少 segment 是的体积,也是一个提速的小妙招。 89 | 90 | 91 | 92 | 93 | ## 时间-间隔策略 94 | 95 | 上面的`合并策略`是讲合并的时候要干嘛,这个属于空间范畴。 96 | 97 | 还有一个时间范畴,就是 加大 refresh 间隔,尽量让每次新生成的 segment 本身大小就比较大。 98 | 99 | 这种方式主要通过延迟提交实现,延迟提交意味着数据从提交到搜索可见有延迟,具体需要结合业务配置,默认值1s; 100 | 101 | 针对索引节点粒度的配置如下: 102 | ``` 103 | curl -XPUT http://host地址:port端口/索引节点名称/_settings -d '{"index.refresh_interval":"10s"}' 104 | ``` 105 | 106 | ## 手动合并要警惕! 107 | 手动合并 _forcemerge 的 API 如下: 108 | ```text 109 | //该命令针对5.0以上版本的ES 110 | POST /INDEX/_forcemerge 111 | { 112 | "max_num_segments":1 113 | } 114 | 115 | //5.0以下可以使用以下 116 | POST /INDEX/_optimize 117 | { 118 | "max_num_segments":1 119 | } 120 | ``` 121 | 122 | 它有很坑的点就是: 123 | ```text 124 | _forcemerge 命令是没有限制资源的,也就是你系统有多少IO资源就会使用多少IO资源, 125 | 这样可能导致一段时间内搜索没有任何响应! 126 | ``` 127 | 128 | 它非常适合那些,静态索引,比如昨天的日志,上个月的数据报表,等几乎不会改动的。 129 | 130 | 如果非要改动,请务必把索引文件先挪到一个 node 上,目标是不要影响别人。 131 | 132 | 但具体怎么做呢?有没有一些方法论? 133 | 134 | ## 原文搬运 135 | * [Elasticsearch搜索引擎:ES的segment段合并原理](https://blog.csdn.net/a745233700/article/details/117953198) 136 | * [Elasticsearch 理解mapping中的store属性](https://www.cnblogs.com/hahaha111122222/p/12157453.html) -------------------------------------------------------------------------------- /es/底层原理/建索引的底层逻辑.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fatpo/backend_note/027983f71ae0b0ceacb11e0baf3430c80288196b/es/底层原理/建索引的底层逻辑.md -------------------------------------------------------------------------------- /es/相关性分数/TF&IDF.md: -------------------------------------------------------------------------------- 1 | es 的相关性得分,默认是 TF&IDF 算法,全称是 Term Frequency 和 Inverse Doc Frequency。 2 | 3 | 它就 3 个特点: 4 | * 搜索文本中的各个词条在 field 文本中出现了多少次,出现次数越多,就越相关 5 | * 搜索文本中的各个词条在整个索引的所有文档中出现了多少次,出现的次数越多,就越不相关 6 | * field 长度,field 越长,相关度越弱 7 | -------------------------------------------------------------------------------- /es/相关性分数/function_scope入门.md: -------------------------------------------------------------------------------- 1 | 2 | * [function score](#function-score) 3 | * [filter vs query](#filter-vs-query) 4 | * [boost_mode vs score_mode](#boost_mode-vs-score_mode) 5 | * [weight](#weight) 6 | * [field_value_factor](#field_value_factor) 7 | * [random_score](#random_score) 8 | * [衰减函数](#衰减函数) 9 | * [属性](#属性) 10 | * [举个栗子](#举个栗子) 11 | * [衰减函数的 3 种模式](#衰减函数的-3-种模式) 12 | * [script_score](#script_score) 13 | * [暗戳戳影响搜索结果](#暗戳戳影响搜索结果) 14 | * [使用 param 来解耦](#使用-param-来解耦) 15 | * [多个 functions 合作](#多个-functions-合作) 16 | * [第一个例子是类似于大众点评的餐厅应用](#第一个例子是类似于大众点评的餐厅应用) 17 | * [新浪微博的社交网站](#新浪微博的社交网站) 18 | * [原文搬运](#原文搬运) 19 | 20 | 21 | 22 | 23 | 24 | 25 | # function score 26 | 是一个自定义打分函数的query 27 | 28 | fsq(function score query) 的结构大致如下: 29 | ```json 30 | { 31 | "filter": {}, 32 | "query": {}, 33 | "functions": [], 34 | "boost_mode": "sum", 35 | "score_mode": "sum", 36 | "field_value_factor": {}, 37 | "random_score": {}, 38 | "script_score": {} 39 | } 40 | ``` 41 | 下面会一一介绍。 42 | 43 | ## filter vs query 44 | 有些时候我们无须使用全文搜索,只想找到 es 字段中包含 query 的所有文档,逻辑用过滤比用查询表达更清晰。 45 | 46 | 过滤器返回的所有文档的评分 _score 的值为 1 。 47 | 48 | function_score 查询接受 query 或 filter ,如果没有特别指定,则默认使用 `match_all` 查询。 49 | 50 | ## boost_mode vs score_mode 51 | 52 | 首先,每个文档由定义的函数打分。 53 | 54 | 参数 `score_mode` 规定计算的分数如何组合: 55 | 56 | |类型|解释| 57 | |:---|:---| 58 | |multiply | 分数相乘(默认)| 59 | |sum|得分相加| 60 | |avg|平均分数| 61 | |first |使用具有匹配过滤器的第一个函数| 62 | |max|最大得分| 63 | |min|最小分数| 64 | 65 | 因为有可能会用到 `functionscore(fsq)` 来替换es 默认打分,这里引进了`boost_mode`。 66 | 67 | 新计算的分数与查询的分数相组合,参数 `boost_mode`定义其组合方式: 68 | 69 | |类型|解释| 70 | |:---|:---| 71 | |multiply|查询得分和函数得分相乘(默认)| 72 | |replace|仅使用函数得分,忽略查询得分| 73 | |sum|查询得分和函数得分相加| 74 | |avg|取平均值| 75 | |max|查询得分和函数得分的最大值| 76 | |min|查询得分和函数得分的最小值| 77 | 78 | 79 | ## weight 80 | 设置权重,我印象中每次都是用于多functions中的 filter + weight 打分,命中一个加 N 分,类似这样子。 81 | dsl: 82 | ```text 83 | GET /_search 84 | { 85 | "query": { 86 | "function_score": { 87 | "filter": { 88 | "term": { "city": "Barcelona" } 89 | }, 90 | "functions": [ 91 | { 92 | "filter": { "term": { "features": "wifi" }}, 93 | "weight": 1 94 | }, 95 | { 96 | "filter": { "term": { "features": "garden" }}, 97 | "weight": 1 98 | }, 99 | { 100 | "filter": { "term": { "features": "pool" }}, 101 | "weight": 2 102 | } 103 | ], 104 | "score_mode": "sum" 105 | } 106 | } 107 | } 108 | ``` 109 | 110 | 111 | ## field_value_factor 112 | 将某个字段的值进行计算得出分数。 113 | 114 | * field 指定某个字段 115 | * factor 对字段初始值的预处理,乘以指定数值,默认是 1 116 | * modifier 用什么方法来修正分数: 117 | * none:不处理 118 | * log:计算对数 119 | * log1p:先将字段值 +1,再计算对数 120 | * log2p:先将字段值 +2,再计算对数 121 | * ln:计算自然对数 122 | * ln1p:先将字段值 +1,再计算自然对数 123 | * ln2p:先将字段值 +2,再计算自然对数 124 | * square:计算平方 125 | * sqrt:计算平方根 126 | * reciprocal:计算倒数 127 | 128 | 举个栗子: 有一个需求,门店看得人越多,就越靠前,但是要避免马太效应,所以不能无脑根据门店的查看数倒序。 129 | 请问怎么办? 130 | 131 | 假设门店有一个字段:`view_num`,我们自定义分数: 132 | ```text 133 | GET /store/_search 134 | { 135 | "query": { 136 | "function_score": { 137 | "query": { 138 | "multi_match": { 139 | "query": "kfc", 140 | "fields": ["tile", "content"] 141 | } 142 | }, 143 | "field_value_factor": { 144 | "field": "view_num", 145 | "modifier": "log1p", 146 | "factor": 0.5 147 | }, 148 | "boost_mode": "sum", 149 | "max_boost": 2 150 | } 151 | } 152 | } 153 | ``` 154 | 解读下: 155 | * log1p是一个函数,用于对字段分数进行修正: 156 | ``` 157 | new_score = old_score * log(1 + factor * follower_num) 158 | ``` 159 | * boost_mode,用于决定最终doc分数与指定字段的值如何计算: 160 | ``` 161 | multiply,sum,min,max,replace 162 | ``` 163 | * max_boost,用于限制计算出来的分数不要超过max_boost指定的值。 164 | 165 | ## random_score 166 | 随机得到 0 到 1 分数,我本来也不是很理解这个东西的使用场景,直到看到这个需求: 167 | ```text 168 | 作为网站的所有者,总会希望让广告有更高的展现率。 169 | 在当前查询下,有相同评分 _score 的文档会每次都以相同次序出现。 170 | 为了提高展现率,在此引入一些随机性可能会是个好主意,这能保证有相同评分的文档都能有均等相似的展现机率。 171 | 172 | 我们想让每个用户看到不同的随机次序,但也同时希望如果是同一用户翻页浏览时,结果的相对次序能始终保持一致。 173 | 这种行为被称为 一致随机(consistently random)。 174 | 175 | random_score 函数会输出一个 0 到 1 之间的数, 当种子 seed 值相同时,生成的随机结果是一致的。 176 | 例如,将用户的会话 ID 作为 seed。 177 | ``` 178 | dsl 如下: 179 | ```text 180 | GET /_search 181 | { 182 | "query": { 183 | "function_score": { 184 | "random_score": { 185 | "seed": 10, 186 | "field": "_seq_no" 187 | } 188 | } 189 | } 190 | } 191 | ``` 192 | 复杂的 dsl 如下: 193 | ```text 194 | GET /_search 195 | { 196 | "query": { 197 | "function_score": { 198 | "filter": { 199 | "term": { "city": "Barcelona" } 200 | }, 201 | "functions": [ 202 | { 203 | "filter": { "term": { "features": "wifi" }}, 204 | "weight": 1 205 | }, 206 | { 207 | "filter": { "term": { "features": "garden" }}, 208 | "weight": 1 209 | }, 210 | { 211 | "filter": { "term": { "features": "pool" }}, 212 | "weight": 2 213 | }, 214 | { 215 | "random_score": { 216 | "seed": "the users session id" 217 | } 218 | } 219 | ], 220 | "score_mode": "sum" 221 | } 222 | } 223 | } 224 | ``` 225 | 这个 dsl 实现了: 226 | * random_score 语句没有任何过滤器 filter ,所以会被应用到所有文档。 227 | * 将用户的会话 ID 作为种子 seed ,让该用户的随机始终保持一致,相同的种子 seed 会产生相同的随机结果。 228 | 229 | 230 | 231 | ## 衰减函数 232 | 同样以某个字段的值为标准,距离某个值越近得分越高 233 | ### 属性 234 | * 原点(origin):该字段最理想的值,这个值可以得到满分(1.0) 235 | * 偏移量(offset):与原点相差在偏移量之内的值也可以得到满分 236 | * 衰减规模(scale):当值超出了原点到偏移量这段范围,它所得的分数就开始进行衰减了,衰减规模决定了这个分数衰减速度的快慢 237 | * 衰减值(decay):该字段可以被接受的值(默认为 0.5),相当于一个分界点,具体的效果与衰减的模式有关 238 | ### 举个栗子 239 | 例子1: 240 | * 买东西,心理预期价格 50 元 241 | * 但是我们不可能非 50 元就不买,而是会划定一个可接受的价格范围,例如 45-55 元,±5 就为偏移量 242 | * 当价格超出了可接受的范围,就会让人觉得越来越不值。如果价格是 70 元,评价可能是不太想买,而如果价格是 200 元,评价则会是不可能会买,这就是由衰减规模和衰减值所组成的一条衰减曲线 243 | 244 | 例子 2: 245 | * 我们想租一套房,它的理想位置是公司附近 246 | * 如果离公司在 5km 以内,是我们可以接受的范围,在这个范围内我们不去考虑距离,而是更偏向于其他信息 247 | * 当距离超过 5km 时,我们对这套房的评价就越来越低了,直到超出了某个范围就再也不会考虑了 248 | 249 | 250 | ### 衰减函数的 3 种模式 251 | * 线性函数(linear) 252 | * 以 e 为底的指数函数(Exp) 253 | * 高斯函数(gauss) 254 | 255 | ![衰减函数.png](衰减函数.png) 256 | 257 | 例子 2的 dsl: 258 | ```json 259 | { 260 | "query": 261 | { 262 | "function_score": 263 | { 264 | "query": 265 | { 266 | "match": 267 | { 268 | "title": "公寓" 269 | } 270 | }, 271 | "gauss": 272 | { 273 | "location": 274 | { 275 | "origin": 276 | { 277 | "lat": 40, 278 | "lon": 116 279 | }, 280 | "offset": "5km", 281 | "scale": "10km" 282 | } 283 | }, 284 | "boost_mode": "sum" 285 | } 286 | } 287 | } 288 | ``` 289 | 290 | 291 | ## script_score 292 | 通过自定义脚本计算分值。 293 | 294 | 295 | ### 暗戳戳影响搜索结果 296 | 假设我们有一批门店,用户搜索 `云南大理`,我就想把云南大理的门店给推给他们。 297 | 298 | 此时此刻,有一个活动,要宣传电影节,我们想要把类别为电影院的门店(es 字段:category)提到靠前的地方。 299 | 300 | 要求是,暗戳戳去影响搜索结果,不能明目张胆得把非电影院的都 filter 掉。 301 | 302 | 想了下,应该用 `boost` 之类的给电影院的提分,难道用: 303 | ```json 304 | { 305 | "query": { 306 | "match": { 307 | "category": "电影院", 308 | "boost": 2.0 309 | } 310 | } 311 | } 312 | ``` 313 | 314 | 不行啊,人家根本不会搜`电影院`,人家搜的都是`天安门`,`kfc`, `附近五星`。 315 | 316 | 我又不能直接把电影院加到 query 中,怎么才能做到`暗戳戳`的影响呢? 317 | 318 | 这时用 `field_value_factor` 和 `weight` 貌似都做不到啊。 319 | 320 | 怎么办呢? 321 | 322 | 在 dsl 中使用 script_score: 323 | ```json 324 | { 325 | "query": { 326 | "function_score": { 327 | "query": { 328 | "match": { 329 | "name": "天安门" 330 | } 331 | }, 332 | "script_score": { 333 | "script": "return doc ['category'].value == '电影院' ? 1.1 : 1.0" 334 | } 335 | } 336 | } 337 | } 338 | ``` 339 | 或者把script保存到:`elasticsearch/config/scripts`,然后 dsl 引用它: 340 | ```json 341 | { 342 | "query": { 343 | "function_score": { 344 | "query": { 345 | "match": { 346 | "name": "天安门" 347 | } 348 | }, 349 | "script_score": { 350 | "script": { 351 | "file": "category-score" 352 | } 353 | } 354 | } 355 | } 356 | } 357 | ``` 358 | 359 | 360 | ### 使用 param 来解耦 361 | 我们不要可以把参数从script中提出来,稍微做到了解耦: 362 | ```json 363 | { 364 | "query": { 365 | "function_score": { 366 | "query": { 367 | "match": { 368 | "name": "天安门" 369 | } 370 | }, 371 | "script_score": { 372 | "script": { 373 | "source": "return doc ['category'].value == recommend_category ? 1.1 : 1.0", 374 | "params": { 375 | "recommend_category": "电影院" 376 | } 377 | } 378 | } 379 | } 380 | } 381 | } 382 | ``` 383 | 或者用 file 的方式,不用去改动脚本的内容,也是解耦: 384 | ```json 385 | { 386 | "query": { 387 | "function_score": { 388 | "query": { 389 | "match": { 390 | "name": "天安门" 391 | } 392 | }, 393 | "script_score": { 394 | "script": { 395 | "file": "category-score", 396 | "params": { 397 | "recommend_category": "电影院" 398 | } 399 | } 400 | } 401 | } 402 | } 403 | } 404 | ``` 405 | 406 | ## 多个 functions 合作 407 | 408 | ### 大众点评的餐厅应用 409 | 410 | 该应用希望向用户推荐一些不错的餐馆,特征是: 411 | * 范围要在当前位置的 5km 以内 412 | * 有停车位是最重要的 413 | * 有 Wi-Fi 更好 414 | * 餐厅的评分(1 分到 5 分)越高越好 415 | * 并且对不同用户最好展示不同的结果以增加随机性 416 | 417 | dsl 如下: 418 | ```text 419 | { 420 | "query": { 421 | "function_score": { 422 | "filter": { 423 | "geo_distance": { 424 | "distance": "5km", 425 | "location": { 426 | "lat": $lat, 427 | "lon": $lng 428 | } 429 | } 430 | }, 431 | "functions": [ 432 | { 433 | "filter": { 434 | "term": { 435 | "features": "wifi" 436 | } 437 | }, 438 | "weight": 1 439 | }, 440 | { 441 | "filter": { 442 | "term": { 443 | "features": "停车位" 444 | } 445 | }, 446 | "weight": 2 447 | }, 448 | { 449 | "field_value_factor": { 450 | "field": "score", 451 | "factor": 1.2 452 | } 453 | }, 454 | { 455 | "random_score": { 456 | "seed": "$id" 457 | } 458 | } 459 | ], 460 | "score_mode": "sum", 461 | "boost_mode": "multiply" 462 | } 463 | } 464 | } 465 | ``` 466 | 467 | ### 新浪微博的社交网站 468 | 现在要优化搜索功能,使其以文本相关度排序为主,但是: 469 | * 越新的微博会排在相对靠前的位置 470 | * 点赞(忽略相同计算方式的转发和评论)数较高的微博也会排在较前面 471 | * 如果这篇微博购买了推广并且是创建不到 24 小时(同时满足),它的位置会非常靠前。 472 | 473 | dsl如下: 474 | ```text 475 | { 476 | "query": { 477 | "function_score": { 478 | "query": { 479 | "match": { 480 | "content": "$text" 481 | } 482 | }, 483 | "functions": [ 484 | { 485 | "gauss": { 486 | "createDate": { 487 | "origin": "$now", 488 | "scale": "6d", 489 | "offset": "1d" 490 | } 491 | } 492 | }, 493 | { 494 | "field_value_factor": { 495 | "field": "like_count", 496 | "modifier": "log1p", 497 | "factor": 0.1 498 | } 499 | }, 500 | { 501 | "script_score": { 502 | "script": "return doc ['is_recommend'].value && doc ['create_date'] > time ? 1.5 : 1.0", 503 | params: { 504 | "time": $time 505 | } 506 | } 507 | } 508 | ], 509 | "boost_mode": "multiply" 510 | } 511 | } 512 | } 513 | ``` 514 | 515 | 公式: 516 | ```text 517 | _score * gauss (create_date, $now, "1d", "6d") * log (1 + 0.1 * like_count) * (is_recommend & doc ['create_date'] > time ? 1.5 : 1.0) 518 | ``` 519 | 520 | 521 | # 原文搬运 522 | * [通过Function Score Query优化Elasticsearch搜索结果](https://www.scienjus.com/elasticsearch-function-score-query/) 523 | * [随机评分 | Elasticsearch: 权威指南 | Elastic](http://www.lvesu.com/blog/es/random-scoring.html) 524 | * [官网文档function score](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html) -------------------------------------------------------------------------------- /es/相关性分数/score_mode和 boost_mode.md: -------------------------------------------------------------------------------- 1 | 首先,每个文档由定义的函数打分。 2 | 3 | 参数 `score_mode` 规定计算的分数如何组合: 4 | 5 | |类型|解释| 6 | |:---|:---| 7 | |multiply | 分数相乘(默认)| 8 | |sum|得分相加| 9 | |avg|平均分数| 10 | |first |使用具有匹配过滤器的第一个函数| 11 | |max|最大得分| 12 | |min|最小分数| 13 | 14 | 因为有可能会用到 `functionscore(fsq)` 来替换es 默认打分,这里引进了`boost_mode`。 15 | 16 | 新计算的分数与查询的分数相组合,参数 `boost_mode`定义其组合方式: 17 | 18 | |类型|解释| 19 | |:---|:---| 20 | |multiply|查询得分和函数得分相乘(默认)| 21 | |replace|仅使用函数得分,忽略查询得分| 22 | |sum|查询得分和函数得分相加| 23 | |avg|取平均值| 24 | |max|查询得分和函数得分的最大值| 25 | |min|查询得分和函数得分的最小值| 26 | -------------------------------------------------------------------------------- /es/相关性分数/为什么es的分数总是不准.md: -------------------------------------------------------------------------------- 1 | # TF&IDF 2 | TF&IDF 相关性算法了解后,发现它有 3 个特点: 3 | * TF: 搜索词组在 field 中的出现次数越高,越相关 4 | * IDF: 搜索词组在全部 doc 的 field 出现的次数越高,越不相关 5 | * Field length : field 越短,越相关 6 | 7 | # 不准的点 8 | 比如在 title 中查询 java: 9 | * 在一个 document 中 java 出现了几次 10 | * 在所有的 document 中 java 出现了几次 11 | * 这个 document 的长度 12 | 13 | 只有第二点的计算,有可能是变化大的,因为所有的 document 的 java 出现次数,默认是只看自己分片的,而不是全部的分片的 documents。 14 | 15 | # 解决方案 16 | 如果搜索的时候,带了参数 `search_type=dfs_query_then_fetch` 参数, 那么就会计算所有的分片上的 doc 作为 IDF分数。 准确性高了,但是性能差了,差了很多,据官网说。 17 | 18 | 或者,只设置一个分片 `number_of_shards=1`,但是容错性就没有保证了。 19 | -------------------------------------------------------------------------------- /es/相关性分数/相关性分数调优.md: -------------------------------------------------------------------------------- 1 | 2 | * [1、query-time boost](#1query-time-boost) 3 | * [2、查询语句提升权重](#2查询语句提升权重) 4 | * [3、minimum_should_match 控制精度](#3minimum_should_match-控制精度) 5 | * [4、negative boost](#4negative-boost) 6 | * [5、constant_score](#5constant_score) 7 | 8 | 9 | 10 | 11 | 12 | 13 | # 1、query-time boost 14 | 15 | 假设有 title 和 content 两个字段,想匹配 `java spark`,如果想要出现在 title 的分数比出现在 content 的分数大,可以试试 boost。 16 | ``` 17 | GET /forum/_search 18 | { 19 | "query": { 20 | "bool": { 21 | "should": [ 22 | { 23 | "match": { 24 | "title": { 25 | "query": "java spark", 26 | "boost": 2 27 | } 28 | } 29 | }, 30 | { 31 | "match": { 32 | "content": "java spark" 33 | } 34 | } 35 | ] 36 | } 37 | } 38 | } 39 | ``` 40 | 41 | # 2、查询语句提升权重 42 | 43 | 假设目前要搜索:`hello world`,并且希望同时出现过`kfc`,`food`的文档有更高的权重,可以试着用 should 给 must 提升权重: 44 | ``` 45 | GET /_search 46 | { 47 | "query": { 48 | "bool": { 49 | "must": { 50 | "match": { 51 | "content": { 52 | "query": "hello world", 53 | "operator": "and" 54 | } 55 | } 56 | }, 57 | "should": [ 58 | { "match": { "content": "kfc" }}, 59 | { "match": { "content": "food"}} 60 | ] 61 | } 62 | } 63 | } 64 | ``` 65 | 甚至这个也能搭配boost: 66 | ``` 67 | GET /_search 68 | { 69 | "query": { 70 | "bool": { 71 | "must": { 72 | "match": { 73 | "content": { 74 | "query": "hello world", 75 | "operator": "and" 76 | } 77 | } 78 | }, 79 | "should": [ 80 | { "match": { "content": {"query": "kfc", "boost": 3}}}, 81 | { "match": { "content": {"query": "food", "boost": 2}}} 82 | ] 83 | } 84 | } 85 | } 86 | ``` 87 | should 命中越多,相关性分数越高。 88 | 89 | # 3、minimum_should_match 控制精度 90 | 91 | ``` 92 | GET /_search 93 | { 94 | "query": { 95 | "bool": { 96 | "minimum_should_match": 2, 97 | "should": [ 98 | { "match": { "content": {"query": "kfc"}}}, 99 | { "match": { "content": {"query": "rice"}}}, 100 | { "match": { "content": {"query": "food"}}} 101 | ] 102 | } 103 | } 104 | } 105 | ``` 106 | 107 | 搜出来的 document 肯定是包含:`kfc + rice` 或者 `kfc + food` 或者 `rice + food`。 108 | 如果有一个 document 是 `kfc + rice + food` 它的相关性分数会更高。 109 | 110 | 111 | # 4、negative boost 112 | 如果不想要 document 带 kfc,可以这么写: 113 | ``` 114 | GET /store/_search 115 | { 116 | "query": { 117 | "bool": { 118 | "must": [ 119 | { 120 | "match": { 121 | "content": "food" 122 | } 123 | } 124 | ], 125 | "must_not": [ 126 | { 127 | "match": { 128 | "content": "kfc" 129 | } 130 | } 131 | ] 132 | } 133 | } 134 | } 135 | ``` 136 | 但是如果想 kfc 出现也行,不过能不能降低它的分数?不要一棍子打死,可以的: 137 | ``` 138 | GET /store/_search 139 | { 140 | "query": { 141 | "boosting": { 142 | "positive": { 143 | "match": { 144 | "content": "food" 145 | } 146 | }, 147 | "negative": { 148 | "match": { 149 | "content": "kfc" 150 | } 151 | }, 152 | "negative_boost": 0.2 153 | } 154 | } 155 | } 156 | ``` 157 | 158 | * positive:正向搜索 159 | * negative:否定的搜索 160 | * negative_boost:否定的权重,包含了 negative term 的 doc,分数乘以 negative boost ,分数降低 161 | 162 | # 5、constant_score 163 | 压根儿不需要相关度评分,直接走 constant_score 加 filter,所有的 doc 分数都是 1,没有评分的概念了,性能起飞: 164 | ``` 165 | GET /store/_search 166 | { 167 | "query": { 168 | "bool": { 169 | "should": [ 170 | { 171 | "constant_score": { 172 | "query": { 173 | "match": { 174 | "title": "kfc" 175 | } 176 | } 177 | } 178 | }, 179 | { 180 | "constant_score": { 181 | "query": { 182 | "match": { 183 | "title": "food" 184 | } 185 | } 186 | } 187 | } 188 | ] 189 | } 190 | } 191 | } 192 | ``` 193 | 194 | # 6、function score 195 | 先看一个需求,门店看得人越多,就越靠前,但是要避免马太效应,所以不能无脑根据门店的查看数倒序。 196 | 请问怎么办? 197 | 198 | 假设门店有一个字段:`view_num`,我们自定义分数: 199 | ```text 200 | GET /store/_search 201 | { 202 | "query": { 203 | "function_score": { 204 | "query": { 205 | "multi_match": { 206 | "query": "kfc", 207 | "fields": ["tile", "content"] 208 | } 209 | }, 210 | "field_value_factor": { 211 | "field": "view_num", 212 | "modifier": "log1p", 213 | "factor": 0.5 214 | }, 215 | "boost_mode": "sum", 216 | "max_boost": 2 217 | } 218 | } 219 | } 220 | ``` 221 | 解读下: 222 | * log1p是一个函数,用于对字段分数进行修正: 223 | ``` 224 | new_score = old_score * log(1 + factor * follower_num) 225 | ``` 226 | * boost_mode,用于决定最终doc分数与指定字段的值如何计算: 227 | ``` 228 | multiply,sum,min,max,replace 229 | ``` 230 | * max_boost,用于限制计算出来的分数不要超过max_boost指定的值。 231 | 232 | 其实 function score 不仅仅只有 `field_value_factor` 这种计分方式,它提供: 233 | * weight:设置权重 234 | * field_value_factor:将某个字段的值进行计算得出分数。 235 | * random_score:随机得到 0 到 1 分数 236 | * 衰减函数:同样以某个字段的值为标准,距离某个值越近得分越高 237 | * script_score:通过自定义脚本计算分值 238 | 239 | 240 | 具体的看 function_score 的入门文档。 241 | -------------------------------------------------------------------------------- /es/相关性分数/衰减函数.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fatpo/backend_note/027983f71ae0b0ceacb11e0baf3430c80288196b/es/相关性分数/衰减函数.png -------------------------------------------------------------------------------- /git/git放弃更改.md: -------------------------------------------------------------------------------- 1 | 单个文件/文件夹: 2 | ``` 3 | git checkout -- filename 4 | ``` 5 | 6 | 所有文件/文件夹: 7 | ``` 8 | git checkout . 9 | ``` 10 | -------------------------------------------------------------------------------- /git/仓库链接到远程.md: -------------------------------------------------------------------------------- 1 | 初始化仓库: 2 | ``` 3 | gjt init 4 | ``` 5 | 6 | 链接到远程仓库: 7 | ``` 8 | git remote add origin [repo-url] 9 | ``` 10 | 11 | 查看远程分支: 12 | ``` 13 | git remote -v 14 | ``` 15 | -------------------------------------------------------------------------------- /leetcode/前缀和/1423.可获得的最大点数.md: -------------------------------------------------------------------------------- 1 | ## 题目 2 | ```text 3 | 几张卡牌 排成一行,每张卡牌都有一个对应的点数。点数由整数数组 cardPoints 给出。 4 | 5 | 每次行动,你可以从行的开头或者末尾拿一张卡牌,最终你必须正好拿 k 张卡牌。 6 | 7 | 你的点数就是你拿到手中的所有卡牌的点数之和。 8 | 9 | 给你一个整数数组 cardPoints 和整数 k,请你返回可以获得的最大点数。 10 | 11 |   12 | 13 | 示例 1: 14 | 15 | 输入:cardPoints = [1,2,3,4,5,6,1], k = 3 16 | 输出:12 17 | 解释:第一次行动,不管拿哪张牌,你的点数总是 1 。但是,先拿最右边的卡牌将会最大化你的可获得点数。最优策略是拿右边的三张牌,最终点数为 1 + 6 + 5 = 12 。 18 | 示例 2: 19 | 20 | 输入:cardPoints = [2,2,2], k = 2 21 | 输出:4 22 | 解释:无论你拿起哪两张卡牌,可获得的点数总是 4 。 23 | 示例 3: 24 | 25 | 输入:cardPoints = [9,7,7,9,7,7,9], k = 7 26 | 输出:55 27 | 解释:你必须拿起所有卡牌,可以获得的点数为所有卡牌的点数之和。 28 | 示例 4: 29 | 30 | 输入:cardPoints = [1,1000,1], k = 1 31 | 输出:1 32 | 解释:你无法拿到中间那张卡牌,所以可以获得的最大点数为 1 。 33 | 示例 5: 34 | 35 | 输入:cardPoints = [1,79,80,1,1,1,200,1], k = 3 36 | 输出:202 37 |   38 | 39 | 提示: 40 | 41 | 1 <= cardPoints.length <= 10^5 42 | 1 <= cardPoints[i] <= 10^4 43 | 1 <= k <= cardPoints.length 44 | 45 | 通过次数43,885 提交次数79,390 46 | 来源:力扣(LeetCode) 47 | 链接:https://leetcode.cn/problems/maximum-points-you-can-obtain-from-cards 48 | 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 49 | ``` 50 | 51 | ## 解题报告 52 | 这道题很经典的前缀数,先预处理后,再按照 k 把前后加起来,找到 max 即可。 53 | ```python3 54 | from itertools import accumulate 55 | 56 | class Solution: 57 | def maxScore(self, cardPoints: List[int], k: int) -> int: 58 | pre = [0] + list(accumulate(cardPoints)) 59 | back = [0] + list(accumulate(cardPoints[::-1])) 60 | 61 | ans = 0 62 | for i in range(k + 1): 63 | ans = max(ans, pre[i] + back[k - i]) 64 | 65 | return ans 66 | ``` 67 | 68 | -------------------------------------------------------------------------------- /leetcode/前缀和/560.和为K的子数组.md: -------------------------------------------------------------------------------- 1 | ## 题目 2 | ```text 3 | 560. 和为 K 的子数组 4 | 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的连续子数组的个数 。 5 | 6 | 7 | 8 | 示例 1: 9 | 10 | 输入:nums = [1,1,1], k = 2 11 | 输出:2 12 | 示例 2: 13 | 14 | 输入:nums = [1,2,3], k = 3 15 | 输出:2 16 | 17 | 18 | 提示: 19 | 20 | 1 <= nums.length <= 2 * 104 21 | -1000 <= nums[i] <= 1000 22 | -107 <= k <= 107 23 | 通过次数273,676 提交次数602,647 24 | ``` 25 | 26 | ## 解题报告 27 | 把问题转换成:`sum[right] - sum[left] = k`,有多少个这样子的组合: 28 | ```python3 29 | class Solution: 30 | def subarraySum(self, nums: List[int], k: int) -> int: 31 | dic = defaultdict(int) 32 | ans = 0 33 | sum = 0 34 | 35 | # sum[right] - sum[left] = k ==> 如果for 循环指针往前挪动的时候,此时此刻sum[right]就是指针的位置 36 | # ==> 也就是说,已经确定了sum[right] 和 k,请问能找到几个sum[left] 37 | # ==> sum[left] = sum[right] - k 38 | 39 | # 构造一个 dic,来存:sum[left]的个数,初始化dic[0] = 1 表示,有 1 个 0 40 | dic[0] = 1 41 | for i in nums: 42 | sum += i 43 | ans += dic[sum-k] 44 | dic[sum] += 1 45 | return ans 46 | ``` 47 | 48 | -------------------------------------------------------------------------------- /leetcode/滑动窗口/3.无重复字符的最长子串.md: -------------------------------------------------------------------------------- 1 | ## 题目 2 | ```text 3 | 3. 无重复字符的最长子串 4 | 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 5 | 6 | 7 | 8 | 示例 1: 9 | 10 | 输入: s = "abcabcbb" 11 | 输出: 3 12 | 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 13 | 示例 2: 14 | 15 | 输入: s = "bbbbb" 16 | 输出: 1 17 | 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。 18 | 示例 3: 19 | 20 | 输入: s = "pwwkew" 21 | 输出: 3 22 | 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 23 | 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。 24 | 25 | 26 | 提示: 27 | 28 | 0 <= s.length <= 5 * 104 29 | s 由英文字母、数字、符号和空格组成 30 | 通过次数2,029,763 提交次数5,201,359 31 | ``` 32 | 33 | ## 解题报告 34 | 经典的滑动窗口题目。 35 | 36 | 用一个dic来记录是否重复,用一个ans来记录max。 37 | 38 | 不断滑动扩大right边界,遇到重复的就滑动left满足不重复的条件,直到right达到边界。 39 | 40 | 41 | ```python 42 | from collections import defaultdict 43 | 44 | class Solution: 45 | def lengthOfLongestSubstring(self, s: str) -> int: 46 | dic = defaultdict(int) 47 | ans = 0 48 | left = right = 0 49 | while left <= right and right < len(s): 50 | if dic[s[right]] == 0: 51 | dic[s[right]] += 1 52 | right += 1 53 | ans = max(ans, right-left) 54 | else: 55 | dic[s[left]] -= 1 56 | left += 1 57 | return ans 58 | ``` 59 | 60 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/001_cat.md: -------------------------------------------------------------------------------- 1 | cat 作用: 2 | ``` 3 | 显示某个文件的内容到终端。 4 | ``` 5 | 6 | 举个例子,我们把"hello world"写入 "test.txt": 7 | ``` 8 | ~ > echo "hello world" > test.txt 9 | ``` 10 | 11 | 然后用`cat`命令看看文件`test.txt`内容: 12 | ``` 13 | ~ > cat test.txt 14 | hello world 15 | ``` 16 | 17 | ![image](https://user-images.githubusercontent.com/6395350/192832561-c6bd6b5d-aee8-4e71-ad37-2e80dc6072a2.png) 18 | 19 | 20 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/002_echo.md: -------------------------------------------------------------------------------- 1 | echo 作用: 2 | ``` 3 | 打印某句话。 4 | ``` 5 | 6 | 类似`print`: 7 | ``` 8 | # echo "hello" 9 | hello 10 | ``` 11 | 一般配合管道输送符号(就是 >),把某个打印的东西输送到某个文件中。 12 | 13 | 举个例子,我们把 "hello world" 写入 "test.txt": 14 | ``` 15 | ~ > echo "hello world" > test.txt 16 | ``` 17 | 18 | 然后用`cat`命令看看文件`test.txt`内容: 19 | ``` 20 | ~ > cat test.txt 21 | hello world 22 | ``` 23 | 24 | ![image](https://user-images.githubusercontent.com/6395350/192832561-c6bd6b5d-aee8-4e71-ad37-2e80dc6072a2.png) 25 | 26 | 27 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/003_clear.md: -------------------------------------------------------------------------------- 1 | 作用: 2 | ``` 3 | 清屏,让终端恢复干净。 4 | ``` 5 | 6 | 7 | clear 前: 8 | 9 | image 10 | 11 | 12 | clear 后: 13 | 14 | image 15 | 16 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/004_pwd.md: -------------------------------------------------------------------------------- 1 | 作用: 2 | ``` 3 | 看看当前自己处在哪一个目录 4 | ``` 5 | 演示: 6 | ``` 7 | [root@rddata web_front]# pwd 8 | /home/workspace/web_front 9 | ``` 10 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/005_cd.md: -------------------------------------------------------------------------------- 1 | 作用: 2 | ``` 3 | 进入某一个文件夹的目录 4 | ``` 5 | 常规用法: 6 | ``` 7 | cd 某一个文件夹 8 | cd 某一个文件夹/它的子文件夹 9 | cd .. 返回上层目录 10 | ``` 11 | 演示: 12 | ``` 13 | [root@rddata build]# pwd 14 | /home/workspace/web_front/build 15 | [root@rddata build]# cd .. 16 | [root@rddata web_front]# pwd 17 | /home/workspace/web_front 18 | [root@rddata web_front]# cd .. 19 | [root@rddata workspace]# pwd 20 | /home/workspace 21 | [root@rddata workspace]# cd web_front/ 22 | [root@rddata web_front]# pwd 23 | /home/workspace/web_front 24 | [root@rddata web_front]# 25 | ``` 26 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/006_tree.md: -------------------------------------------------------------------------------- 1 | 作用: 2 | ``` 3 | 显示当前目录的树状目录结构图 4 | ``` 5 | 演示: 6 | ``` 7 | [root@rddata web]# tree 8 | . 9 | ├── cpu.sh 10 | ├── disk.sh 11 | ├── load.sh 12 | ├── mem.sh 13 | ├── server-0.0.1-SNAPSHOT.jar 14 | ├── test 15 | │   └── t.txt 16 | └── web.log 17 | 18 | 1 directory, 7 files 19 | ``` 20 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/007_ls.md: -------------------------------------------------------------------------------- 1 | 作用: 2 | ``` 3 | 显示当前目录下的文件以及相关信息 4 | ``` 5 | 常规用法: 6 | ``` 7 | ls 输出文件 8 | ls -l 竖屏输出文件(也可以:ll) 9 | ls -l -a 竖屏输出包括隐藏文件的文件(也可以:ls -la) 10 | ls -l -a -h 竖屏输出包括隐藏文件的文件,并且 size 帮忙换算,友好阅读(也可以:ls -lah) 11 | ``` 12 | 13 | 演示: 14 | ``` 15 | [root@rddata web]# ls 16 | cpu.sh disk.sh load.sh mem.sh server-0.0.1-SNAPSHOT.jar test web.log 17 | 18 | [root@rddata web]# ls -l 19 | 总用量 24888 20 | -rw-r--r-- 1 root root 1047 9月 28 21:37 cpu.sh 21 | -rw-r--r-- 1 root root 40 9月 28 21:34 disk.sh 22 | -rw-r--r-- 1 root root 37 9月 28 21:35 load.sh 23 | -rw-r--r-- 1 root root 33 9月 28 21:33 mem.sh 24 | -rw-r--r-- 1 root root 25456855 9月 29 00:36 server-0.0.1-SNAPSHOT.jar 25 | drwxr-xr-x 2 root root 4096 9月 29 15:29 test 26 | -rw-r--r-- 1 root root 3110 9月 29 14:13 web.log 27 | [root@rddata web]# ls -l -a 28 | 总用量 24896 29 | drwxr-xr-x 3 root root 4096 9月 29 15:29 . 30 | drwxr-xr-x 5 root root 4096 9月 28 16:59 .. 31 | -rw-r--r-- 1 root root 1047 9月 28 21:37 cpu.sh 32 | -rw-r--r-- 1 root root 40 9月 28 21:34 disk.sh 33 | -rw-r--r-- 1 root root 37 9月 28 21:35 load.sh 34 | -rw-r--r-- 1 root root 33 9月 28 21:33 mem.sh 35 | -rw-r--r-- 1 root root 25456855 9月 29 00:36 server-0.0.1-SNAPSHOT.jar 36 | drwxr-xr-x 2 root root 4096 9月 29 15:29 test 37 | -rw-r--r-- 1 root root 3110 9月 29 14:13 web.log 38 | [root@rddata web]# ls -l -a -h 39 | 总用量 25M 40 | drwxr-xr-x 3 root root 4.0K 9月 29 15:29 . 41 | drwxr-xr-x 5 root root 4.0K 9月 28 16:59 .. 42 | -rw-r--r-- 1 root root 1.1K 9月 28 21:37 cpu.sh 43 | -rw-r--r-- 1 root root 40 9月 28 21:34 disk.sh 44 | -rw-r--r-- 1 root root 37 9月 28 21:35 load.sh 45 | -rw-r--r-- 1 root root 33 9月 28 21:33 mem.sh 46 | -rw-r--r-- 1 root root 25M 9月 29 00:36 server-0.0.1-SNAPSHOT.jar 47 | drwxr-xr-x 2 root root 4.0K 9月 29 15:29 test 48 | -rw-r--r-- 1 root root 3.1K 9月 29 14:13 web.log 49 | ``` 50 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/008_history.md: -------------------------------------------------------------------------------- 1 | 作用: 2 | ``` 3 | 显示历史你输入过的命令 4 | ``` 5 | 演示: 6 | ``` 7 | [root@rddata web]# history 8 | 1 2022-09-29 14:10:25 9 | 2 2022-09-17 10:20:15 if [ ! -f ~/.bash-preexec.sh ];then echo -e "\x21\x62\x63\x75\x69\x21"; else echo -e "\x21\x62\x63\x69\x21"; fi; 10 | 3 2022-09-17 10:20:35 vi ~/.ssh/authorized_keys 11 | 4 2022-09-17 10:22:29 cat ~/.ssh/authorized_keys 12 | 5 2022-09-17 10:23:53 hostnamectl set-hostname rddata 13 | 6 2022-09-17 10:32:49 vi ~/.ssh/authorized_keys 14 | 7 2022-09-17 10:33:19 cat ~/.ssh/authorized_keys 15 | 8 2022-09-17 10:33:31 vi ~/.ssh/authorized_keys 16 | ``` 17 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/009_ps.md: -------------------------------------------------------------------------------- 1 | 作用: 2 | ``` 3 | 显示当前服务器的进程 4 | ``` 5 | 演示: 6 | ``` 7 | [root@rddata web]# ps -ef 8 | UID PID PPID C STIME TTY TIME CMD 9 | root 2 0 0 9月17 ? 00:00:00 [kthreadd] 10 | root 3 2 0 9月17 ? 00:00:00 [rcu_gp] 11 | root 4 2 0 9月17 ? 00:00:00 [rcu_par_gp] 12 | root 6 2 0 9月17 ? 00:00:00 [kworker/0:0H-events_highpri] 13 | root 9 2 0 9月17 ? 00:00:00 [mm_percpu_wq] 14 | root 10 2 0 9月17 ? 00:00:13 [ksoftirqd/0] 15 | root 11 2 0 9月17 ? 00:02:24 [rcu_sched] 16 | ``` 17 | 实战情况下,一般进程太多,需要 `grep` 过滤,比如我们想看 nginx 的进程: 18 | ``` 19 | [root@rddata web]# ps -ef | grep nginx 20 | root 53399 1 0 9月17 ? 00:00:00 nginx: master process nginx 21 | root 2243123 53399 0 9月28 ? 00:00:00 nginx: worker process 22 | root 2243124 53399 0 9月28 ? 00:00:00 nginx: worker process 23 | root 2423215 2409741 0 15:46 pts/0 00:00:00 grep --color=auto nginx 24 | ``` 25 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/010_grep.md: -------------------------------------------------------------------------------- 1 | 作用: 2 | ``` 3 | 过滤,筛选出某个关键词。 4 | ``` 5 | 比如我们想过滤下包含 `nginx` 的进程信息: 6 | ``` 7 | [root@rddata web]# ps -ef | grep nginx 8 | root 53399 1 0 9月17 ? 00:00:00 nginx: master process nginx 9 | root 2243123 53399 0 9月28 ? 00:00:00 nginx: worker process 10 | root 2243124 53399 0 9月28 ? 00:00:00 nginx: worker process 11 | root 2423215 2409741 0 15:46 pts/0 00:00:00 grep --color=auto nginx 12 | ``` 13 | 比如我们想过滤下当前目录包含`.log`后缀的文件名: 14 | ``` 15 | [root@rddata web]# ll 16 | 总用量 24884 17 | -rw-r--r-- 1 root root 1047 9月 28 21:37 cpu.sh 18 | -rw-r--r-- 1 root root 40 9月 28 21:34 disk.sh 19 | -rw-r--r-- 1 root root 37 9月 28 21:35 load.sh 20 | -rw-r--r-- 1 root root 33 9月 28 21:33 mem.sh 21 | -rw-r--r-- 1 root root 25456855 9月 29 00:36 server-0.0.1-SNAPSHOT.jar 22 | -rw-r--r-- 1 root root 3110 9月 29 14:13 web.log 23 | 24 | 25 | [root@rddata web]# ll | grep *.log 26 | -rw-r--r-- 1 root root 3110 9月 29 14:13 web.log 27 | ``` 28 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/011_date.md: -------------------------------------------------------------------------------- 1 | 作用: 2 | ``` 3 | 输出当前时间 4 | ``` 5 | 演示: 6 | ``` 7 | [root@rddata web]# date 8 | 2022年 09月 29日 星期四 16:56:10 CST 9 | ``` 10 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/012_top.md: -------------------------------------------------------------------------------- 1 | 作用: 2 | ``` 3 | 查看当前服务器全局性能状态。 4 | ``` 5 | ps: 6 | ``` 7 | 在运维方面很高频使用,能对服务器状态一览无遗,快速定位问题。 8 | top 会进入一个交互界面: 9 | 按 M,看看内存条使用状态。 10 | 按P(必须大写)可以按照 CPU 排序。 11 | ``` 12 | 演示: 13 | 14 | image 15 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/013_head.md: -------------------------------------------------------------------------------- 1 | 作用: 2 | ``` 3 | 查看某个文件的前几行 4 | ``` 5 | 演示: 6 | ``` 7 | [root@rddata web]# echo -e "1\n2\n3\n4\n5\n" > test.txt 8 | [root@rddata web]# 9 | [root@rddata web]# cat test.txt 10 | 1 11 | 2 12 | 3 13 | 4 14 | 5 15 | 16 | [root@rddata web]# 17 | [root@rddata web]# 18 | [root@rddata web]# head -3 test.txt 19 | 1 20 | 2 21 | 3 22 | ``` 23 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/014_tail.md: -------------------------------------------------------------------------------- 1 | 作用: 2 | ``` 3 | 查看某个文件的后几行 4 | ``` 5 | ps: 6 | ``` 7 | 对于后台开发同学来说,非常高频的命令,经常用来看日志。 8 | tail -f xxx.log 9 | -f 的意思是监听最新的文件改动,滚动更新。 10 | ``` 11 | 演示: 12 | ``` 13 | [root@rddata web]# echo -e "1\n2\n3\n4\n5\n" > test.txt 14 | [root@rddata web]# 15 | [root@rddata web]# cat test.txt 16 | 1 17 | 2 18 | 3 19 | 4 20 | 5 21 | 22 | [root@rddata web]# 23 | [root@rddata web]# 24 | [root@rddata web]# head -3 test.txt 25 | 1 26 | 2 27 | 3 28 | [root@rddata web]# tail -3 test.txt 29 | 4 30 | 5 31 | ``` 32 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/015_ping.md: -------------------------------------------------------------------------------- 1 | 作用: 2 | ``` 3 | 1、看网络通不通。 4 | 2、看网络快不快。 5 | 3、拿到域名后的 IP。 6 | ``` 7 | 演示: 8 | ``` 9 | [root@rddata web]# ping www.baidu.com 10 | PING www.a.shifen.com (14.215.177.38) 56(84) bytes of data. 11 | 64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=1 ttl=53 time=3.38 ms 12 | 64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=2 ttl=53 time=3.42 ms 13 | 64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=3 ttl=53 time=3.40 ms 14 | 64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=4 ttl=53 time=3.39 ms 15 | ``` 16 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/016_rm.md: -------------------------------------------------------------------------------- 1 | 作用: 2 | ``` 3 | 删除文件或者文件夹 4 | rm -f test.txt , 其中 -f 表示一意孤行,不用询问。 5 | rm -rf test/test.txt, 其中 -r 表示删除文件夹。 6 | ``` 7 | 删除 `test.txt`文件和`test`文件夹: 8 | ``` 9 | [root@rddata web]# tree 10 | . 11 | ├── cpu.sh 12 | ├── disk.sh 13 | ├── load.sh 14 | ├── mem.sh 15 | ├── server-0.0.1-SNAPSHOT.jar 16 | ├── test 17 | │   └── test.txt 18 | ├── test.txt 19 | └── web.log 20 | 21 | 1 directory, 8 files 22 | 23 | [root@rddata web]# rm -f test.txt 24 | [root@rddata web]# rm -rf test 25 | [root@rddata web]# tree 26 | . 27 | ├── cpu.sh 28 | ├── disk.sh 29 | ├── load.sh 30 | ├── mem.sh 31 | ├── server-0.0.1-SNAPSHOT.jar 32 | └── web.log 33 | 34 | 0 directories, 6 files 35 | ``` 36 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/017_mkdir.md: -------------------------------------------------------------------------------- 1 | 作用: 2 | ``` 3 | 创建目录 4 | mkdir test 5 | mkdir -p test/test ,其中 -p 表示允许创建子目录 6 | ``` 7 | 演示: 8 | ``` 9 | [root@rddata web]# mkdir test 10 | [root@rddata web]# mkdir -p test2/test2 11 | [root@rddata web]# tree 12 | . 13 | ├── cpu.sh 14 | ├── disk.sh 15 | ├── load.sh 16 | ├── mem.sh 17 | ├── server-0.0.1-SNAPSHOT.jar 18 | ├── test 19 | ├── test2 20 | │   └── test2 21 | └── web.log 22 | ``` 23 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/018_ifconfig.md: -------------------------------------------------------------------------------- 1 | 作用: 2 | ``` 3 | 1、查看本机的网络 IP 4 | 2、查看网卡信息 5 | 3、查看网关 IP 6 | ``` 7 | 演示,可以看到我本机 IP 是`10.0.8.8`和` 127.0.0.1 `: 8 | ``` 9 | [root@rddata web]# ifconfig 10 | eth0: flags=4163 mtu 1500 11 | inet 10.0.8.8 netmask 255.255.252.0 broadcast 10.0.11.255 12 | inet6 fe80::5054:ff:fe7a:5f4f prefixlen 64 scopeid 0x20 13 | ether 52:54:00:7a:5f:4f txqueuelen 1000 (Ethernet) 14 | RX packets 52101434 bytes 33282049666 (30.9 GiB) 15 | RX errors 0 dropped 0 overruns 0 frame 0 16 | TX packets 49291398 bytes 3775908372 (3.5 GiB) 17 | TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 18 | 19 | lo: flags=73 mtu 65536 20 | inet 127.0.0.1 netmask 255.0.0.0 21 | inet6 ::1 prefixlen 128 scopeid 0x10 22 | loop txqueuelen 1000 (Local Loopback) 23 | RX packets 1529885 bytes 222196587 (211.9 MiB) 24 | RX errors 0 dropped 0 overruns 0 frame 0 25 | TX packets 1529885 bytes 222196587 (211.9 MiB) 26 | TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 27 | ``` 28 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/019_touch.md: -------------------------------------------------------------------------------- 1 | 作用: 2 | ``` 3 | 创建一个空白文件,里面没有任何内容,用 cat 命令可以看到没有内容。 4 | ``` 5 | 演示: 6 | ``` 7 | [root@rddata web]# touch 1.txt 8 | [root@rddata web]# cat 1.txt 9 | [root@rddata web]# ll 10 | 总用量 24892 11 | -rw-r--r-- 1 root root 0 9月 29 18:28 1.txt 12 | -rw-r--r-- 1 root root 1047 9月 28 21:37 cpu.sh 13 | -rw-r--r-- 1 root root 40 9月 28 21:34 disk.sh 14 | -rw-r--r-- 1 root root 37 9月 28 21:35 load.sh 15 | -rw-r--r-- 1 root root 33 9月 28 21:33 mem.sh 16 | -rw-r--r-- 1 root root 25456855 9月 29 00:36 server-0.0.1-SNAPSHOT.jar 17 | -rw-r--r-- 1 root root 3110 9月 29 14:13 web.log 18 | ``` 19 | 瞬间生成 100 个文件: 20 | ``` 21 | touch file-{001..100} 22 | ``` 23 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/020_vi.md: -------------------------------------------------------------------------------- 1 | 作用: 2 | ``` 3 | 编辑文件,会进入一个交互界面。也可以用 vim,有些操作系统都支持 vi 和 vim。vim 比 vi 稍微丰富一些功能。 4 | 5 | 按 i:进入编辑模式 6 | 按 esc:再输入:wq,保存并退出 7 | 按 u:回滚编辑操作 8 | 按 yy:复制一行,配合按 p:粘贴 9 | 按 dd:删除一行 10 | ``` 11 | 演示: 12 | 13 | image 14 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/021_cp.md: -------------------------------------------------------------------------------- 1 | ## cp 2 | 复制文件、文件夹 3 | 4 | ## 演示 5 | 复制文件,从 source.txt 到 target.txt : 6 | ``` 7 | cp source.txt target.txt 8 | ``` 9 | 复制文件夹: 10 | ``` 11 | cp -r source_dir target_dir 12 | ``` 13 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/022_scp.md: -------------------------------------------------------------------------------- 1 | ## scp 2 | 是一个很适合用来传输文件的命令,本意是 secure copy 的缩写。 网络版本的`cp`命令。 3 | 4 | 5 | ## 从本地上传文件到远程计算机或服务器的命令如下: 6 | 先进入本地目录下,然后运行如下命令: 7 | ``` 8 | scp my_local_file.zip root@192.168.1.104:/usr/local/nginx/html/webs 9 | ``` 10 | 11 | ## 从远程主机复制文件到本地主机(下载)的命令如下: 12 | 先进入本地目录下,然后运行如下命令:(假如远程文件是about.zip) 13 | ``` 14 | scp root@192.168.1.104:/usr/local/nginx/html/webs/about.zip . 15 | ``` 16 | 17 | ## 从本地文件复制多个文件到远程主机 18 | 先进入本地目录下,然后运行如下命令:(多个文件使用空格分隔开) 19 | ``` 20 | scp index.css json.js root@192.168.1.104:/usr/local/nginx/html/webs 21 | ``` 22 | 23 | ## 从远程主机复制多个文件到当前目录 24 | 先进入本地目录下,然后运行如下命令: 25 | ``` 26 | scp root@192.168.1.104:/usr/local/nginx/html/webs/\{index.css,json.js\} . 27 | ``` 28 | 29 | ## 从本地文件复制整个文件夹到远程主机上 30 | 先进入本地目录下,然后运行如下命令:(文件夹假如是diff) 31 | ``` 32 | scp -v -r diff root@192.168.1.104:/usr/local/nginx/html/webs 33 | ``` 34 | 35 | ## 从远程主机复制整个文件夹到本地目录下 36 | 先进入本地目录下,然后运行如下命令:(文件夹假如是diff) 37 | ``` 38 | scp -r root@192.168.1.104:/usr/local/nginx/html/webs/diff . 39 | ``` 40 | 41 | ## 在两个远程主机之间复制文件 42 | scp也可以把文件从一个远程主机复制到另一个远程主机上。 43 | ``` 44 | scp root@192.168.1.104:/usr/local/nginx/html/webs/xx.txt root@192.168.1.105:/usr/local/nginx/html/webs/ 45 | ``` 46 | 47 | ## 使用压缩来加快传输 48 | 在文件传输的过程中,我们可以使用压缩文件来加快文件传输,我们可以使用 C选项来启用压缩功能,该文件在传输过程中被压缩, 49 | 在目的主机上被解压缩。 50 | ``` 51 | scp -vrC diff root@192.168.1.104:/usr/local/nginx/html/webs 52 | ``` 53 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/023_awk_1.md: -------------------------------------------------------------------------------- 1 | ## awk 2 | 这里是 awk 的第一次出场,大家可以看到这个 awk 的文件格式和别人不一样,多一个`_1`。 3 | 4 | 因为以后它会出现很多很多次,它是 linux 中最强的命令,没有之一。 5 | 6 | `AWK` 是一种处理文本文件的语言,是一个强大的文本分析工具。 7 | 8 | 之所以叫 AWK 是因为其取了三位创始人 `Alfred Aho`,`Peter Weinberger`, 和 `Brian Kernighan` 的 Family Name 的首字符。 9 | 10 | ## 创建一个很多行的文件 11 | ``` 12 | awk 'BEGIN{for(i=1;i<10000;i++){print i}}' | xargs -n 1 echo >> 1.txt 13 | ``` 14 | 15 | 为什么要先说这个命令,因为我后面要介绍 `less` 、 `more`、 `most`,所以需要先创建这么一个文件出来。 16 | 17 | 18 | ## 命令分解 19 | ``` 20 | awk 'BEGIN{for(i=1;i<10;i++){print i}}' 21 | ``` 22 | awk 支持 for 循环,从 1 数到 10,结果: 23 | ``` 24 | [root@rddata tmp]# awk 'BEGIN{for(i=1;i<10;i++){print i}}' 25 | 1 26 | 2 27 | 3 28 | 4 29 | 5 30 | 6 31 | 7 32 | 8 33 | 9 34 | ``` 35 | 36 | `xargs -n 1 ` 表示对上一个命令产生的结果逐一传给下一个命令。其中`-n 1`是`逐一`,不带`-n`表示一股脑传给下一个命令。 37 | 38 | `echo >> 1.txt` 这里其实是省略了中间结果,完整的是:` echo 中间结果 >> 1.txt` 39 | 40 | 组合起来就是生产 10000 个数字,每个数字一行,写到 1.txt 文件中。 41 | 42 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/024_more.md: -------------------------------------------------------------------------------- 1 | ## more 2 | 类似 `vi` 和 `cat`,也是查看文件内容的。 3 | 4 | 不过它支持一些互动操作,可以翻页什么的,比较方便。 5 | 6 | 和 `less` 非常相似。 `less is more`,这里说一下自己的观点,尽可能用 `less` 而不是 `more`,因为`less`从实操便捷度,隐私性,性能处理上,各方面吊打`more`。 7 | 8 | ## 演示 9 | 交互命令: 10 | * Enter 向下n行,需要定义。默认为1行 11 | * Ctrl+F 向下滚动一屏 12 | * 空格键 向下滚动一屏 13 | * Ctrl+B 返回上一屏 14 | * = 输出当前行的行号 15 | * :f 输出文件名和当前行的行号 16 | * v 调用vi编辑器 17 | * !命令 调用Shell,并执行命令 18 | * q 退出more 19 | 20 | ## more 和 less 的关键区别 21 | 22 | * `less`可以按键盘上下方向键显示上下内容, `more` 不能通过上下方向键控制显示。 23 | * `less`不必读整个文件,加载速度会比`more`更快。 24 | ``` 25 | The main difference between more and less is that less command is faster 26 | because it does not load the entire file at once 27 | and allows navigation though file using page up/down keys. 28 | ``` 29 | * `less`退出后shell不会留下刚显示的内容, 而`more`退出后会在shell上留下刚显示的内容。 30 | 31 | ## more 和 less 非关键区别 32 | * `more`和`less`都支持往前滚动,但是往后滚没有`less`灵活(比如没有半屏滚动),因为`more`听说很久之前不支持向后滚,不过现在实操下来是支持往后滚的。 33 | * `more` 不支持 `less`的`上下行` 滚动(j 往前,k 往后)。 34 | * 当`more`到达文件末尾时它会自动关闭,而无需按下按钮。而`less`需要手动按q。 35 | * `more`会提示文件进度,如:`--更多--(4%)`, less 不会提示进度。 36 | * 按`=`号的时候,`more` 会提示第几行,`less` 会提示进度+第几行: `jj.txt lines 37-46/47 byte 13083/46422 28% (press RETURN)` 37 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/025_less.md: -------------------------------------------------------------------------------- 1 | ## less 2 | 类似 `vi`和 `cat`,也是查看文件内容的。 3 | 4 | 不过它支持一些互动操作,可以翻页什么的,比较方便。 5 | 6 | 和 `more` 非常相似。 `less is more`,这里说一下自己的观点,尽可能用 `less` 而不是 `more`,因为`less`从实操便捷度,隐私性,性能处理上,各方面吊打`more`。 7 | 8 | ## 谈谈 less 的由来 9 | ``` 10 | less was written by a man who was fed up with more's inability to scroll backwards through a file. 11 | He turned less into an open source project and over time, various individuals added new features to it. 12 | less is massive now. That's why some small embedded systems have more but not less. 13 | For comparison, less's source is over 27000 lines long. more implementations are generally only a little over 2000 lines long. 14 | ``` 15 | 有个哥们,因为老版本的 more 不支持向后滚动(新版本 more 是支持的),重写了一个 less。 16 | 17 | 然后他开源了,一堆网友往里面加功能,加着加着就2万多行代码,源代码量是 more 的 15 倍多。 18 | 19 | 一些老款的 linux 系统、嵌入式系统只支持 more,而不支持 less,也有可能是因为 more 小一些,less 太大了。 20 | 21 | ## 参数 22 | 23 | 我最喜欢这么用: 24 | ``` 25 | less -N -m 1.txt 2.txt 26 | ``` 27 | 其中: 28 | ``` 29 | -N 表示带行数,有这个比较有安全感。 30 | -m 表示和 more 一样,显示进度条 31 | ``` 32 | 33 | ## 交互 34 | 经验来看,用的最高频就`翻页`和`上下行`以及`搜索` 3 个操作。 35 | 36 | 搜索: 37 | ``` 38 | 比如想搜索 super 这个单词, 可以输入 /super 或者 ?super 39 | 两者的区别是 / 是从上往下搜索,? 是从下往上搜索 40 | ``` 41 | 翻页操作: 42 | ``` 43 | ctrl + F - 向前移动一屏 44 | ctrl + B - 向后移动一屏 45 | ctrl + D - 向前移动半屏 46 | ctrl + U - 向后移动半屏 47 | ``` 48 | 上下行操作: 49 | ``` 50 | j - 下一行 51 | k - 上一行 52 | ``` 53 | 多文件的时候换文件: 54 | ``` 55 | :n 下一个文件 56 | :p 上一个文件 57 | ``` 58 | 进入`vi`编辑模式: 59 | ``` 60 | v 61 | ``` 62 | 63 | 64 | 和 `vi` 一样,按 q 退出。 65 | 66 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/026_most.md: -------------------------------------------------------------------------------- 1 | ## most 2 | 一般来说,都是用来和`less`和`more`作比较。 3 | 4 | 我说过,用`less`就好,即使`most`参与比较,我依旧推荐`less`。 5 | 6 | 7 | ## most 的优点 8 | * 支持多窗口,但是`less`现在也支持多窗口。 9 | * 支持j跳到某行,这个确实不错。 10 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/027_sort.md: -------------------------------------------------------------------------------- 1 | ## sort 2 | 排序。 3 | 4 | ## 给文件排序 5 | 我们先创建一个文件,再分别 `sort 3.txt`和`sort -n 1 3.txt`,前者是字母序,后者是数字序: 6 | ``` 7 | [root@rddata tmp]# awk 'BEGIN{for(i=1;i<15;i++){print i}}' | xargs -n 1 echo >> 3.txt 8 | [root@rddata tmp]# 9 | [root@rddata tmp]# sort 3.txt 10 | 1 11 | 10 12 | 11 13 | 12 14 | 13 15 | 14 16 | 2 17 | 3 18 | 4 19 | 5 20 | 6 21 | 7 22 | 8 23 | 9 24 | [root@rddata tmp]# sort -n 3.txt 25 | 1 26 | 2 27 | 3 28 | 4 29 | 5 30 | 6 31 | 7 32 | 8 33 | 9 34 | 10 35 | 11 36 | 12 37 | 13 38 | 14 39 | ``` 40 | 41 | ## 给管道内容排序 42 | ``` 43 | [root@rddata tmp]# cat 3.txt | sort 44 | 1 45 | 10 46 | 11 47 | 12 48 | 13 49 | 14 50 | 2 51 | 3 52 | 4 53 | 5 54 | 6 55 | 7 56 | 8 57 | 9 58 | ``` 59 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/028_sed_1_插入一行.md: -------------------------------------------------------------------------------- 1 | ## sed 2 | 看到带数字后缀的命令,要小心谨慎,说明它非常重要。 3 | 4 | sed 也是一个很牛逼的文本处理命令,牛逼仅次于 awk。 5 | 6 | 7 | ## 给文件插入一行 8 | ``` 9 | [root@rddata tmp]# cat 3.txt 10 | 1 11 | 2 12 | 3 13 | 4 14 | 5 15 | [root@rddata tmp]# sed -e4ifatpo 3.txt 16 | 1 17 | 2 18 | 3 19 | fatpo 20 | 4 21 | 5 22 | [root@rddata tmp]# sed -e4a'fatpo' 3.txt 23 | 1 24 | 2 25 | 3 26 | 4 27 | fatpo 28 | 5 29 | ``` 30 | 注意: 31 | ``` 32 | sed 并不会操作源文件,如果非要修改源文件需要加一个-i参数:sed -i -e4a'fatpo' 3.txt 33 | ``` 34 | 35 | ## 命令解读 36 | `sed -e`表示我后面跟着是一个动作。`4` 表示第四行。`a`表示插到第四行后面,`i`表示插到第四行前面。 37 | 38 | 拓展下,动作列表: 39 | * a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~ 40 | * c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行! 41 | * d :删除,因为是删除啊,所以 d 后面通常不接任何东东; 42 | * i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行); 43 | * p :打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~ 44 | * s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正则表达式!例如 1,20s/old/new/g 就是啦! 45 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/029_sed_2_在某行处替换一行.md: -------------------------------------------------------------------------------- 1 | ## sed 2 | 看到带数字后缀的命令,要小心谨慎,说明它非常重要。 3 | 4 | sed 也是一个很牛逼的文本处理命令,牛逼仅次于 awk。 5 | 6 | 7 | ## 在第四行处替换成fatpo 8 | ``` 9 | [root@rddata tmp]# cat 3.txt 10 | 1 11 | 2 12 | 3 13 | 4 14 | 5 15 | [root@rddata tmp]# sed -e4c'fatpo' 3.txt 16 | 1 17 | 2 18 | 3 19 | fatpo 20 | 5 21 | ``` 22 | 注意: 23 | ``` 24 | sed 并不会操作源文件,如果非要修改源文件需要加一个-i参数:sed -i -e4c'fatpo' 3.txt 25 | ``` 26 | 27 | ## 解读 28 | `-e`后面跟数字+动作,数字表示第几行,动作目前有: 29 | * a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~ 30 | * c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行! 31 | * d :删除,因为是删除啊,所以 d 后面通常不接任何东东; 32 | * i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行); 33 | * p :打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~ 34 | * s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正则表达式!例如 1,20s/old/new/g 就是啦! 35 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/030_sed_3_删除一行.md: -------------------------------------------------------------------------------- 1 | ## sed 2 | 看到带数字后缀的命令,要小心谨慎,说明它非常重要。 3 | 4 | sed 也是一个很牛逼的文本处理命令,牛逼仅次于 awk。 5 | 6 | ## 删除第四行 7 | ``` 8 | [root@rddata tmp]# cat 3.txt 9 | 1 10 | 2 11 | 3 12 | 4 13 | 5 14 | [root@rddata tmp]# sed -e4d 3.txt 15 | 1 16 | 2 17 | 3 18 | 5 19 | ``` 20 | 注意: 21 | ``` 22 | sed 并不会操作源文件,如果非要修改源文件需要加一个-i参数:sed -i -e4d 3.txt 23 | ``` 24 | 25 | 26 | ## 解读 27 | `-e`后面跟数字+动作,数字表示第几行,动作目前有: 28 | * a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~ 29 | * c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行! 30 | * d :删除,因为是删除啊,所以 d 后面通常不接任何东东; 31 | * i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行); 32 | * p :打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~ 33 | * s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正则表达式!例如 1,20s/old/new/g 就是啦! 34 | -------------------------------------------------------------------------------- /linux/100个高频linux命令/031_nl.md: -------------------------------------------------------------------------------- 1 | ## nl 2 | 类似 `cat`,可以打印文本内容,不过优点是自带行号,还能对行号玩出花。 3 | 4 | ## 演示 5 | 文本内容: 6 | ```txt 7 | [root@rddata tmp]# cat 3.txt 8 | 1 9 | 2 10 | 3 11 | 4 12 | 13 | 5 14 | ``` 15 | 用 nl 的效果: 16 | ```txt 17 | [root@rddata tmp]# nl 3.txt 18 | 1 1 19 | 2 2 20 | 3 3 21 | 4 4 22 | 23 | 5 5 24 | ``` 25 | 参数: 26 | * -b :指定行号指定的方式,主要有两种: 27 | * -b a :表示不论是否为空行,也同样列出行号(类似 cat -n); 28 | * -b t :如果有空行,空的那一行不要列出行号(默认值); 29 | * -n :列出行号表示的方法,主要有三种: 30 | 31 | -n ln :行号在萤幕的最左方显示; 32 | 33 | -n rn :行号在自己栏位的最右方显示,且不加 0 ; 34 | 35 | -n rz :行号在自己栏位的最右方显示,且加 0 ; 36 | 37 | -w :行号栏位的占用的位数。 38 | 39 | -p 在逻辑定界符处不重新开始计算。 -------------------------------------------------------------------------------- /linux/100个高频linux命令/032_mtr.md: -------------------------------------------------------------------------------- 1 | ## mtr 介绍 2 | 常用的 ping,tracert,nslookup 一般用来判断主机的网络连通性,其实 Linux 下有一个更好用的网络联通性判断工具,它可以结合ping nslookup tracert 来判断网络的相关特性, 3 | 4 | 这个命令就是 mtr。mtr 全称 my traceroute,是一个把 ping 和 traceroute 合并到一个程序的网络诊断工具。 5 | 6 | traceroute 默认使用 UDP 数据包探测,而 mtr 默认使用ICMP报文探测,ICMP在某些路由节点的优先级要比其他数据包低,所以测试得到的数据可能低于实际情况。 7 | 8 | ## 安装 9 | ``` 10 | apt-get install mtr 11 | ``` 12 | 效果(往右拉): 13 | ``` 14 | VM-0-10-ubuntu (172.17.0.10) 2022-10-26T16:21:32+0800 15 | Keys: Help Display mode Restart statistics Order of fields quit 16 | Packets Pings 17 | Host Loss% Snt Last Avg Best Wrst StDev 18 | 1. ??? 19 | 2. 9.112.119.144 28.6% 7 1.7 2.5 1.7 5.6 1.7 20 | 3. ??? 21 | 4. 10.196.88.90 0.0% 7 4.9 5.0 4.9 5.1 0.1 22 | 5. 59.111.19.11 0.0% 7 5.4 5.4 5.4 5.4 0.0 23 | 24 | 25 | ``` 26 | 27 | ## 参考 28 | [每天学习一个命令: mtr 查看路由网络连通性](https://einverne.github.io/post/2017/11/mtr-usage.html) 29 | -------------------------------------------------------------------------------- /linux/cd跳最新文件夹.md: -------------------------------------------------------------------------------- 1 | ## 背景 2 | 我有多个地区的目录要进入,比如 id,th,my,tw,sg 等。 3 | 4 | 然后每个地区的目录,都要进入最新的目录下。 5 | 6 | ps:这个目录经常变的。 7 | 8 | ## 目标 9 | 我想要快速进入当前目录的最新目录下。 10 | 11 | ## 方案 12 | 先写一个脚本 jump.sh: 13 | ``` 14 | #!/bin/bash 15 | cd `ls -ltrh|grep 2022| awk 'END {print $NF}'` 16 | ``` 17 | 18 | 然后在写入环境 zshrc 中, `vi ~/.zshrc`: 19 | ``` 20 | alias cd5="source /root/diff_total/jump.sh" 21 | ``` 22 | 23 | ## 效果 24 | ``` 25 | cd5 26 | pwd 27 | ``` 28 | 跳来跳去,非常有效。这个真的解决了我多个地区的最新目录跳来跳去的痛点。 29 | 30 | ## 为什么不直接 alias 31 | 最开始的版本是直接在 `vi ~/.zshrc`: 32 | ``` 33 | alias cd5="cd `ls -ltrh|grep 2022| awk 'END {print $NF}'` " 34 | ``` 35 | 但是无效,每次都只有第一次有效,后面的都认准了第一次的目录,非常讨厌,好像被固化了。 36 | 37 | 具体原因不懂,所以我才抽成一个 sh 脚本来执行。 38 | -------------------------------------------------------------------------------- /linux/centos下查看网络流量.md: -------------------------------------------------------------------------------- 1 | ## nload 2 | centos: 3 | ``` 4 | yum install -y epel-release && yum install -y nload 5 | ``` 6 | 运行: 7 | ``` 8 | nload 9 | ``` 10 | 会出来一个小界面,还是很直观的。 11 | 12 | ![image](https://user-images.githubusercontent.com/6395350/190845417-7656400b-fd0c-4aa4-bd35-876859bef525.png) 13 | 14 | 15 | ## dstat 16 | 安装: 17 | ``` 18 | yum install -y dstat 19 | ``` 20 | 运行效果: 21 | ``` 22 | [root@server ~]# dstat 23 | You did not select any stats, using -cdngy by default. 24 | ----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system-- 25 | usr sys idl wai hiq siq| read writ| recv send| in out | int csw 26 | 0 0 99 0 0 0| 42k 67k| 0 0 | 0 0 | 618 1139 27 | 1 1 99 0 0 0| 0 0 | 648B 2136B| 0 0 | 654 1133 28 | 0 1 100 0 0 0| 0 0 | 96B 896B| 0 0 | 546 1012 29 | 1 0 100 0 0 0| 0 0 | 54B 362B| 0 0 | 495 942 30 | 1 1 99 0 0 1| 0 100k|1035B 1700B| 0 0 | 719 1247 31 | 1 1 99 0 0 0| 0 4096B|1200B 3547B| 0 0 | 666 1138 32 | 1 0 99 0 0 0| 0 0 | 108B 416B| 0 0 | 638 1201 33 | 0 0 99 0 0 0| 0 0 | 96B 1252B| 0 0 | 594 1150 34 | 1 0 100 0 0 0| 0 0 | 96B 404B| 0 0 | 584 1083 35 | 0 0 100 0 0 0| 0 0 | 96B 404B| 0 0 | 519 974 36 | 1 0 100 0 0 0| 0 40k| 54B 42B| 0 0 | 524 978 37 | 1 1 99 0 0 0| 0 0 | 270B 948B| 0 0 | 655 1172 38 | 0 0 99 0 0 0| 0 0 | 528B 1068B| 0 0 | 568 1025 39 | 0 0 100 0 0 0| 0 0 | 96B 108B| 0 0 | 520 965 40 | 1 0 99 0 0 0| 0 0 | 892B 1870B| 0 0 | 628 1108 41 | 1 1 99 0 0 0| 0 4096B|1200B 3231B| 0 0 | 659 1138 42 | 1 0 99 1 0 0| 0 40k| 54B 54B| 0 0 | 682 1354 43 | 1 1 99 0 0 0| 0 0 | 138B 766B| 0 0 | 666 1218 44 | 0 0 100 0 0 0| 0 0 | 96B 404B| 0 0 | 568 1064 45 | 1 0 100 0 0 0| 0 0 | 54B 42B| 0 0 | 515 976 46 | 0 0 99 0 0 0| 0 4096B| 754B 1490B| 0 0 | 649 1162 47 | 2 2 97 0 0 0| 0 156k| 648B 1270B| 0 0 | 868 1609 48 | ``` 49 | 50 | 51 | ## sar 52 | 53 | sar 是`System Activity Report`的缩写,是一款全面的Linux系统运行状态统计和性能分析工具,可从磁盘IO、CPU负载、内存使用等多个维度对系统活动进行报告。 54 | 55 | sar 命令来自 sysstat 包,可使用这个命令安装: 56 | ``` 57 | yum install -y sysstat 58 | ``` 59 | 60 | sar -n TCP 1 10可查看接下来10秒内的tcp数据: 61 | ``` 62 | [root@server ~]# sar -n TCP 1 10 63 | Linux 3.10.0-1160.71.1.el7.x86_64 (rdserver) 09/17/2022 _x86_64_ (2 CPU) 64 | 65 | 03:10:14 PM active/s passive/s iseg/s oseg/s 66 | 03:10:15 PM 1.00 0.00 9.00 8.00 67 | 03:10:16 PM 2.00 0.00 14.00 15.00 68 | 03:10:17 PM 0.00 0.00 1.00 1.00 69 | 03:10:18 PM 0.00 0.00 1.00 1.00 70 | 03:10:19 PM 0.00 0.00 3.00 3.00 71 | 03:10:20 PM 0.00 0.00 2.00 3.00 72 | 03:10:21 PM 0.00 0.00 1.00 1.00 73 | 03:10:22 PM 1.00 0.00 7.00 7.00 74 | 03:10:23 PM 0.00 0.00 1.00 1.00 75 | 03:10:24 PM 0.00 0.00 1.00 1.00 76 | Average: 0.40 0.00 4.00 4.10 77 | 78 | ``` 79 | 80 | ## ifto 81 | 安装: 82 | ``` 83 | yum install -y epel-release && yum install -y ifto 84 | ``` 85 | 运行: 86 | ``` 87 | iftop -nN -i eth0 88 | ``` 89 | 这个能看到和具体的IP连接的数据流量,还是很棒的。 90 | ![image](https://user-images.githubusercontent.com/6395350/190845374-32511eff-d115-4ae9-93cd-45ac864a260a.png) 91 | 92 | 93 | 94 | ## 参考资料 95 | [https://segmentfault.com/a/1190000022275523](https://segmentfault.com/a/1190000022275523) 96 | -------------------------------------------------------------------------------- /linux/nc做端口转发.md: -------------------------------------------------------------------------------- 1 | ## 架构图 2 | server(10.0.12.15) <---agent(10.0.8.9)---> data(10.0.8.8) 3 | 4 | ## nc做转发 5 | 下载nc: 6 | ``` 7 | yum install nmap-ncat -y 8 | ``` 9 | 原理: 10 | ``` 11 | 监听本机 9876 端口,将数据转发到 192.168.172.131的 80 端口 12 | 13 | ncat --sh-exec "ncat 192.168.172.131 80" -l 9876 --keep-open 14 | ``` 15 | 在agent上: 16 | ``` 17 | ncat --sh-exec "ncat 10.0.8.8 8098" -l 9000 --keep-open & 18 | ncat --sh-exec "ncat 10.0.12.15 8099" -l 9001 --keep-open & 19 | 20 | ncat --sh-exec "ncat -v -o 11.log 10.0.8.8 8098" -l 9000 --keep-open -o 1.log & 21 | ncat --sh-exec "ncat -v -o 22.log 10.0.12.15 8099" -l 9001 --keep-open -o 2.log & 22 | ``` 23 | 然后在server上: 24 | ``` 25 | 访问:10.0.8.9:9000 就是访问data:8098端口 26 | ``` 27 | 然后在data上: 28 | ``` 29 | 访问:10.0.8.9:9001 就是访问server:8099端口 30 | ``` 31 | 32 | 33 | ## nc做中间人通话 34 | 35 | 目标: 36 | ``` 37 | server1 <---agent---> server2 38 | 39 | server1和server2能交流信息。 40 | ``` 41 | 42 | 在agent上开2个nc: 43 | ``` 44 | mkfifo hubpipe 45 | nc -l -p 2222 0> /etc/fstab 135 | # echo /dev/vdb1 /data ext4 defaults,noatime,nofail 0 0 >> /etc/fstab 136 | # mount /data 137 | ``` 138 | 其中 `/etc/fstab` 处理自动挂载的,不然下次重启又要手动挂一次。 139 | -------------------------------------------------------------------------------- /linux/portmap端口转发.md: -------------------------------------------------------------------------------- 1 | ## 架构图 2 | server(10.0.12.15) <---agent(10.0.8.9)---> data(10.0.8.8) 3 | 4 | ## portmap做转发 5 | 下载portmap(就是 linux 版本的lcx): 6 | ``` 7 | http://www.vuln.cn/wp-content/uploads/2016/06/lcx_vuln.cn_.zip 8 | unzip lcx_vuln.cn_.zip 9 | chmod +x portmap 10 | ``` 11 | 在agent上: 12 | ``` 13 | ./portmap -m 1 -p1 9000 -h2 10.0.8.8 -p2 8098 & 14 | ./portmap -m 1 -p1 9001 -h2 10.0.12.15 -p2 8099 & 15 | ``` 16 | 然后在server上: 17 | ``` 18 | 访问:10.0.8.9:9000 就是访问data:8098端口 19 | ``` 20 | 然后在data上: 21 | ``` 22 | 访问:10.0.8.9:9001 就是访问server:8099端口 23 | ``` 24 | 25 | ## 参考资料 26 | * [Linux下常用的端口转发工具](https://www.cnblogs.com/xtxk110/p/14678178.html) 27 | -------------------------------------------------------------------------------- /linux/python3/logger怎么玩.md: -------------------------------------------------------------------------------- 1 | python2.7 简单的配置: 2 | ``` 3 | import logging.config 4 | 5 | LOGGING_CONFIG = { 6 | "version": 1, 7 | "formatters": { 8 | "default": { 9 | 'format': '%(asctime)s %(filename)s %(lineno)s [%(levelname)s] %(message)s', 10 | }, 11 | "plain": { 12 | "format": "%(message)s", 13 | }, 14 | }, 15 | "handlers": { 16 | "file": { 17 | "class": "logging.FileHandler", 18 | "level": "DEBUG", 19 | "filename": "./searchservice_api/log/invalid_request.txt", 20 | "formatter": "default", 21 | } 22 | }, 23 | "loggers": { 24 | "file_logger": { 25 | "handlers": ["file"], 26 | "level": "DEBUG", 27 | "propagate": True, 28 | } 29 | }, 30 | "disable_existing_loggers": False, 31 | } 32 | 33 | logging.config.dictConfig(LOGGING_CONFIG) 34 | invalid_request_logger = logging.getLogger("file_logger") 35 | 36 | invalid_request_logger.info("invalid_request_logger init success") 37 | ``` 38 | 39 | propagate: 40 | ``` 41 | 传播,If this evaluates to true, events logged to this logger will be passed to the handlers of higher level (ancestor) loggers, in addition to any handlers attached to this logger. 42 | 43 | 我个人理解就是比如你自己的 logger 挂了某个 handler,然后 root 的 logger 挂了 3 个 handler,这个配置打开后,相当于自己的 logger 挂了 4 个 handler。 44 | ``` 45 | 46 | disable_existing_loggers: 47 | ``` 48 | 把其他的 logger 干掉, 默认配置中的logger全部被禁用。被禁用的logger并不是被删除了,它们仍然存在,只是静默地丢弃所有发来的日志请求. 49 | ``` 50 | 51 | 上面的配置仅仅是打日志,还有类似的更多的配置: 52 | ``` 53 | from logging.config import dictConfig 54 | 55 | LOGGING_CONFIG = { 56 | 'version': 1, 57 | 'loggers': { 58 | '': { # root logger 59 | 'level': 'NOTSET', 60 | 'handlers': ['debug_console_handler', 'info_rotating_file_handler', 'error_file_handler', 'critical_mail_handler'], 61 | }, 62 | 'my.package': { 63 | 'level': 'WARNING', 64 | 'propagate': False, 65 | 'handlers': ['info_rotating_file_handler', 'error_file_handler' ], 66 | }, 67 | }, 68 | 'handlers': { 69 | 'debug_console_handler': { 70 | 'level': 'DEBUG', 71 | 'formatter': 'info', 72 | 'class': 'logging.StreamHandler', 73 | 'stream': 'ext://sys.stdout', 74 | }, 75 | 'info_rotating_file_handler': { 76 | 'level': 'INFO', 77 | 'formatter': 'info', 78 | 'class': 'logging.handlers.RotatingFileHandler', 79 | 'filename': 'info.log', 80 | 'mode': 'a', 81 | 'maxBytes': 1048576, 82 | 'backupCount': 10 83 | }, 84 | 'error_file_handler': { 85 | 'level': 'WARNING', 86 | 'formatter': 'error', 87 | 'class': 'logging.FileHandler', 88 | 'filename': 'error.log', 89 | 'mode': 'a', 90 | }, 91 | 'critical_mail_handler': { 92 | 'level': 'CRITICAL', 93 | 'formatter': 'error', 94 | 'class': 'logging.handlers.SMTPHandler', 95 | 'mailhost' : 'localhost', 96 | 'fromaddr': 'monitoring@domain.com', 97 | 'toaddrs': ['dev@domain.com', 'qa@domain.com'], 98 | 'subject': 'Critical error with application name' 99 | } 100 | }, 101 | 'formatters': { 102 | 'info': { 103 | 'format': '%(asctime)s-%(levelname)s-%(name)s::%(module)s|%(lineno)s:: %(message)s' 104 | }, 105 | 'error': { 106 | 'format': '%(asctime)s-%(levelname)s-%(name)s-%(process)d::%(module)s|%(lineno)s:: %(message)s' 107 | }, 108 | }, 109 | 110 | } 111 | 112 | dictConfig(LOGGING_CONFIG) 113 | ``` 114 | -------------------------------------------------------------------------------- /linux/python3/ubuntu18.04下pip3安装失败合集.md: -------------------------------------------------------------------------------- 1 | # 背景 2 | ubuntu18.04 3 | 4 | # 问题合集 5 | ## 问题 1 6 | ``` 7 | src/gevent/libev/corecext.c:95:20: 致命错误:Python.h:没有那个文件或目录 8 | #include "Python.h" 9 | ``` 10 | 解决方案: 11 | ``` 12 | apt-get install python3-devel 13 | ``` 14 | 15 | ## 问题 2 16 | ``` 17 | Attempting uninstall: httplib2 18 | Found existing installation: httplib2 0.9.2 19 | ERROR: Cannot uninstall 'httplib2'. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall. 20 | ``` 21 | 解决方案: 22 | ``` 23 | pip3 install firebase_admin --ignore-installed httplib2 24 | ``` 25 | 26 | ## 问题 3 27 | ``` 28 | protobuf requires Python '>=3.7' but the running Python is 3.6.5 29 | ``` 30 | 解决方案: 31 | ``` 32 | python3 -m pip install --upgrade pip 33 | ``` 34 | -------------------------------------------------------------------------------- /linux/python3/ubuntu18.04安装gevent失败的解决方案.md: -------------------------------------------------------------------------------- 1 | # 问题 2 | ``` 3 | x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -DLIBEV_EMBED=1 -DEV_COMMON= -DEV_CLEANUP_ENABLE=0 -DEV_EMBED_ENABLE=0 -DEV_PERIODIC_ENABLE=0 -DEV_USE_REALTIME=1 -DEV_USE_MONOTONIC=1 -DEV_USE_FLOOR=1 -I/tmp/pip-build-yu4klgzm/gevent/deps -I/tmp/pip-build-yu4klgzm/gevent/src/gevent/libev -I/tmp/pip-build-yu4klgzm/gevent/deps/libev -Isrc/gevent -Isrc/gevent/libev -Isrc/gevent/resolver -I. -I/usr/include/python3.6m -c src/gevent/libev/corecext.c -o build/temp.linux-x86_64-3.6/src/gevent/libev/corecext.o 4 | src/gevent/libev/corecext.c:94:10: fatal error: Python.h: No such file or directory 5 | #include "Python.h" 6 | ^~~~~~~~~~ 7 | compilation terminated. 8 | error: command 'x86_64-linux-gnu-gcc' failed with exit status 1 9 | 10 | ---------------------------------------- 11 | Failed building wheel for gevent 12 | Running setup.py clean for gevent 13 | Failed to build gevent 14 | ``` 15 | 16 | # 解决 17 | 升级pip: 18 | ``` 19 | root@shell:~/www/VirtualSIM_BackEnd# pip3 install pip --upgrade 20 | Collecting pip 21 | Downloading https://files.pythonhosted.org/packages/a4/6d/6463d49a933f547439d6b5b98b46af8742cc03ae83543e4d7688c2420f8b/pip-21.3.1-py3-none-any.whl (1.7MB) 22 | 100% |################################| 1.7MB 299kB/s 23 | Installing collected packages: pip 24 | Found existing installation: pip 9.0.1 25 | Not uninstalling pip at /usr/lib/python3/dist-packages, outside environment /usr 26 | Successfully installed pip-21.3.1 27 | ``` 28 | 再次安装gevent: 29 | ``` 30 | root@shell:~/www/VirtualSIM_BackEnd# pip3 install 'gevent>=1.5a2' 31 | WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip. 32 | Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue. 33 | To avoid this problem you can invoke Python with '-m pip' instead of running pip directly. 34 | Collecting gevent>=1.5a2 35 | Downloading gevent-21.12.0-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl (5.6 MB) 36 | |################################| 5.6 MB 14.3 MB/s 37 | Requirement already satisfied: greenlet<2.0,>=1.1.0 in /usr/local/lib/python3.6/dist-packages (from gevent>=1.5a2) (1.1.2) 38 | Requirement already satisfied: zope.event in /usr/local/lib/python3.6/dist-packages (from gevent>=1.5a2) (4.5.0) 39 | Requirement already satisfied: zope.interface in /usr/lib/python3/dist-packages (from gevent>=1.5a2) (4.3.2) 40 | Requirement already satisfied: setuptools in /usr/local/lib/python3.6/dist-packages (from gevent>=1.5a2) (59.6.0) 41 | Installing collected packages: gevent 42 | Successfully installed gevent-21.12.0 43 | WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv 44 | ``` 45 | -------------------------------------------------------------------------------- /linux/python3/替换敏感词.md: -------------------------------------------------------------------------------- 1 | ## 自己写替换逻辑 2 | ``` 3 | def replace_case(old, new, text): 4 | index = text.lower().find(old.lower()) 5 | if index == -1: 6 | return text 7 | return replace_case(old, new, text[:index] + new + text[index + len(old):]) 8 | 9 | 10 | if __name__ == '__main__': 11 | dest = "Fuck you!" 12 | print(dest) 13 | print(replace_case("Fuck", "F**k", dest)) 14 | 15 | ``` 16 | 效果: 17 | ``` 18 | Fuck you! 19 | F**k you! 20 | ``` 21 | 22 | ## 正则替换 23 | ``` 24 | import re 25 | 26 | 27 | def replace_case(old, new, text): 28 | reg = re.compile(re.escape(old), re.IGNORECASE) 29 | return reg.sub(new, text) 30 | 31 | 32 | if __name__ == '__main__': 33 | dest = "Fuck you!" 34 | print(dest) 35 | print(replace_case("Fuck", "F**k", dest)) 36 | 37 | ``` 38 | 效果: 39 | ``` 40 | Fuck you! 41 | F**k you! 42 | ``` 43 | -------------------------------------------------------------------------------- /linux/shell/awk/求和求均最大最小.md: -------------------------------------------------------------------------------- 1 | ## 1、求和 2 | ``` 3 | cat data|awk '{sum+=$1} END {print "Sum = ", sum}' 4 | ``` 5 | 6 | 7 | ## 2、求平均 8 | ``` 9 | cat data|awk '{sum+=$1} END {print "Average = ", sum/NR}' 10 | ``` 11 | 12 | 13 | ## 3、求最大值 14 | ``` 15 | cat data|awk 'BEGIN {max = 0} {if ($1>max) max=$1 fi} END {print "Max=", max}' 16 | ``` 17 | 18 | 19 | ## 4、求最小值(min的初始值设置一个超大数即可) 20 | ``` 21 | awk 'BEGIN {min = 1999999} {if ($1> ~/.bashrc 12 | 13 | 14 | if [ -d "${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-history-substring-search" ]; then 15 | git clone https://github.com/zsh-users/zsh-history-substring-search ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-history-substring-search 16 | fi 17 | 18 | if [ -d "${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting" ]; then 19 | git clone https://github.com/zsh-users/zsh-syntax-highlighting ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting 20 | fi 21 | 22 | if [ -d "${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions" ]; then 23 | git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions 24 | fi 25 | 26 | 27 | sed -i 's/plugins=(git)/plugins=(git zsh-autosuggestions zsh-syntax-highlighting zsh-history-substring-search)/g' ~/.zshrc 28 | ``` 29 | 30 | 执行: 31 | ``` 32 | sh 1.sh 33 | ``` 34 | -------------------------------------------------------------------------------- /linux/shell/zsh/一键初始化zsh下的diff环境.md: -------------------------------------------------------------------------------- 1 | 先安装下上传工具: 2 | ``` 3 | apt-get install -y lrzsz 4 | ``` 5 | 6 | 执行下面脚本: 7 | ``` 8 | #!/bin/bash 9 | apt-get install -y zsh 10 | 11 | sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" -y 12 | 13 | 14 | echo "zsh" >> ~/.bashrc 15 | 16 | 17 | folder1=${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-history-substring-search 18 | folder2=${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting 19 | folder3=${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions 20 | 21 | echo "check $folder1" 22 | if [ ! -d "$folder1" ]; then 23 | git clone https://github.com/zsh-users/zsh-history-substring-search ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-history-substring-search 24 | fi 25 | 26 | echo "check $folder2" 27 | if [ ! -d "$folder2" ]; then 28 | git clone https://github.com/zsh-users/zsh-syntax-highlighting ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting 29 | fi 30 | 31 | echo "check $folder3" 32 | if [ ! -d "$folder3" ]; then 33 | git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions 34 | fi 35 | 36 | 37 | sed -i 's/plugins=(git)/plugins=(git zsh-autosuggestions zsh-syntax-highlighting zsh-history-substring-search)/g' ~/.zshrc 38 | 39 | if [ -f "./diff_total.zip" ]; then 40 | 41 | unzip ./diff_total.zip 42 | 43 | cp ./diff_total/diff* ./diff_total/id 44 | cp ./diff_total/diff* ./diff_total/th 45 | cp ./diff_total/diff* ./diff_total/my 46 | 47 | unzip ./diff_total/id/id.zip -d ./diff_total/id/ 48 | unzip ./diff_total/th/th.zip -d ./diff_total/th/ 49 | unzip ./diff_total/my/my.zip -d ./diff_total/my/ 50 | 51 | head -3000 ./diff_total/id/id.txt > ./diff_total/id/id_3000.txt 52 | head -5000 ./diff_total/id/id.txt > ./diff_total/id/id_5000.txt 53 | head -10000 ./diff_total/id/id.txt > ./diff_total/id/id_10000.txt 54 | 55 | unzip ./diff_total/th/th.zip 56 | head -1000 ./diff_total/th/th.txt > ./diff_total/th/th_1000.txt 57 | head -3000 ./diff_total/th/th.txt > ./diff_total/th/th_3000.txt 58 | head -5000 ./diff_total/th/th.txt > ./diff_total/th/th_5000.txt 59 | head -10000 ./diff_total/th/th.txt > ./diff_total/th/th_10000.txt 60 | 61 | unzip ./diff_total/my/my.zip 62 | head -1000 ./diff_total/my/my.txt > ./diff_total/my/my_1000.txt 63 | head -3000 ./diff_total/my/my.txt > ./diff_total/my/my_3000.txt 64 | head -5000 ./diff_total/my/my.txt > ./diff_total/my/my_5000.txt 65 | head -10000 ./diff_total/my/my.txt > ./diff_total/my/my_10000.txt 66 | fi 67 | 68 | echo "you can exec like this: cd ./diff_total/id; ./diff.sh IP1:8080 IP2:8080 20 10 &" 69 | 70 | chsh -s /bin/zsh 71 | ``` 72 | 73 | 请注意: 74 | ``` 75 | 如果之前没安装过 zsh,需要执行脚本两次,第一次安装 zsh 会中断这个 shell 的执行,第二次解压 diff 数据。 76 | ``` 77 | 78 | -------------------------------------------------------------------------------- /linux/shell/zsh/调整命令行的prompt.md: -------------------------------------------------------------------------------- 1 | # 左边增加 root@username 2 | 我用的主题: 3 | ``` 4 | with root@gg ~/www > cat ~/.zshrc | grep -i ZSH_THEME with root@gg at 05:17:34 5 | ZSH_THEME="powerlevel10k/powerlevel10k" 6 | ``` 7 | 8 | 想在左边看到`with root@gg`,需要修改 `~/.p10k.zsh`,加上`context`: 9 | ``` 10 | typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=( 11 | #os_icon # os identifier 12 | context # 加上这个 13 | dir # current directory 14 | vcs # git status 15 | prompt_char # prompt symbol 16 | ``` 17 | 18 | 然后重启: 19 | ``` 20 | source ~/.zshrc 21 | ``` 22 | 23 | # 关闭左边或右边 24 | 25 | 左边: 26 | ``` 27 | # 注左边的提示段测试关闭失败,可能是p10k强制不允许关闭左边提示段的原因 28 | typeset -g POWERLEVEL9K_DISABLE_PROMPT=true 29 | ``` 30 | 31 | 右边: 32 | ``` 33 | typeset -g POWERLEVEL9K_DISABLE_RPROMPT=true 34 | ``` 35 | -------------------------------------------------------------------------------- /linux/shell/遍历日期然后执行命令.md: -------------------------------------------------------------------------------- 1 | 假设我们有一个脚本: `/www/shell/tool_update_everyday.py` 2 | 3 | 现在需要跑一下最近20多天的数据: 4 | 5 | v1 tmp.sh: 6 | ``` 7 | #! /bin/bash 8 | 9 | start_date=20220803 10 | end_date=20220824 11 | start_sec=`date -d "$start_date" "+%s"` 12 | end_sec=`date -d "$end_date" "+%s"` 13 | for((i=start_sec;i<=end_sec;i+=86400)); do 14 | day=$(date -d "@$i" "+%Y%m%d") 15 | echo $day 16 | /usr/bin/python3 /www/shell/tool_update_everyday.py $day 17 | done 18 | ``` 19 | 20 | 记得给 tmp.sh加权限: 21 | ``` 22 | chmod +x tmp.sh 23 | ``` 24 | 然后就可以愉快的跑起来啦: 25 | ``` 26 | ./tmp.sh & 27 | ``` 28 | 如果没有 chmod 加权限,也行: 29 | ``` 30 | sh ./tmp.sh & 31 | ``` 32 | -------------------------------------------------------------------------------- /linux/ssh/端口转发.md: -------------------------------------------------------------------------------- 1 | # 命令介绍 2 | ``` 3 | ssh -L opens a local port. Everything that you send to that port is put through the ssh connection and leaves through the server. 4 | ``` 5 | -------------------------------------------------------------------------------- /linux/修改命令行显示的用户名.md: -------------------------------------------------------------------------------- 1 | # 实战 2 | 我们进入到 linux 的 shell,看到这种命令行: 3 | ``` 4 | [root@VM-12-15-centos ~]# 5 | ``` 6 | 毫无辨识度啊。 7 | 8 | 我们期望的命令行: 9 | ``` 10 | [root@fatpo.mysql ~]# 11 | ``` 12 | 13 | 命令: 14 | ``` 15 | hostnamectl set-hostname fatpo.mysql 16 | ``` 17 | 18 | 然后退出 shell,再 ssh 登录一次即可。 19 | 20 | 21 | 22 | # 科普 23 | 下面都可以设置 hostname,不同角度: 24 | ``` 25 | sudo hostnamectl set-hostname host.example.com 26 | sudo hostnamectl set-hostname "Your Pretty HostName" --pretty 27 | sudo hostnamectl set-hostname host.example.com --static 28 | sudo hostnamectl set-hostname host.example.com --transient 29 | ``` 30 | 单纯检查是否设计完毕: 31 | ``` 32 | hostnamectl 33 | ``` 34 | 关于 static 和 pretty 的区别: 35 | ``` 36 | 静态主机名被存储在/etc/hostname, pretty 主机名被存储在/etc/machine-info文件。 37 | ``` 38 | -------------------------------------------------------------------------------- /linux/加固/firewall-cmd防火墙.md: -------------------------------------------------------------------------------- 1 | ## 背景 2 | centos7以上都采用 `firewall-cmd` 来替代`iptables` 管理白名单 3 | 4 | ### 富规则(rich rules的背景) 5 | 在某些情况下,我们可能需要创建更复杂的规则,而不仅仅是允许区域中的某些端口或服务。 6 | 7 | 例如,我们可能想要创建一条规则来阻止来自特定机器的某种类型的流量。 8 | 9 | 这就是rich规则的意义所在。 10 | 11 | 规则基本上由两部分组成:在第一部分中,我们指定要应用规则必须满足的条件,在第二部分中,指定要执行的操作:accept、drop或reject 12 | 13 | 14 | ### 富规则的语法 15 | 16 | --add-rich-rule选项,将该规则描述为其参数。规则以rule关键字开头: 17 | ``` 18 | family:我们指定该规则仅应用于IPv4数据包:如果未提供此关键字,则该规则将同时应用于IPv4和IPv6。 19 | source address:我们提供数据包必须具有的源地址,才能使用源地址触发规则。 20 | service,我们指定了规则的服务类型,在本例中为ssh。 21 | reject/drop/accept,我们提供了数据包与规则匹配时要执行的操作,在本例中为reject. 22 | ``` 23 | 24 | 25 | ## 打开防火墙 & 开机自启动 26 | ``` 27 | systemctl start firewalld 28 | systemctl enable firewalld 29 | ``` 30 | ## 查看状态 31 | ``` 32 | systemctl status firewalld 33 | ``` 34 | 效果: 35 | ``` 36 | ● firewalld.service - firewalld - dynamic firewall daemon 37 | Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled) 38 | Active: active (running) since Sat 2022-09-17 11:56:30 CST; 45s ago 39 | Docs: man:firewalld(1) 40 | Main PID: 21914 (firewalld) 41 | CGroup: /system.slice/firewalld.service 42 | └─21914 /usr/bin/python2 -Es /usr/sbin/firewalld --nofork --nopid 43 | 44 | Sep 17 11:56:30 server systemd[1]: Starting firewalld - dynamic firewall daemon... 45 | Sep 17 11:56:30 server systemd[1]: Started firewalld - dynamic firewall daemon. 46 | Sep 17 11:56:30 server firewalld[21914]: WARNING: AllowZoneDrifting is enabled. This is considered an insecure configuration option. It will be removed in a future release. Please consider disabling it now. 47 | ``` 48 | 49 | ## 添加一个ip:port的访问权限 50 | ``` 51 | firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="10.0.8.9" port protocol="tcp" port="2000" accept" 52 | 53 | firewall-cmd --reload 54 | ``` 55 | ## 删除一个ip:port的访问权限 56 | ``` 57 | firewall-cmd --permanent --remove-rich-rule="rule family="ipv4" source address="10.0.12.16" port protocol="tcp" port="2000" accept" 58 | 59 | firewall-cmd --reload 60 | ``` 61 | 62 | ## 查看当前规则 63 | ``` 64 | firewall-cmd --zone=public --list-rich-rules 65 | ``` 66 | 效果: 67 | ``` 68 | rule family="ipv4" source address="10.0.8.9" port port="2000" protocol="tcp" accept 69 | ``` 70 | 查看更多的规则: 71 | ``` 72 | [root@server ~]# firewall-cmd --zone=public --list-all 73 | public 74 | target: default 75 | icmp-block-inversion: no 76 | interfaces: 77 | sources: 78 | services: dhcpv6-client ssh 79 | ports: 80 | protocols: 81 | masquerade: no 82 | forward-ports: 83 | source-ports: 84 | icmp-blocks: 85 | rich rules: 86 | rule family="ipv4" source address="10.0.8.9" port port="2000" protocol="tcp" accept 87 | ``` 88 | 89 | ## 重新载入一下防火墙设置,使设置生效 90 | ``` 91 | firewall-cmd --reload 92 | ``` 93 | 94 | ## 查询打开的端口 95 | ``` 96 | firewall-cmd --zone=public --list-ports 97 | ``` 98 | 99 | 100 | ## 查询资料 101 | [https://www.jianshu.com/p/20b8ec56b9f8](https://www.jianshu.com/p/20b8ec56b9f8) 102 | -------------------------------------------------------------------------------- /linux/加固/ssh 禁止密码登录.md: -------------------------------------------------------------------------------- 1 | ``` 2 | vi /etc/ssh/sshd_config 3 | 4 | PasswordAuthentication no 5 | 6 | systemctl restart sshd.service 7 | ``` 8 | -------------------------------------------------------------------------------- /linux/加固/ubuntu18.04使用fail2ban加固服务器.md: -------------------------------------------------------------------------------- 1 | # 背景 2 | 加固服务器, fail2ban 可以把那些重试我们 SSH 的坏用户拉到黑名单。 3 | 4 | `man fail2ban` : 5 | ``` 6 | fail2ban - a set of server and client programs to limit brute force authentication attempts. 7 | 8 | 一组服务器和客户端程序,用于限制暴力验证尝试。 9 | ``` 10 | 11 | # 安装并开启 12 | ``` 13 | sudo apt-get update 14 | sudo apt-get upgrade 15 | 16 | sudo apt-get install -y fail2ban 17 | 18 | sudo systemctl start fail2ban 19 | sudo systemctl enable fail2ban 20 | ``` 21 | 22 | # 配置 23 | `vi /etc/fail2ban/jail.local` 24 | ``` 25 | [sshd] 26 | enabled = true 27 | port = 22 28 | filter = sshd 29 | logpath = /var/log/auth.log 30 | maxretry = 3 31 | ``` 32 | 33 | 重启下: 34 | ``` 35 | sudo systemctl restart fail2ban 36 | ``` 37 | 38 | # 效果 39 | 一天的量: 40 | ``` 41 | root@shell:~# cat /var/log/auth.log | wc -l 42 | 1563 43 | ``` 44 | 给你们看看部分坏用户: 45 | ``` 46 | Aug 3 03:47:23 wahaha sshd[15609]: Invalid user oracle from 51.77.116.67 port 58878 47 | Aug 3 03:47:24 wahaha sshd[15609]: Connection closed by invalid user oracle 51.77.116.67 port 58878 [preauth] 48 | Aug 3 03:51:48 wahaha sshd[15635]: Invalid user visuelconcept from 79.104.0.82 port 35548 49 | Aug 3 03:51:48 wahaha sshd[15635]: Disconnected from invalid user visuelconcept 79.104.0.82 port 35548 [preauth] 50 | Aug 3 03:51:58 wahaha sshd[15637]: Invalid user ailina from 148.63.215.173 port 55568 51 | Aug 3 03:51:58 wahaha sshd[15637]: Disconnected from invalid user ailina 148.63.215.173 port 55568 [preauth] 52 | Aug 3 03:52:29 wahaha sshd[15640]: Invalid user oracle from 103.160.24.2 port 49862 53 | Aug 3 03:52:30 wahaha sshd[15640]: Disconnected from invalid user oracle 103.160.24.2 port 49862 [preauth] 54 | Aug 3 03:52:56 wahaha sshd[15642]: Invalid user ailina from 134.17.16.43 port 15371 55 | Aug 3 03:52:57 wahaha sshd[15642]: Disconnected from invalid user ailina 134.17.16.43 port 15371 [preauth] 56 | Aug 3 03:53:20 wahaha sshd[15644]: Invalid user joseph from 201.236.182.196 port 37452 57 | Aug 3 03:53:20 wahaha sshd[15644]: Disconnected from invalid user joseph 201.236.182.196 port 37452 [preauth] 58 | Aug 3 03:53:43 wahaha sshd[15646]: Invalid user will from 165.227.142.62 port 53370 59 | Aug 3 03:53:43 wahaha sshd[15646]: Disconnected from invalid user will 165.227.142.62 port 53370 [preauth] 60 | Aug 3 03:54:41 wahaha sshd[15649]: Invalid user user from 177.92.98.254 port 53788 61 | Aug 3 03:54:41 wahaha sshd[15649]: Disconnected from invalid user user 177.92.98.254 port 53788 [preauth] 62 | Aug 3 03:54:45 wahaha sshd[15651]: Invalid user steve from 39.109.127.242 port 35102 63 | Aug 3 03:54:45 wahaha sshd[15651]: Disconnected from invalid user steve 39.109.127.242 port 35102 [preauth] 64 | Aug 3 03:55:30 wahaha sshd[15653]: Invalid user gerry from 52.12.139.92 port 46340 65 | Aug 3 03:55:30 wahaha sshd[15653]: Disconnected from invalid user gerry 52.12.139.92 port 46340 [preauth] 66 | Aug 3 03:57:09 wahaha sshd[15657]: Invalid user zr from 193.123.117.41 port 35666 67 | Aug 3 03:57:09 wahaha sshd[15657]: Disconnected from invalid user zr 193.123.117.41 port 35666 [preauth] 68 | Aug 3 03:59:33 wahaha sshd[15662]: Invalid user teampspeak3 from 189.135.237.156 port 54170 69 | Aug 3 03:59:33 wahaha sshd[15662]: Disconnected from invalid user teampspeak3 189.135.237.156 port 54170 [preauth] 70 | ``` 71 | 72 | 73 | # 参考教程: 74 | [https://www.techrepublic.com/article/how-to-install-fail2ban-on-ubuntu-server-18-04/](https://www.techrepublic.com/article/how-to-install-fail2ban-on-ubuntu-server-18-04/) 75 | -------------------------------------------------------------------------------- /linux/加固/ubuntu18.04搞ufw.md: -------------------------------------------------------------------------------- 1 | # 背景 2 | ``` 3 | ufw 是 ubuntu 的一个自带的防火墙。 18.04 是自带安装的。 4 | ``` 5 | 6 | 如果没有安装的话: 7 | ``` 8 | apt-get install ufw -y 9 | ``` 10 | 11 | # 命令 12 | 查看utf状态: 13 | ``` 14 | root@shell:~/.acme.sh/api.virtualsim.xyz# ufw status 15 | Status: active 16 | 17 | To Action From 18 | -- ------ ---- 19 | 22 ALLOW Anywhere 20 | 80 ALLOW Anywhere 21 | 443 ALLOW Anywhere 22 | 22 (v6) ALLOW Anywhere (v6) 23 | 80 (v6) ALLOW Anywhere (v6) 24 | 443 (v6) ALLOW Anywhere (v6) 25 | ``` 26 | 27 | 允许某个服务: 28 | ``` 29 | ufw allow ssh 30 | ufw allow http 31 | ``` 32 | 33 | 关闭某个服务: 34 | ``` 35 | ufw deny http 36 | ``` 37 | 38 | 添加某个 IP 到端口: 39 | ``` 40 | # 允许某个 ip 访问我们的 8000 端口 41 | ufw allow from 1.2.3.4 to any port 8000 42 | 43 | # 允许某个 ip 访问我们的 8000 端口 以 TCP 协议 44 | ufw allow from 1.2.3.4 to any port 8000 proto tcp 45 | ``` 46 | 47 | 删除某个规则: 48 | ``` 49 | root@shell:~# ufw status 50 | Status: active 51 | 52 | To Action From 53 | -- ------ ---- 54 | 22 ALLOW Anywhere 55 | 22 (v6) ALLOW Anywhere (v6) 56 | 80/tcp (v6) DENY Anywhere (v6) 57 | 58 | root@shell:~# ufw delete 3 59 | Deleting: 60 | deny 80/tcp 61 | Proceed with operation (y|n)? y 62 | Rule deleted (v6) 63 | root@shell:~# 64 | ``` 65 | 66 | -------------------------------------------------------------------------------- /linux/开机启动/ubuntu18.04新增supervisor开机自启动.md: -------------------------------------------------------------------------------- 1 | # 1、sysv-rc-conf简介 2 | 简单来说,就是linux上面一个很好用的管理开机启动的软件。 3 | 4 | 安装: 5 | ``` 6 | sudo apt-get install sysv-rc-conf 7 | ``` 8 | 你大概率是没有源的,如果没有源: 9 | ``` 10 | 编辑软件源列表:sudo vim /etc/apt/sources.list 11 | 末尾添加软件源:deb http://archive.ubuntu.com/ubuntu/ trusty main universe restricted multiverse 12 | 更新apt-get:sudo apt-get update 13 | ``` 14 | 启动(带操作界面): 15 | ``` 16 | sudo sysv-rc-conf 17 | ``` 18 | 启动(单纯查看): 19 | ``` 20 | sysv-rc-conf --list 21 | ``` 22 | 23 | 24 | # 2、查看是否开机启动 25 | ``` 26 | root@fatpo:~# sysv-rc-conf --list mysql 27 | mysql 0:off 1:off 2:on 3:on 4:on 5:on 6:off 28 | root@fatpo:~# sysv-rc-conf --list redis-server 29 | redis-server 0:off 1:off 2:on 3:on 4:on 5:on 6:off 30 | root@fatpo:~# sysv-rc-conf --list nginx 31 | nginx 0:off 1:off 2:on 3:on 4:on 5:on 6:off 32 | ``` 33 | 至此,看到3个关键的服务nginx,mysql,redis,都有2,3,4,5级别的开机启动,就很安心啦~ 34 | 35 | 看来ubuntu18.04之前安装这些软件时,已经帮我们这些小白顺便搞定了开启启动,没这么蠢~ 36 | 37 | # 3、添加开机启动的demo 38 | ``` 39 | sudo sysv-rc-conf --level 2345 mysql on 40 | ``` 41 | 42 | # 4、安装supervisor 43 | 有两条路子: 44 | * apt-get install supervisor 45 | * pip3 install supervisor==4.2.2 46 | 47 | 但是实操来看,用pip3安装的,总是无法开机自启动,非常疑惑,建议大家就用`apt-get install`。 48 | 49 | # 5、添加开机启动 50 | ``` 51 | sudo sysv-rc-conf --level 2345 supervisord on 52 | ``` 53 | 54 | 检查下 `cat /etc/init.d/supervisor` ,如果不存在创建之: 55 | ``` 56 | #! /bin/sh 57 | # 58 | # skeleton example file to build /etc/init.d/ scripts. 59 | # This file should be used to construct scripts for /etc/init.d. 60 | # 61 | # Written by Miquel van Smoorenburg . 62 | # Modified for Debian 63 | # by Ian Murdock . 64 | # Further changes by Javier Fernandez-Sanguino 65 | # 66 | # Version: @(#)skeleton 1.9 26-Feb-2001 miquels@cistron.nl 67 | # 68 | ### BEGIN INIT INFO 69 | # Provides: supervisor 70 | # Required-Start: $remote_fs $network $named 71 | # Required-Stop: $remote_fs $network $named 72 | # Default-Start: 2 3 4 5 73 | # Default-Stop: 0 1 6 74 | # Short-Description: Start/stop supervisor 75 | # Description: Start/stop supervisor daemon and its configured 76 | # subprocesses. 77 | ### END INIT INFO 78 | 79 | . /lib/lsb/init-functions 80 | 81 | PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 82 | DAEMON=/usr/local/bin/supervisord 83 | NAME=supervisord 84 | DESC=supervisor 85 | 86 | test -x $DAEMON || exit 0 87 | 88 | LOGDIR=/var/log/supervisor 89 | PIDFILE=/var/run/$NAME.pid 90 | DODTIME=5 # Time to wait for the server to die, in seconds 91 | # If this value is set too low you might not 92 | # let some servers to die gracefully and 93 | # 'restart' will not work 94 | 95 | # Include supervisor defaults if available 96 | if [ -f /etc/default/supervisor ] ; then 97 | . /etc/default/supervisor 98 | fi 99 | DAEMON_OPTS="-c /etc/supervisor/supervisord.conf $DAEMON_OPTS" 100 | 101 | set -e 102 | 103 | running_pid() 104 | { 105 | # Check if a given process pid's cmdline matches a given name 106 | pid=$1 107 | name=$2 108 | [ -z "$pid" ] && return 1 109 | [ ! -d /proc/$pid ] && return 1 110 | (cat /proc/$pid/cmdline | tr "\000" "\n"|grep -q $name) || return 1 111 | return 0 112 | } 113 | 114 | running() 115 | { 116 | # Check if the process is running looking at /proc 117 | # (works for all users) 118 | 119 | # No pidfile, probably no daemon present 120 | [ ! -f "$PIDFILE" ] && return 1 121 | # Obtain the pid and check it against the binary name 122 | pid=`cat $PIDFILE` 123 | running_pid $pid $DAEMON || return 1 124 | return 0 125 | } 126 | 127 | force_stop() { 128 | # Forcefully kill the process 129 | [ ! -f "$PIDFILE" ] && return 130 | if running ; then 131 | kill -15 $pid 132 | # Is it really dead? 133 | [ -n "$DODTIME" ] && sleep "$DODTIME"s 134 | if running ; then 135 | kill -9 $pid 136 | [ -n "$DODTIME" ] && sleep "$DODTIME"s 137 | if running ; then 138 | echo "Cannot kill $LABEL (pid=$pid)!" 139 | exit 1 140 | fi 141 | fi 142 | fi 143 | rm -f $PIDFILE 144 | return 0 145 | } 146 | 147 | case "$1" in 148 | start) 149 | echo -n "Starting $DESC: " 150 | start-stop-daemon --start --quiet --pidfile $PIDFILE \ 151 | --startas $DAEMON -- $DAEMON_OPTS 152 | test -f $PIDFILE || sleep 1 153 | if running ; then 154 | echo "$NAME." 155 | else 156 | echo " ERROR." 157 | fi 158 | ;; 159 | stop) 160 | echo -n "Stopping $DESC: " 161 | start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE 162 | echo "$NAME." 163 | ;; 164 | force-stop) 165 | echo -n "Forcefully stopping $DESC: " 166 | force_stop 167 | if ! running ; then 168 | echo "$NAME." 169 | else 170 | echo " ERROR." 171 | fi 172 | ;; 173 | #reload) 174 | # 175 | # If the daemon can reload its config files on the fly 176 | # for example by sending it SIGHUP, do it here. 177 | # 178 | # If the daemon responds to changes in its config file 179 | # directly anyway, make this a do-nothing entry. 180 | # 181 | # echo "Reloading $DESC configuration files." 182 | # start-stop-daemon --stop --signal 1 --quiet --pidfile \ 183 | # /var/run/$NAME.pid --exec $DAEMON 184 | #;; 185 | force-reload) 186 | # 187 | # If the "reload" option is implemented, move the "force-reload" 188 | # option to the "reload" entry above. If not, "force-reload" is 189 | # just the same as "restart" except that it does nothing if the 190 | # daemon isn't already running. 191 | # check wether $DAEMON is running. If so, restart 192 | start-stop-daemon --stop --test --quiet --pidfile $PIDFILE \ 193 | --startas $DAEMON \ 194 | && $0 restart \ 195 | || exit 0 196 | ;; 197 | restart) 198 | echo -n "Restarting $DESC: " 199 | start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE 200 | [ -n "$DODTIME" ] && sleep $DODTIME 201 | start-stop-daemon --start --quiet --pidfile $PIDFILE \ 202 | --startas $DAEMON -- $DAEMON_OPTS 203 | echo "$NAME." 204 | ;; 205 | status) 206 | echo -n "$LABEL is " 207 | if running ; then 208 | echo "running" 209 | else 210 | echo " not running." 211 | exit 1 212 | fi 213 | ;; 214 | *) 215 | N=/etc/init.d/$NAME 216 | # echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2 217 | echo "Usage: $N {start|stop|restart|force-reload|status|force-stop}" >&2 218 | exit 1 219 | ;; 220 | esac 221 | 222 | exit 0 223 | 224 | ``` 225 | 添加权限: 226 | ``` 227 | chmod +x /etc/init.d/supervisor 228 | ``` 229 | 230 | 231 | # 6、想进一步了解开机启动的这边 232 | 233 | 234 | [fatpo.github.io/#/我干运维那些事/生产实战/linux私房菜/ubuntu18.04用sysv-rc-conf管理开机自启动](https://fatpo.github.io/#/%E6%88%91%E5%B9%B2%E8%BF%90%E7%BB%B4%E9%82%A3%E4%BA%9B%E4%BA%8B/%E7%94%9F%E4%BA%A7%E5%AE%9E%E6%88%98/linux%E7%A7%81%E6%88%BF%E8%8F%9C/ubuntu18.04%E7%94%A8sysv-rc-conf%E7%AE%A1%E7%90%86%E5%BC%80%E6%9C%BA%E8%87%AA%E5%90%AF%E5%8A%A8) 235 | 236 | 237 | -------------------------------------------------------------------------------- /linux/查看上次开机时间.md: -------------------------------------------------------------------------------- 1 | 查看linux系统的开机时间/重启历史记录 2 | 3 | ## 1、who -b命令 4 | ``` 5 | [root@rusky opt]# who -b ---查看最后一次(上次)系统启动的时间 6 | system boot Dec 27 05:06 7 | ``` 8 | 9 | ## 2、who -r命令 10 | ``` 11 | [root@rusky opt]# who -r ---查看最后一次(上次)系统启动的时间,及运行级别 12 | run-level 5 Dec 27 05:06 13 | ``` 14 | ## 3、last reboot命令 15 | 16 | ``` 17 | [root@rusky opt]# last reboot 18 | reboot system boot 2.6.32-358.el6.x Sat Dec 27 05:06 - 16:07 (4+11:00) 19 | reboot system boot 2.6.32-358.el6.x Wed Nov 5 20:00 - 16:07 (55+20:06) 20 | reboot system boot 2.6.32-358.el6.x Mon Oct 13 14:00 - 19:15 (23+05:15) 21 | reboot system boot 2.6.32-358.el6.x Sat Oct 11 09:14 - 13:59 (2+04:44) 22 | reboot system boot 2.6.32-358.el6.x Thu Oct 9 05:40 - 09:13 (2+03:32) 23 | reboot system boot 2.6.32-358.el6.x Wed Oct 8 21:48 - 05:40 (07:51) 24 | reboot system boot 2.6.32-358.el6.x Wed Oct 8 20:08 - 21:48 (01:39) 25 | reboot system boot 2.6.32-358.el6.x Wed Oct 8 16:29 - 20:08 (03:38) 26 | reboot system boot 2.6.32-358.el6.x Wed Oct 8 16:24 - 16:27 (00:02) 27 | reboot system boot 2.6.32-358.el6.x Mon Sep 29 18:59 - 16:23 (8+21:24) 28 | reboot system boot 2.6.32-358.el6.x Sun Sep 28 22:02 - 18:58 (20:56) 29 | reboot system boot 2.6.32-358.el6.x Sun Sep 28 20:18 - 22:01 (01:42) 30 | reboot system boot 2.6.32-358.el6.x Sun Sep 28 20:14 - 20:17 (00:02) 31 | reboot system boot 2.6.32-358.el6.x Sun Sep 28 20:12 - 20:17 (00:04) 32 | 33 | wtmp begins Sun Sep 28 20:12:54 2014 34 | ``` 35 | 36 | ## 4、top命令 37 | up后表示系统到目前运行了多久时间。反过来推算系统重启时间 38 | ``` 39 | [root@rusky opt]# top 40 | 41 | top - 16:10:12 up 4 days, 11:05, 4 users, load average: 0.00, 0.00, 0.00 42 | Tasks: 421 total, 1 running, 420 sleeping, 0 stopped, 0 zombie 43 | …… 44 | ``` 45 | 46 | ## 5、w命令 47 | up后表示系统到目前运行了多久时间。反过来推算系统重启时间 48 | ``` 49 | [root@rdserver ~]# w 50 | 00:08:59 up 12 days, 4:00, 2 users, load average: 0.02, 0.07, 0.15 51 | USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT 52 | root pts/1 27.37.138.202 22:04 1:40m 4:19 0.12s -bash 53 | root pts/2 113.87.183.216 23:40 3.00s 0.02s 0.00s w 54 | 55 | ``` 56 | 这个命令还能看谁登录了这台机器,不错不错。 57 | 58 | 稍微看下w这个命令`man w`: 59 | ``` 60 | W(1) User Commands W(1) 61 | 62 | NAME 63 | w - Show who is logged on and what they are doing. 64 | 65 | SYNOPSIS 66 | w [options] user [...] 67 | 68 | DESCRIPTION 69 | w displays information about the users currently on the machine, and their processes. The header shows, in this order, the current time, how long the system has been running, how many users are currently logged on, and the 70 | system load averages for the past 1, 5, and 15 minutes. 71 | 72 | The following entries are displayed for each user: login name, the tty name, the remote host, login time, idle time, JCPU, PCPU, and the command line of their current process. 73 | 74 | The JCPU time is the time used by all processes attached to the tty. It does not include past background jobs, but does include currently running background jobs. 75 | 76 | The PCPU time is the time used by the current process, named in the "what" field. 77 | 78 | ``` 79 | 80 | ## 6、uptime命令及查看/proc/uptime 81 | 82 | ``` 83 | [root@rusky opt]# uptime 84 | 16:47:53 up 4 days, 11:42, 3 users, load average: 0.00, 0.00, 0.00 85 | 86 | [root@rusky opt]# date -d "`cut -f1 -d. /proc/uptime` seconds ago" --查看最近一次系统重启的时间 87 | Sat Dec 27 05:05:12 CST 2014 88 | 89 | [root@rusky opt]# date -d "$(awk -F. '{print $1}' /proc/uptime) second ago" +"%Y-%m-%d %H:%M:%S" 90 | 2014-12-27 05:05:12 91 | ``` 92 | 93 | ## 7、链接 94 | [https://www.cnblogs.com/rusking/p/4196194.html](https://www.cnblogs.com/rusking/p/4196194.html) 95 | -------------------------------------------------------------------------------- /linux/查看网络质量.md: -------------------------------------------------------------------------------- 1 | ## 1、ping 2 | ``` 3 | ping www.baidu.com 4 | ``` 5 | 6 | ## 2、mtr 7 | ping 有的时候被对端禁用。 8 | 9 | 当客户端访问目标服务器或负载均衡,使用ping命令测试出现丢包或不通时,可以通过MTR等工具进行链路测试来判断问题来源。 10 | 11 | ``` 12 | ># mtr -r www.baidu.com 13 | Start: 2022-09-23T08:59:32+0000 14 | HOST: server Loss% Snt Last Avg Best Wrst StDev 15 | 1.|-- ??? 100.0 10 0.0 0.0 0.0 0.0 0.0 16 | 2.|-- 100.100.100.1 0.0% 10 0.5 0.5 0.4 0.8 0.1 17 | 3.|-- 10.64.5.205 0.0% 10 1.1 2.4 1.1 6.7 2.2 18 | 4.|-- 10.64.4.217 0.0% 10 1.0 4.8 1.0 17.7 6.1 19 | 5.|-- 10.64.0.249 0.0% 10 2.8 4.7 0.9 30.2 9.0 20 | 6.|-- Unassigned230.nyiix.net 0.0% 10 1.7 2.0 1.7 3.0 0.4 21 | 7.|-- 223.118.11.89 0.0% 10 21.0 21.1 20.9 21.4 0.2 22 | 8.|-- 223.118.12.66 0.0% 10 69.6 69.6 69.3 70.9 0.5 23 | 9.|-- 221.183.30.173 0.0% 10 215.4 216.1 215.4 218.4 1.0 24 | 10.|-- 221.183.25.122 0.0% 10 215.3 215.3 215.1 215.8 0.2 25 | 11.|-- 221.176.22.157 0.0% 10 222.7 219.3 218.9 222.7 1.2 26 | 12.|-- 111.24.5.193 0.0% 10 220.6 214.5 211.2 222.2 4.3 27 | 13.|-- ??? 100.0 10 0.0 0.0 0.0 0.0 0.0 28 | 14.|-- 120.196.198.198 90.0% 10 219.6 219.6 219.6 219.6 0.0 29 | 15.|-- 120.241.49.42 0.0% 10 226.9 227.9 226.8 230.1 1.0 30 | 16.|-- ??? 100.0 10 0.0 0.0 0.0 0.0 0.0 31 | 17.|-- ??? 100.0 10 0.0 0.0 0.0 0.0 0.0 32 | 18.|-- ??? 100.0 10 0.0 0.0 0.0 0.0 0.0 33 | 19.|-- ??? 100.0 10 0.0 0.0 0.0 0.0 0.0 34 | 20.|-- 183.232.231.173 0.0% 10 224.3 224.4 224.3 224.6 0.1 35 | ``` 36 | 37 | mtr的参数: 38 | ``` 39 | -r 或 -report:以报告模式显示输出。 40 | -p 或 -split:将每次追踪的结果分别列出来。 41 | -s 或 -psize:指定ping数据包的大小。 42 | -n 或 -no-dns:不对IP地址做域名反解析。 43 | -a 或 -address:设置发送数据包的IP地址。用于主机有多个IP时。 44 | -4:只使用IPv4协议。 45 | -6:只使用IPv6协议。 46 | 47 | 另外,也可以在mtr命令运行过程中,输入相应字母来快速切换模式。 48 | ?或 h:显示帮助菜单。 49 | d:切换显示模式。 50 | n:切换启用或禁用DNS域名解析。 51 | u:切换使用ICMP或UDP数据包进行探测。 52 | ``` 53 | 54 | 我们一般用`mtr -r` 就好了。 55 | 56 | ## 3、dig 57 | dig (域信息搜索器)命令是一个用于询问 DNS 域名服务器的灵活的工具。 58 | 59 | ``` 60 | ># dig google.com 61 | 62 | ; <<>> DiG 9.11.3-1ubuntu1.17-Ubuntu <<>> google.com 63 | ;; global options: +cmd 64 | ;; Got answer: 65 | ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28220 66 | ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 67 | 68 | ;; OPT PSEUDOSECTION: 69 | ; EDNS: version: 0, flags:; udp: 65494 70 | ;; QUESTION SECTION: 71 | ;google.com. IN A 72 | 73 | ;; ANSWER SECTION: 74 | google.com. 181 IN A 142.250.64.110 75 | 76 | ;; Query time: 0 msec 77 | ;; SERVER: 127.0.0.53#53(127.0.0.53) 78 | ;; WHEN: Fri Sep 23 08:43:49 UTC 2022 79 | ;; MSG SIZE rcvd: 55 80 | ``` 81 | 82 | 稍微解释下返回,dig 命令默认的输出信息比较丰富,大概可以分为 5 个部分: 83 | ``` 84 | 第一部分显示 dig 命令的版本和输入的参数。 85 | 第二部分显示服务返回的一些技术详情,比较重要的是 status。如果 status 的值为 NOERROR 则说明本次查询成功结束。 86 | 第三部分中的 "QUESTION SECTION" 显示我们要查询的域名。 87 | 第四部分的 "ANSWER SECTION" 是查询到的结果。 88 | 第五部分则是本次查询的一些统计信息,比如用了多长时间,查询了哪个 DNS 服务器,在什么时间进行的查询等等。 89 | ``` 90 | 默认情况下 dig 命令查询 A 记录,上图中显示的 A 即说明查询的记录类型为 A 记录。常见的 DNS 记录类型: 91 | 92 | |DNS类型|备注| 93 | |:---|:---| 94 | |A| 地址记录,用来指定域名的 IPv4 地址,如果需要将域名指向一个 IP 地址,就需要添加 A 记录。| 95 | |AAAA |用来指定主机名(或域名)对应的 IPv6 地址记录。| 96 | |CNAME |如果需要将域名指向另一个域名,再由另一个域名提供 ip 地址,就需要添加 CNAME 记录。| 97 | |MX| 如果需要设置邮箱,让邮箱能够收到邮件,需要添加 MX 记录。| 98 | |NS |域名服务器记录,如果需要把子域名交给其他 DNS 服务器解析,就需要添加 NS 记录。| 99 | |SOA |SOA 这种记录是所有区域性文件中的强制性记录。它必须是一个文件中的第一个记录。| 100 | |TXT |可以写任何东西,长度限制为 255。绝大多数的 TXT记录是用来做 SPF 记录(反垃圾邮件)。| 101 | 102 | 103 | # 4、参考 104 | 105 | * [linux dig 命令](https://www.cnblogs.com/sparkdev/p/7777871.html) 106 | * [MTR工具使用说明与结果分析](https://help.aliyun.com/document_detail/98706.html) 107 | -------------------------------------------------------------------------------- /mysql/5.7创建新用户.md: -------------------------------------------------------------------------------- 1 | ``` 2 | CREATE USER 'admin'@'%' IDENTIFIED BY '123456'; 3 | GRANT ALL PRIVILEGES ON *.* TO 'admin'@'%' WITH GRANT OPTION; 4 | ``` 5 | -------------------------------------------------------------------------------- /mysql/mysqldump导数据.md: -------------------------------------------------------------------------------- 1 | ## 简单把结构导出来 2 | ``` 3 | mysqldump -h localhost -uroot -p -d mydb > dump.sql 4 | ``` 5 | 6 | 怎么看表的 auto_increment: 7 | ``` 8 | select table_name, AUTO_INCREMENT From INFORMATION_SCHEMA. TABLES where AUTO_INCREMENT is not null; 9 | ``` 10 | 11 | 12 | ## 更多命令 13 | 链接:[https://www.cnblogs.com/qmfsun/p/5405599.html](https://www.cnblogs.com/qmfsun/p/5405599.html) 14 | ``` 15 | mysqldump -u用戶名 -p密码 -d 数据库名 表名 > 脚本名; 16 | 17 | 18 | 导出整个数据库结构和数据 19 | mysqldump -h localhost -uroot -p123456 database > dump.sql 20 | 21 | 22 | 23 | 导出单个数据表结构和数据 24 | mysqldump -h localhost -uroot -p123456 database table > dump.sql 25 | 26 | 27 | 导出整个数据库结构(不包含数据) 28 | mysqldump -h localhost -uroot -p123456 -d database > dump.sql 29 | 30 | 31 | 32 | 导出单个数据表结构(不包含数据) 33 | mysqldump -h localhost -uroot -p123456 -d database table > dump.sql 34 | 35 | 36 | 37 | mysqldump 备份导出数据排除某张表 38 | 就用 --ignore-table=dbname.tablename参数就行了。 39 | 40 | mysqldump -uusername -ppassword -h192.168.0.1 -P3306 dbname --ignore-table=dbname.dbtanles > dump.sql 41 | ``` 42 | 43 | ## 导入 mysql 44 | 导入到 mysql 中: 45 | ``` 46 | 首先要进入 mysql 47 | mysql> source /tmp/dump2.sql; 48 | ``` 49 | -------------------------------------------------------------------------------- /mysql/ubuntu18.04下安装mysql5.6.md: -------------------------------------------------------------------------------- 1 | 安装: 2 | ``` 3 | sudo apt-get install mysql-server 4 | ``` 5 | 改密: 6 | ``` 7 | $ mysql -u root 8 | 9 | mysql> USE mysql; 10 | mysql> update user set authentication_string=PASSWORD('your_password_here') where user='root'; 11 | mysql> update user set plugin="mysql_native_password" where User='root'; 12 | mysql> flush privileges; 13 | mysql> quit 14 | ``` 15 | 16 | -------------------------------------------------------------------------------- /mysql/连接数过大.md: -------------------------------------------------------------------------------- 1 | 睡觉的时候,突然收到告警,说是连接池不够用,奇怪,上来mysql看了下: 2 | ``` 3 | mysql> show status like 'Threads%'; 4 | +-------------------+-------+ 5 | | Variable_name | Value | 6 | +-------------------+-------+ 7 | | Threads_cached | 6 | 8 | | Threads_connected | 72 | 9 | | Threads_created | 49783 | 10 | | Threads_running | 1 | 11 | +-------------------+-------+ 12 | 4 rows in set (0.02 sec) 13 | 14 | mysql> show processlist; 15 | +----------+------+----------------------+----------+---------+------+----------+------------------+ 16 | | Id | User | Host | db | Command | Time | State | Info | 17 | +----------+------+----------------------+----------+---------+------+----------+------------------+ 18 | | 14975161 | root | 66.1.2.3:38790 | secphone | Sleep | 2867 | | NULL | 19 | | 14976185 | root | localhost:59384 | secphone | Sleep | 209 | | NULL | 20 | | 14976202 | root | localhost:59386 | secphone | Sleep | 209 | | NULL | 21 | | 14976415 | root | 66.1.2.3:40460 | secphone | Sleep | 1867 | | NULL | 22 | | 14977443 | root | 66.1.2.3:41718 | secphone | Sleep | 596 | | NULL | 23 | | 14977447 | root | 66.1.2.3:41724 | secphone | Sleep | 592 | | NULL | 24 | | 14977476 | root | 66.1.2.3:41784 | secphone | Sleep | 545 | | NULL | 25 | | 14977484 | root | 66.1.2.3:41798 | secphone | Sleep | 526 | | NULL | 26 | | 14977490 | root | 66.1.2.3:41806 | secphone | Sleep | 526 | | NULL | 27 | | 14977492 | root | 66.1.2.3:41810 | secphone | Sleep | 509 | | NULL | 28 | | 14977519 | root | 66.1.2.3:41840 | secphone | Sleep | 491 | | NULL | 29 | | 14977526 | root | 66.1.2.3:41850 | secphone | Sleep | 497 | | NULL | 30 | | 14977531 | root | 66.1.2.3:41860 | secphone | Sleep | 490 | | NULL | 31 | | 14977543 | root | 66.1.2.3:41870 | secphone | Sleep | 487 | | NULL | 32 | | 14977545 | root | 66.1.2.3:41876 | secphone | Sleep | 491 | | NULL | 33 | | 14977560 | root | 66.1.2.3:41894 | secphone | Sleep | 480 | | NULL | 34 | | 14977561 | root | 66.1.2.3:41896 | secphone | Sleep | 480 | | NULL | 35 | | 14977625 | root | 66.1.2.3:41974 | secphone | Sleep | 449 | | NULL | 36 | | 14977631 | root | 66.1.2.3:41980 | secphone | Sleep | 449 | | NULL | 37 | | 14977636 | root | 66.1.2.3:41986 | secphone | Sleep | 449 | | NULL | 38 | | 14977640 | root | 66.1.2.3:41992 | secphone | Sleep | 449 | | NULL | 39 | | 14977646 | root | 66.1.2.3:42004 | secphone | Sleep | 449 | | NULL | 40 | | 14977654 | root | 66.1.2.3:42016 | secphone | Sleep | 449 | | NULL | 41 | | 14977660 | root | 66.1.2.3:42024 | secphone | Sleep | 449 | | NULL | 42 | | 14977662 | root | 66.1.2.3:42030 | secphone | Sleep | 449 | | NULL | 43 | | 14977663 | root | 66.1.2.3:42026 | secphone | Sleep | 449 | | NULL | 44 | | 14977665 | root | 66.1.2.3:42032 | secphone | Sleep | 445 | | NULL | 45 | | 14977667 | root | 66.1.2.3:42034 | secphone | Sleep | 445 | | NULL | 46 | | 14977669 | root | 66.1.2.3:42036 | secphone | Sleep | 445 | | NULL | 47 | | 14977686 | root | 66.1.2.3:42058 | secphone | Sleep | 425 | | NULL | 48 | | 14977709 | root | 66.1.2.3:42094 | secphone | Sleep | 425 | | NULL | 49 | | 14977769 | root | 66.1.2.3:42182 | secphone | Sleep | 412 | | NULL | 50 | | 14977774 | root | 66.1.2.3:42192 | secphone | Sleep | 412 | | NULL | 51 | | 14977777 | root | 66.1.2.3:42194 | secphone | Sleep | 413 | | NULL | 52 | | 14977783 | root | 66.1.2.3:42200 | secphone | Sleep | 406 | | NULL | 53 | | 14977786 | root | 66.1.2.3:42208 | secphone | Sleep | 413 | | NULL | 54 | | 14977792 | root | 66.1.2.3:42216 | secphone | Sleep | 397 | | NULL | 55 | | 14977818 | root | 66.1.2.3:42254 | secphone | Sleep | 393 | | NULL | 56 | | 14977819 | root | 66.1.2.3:42256 | secphone | Sleep | 391 | | NULL | 57 | | 14977822 | root | 66.1.2.3:42260 | secphone | Sleep | 392 | | NULL | 58 | | 14977842 | root | 66.1.2.3:42318 | secphone | Sleep | 367 | | NULL | 59 | | 14977843 | root | 66.1.2.3:42320 | secphone | Sleep | 367 | | NULL | 60 | | 14977877 | root | 66.1.2.3:42368 | secphone | Sleep | 335 | | NULL | 61 | | 14977934 | root | 66.1.2.3:42458 | secphone | Sleep | 335 | | NULL | 62 | | 14977936 | root | 66.1.2.3:42470 | secphone | Sleep | 336 | | NULL | 63 | | 14977939 | root | 66.1.2.3:42476 | secphone | Sleep | 336 | | NULL | 64 | | 14977941 | root | 66.1.2.3:42480 | secphone | Sleep | 336 | | NULL | 65 | | 14977958 | root | 66.1.2.3:42506 | secphone | Sleep | 332 | | NULL | 66 | | 14977967 | root | 66.1.2.3:42522 | secphone | Sleep | 332 | | NULL | 67 | | 14977973 | root | 66.1.2.3:42528 | secphone | Sleep | 332 | | NULL | 68 | | 14977976 | root | 66.1.2.3:42534 | secphone | Sleep | 332 | | NULL | 69 | | 14977979 | root | 66.1.2.3:42538 | secphone | Sleep | 329 | | NULL | 70 | | 14978017 | root | 66.1.2.3:42602 | secphone | Sleep | 321 | | NULL | 71 | | 14978048 | root | 66.1.2.3:42646 | secphone | Sleep | 313 | | NULL | 72 | | 14978094 | root | 66.1.2.3:42770 | secphone | Sleep | 273 | | NULL | 73 | | 14978107 | root | 66.1.2.3:42790 | secphone | Sleep | 252 | | NULL | 74 | | 14978129 | root | 66.1.2.3:42820 | secphone | Sleep | 259 | | NULL | 75 | | 14978136 | root | 66.1.2.3:42830 | secphone | Sleep | 248 | | NULL | 76 | | 14978137 | root | 66.1.2.3:42832 | secphone | Sleep | 253 | | NULL | 77 | | 14978140 | root | 66.1.2.3:42834 | secphone | Sleep | 248 | | NULL | 78 | | 14978209 | root | 66.1.2.3:42908 | secphone | Sleep | 210 | | NULL | 79 | | 14978220 | root | 66.1.2.3:42926 | secphone | Sleep | 204 | | NULL | 80 | | 14978242 | root | 66.1.2.3:42954 | secphone | Sleep | 204 | | NULL | 81 | | 14978246 | root | 66.1.2.3:42964 | secphone | Sleep | 204 | | NULL | 82 | | 14978249 | root | 66.1.2.3:42968 | secphone | Sleep | 204 | | NULL | 83 | | 14978273 | root | 66.1.2.3:42996 | secphone | Sleep | 202 | | NULL | 84 | | 14978286 | root | 66.1.2.3:43026 | secphone | Sleep | 201 | | NULL | 85 | | 14978390 | root | localhost | secphone | Query | 0 | starting | show processlist | 86 | | 14978552 | root | 66.1.2.3:43478 | secphone | Sleep | 50 | | NULL | 87 | | 14978615 | root | 66.1.2.3:43554 | secphone | Sleep | 5 | | NULL | | 88 | +----------+------+----------------------+----------+---------+------+----------+------------------+ 89 | 72 rows in set (0.00 sec) 90 | ``` 91 | 92 | 为什么没有连接池? 93 | 94 | 可能是因为我的django没配置吧,加上配置: 95 | ``` 96 | DATABASES = { 97 | 'default': { 98 | 'ENGINE': 'django.db.backends.mysql', 99 | 'NAME': env('DB_DATABASE_NAME_KEY'), 100 | 'USER': env('DB_USER_KEY'), 101 | 'PASSWORD': env('DB_PASSWORD_KEY'), 102 | 'HOST': env('DB_HOST_KEY'), 103 | 'PORT': env('DB_PORT_KEY'), 104 | 'OPTIONS': {'charset': 'utf8mb4'}, 105 | "POOL_OPTIONS": { 106 | "POOL_SIZE": 15, 107 | "MAX_OVERFLOW": 5, 108 | "RECYCLE": 10 * 60 # 10 min, 109 | }, 110 | } 111 | } 112 | ``` 113 | 效果挺好的。 114 | -------------------------------------------------------------------------------- /nginx/ubuntu18.04新增 geoip 控制.md: -------------------------------------------------------------------------------- 1 | # 教程来源 2 | ``` 3 | https://guides.wp-bullet.com/blocking-country-and-continent-with-nginx-geoip-on-ubuntu-18-04/ 4 | ``` 5 | 6 | # 1 7 | ``` 8 | sudo apt-get install geoip-database-extra libgeoip1 libnginx-mod-http-geoip -y 9 | ``` 10 | 11 | # 2 12 | 避免编译了,牛逼。 13 | ``` 14 | cd /usr/share/GeoIP 15 | mv GeoIP.dat GeoIP.dat.bak 16 | wget https://dl.miyuru.lk/geoip/maxmind/country/maxmind.dat.gz 17 | gunzip maxmind.dat.gz 18 | mv maxmind.dat GeoIP.dat 19 | mv GeoIPCity.dat GeoIPCity.dat.bak 20 | wget https://dl.miyuru.lk/geoip/maxmind/city/maxmind.dat.gz 21 | gunzip maxmind.dat.gz 22 | mv maxmind.dat GeoIPCity.dat 23 | ``` 24 | 25 | # 3 26 | `http`配置块中: 27 | ``` 28 | geoip_country /usr/share/GeoIP/GeoIP.dat; 29 | geoip_city /usr/share/GeoIP/GeoIPCity.dat; 30 | ``` 31 | 比如: 32 | ``` 33 | #WP-Bullet.com nginx configuration 34 | user www-data; 35 | worker_processes auto; 36 | pid /run/nginx.pid; 37 | include /etc/nginx/modules-enabled/*.conf; 38 | 39 | events { 40 | worker_connections 768; 41 | multi_accept on; 42 | } 43 | 44 | http { 45 | # GeoIP databases 46 | geoip_country /usr/share/GeoIP/GeoIP.dat; 47 | geoip_city /usr/share/GeoIP/GeoIPCity.dat; 48 | ... 49 | 50 | ``` 51 | # 4 52 | 也配置到`http`块中: 53 | ``` 54 | # map the list of denied countries 55 | map $geoip_country_code $allowed_country { 56 | default yes; 57 | # Pakistan 58 | PK no; 59 | # Ukraine 60 | UA no; 61 | # Russia 62 | RU no; 63 | # China 64 | CN no; 65 | } 66 | ``` 67 | 68 | # 5 69 | 在自己的虚拟机配置中: 70 | ``` 71 | # block the country 72 | if ($allowed_country = no) { 73 | return 403; 74 | } 75 | ``` 76 | -------------------------------------------------------------------------------- /nginx/简单的配置.md: -------------------------------------------------------------------------------- 1 | 路径: 2 | ``` 3 | /etc/nginx/conf.d/haha.conf 4 | ``` 5 | 6 | 配置: 7 | ``` 8 | server { 9 | listen 80; 10 | server_name 1.2.3.4; 11 | 12 | if ($request_method = 'OPTIONS') { 13 | return 200; 14 | } 15 | client_max_body_size 100m; 16 | add_header 'Access-Control-Allow-Origin' '*' always; 17 | add_header 'Access-Control-Max-Age' '3600' always; 18 | add_header 'Access-Control-Allow-Methods' "POST, GET, OPTIONS, DELETE, PUT" always; 19 | add_header 'Access-Control-Allow-Headers' "Origin, X-Requested-With, Content-Type, Accept,timestamp,token,sign" always; 20 | add_header 'Access-Control-Allow-Credentials' 'true'; 21 | 22 | location /hs/ { 23 | # 4.后端反向代理 24 | proxy_pass http://127.0.0.1:9999/; 25 | 26 | } 27 | } 28 | ``` 29 | -------------------------------------------------------------------------------- /nginx/配置实战&https证书配置.md: -------------------------------------------------------------------------------- 1 | ## 链接 2 | [CSDN: 使用acme.sh给Nginx配置HTTPS证书](https://blog.csdn.net/aouoy/article/details/115748036) 3 | 4 | ## 0. nginx配置项目 5 | 新增配置文件 `cat /etc/nginx/conf.d/haha.conf`: 6 | ``` 7 | upstream myapp{ 8 | server 127.0.0.1:8000 weight=1; 9 | } 10 | 11 | server { 12 | listen 80; 13 | listen [::]:80; 14 | 15 | listen 443 ssl; 16 | 17 | server_name api.haha.xyz; 18 | 19 | client_max_body_size 20m; 20 | 21 | location ~* \.(html|gif|jpg|jpeg|png|css|js|ico)$ { 22 | root /root/www/haha/static/; 23 | } 24 | location /static/ { 25 | root /root/www/haha/; 26 | } 27 | 28 | location ~* ^/haha_api/ { 29 | proxy_set_header REMOTE_ADDR $proxy_add_x_forwarded_for; 30 | 31 | add_header Access-Control-Allow-Origin *; 32 | add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; 33 | add_header Access-Control-Allow-Headers 'DNT, X-Mx-ReqToken, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Authorization'; 34 | 35 | if ($request_method = 'OPTIONS') { 36 | return 204; 37 | } 38 | 39 | proxy_set_header Host $host:8000; 40 | proxy_set_header X-Real-IP $remote_addr; 41 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 42 | proxy_set_header Cookies $http_cookies; 43 | proxy_pass http://myapp; 44 | } 45 | } 46 | ``` 47 | 然后重启: 48 | ``` 49 | nginx -t 50 | nginx -s reload 51 | ``` 52 | 此时此刻,应该可以`curl http://api.haha.xyz` 53 | 54 | 55 | 56 | ## 1. 安装 acme.sh 57 | ``` 58 | curl https://get.acme.sh | sh 59 | source ~/.bashrc 60 | ``` 61 | 设置为自动更新 62 | ``` 63 | acme.sh --upgrade --auto-upgrade 64 | ``` 65 | 66 | ## 2. 生成证书 67 | 68 | 安装命令 69 | ``` 70 | acme.sh --issue -d 域名 --nginx /usr/local/nginx/conf/conf.d/域名配置 71 | ``` 72 | 比如: 73 | ``` 74 | acme.sh --issue -d api.haha.xyz --nginx /etc/nginx/conf.d/haha.conf 75 | ``` 76 | 77 | 它安装完毕后,会输出: 78 | ``` 79 | -----END CERTIFICATE----- 80 | [Wed Nov 23 07:33:58 UTC 2022] Your cert is in: /root/.acme.sh/api.haha.xyz/api.haha.xyz.cer 81 | [Wed Nov 23 07:33:58 UTC 2022] Your cert key is in: /root/.acme.sh/api.haha.xyz/api.haha.xyz.key 82 | [Wed Nov 23 07:33:58 UTC 2022] The intermediate CA cert is in: /root/.acme.sh/api.haha.xyz/ca.cer 83 | [Wed Nov 23 07:33:58 UTC 2022] And the full chain certs is there: /root/.acme.sh/api.haha.xyz/fullchain.cer 84 | [Wed Nov 23 07:33:58 UTC 2022] Installing key to: /root/.acme.sh/api.haha.xyz/api.haha.xyz.key 85 | [Wed Nov 23 07:33:58 UTC 2022] Installing full chain to: /root/.acme.sh/api.haha.xyz/fullchain.cer 86 | [Wed Nov 23 07:33:58 UTC 2022] Run reload cmd: nginx -s reload 87 | [Wed Nov 23 07:33:58 UTC 2022] Reload success 88 | ``` 89 | 90 | 91 | ## 3. copy/安装 证书 92 | 安装命令 93 | ``` 94 | acme.sh --install-cert -d 域名 \ 95 | --key-file 域名证书key \ 96 | --fullchain-file 域名证书cert \ 97 | --reloadcmd "nginx -s reload" 98 | ``` 99 | 例如: 100 | ``` 101 | acme.sh --install-cert -d api.haha.xyz 102 | --key-file /root/.acme.sh/api.haha.xyz/api.haha.xyz.key 103 | --fullchain-file /root/.acme.sh/api.haha.xyz/fullchain.cer 104 | --reloadcmd "nginx -s reload" 105 | ``` 106 | 107 | 108 | ## 4. Nginx添加https配置 109 | 修改/etc/nginx/conf.d/haha.conf, 添加这一段: 110 | ``` 111 | ssl_certificate /root/.acme.sh/api.haha.xyz/fullchain.cer; 112 | ssl_certificate_key /root/.acme.sh/api.haha.xyz/api.haha.xyz.key; 113 | ssl_session_timeout 5m; 114 | ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; 115 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 116 | ssl_prefer_server_ciphers on; 117 | ``` 118 | 总的配置: 119 | ``` 120 | upstream myapp{ 121 | server 127.0.0.1:8000 weight=1; 122 | } 123 | 124 | server { 125 | listen 80; 126 | listen [::]:80; 127 | 128 | listen 443 ssl; 129 | 130 | server_name api.haha.xyz; 131 | 132 | ssl_certificate /root/.acme.sh/api.haha.xyz/fullchain.cer; 133 | ssl_certificate_key /root/.acme.sh/api.haha.xyz/api.haha.xyz.key; 134 | ssl_session_timeout 5m; 135 | ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; 136 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 137 | ssl_prefer_server_ciphers on; 138 | 139 | client_max_body_size 20m; 140 | 141 | location ~* \.(html|gif|jpg|jpeg|png|css|js|ico)$ { 142 | root /root/www/haha/static/; 143 | } 144 | location /static/ { 145 | root /root/www/haha/; 146 | } 147 | 148 | location ~* ^/haha_api/ { 149 | proxy_set_header REMOTE_ADDR $proxy_add_x_forwarded_for; 150 | 151 | add_header Access-Control-Allow-Origin *; 152 | add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; 153 | add_header Access-Control-Allow-Headers 'DNT, X-Mx-ReqToken, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Authorization'; 154 | 155 | if ($request_method = 'OPTIONS') { 156 | return 204; 157 | } 158 | 159 | proxy_set_header Host $host:8000; 160 | proxy_set_header X-Real-IP $remote_addr; 161 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 162 | proxy_set_header Cookies $http_cookies; 163 | proxy_pass http://myapp; 164 | } 165 | } 166 | ``` 167 | ps: 168 | ``` 169 | 这里的key-file路径对应到Nginx配置的ssl_certificate_key路径,fullchain-file路径对应到Nginx配置的ssl_certificate路径。 170 | ``` 171 | 重启Nginx使https配置生效 172 | ``` 173 | nginx -t 174 | nginx -s reload 175 | ``` 176 | 177 | ## 5. 撤销和强制更新证书 178 | 强制更新证书 `acme.sh --renew -f -d 域名`,如: 179 | ``` 180 | acme.sh --renew -f -d api.haha.xyz 181 | ``` 182 | 183 | 撤销证书 `acme.sh --renew -f -d 域名`,如: 184 | ``` 185 | acme.sh --revoke -d api.haha.xyz 186 | ``` 187 | -------------------------------------------------------------------------------- /ssl/CA机构在干嘛.md: -------------------------------------------------------------------------------- 1 | # 去 CA 机构在申请证书步骤: 2 | 3 | 第一步: 4 | ``` 5 | 生成客户端的密钥,即客户端的公私钥对,且要保证私钥只有客户端自己拥有。 6 | ``` 7 | 8 | 第二步: 9 | ``` 10 | 以客户端的密钥和客户端自身的信息(国家、机构、域名、邮箱等)为输入,生成证书请求文件。 11 | ps: 12 | * 其中客户端的公钥和客户端信息是明文保存在证书请求文件中的 13 | * 而客户端私钥的作用是对客户端公钥及客户端信息做签名,自身是不包含在证书请求中的。 14 | 然后把证书请求文件发送给CA机构。 15 | ``` 16 | 17 | 第三步: 18 | ``` 19 | CA机构接收到客户端的证书请求文件后,首先校验其签名,然后审核客户端的信息。 20 | 21 | 最后CA机构使用自己的私钥为证书请求文件签名,生成证书文件,下发给客户端。 22 | 23 | 此证书就是客户端的身份证,来表明用户的身份。至此客户端申请证书流程结束。 24 | ``` 25 | 26 | # 证书怎么用 27 | 其中涉及到证书签发机构CA,CA是被绝对信任的机构。如果把客户端证书比作用户身份证,那么CA就是颁发身份证的机构,我们以https为例说明证书的用处。 28 | 29 | 为了数据传输安全,越来越多的网站启用https。 30 | * 1、在https握手阶段,服务器首先把自己的证书发送给用户(浏览器); 31 | * 2、浏览器查看证书中的发证机构,然后在机器内置的证书中(在PC或者手机上,内置了世界上著名的CA机构的证书)查找对应CA证书; 32 | * 3、然后使用内置的证书公钥校验服务器的证书真伪; 33 | * 4、如果校验失败,浏览器会提示服务器证书有问题,询问用户是否继续。 34 | 35 | 例如12306网站,它使用的自签名的证书,所以浏览器会提示证书有问题,在12306的网站上有提示下载安装根证书,其用户就是把自己的根证书安装到用户机器的内置证书中,这样浏览器就不会报证书错误。但是注意,除非特别相信某个机构,否则不要在机器上随便导入证书,很危险。 36 | -------------------------------------------------------------------------------- /ssl/acme.sh创建ssl证书.md: -------------------------------------------------------------------------------- 1 | 中文教程: 2 | ``` 3 | https://www.cnblogs.com/clsn/p/10040334.html#12-acmesh 4 | ``` 5 | 英文教程: 6 | ``` 7 | https://github.com/acmesh-official/acme.sh 8 | ``` 9 | 写在前面1: 10 | ``` 11 | 如果要搞 ssl 证书,前提是 DNS 已经配置好了映射。 12 | ``` 13 | 写在前面2: 14 | ``` 15 | 在用 acme 命令前,nginx 不要提前配置 443 端口!! 16 | 在用 acme 命令前,nginx 不要提前配置 443 端口!! 17 | 在用 acme 命令前,nginx 不要提前配置 443 端口!! 18 | ``` 19 | 20 | 安装脚本: 21 | ``` 22 | curl https://get.acme.sh | sh 23 | 24 | alias acme.sh=~/.acme.sh/acme.sh 25 | echo 'alias acme.sh=~/.acme.sh/acme.sh' >>/etc/profile 26 | ``` 27 | 28 | 如果下面执行命令的时候,遇到这个错误,还要申请账号: 29 | ``` 30 | [Thu Feb 2 06:37:13 UTC 2023] acme.sh is using ZeroSSL as default CA now. 31 | [Thu Feb 2 06:37:13 UTC 2023] Please update your account with an email address first. 32 | [Thu Feb 2 06:37:13 UTC 2023] acme.sh --register-account -m my@example.com 33 | [Thu Feb 2 06:37:13 UTC 2023] See: https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA 34 | [Thu Feb 2 06:37:13 UTC 2023] _on_issue_err 35 | [Thu Feb 2 06:37:13 UTC 2023] Please add '--debug' or '--log' to check more details. 36 | [Thu Feb 2 06:37:13 UTC 2023] See: https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh 37 | [Thu Feb 2 06:37:13 UTC 2023] socat doesn't exist. 38 | 39 | 40 | acme.sh --register-account -m my@example.com 41 | ``` 42 | 43 | 44 | 第一次申请证书,让我们弄个账户: 45 | ``` 46 | root@shell:~/.acme.sh# acme.sh --issue -d api.abc.xyz --nginx 47 | [Sun Dec 5 13:53:44 UTC 2021] Using CA: https://acme.zerossl.com/v2/DX12130 48 | [Sun Dec 5 13:53:45 UTC 2021] No EAB credentials found for ZeroSSL, let's get one 49 | [Sun Dec 5 13:53:45 UTC 2021] acme.sh is using ZeroSSL as default CA now. 50 | [Sun Dec 5 13:53:45 UTC 2021] Please update your account with an email address first. 51 | [Sun Dec 5 13:53:45 UTC 2021] acme.sh --register-account -m my@example.com 52 | [Sun Dec 5 13:53:45 UTC 2021] See: https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA 53 | [Sun Dec 5 13:53:45 UTC 2021] Please add '--debug' or '--log' to check more details. 54 | [Sun Dec 5 13:53:45 UTC 2021] See: https://github.com/acmesh-official/acme.sh/wiki/How-to-debug-acme.sh 55 | root@shell:~/.acme.sh# acme.sh --register-account -m 123@qq.com 56 | [Sun Dec 5 13:54:38 UTC 2021] No EAB credentials found for ZeroSSL, let's get one 57 | [Sun Dec 5 13:54:39 UTC 2021] Registering account: https://acme.zerossl.com/v2/DV9110 58 | [Sun Dec 5 13:54:40 UTC 2021] Registered 59 | [Sun Dec 5 13:54:40 UTC 2021] ACCOUNT_THUMBPRINT='FAKEADAGqDrC4-cVtNVS12312312EIxB_K12Nee2m75k74Ys598' 60 | ``` 61 | 62 | 第二次申请证书: 63 | ``` 64 | root@shell:~/.acme.sh# acme.sh --issue -d api.abc.xyz --nginx 65 | [Sun Dec 5 13:55:08 UTC 2021] Using CA: https://acme.zerossl.com/v2/DX12130 66 | [Sun Dec 5 13:55:08 UTC 2021] Single domain='api.abc.xyz' 67 | [Sun Dec 5 13:55:08 UTC 2021] Getting domain auth token for each domain 68 | [Sun Dec 5 13:55:11 UTC 2021] Getting webroot for domain='api.abc.xyz' 69 | [Sun Dec 5 13:55:11 UTC 2021] Verifying: api.abc.xyz 70 | [Sun Dec 5 13:55:11 UTC 2021] Nginx mode for domain:api.abc.xyz 71 | [Sun Dec 5 13:55:11 UTC 2021] Found conf file: /etc/nginx/conf.d/abc.conf 72 | [Sun Dec 5 13:55:11 UTC 2021] Backup /etc/nginx/conf.d/abc.conf to /root/.acme.sh/api.abc.xyz/backup/api.abc.xyz.nginx.conf 73 | [Sun Dec 5 13:55:11 UTC 2021] Check the nginx conf before setting up. 74 | [Sun Dec 5 13:55:11 UTC 2021] OK, Set up nginx config file 75 | [Sun Dec 5 13:55:11 UTC 2021] nginx conf is done, let's check it again. 76 | [Sun Dec 5 13:55:11 UTC 2021] Reload nginx 77 | [Sun Dec 5 13:55:15 UTC 2021] Processing, The CA is processing your order, please just wait. (1/30) 78 | [Sun Dec 5 13:55:18 UTC 2021] Success 79 | [Sun Dec 5 13:55:18 UTC 2021] Restoring from /root/.acme.sh/api.abc.xyz/backup/api.abc.xyz.nginx.conf to /etc/nginx/conf.d/abc.conf 80 | [Sun Dec 5 13:55:18 UTC 2021] Reload nginx 81 | [Sun Dec 5 13:55:18 UTC 2021] Verify finished, start to sign. 82 | [Sun Dec 5 13:55:18 UTC 2021] Lets finalize the order. 83 | [Sun Dec 5 13:55:18 UTC 2021] Le_OrderFinalize='https://acme.zerossl.com/v2/DX12130/order/gts9RFHAw1NVcKq-pPuvWQ/finalize' 84 | [Sun Dec 5 13:55:19 UTC 2021] Order status is processing, lets sleep and retry. 85 | [Sun Dec 5 13:55:19 UTC 2021] Retry after: 15 86 | [Sun Dec 5 13:55:35 UTC 2021] Polling order status: https://acme.zerossl.com/v2/DX12130/order/gts9RFHAw1NVcKq-pPuvWQ 87 | [Sun Dec 5 13:55:36 UTC 2021] Downloading cert. 88 | [Sun Dec 5 13:55:36 UTC 2021] Le_LinkCert='https://acme.zerossl.com/v2/DX12130/cert/WMqtmDy-VVk8BDzXCySFjw' 89 | [Sun Dec 5 13:55:37 UTC 2021] Cert success. 90 | -----BEGIN CERTIFICATE----- 91 | MIIGcjCCBFqgAwIBAgIQXKNAHmgaZMUUSS4BvexcpDANBgkqhkiG9w0BAQwFADBL 92 | MQswCQYDVQQGEwJBVDEQMA4GA1UEChMHWmVyb1NTTDEqMCgGA1UEAxMhWmVyb1NT 93 | TCBSU0EgRG9tYWluIFNlY3VyZSBTaXRlIENBMB4XDTIxMTIwNTAwMDAwMFoXDTIy 94 | MDMwNTIzNTk1OVowHTEbMBkGA1UEAxMSYXBpLnZpcnR1YWxzaW0ueHl6MIIBIjAN 95 | BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw8LM35PqIxqm2UIXtBTtG+3Jb03O 96 | WtFFjlUpnXGKjydhZs69ALXqN4acpSdYzDhC8TrofpvL9Th2GzYLeJktfnOFfSwm 97 | hfGtbTzsk4Qd+d7L1AO4+wDyt6r6ZRZR/g/u6fLxWUouChJEu3q/CHQnGTZ3kolH 98 | uqb+f6z/psrUElUJcXolQFJjlGE9xx4NlOqZswrdOY/M2ssr0Do7OOxKh8Ui1sX3 99 | ojKAoqhTk6EH3IPg+59fZ7RdOG/IPkoALiozP/b0U/SA6vpzPab13iyymp0YMzMw 100 | X1WaOt5CU2UsTMeEY6ou7hsf9iZ4HA== 101 | -----END CERTIFICATE----- 102 | [Sun Dec 5 13:55:37 UTC 2021] Your cert is in: /root/.acme.sh/api.abc.xyz/api.abc.xyz.cer 103 | [Sun Dec 5 13:55:37 UTC 2021] Your cert key is in: /root/.acme.sh/api.abc.xyz/api.abc.xyz.key 104 | [Sun Dec 5 13:55:37 UTC 2021] The intermediate CA cert is in: /root/.acme.sh/api.abc.xyz/ca.cer 105 | [Sun Dec 5 13:55:37 UTC 2021] And the full chain certs is there: /root/.acme.sh/api.abc.xyz/fullchain.cer 106 | ``` 107 | 检查下: 108 | ``` 109 | root@shell:~/.acme.sh# 110 | root@shell:~/.acme.sh# "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" 111 | [Sun Dec 5 13:59:57 UTC 2021] ===Starting cron=== 112 | [Sun Dec 5 13:59:57 UTC 2021] Already uptodate! 113 | [Sun Dec 5 13:59:57 UTC 2021] Upgrade success! 114 | [Sun Dec 5 13:59:57 UTC 2021] Auto upgraded to: 3.0.2 115 | [Sun Dec 5 13:59:57 UTC 2021] Renew: 'api.abc.xyz' 116 | [Sun Dec 5 13:59:57 UTC 2021] Skip, Next renewal time is: Thu Feb 3 13:55:37 UTC 2022 117 | [Sun Dec 5 13:59:57 UTC 2021] Add '--force' to force to renew. 118 | [Sun Dec 5 13:59:57 UTC 2021] Skipped api.abc.xyz 119 | [Sun Dec 5 13:59:57 UTC 2021] Renew: 'abc.xyz' 120 | [Sun Dec 5 13:59:57 UTC 2021] Skip invalid cert for: abc.xyz 121 | [Sun Dec 5 13:59:57 UTC 2021] Skipped abc.xyz 122 | [Sun Dec 5 13:59:57 UTC 2021] ===End cron=== 123 | ``` 124 | 125 | 然后nginx配置好路径: 126 | ``` 127 | server { 128 | listen 443; 129 | listen [::]:443; 130 | 131 | server_name api.abc.xyz; 132 | ssl on; 133 | root html; 134 | index index.html index.htm; 135 | #ssl_certificate /etc/nginx/ssl/api.abc.xyz/fullchain.cer; 136 | #ssl_certificate_key /etc/nginx/ssl/api.abc.xyz/api.abc.xyz.key; 137 | ssl_certificate /root/.acme.sh/api.abc.xyz/api.abc.xyz.cer; 138 | ssl_certificate_key /root/.acme.sh/api.abc.xyz/api.abc.xyz.key; 139 | ssl_session_timeout 5m; 140 | ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; 141 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 142 | ssl_prefer_server_ciphers on; 143 | 144 | client_max_body_size 20m; 145 | 146 | location ~* \.(html|gif|jpg|jpeg|png|css|js|ico)$ { 147 | root /root/www/Abc_BackEnd/static/; 148 | } 149 | location /static/ { 150 | root /root/www/Abc_BackEnd/; 151 | } 152 | 153 | location ~* ^/(user|config|report)/ { 154 | add_header Access-Control-Allow-Origin *; 155 | add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; 156 | add_header Access-Control-Allow-Headers 'DNT, X-Mx-ReqToken, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Authorization'; 157 | 158 | if ($request_method = 'OPTIONS') { 159 | return 204; 160 | } 161 | 162 | proxy_set_header Host $host:8000; 163 | proxy_set_header X-Real-IP $remote_addr; 164 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 165 | proxy_set_header Cookies $http_cookies; 166 | proxy_pass http://myapp; 167 | } 168 | } 169 | 170 | 171 | ``` 172 | 173 | 如果想换证书位置: 174 | ``` 175 | acme.sh --installcert -d api.abc.xyz \ 176 | --key-file /etc/nginx/ssl/api.abc.xyz/api.abc.xyz.key \ 177 | --fullchain-file /etc/nginx/ssl/api.abc.xyz/fullchain.cer \ 178 | --reloadcmd "service nginx force-reload" 179 | ``` 180 | -------------------------------------------------------------------------------- /ssl/openssl入门.md: -------------------------------------------------------------------------------- 1 | 2 | ## OpenSSL 组件: 3 | 4 | * libcrypto, libssl主要由开发者使用 5 | * openssl:多用途命令行工具 6 | * 标准命令 7 | * 生成用户密码 8 | * openssl passwd -1 -salt SALT 9 | * 生成随机数 10 | * openssl rand -hex NUM 11 | * openssl rand -base NUM 12 | * 消息摘要命令(dgst子命令) 13 | * 加密命令(enc子命令) 14 | * 对称加密: 15 | * `openssl enc -e -des3 -a -salt -in fstab -out fstab.ciphertext 16 | * -e 选择加密算法,可以选:3des, aes, blowfish, towfish 17 | * -a 采用base64编码 18 | * -salt 往文件加盐,自动插入一个随机数作为文件内容加密 19 | * -in 输入文件 20 | * -out 输出文件 21 | * 单向加密: 22 | * openssl dgst -md5 /PATH/TO/SOMEFILE 23 | * -md5 to use the md5 message digest algorithm 用于签名 24 | * 公钥加密 25 | * 加密解密 26 | * openssl rsautl, gpg 27 | * 生成私钥 28 | * 无加密:openssl genrsa -out rsa_private_20220823.key 2048 29 | * 有加密:openssl genrsa -aes256 -passout pass:111111 -out rsa_aes_private_20220823_withpwd.key 2048 30 | * 私钥转非加密:openssl rsa -in rsa_aes_private_20220823_withpwd.key -passin pass:111111 -out 31 | rsa_aes_private_20220823_withoutpwd.key 32 | * 私钥转加密:openssl rsa -in rsa_aes_private_20220823_withoutpwd.key -aes256 -passout pass:111111 33 | -out rsa_aes_private_20220823_withpwd.key 34 | * 根据私钥生成公钥 35 | * 无加密:openssl rsa -in rsa_private_20220823.key -pubout -out rsa_public_20220823.key 36 | * 有加密:openssl rsa -in rsa_aes_private_20220823_withpwd.key -passin pass:111111 -pubout -out 37 | rsa_public_20220823_withpwd.key 38 | * 数字签名 39 | * openssl rsautl, gpg 40 | * 密钥交换 41 | * 生成密钥 42 | * (umask 077; openssl genrsa -out /PATH/TO/PRIVATE_KEY_FILE NUM_BITS) 43 | * 提出公钥 44 | * openssl rsa -in /PATH/FROM/PRIVATE_KEY_FILE -pubout 45 | * 证书相互转换 46 | * PEM to DER 47 | * openssl x509 -outform der -in certificate.pem -out certificate.der 48 | * PEM to PFX 49 | * openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile CACert.crt 50 | * DER to PEM 51 | * openssl x509 -inform der -in certificate.cer -out certificate.pem 52 | * PFX to PEM 53 | * openssl pkcs12 -in certificate.pfx -out certificate.cer -nodes 54 | -------------------------------------------------------------------------------- /ssl/openssl生成证书.md: -------------------------------------------------------------------------------- 1 | ## 生成私钥 2 | ``` 3 | openssl genrsa -des3 -out privkey.pem 2048 4 | ``` 5 | 需要输入密码哦,也可以不要密码: 6 | ``` 7 | openssl genrsa -out privkey.pem 2048 8 | ``` 9 | 10 | ## 根据私钥生成csr 11 | ``` 12 | openssl req -new -key privkey.pem -out cert.csr 13 | ``` 14 | 这里要填什么国家、省份等基础信息,毕竟 CA 机构要看的。。。 15 | ``` 16 | Country Name (2 letter code) [AU]: 17 | State or Province Name (full name) [Some-State]: 18 | Locality Name (eg, city) []: 19 | Organization Name (eg, company) [Internet Widgits Pty Ltd]: 20 | Organizational Unit Name (eg, section) []: 21 | Common Name (e.g. server FQDN or YOUR name) []: 22 | Email Address []: 23 | ``` 24 | 25 | ## CA 机构生成证书 26 | 然后拿着这个`cert.csr` 即一个证书请求文件,你可以拿着这个文件去数字证书颁发机构(即CA)申请一个数字证书。CA会给你一个新的文件cacert.pem,那才是你的数字证书。 27 | 28 | ## 不想去 CA 机构 29 | 如果是自己做测试,那么证书的申请机构和颁发机构都是自己。就可以用下面这个命令来生成证书: 30 | ``` 31 | openssl req -new -x509 -key privkey.pem -out cacert.pem -days 3650 32 | ``` 33 | 输入密码后,输入国家省份邮箱等信息。 34 | 35 | 36 | ## 不想去 CA 机构还想一步到位 37 | 如果还想更简单的生成私钥和证书: 38 | ``` 39 | openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout privkey.pem -out cacert.pem -days 3650 40 | ``` 41 | 42 | 43 | 参数说明: 44 | * req是证书请求的子命令 45 | * -newkey rsa:2048 -keyout private_key.pem 表示生成私钥(PKCS8格式); 46 | * -nodes 表示私钥不加密,若不带参数将提示输入密码; 47 | * -x509表示输出证书; 48 | * -days 3650 为有效期,此后根据提示输入证书拥有者信息; 49 | * 若执行自动输入,可使用-subj选项: 50 | 51 | 参数集合: 52 | ``` 53 | Usage: req [options] 54 | Valid options are: 55 | -help Display this summary 56 | -inform PEM|DER Input format - DER or PEM 57 | -outform PEM|DER Output format - DER or PEM 58 | -in infile Input file 59 | -out outfile Output file 60 | -key val Private key to use 61 | -keyform format Key file format 62 | -pubkey Output public key 63 | -new New request 64 | -config infile Request template file 65 | -keyout outfile File to send the key to 66 | -passin val Private key password source 67 | -passout val Output file pass phrase source 68 | -rand val Load the file(s) into the random number generator 69 | -writerand outfile Write random data to the specified file 70 | -newkey val Specify as type:bits 71 | -pkeyopt val Public key options as opt:value 72 | -sigopt val Signature parameter in n:v form 73 | -batch Do not ask anything during request generation 74 | -newhdr Output "NEW" in the header lines 75 | -modulus RSA modulus 76 | -verify Verify signature on REQ 77 | -nodes Don't encrypt the output key 78 | -noout Do not output REQ 79 | -verbose Verbose output 80 | -utf8 Input characters are UTF8 (default ASCII) 81 | -nameopt val Various certificate name options 82 | -reqopt val Various request text options 83 | -text Text form of request 84 | -x509 Output a x509 structure instead of a cert request 85 | (Required by some CA's) 86 | -subj val Set or modify request subject 87 | -subject Output the request's subject 88 | -multivalue-rdn Enable support for multivalued RDNs 89 | -days +int Number of days cert is valid for 90 | -set_serial val Serial number to use 91 | -addext val Additional cert extension key=value pair (may be given more than once) 92 | -extensions val Cert extension section (override value in config file) 93 | -reqexts val Request extension section (override value in config file) 94 | -precert Add a poison extension (implies -new) 95 | -* Any supported digest 96 | -engine val Use engine, possibly a hardware device 97 | -keygen_engine val Specify engine to be used for key generation operations 98 | ``` 99 | -------------------------------------------------------------------------------- /ssl/ssl入门.md: -------------------------------------------------------------------------------- 1 | ## SSL会话主要三步: 2 | 3 | ```commandline 4 | ①客户端向服务器端索要并验正证书; 5 | ②双方协商生成“会话密钥”; 6 | ③双方采用“会话密钥”进行加密通信; 7 | ``` 8 | 9 | ## SSL 握手协议 Handshake Protocol: 10 | 11 | ```commandline 12 | 第一阶段:ClientHello 13 | 支持的协议版本,比如tls 1.2; 14 | 客户端生成一个随机数,稍后用户生成“会话密钥” 15 | 支持的加密算法,比如AES、3DES、RSA; 16 | 支持的压缩算法; 17 | 18 | 第二阶段:ServerHello 19 | 确认使用的加密通信协议版本,比如tls 1.2; 20 | 服务器端生成一个随机数,稍后用于生成“会话密钥” 21 | 确认使用的加密方法; 22 | 服务器证书; 23 | 24 | 第三阶段 25 | 验正服务器证书,在确认无误后取出其公钥;(发证机构、证书完整性、证书持有者、证书有效期、吊销列表) 26 | 发送以下信息给服务器端: 27 | 编码变更通知,表示随后的信息都将用双方商定的加密方法和密钥发送; 28 | 客户端握手结束通知; 29 | 30 | 第四阶段 31 | 收到客户端发来的第三个随机数pre-master-key后,计算生成本次会话所有到的“会话密钥”; 32 | 向客户端发送如下信息: 33 | 编码变更通知,表示随后的信息都将用双方商定的加密方法和密钥发送; 34 | 服务端握手结束通知; 35 | ``` 36 | 37 | ## 什么是CSR ? 什么是公钥和私钥? 38 | 39 | * CSR 40 | * 含义 41 | * Certificate Signing Request的英文缩写,即证书请求文件 42 | * 背景 43 | * 我们想要证明我们的网站是可信的,数据传输是加密的,我们就需要由第三方CA机构颁发的证书来证明,比如Symantec,GeoTrust等等。 44 | * 申请证书步骤 45 | * 1、想要申请这样的证书,我们的第一步就是需要生成我们自己的CSR文件。 46 | * 2、CSR需要由申请人提供域名、公司名称、部门、省份、城市、国家借助相关工具(`比如openssl`)生成。 47 | * 3、工具同时会生成`证书请求文件`和`私钥文件`,其中的证书请求文件就是CSR文件,这两个文件是相互匹配的。 48 | * 4、我们将CSR文件提交给CA申请证书,经过CA身份对申请者身份进行审核后,颁发`证书公钥`。 49 | * 5、申请人收到证书文件后,将证书公钥文件配合私钥文件转化成服务器对应的格式的文件部署在HTTP服务器上面。 50 | 51 | ## CA 证书的分类 52 | 53 | * 证书 54 | * 有些证书将以`合并形式`出现。其中一个文件可以`包含以下任何一个`:证书,私钥,公钥,签名证书,证书颁发机构(CA)和/或授权链。 55 | * 后缀: 56 | * .DER:用二进制DER编码的证书; 57 | * .PEM:用ASCLL(BASE64)编码的证书; 58 | * .CER:存放公钥,没有私钥; 59 | * .PFX:存放公钥和私钥,.pfx 主要用于windows平台,浏览器可以使用,也是包含证书和私钥,获取私钥需要密码才可以 60 | * 编码 61 | * PEM = PEM扩展名用于不同类型的X.509v3文件,这些文件包含前缀为“-BEGIN ...”行的ASCII(Base64)装载数据。 62 | * X509文件扩展名(x509 这种证书只有公钥,不包含私钥。) 63 | * DER 64 | * DER扩展用于二进制DER编码证书。这些文件也可能带有CER或CRT扩展名。 65 | * 正确的英语用法是“我有DER编码证书”而不是“我有DER证书”。 66 | * 组合 67 | * 在某些情况下,将多个X.509基础结构组合成单个文件是有利的。一个常见的例子是将私钥和公钥组合到同一个证书中。 68 | * 组合证书密钥和链的最简单方法是将每个密钥转换为PEM编码证书,然后将每个文件的内容简单复制到新文件中。这适用于组合文件以在Apache应用程序中使用。 69 | * 萃取 70 | * 有些证书将以合并形式出现。其中一个文件可以包含以下任何一个:证书,私钥,公钥,签名证书,证书颁发机构(CA)和/或授权链。 71 | 72 | ## pem文件和key文件的区别? 73 | 74 | * PEM 75 | * 含义:用ASCLL(BASE64)编码的证书; 76 | * 存储的是证书base64加密+分隔符,也就是说pem存的是证书; 77 | * PEM格式通常用于数字证书认证机构(Certificate Authorities,CA),扩展名为.pem, .crt, .cer, and .key; 78 | * 内容为Base64编码的ASCII码文件,有类似"-----BEGIN CERTIFICATE-----" 和 "-----END CERTIFICATE-----"的头尾标记; 79 | * 服务器认证证书,中级认证证书和私钥都可以储存为PEM格式(认证证书其实就是公钥)。 80 | * Apache和类似的服务器使用PEM格式证书。 81 | * KEY 82 | * 私钥base64加密还有格式+分割符,key 存的是私钥 83 | -------------------------------------------------------------------------------- /zk/ubuntu安装zk3.4.13.md: -------------------------------------------------------------------------------- 1 | # 原文链接 2 | [https://juejin.cn/post/6844903924172849166](https://juejin.cn/post/6844903924172849166) 3 | 4 | # 安装 jdk 5 | ``` 6 | sudo apt-get install openjdk-8-jre 7 | ``` 8 | 9 | # 下载 10 | ``` 11 | wget https://archive.apache.org/dist/zookeeper/zookeeper-3.4.13/zookeeper-3.4.13.tar.gz 12 | ``` 13 | 解压: 14 | ``` 15 | tar -xvf zookeeper-3.4.13.tar.gz 16 | ``` 17 | 18 | # 找个好位置 19 | ``` 20 | mv zookeeper-3.4.13 /usr/local/zookeeper/zookeeper-3.4.13 21 | ``` 22 | 创建软链接(方便更换版本): 23 | ``` 24 | ln -s /usr/local/zookeeper/zookeeper-3.4.13 /usr/local/zookeeper/apache-zookeeper 25 | ``` 26 | 27 | # 加到 path 28 | vi ~/.zshrc 29 | ``` 30 | export ZK_HOME=/usr/local/zookeeper/apache-zookeeper 31 | export PATH=$ZK_HOME/bin:$PATH 32 | ``` 33 | 生效: 34 | ``` 35 | source ~/.zshrc 36 | ``` 37 | -------------------------------------------------------------------------------- /乱码/ubuntu18.04vim中文乱码.md: -------------------------------------------------------------------------------- 1 | 先解决vim中文乱码问题: 2 | ``` 3 | cat ~/.vimrc root@gateway 08:30:11 4 | set fileencodings=ucs-bom,utf-8,utf-16,gbk,big5,gb18030,latin1 5 | set fileencoding=utf-8 6 | ``` 7 | -------------------------------------------------------------------------------- /乱码/ubuntu18.04vim中文乱码解决.md: -------------------------------------------------------------------------------- 1 | 编辑vim的配置文件vimrc,在最后添加 三行 2 | ``` 3 | set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936 4 | set termencoding=utf-8 5 | set encoding=utf-8 6 | ``` 7 | 8 | 我们的路径是: 9 | ``` 10 | /etc/vim/vimrc 11 | ``` 12 | 有些系统路径是: 13 | ``` 14 | /etc/vimrc 15 | ``` 16 | 有些是: 17 | ``` 18 | ~/.vimrc 19 | ``` 20 | -------------------------------------------------------------------------------- /乱码/ubuntu18.04修改python3默认编码为utf8.md: -------------------------------------------------------------------------------- 1 | # 问题 2 | 不知道为啥,python3 的默认编码是 latin,导致我的脚本报错: 3 | ``` 4 | print(f"\u6ca1\u6709\u4e70\u53f7\uff01\uff01") 5 | UnicodeEncodeError: 'latin-1' codec can't encode characters in position 0-5: ordinal not in range(256) 6 | ``` 7 | 8 | # 解决 9 | ``` 10 | root@shell: export PYTHONIOENCODING=utf-8 11 | ``` 12 | 13 | # crontab不服气 14 | 发现虽然用shell执行python脚本已经没问题了,但是crontab依旧报错,解决方案是加上编码集: 15 | 先查看自己的编码: 16 | ``` 17 | echo $LANG 18 | ``` 19 | 然后crontab -e: 20 | ``` 21 | 55 7 * * * LANG=en_US.UTF-8 /usr/bin/python3 /shell/python1.py >>/tmp/python1.log 2>&1 22 | ``` 23 | -------------------------------------------------------------------------------- /乱码/ubuntu18.04设置vim中文编码.md: -------------------------------------------------------------------------------- 1 | # 背景 2 | 某些 ubuntu18.04 竟然 vim 下中文乱码,难以理解。 3 | 4 | # 解决 5 | ``` 6 | vi ~/.vimrc 7 | 8 | 9 | """""""""""""""""""""""""""""""""""" 10 | """=>编码设置<=""" 11 | """""""""""""""""""""""""""""""""""" 12 | "设置编码" 13 | set encoding=utf-8 14 | set fencs=utf-8,ucs-bom,shift-jis,gb18030,gbk,gb2312,cp936 15 | 16 | "设置文件编码" 17 | set fileencodings=utf-8 18 | 19 | "设置终端编码" 20 | set termencoding=utf-8 21 | 22 | "设置语言编码" 23 | set langmenu=zh_CN.UTF-8 24 | set helplang=cn 25 | ``` 26 | 27 | 或者暂时不要中文注释,因为你本来就中文乱码: 28 | ``` 29 | vi ~/.vimrc 30 | 31 | set encoding=utf-8 32 | set fencs=utf-8,ucs-bom,shift-jis,gb18030,gbk,gb2312,cp936 33 | set fileencodings=utf-8 34 | set termencoding=utf-8 35 | set langmenu=zh_CN.UTF-8 36 | set helplang=cn 37 | ``` 38 | -------------------------------------------------------------------------------- /奇技淫巧/切割文件.md: -------------------------------------------------------------------------------- 1 | ``` 2 | split -d -b 500m G_WIN10_X64_V2022JF.iso 3 | ``` 4 | 我服务器是1C1GB,基本上内存没涨,CPU 20%, 持续1分钟。 5 | -------------------------------------------------------------------------------- /奇技淫巧/生成大文件.md: -------------------------------------------------------------------------------- 1 | 生成20M的里面全是随机数的文件,文件名叫`randomfile`: 2 | ``` 3 | dd if=/dev/urandom of=randomfile bs=1M count=20 4 | ``` 5 | 6 | 生成20M的里面全是0的文件,文件名叫`zerofile`: 7 | ``` 8 | dd if=/dev/zero of=zerofil bs=1M count=20 9 | ``` 10 | 11 | 这个`dd`甚至可以生成几个GB大小的文件,很厉害~ 12 | -------------------------------------------------------------------------------- /服务排查.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fatpo/backend_note/027983f71ae0b0ceacb11e0baf3430c80288196b/服务排查.png -------------------------------------------------------------------------------- /服务访问不了怎么办.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fatpo/backend_note/027983f71ae0b0ceacb11e0baf3430c80288196b/服务访问不了怎么办.jpg --------------------------------------------------------------------------------