Nginx的location匹配规则解析

情况1:

proxy_pass  http://IPaddr/    #删除匹配段,一般配置接口使用

访问 http://域名/abc/test.map 分下面两种情况
1)location /abc/
会转发到 http://IPaddr/test.map
2) location /abc
会转发成 http://IPaddr//test.map —————-linux //路径=/路径
所以也等价于 http://IPaddr/test.map 的访问

情况2:

proxy_pass  http://IPaddr    #匹配段和此地址段拼接

这个也分两种情况
1) location /abc
这种可以匹配 /abc 和 /abc/
2)location /abc/
这种只能匹配 /abc/ 匹配目录

容器中的JVM资源该如何被安全的限制

前言

Java与Docker的结合,虽然更好的解决了application的封装问题。但也存在着不兼容,比如Java并不能自动的发现Docker设置的内存限制,CPU限制。

这将导致JVM不能稳定服务业务!容器会杀死你JVM进程,而健康检查又将拉起你的JVM进程,进而导致你监控你的pod一天重启次数甚至能达到几百次。

我们希望当Java进程运行在容器中时,java能够自动识别到容器限制,获取到正确的内存和CPU信息,而不用每次都需要在kubernetes的yaml描述文件中显示的配置完容器,还需要配置JVM参数。

使用JVM MaxRAM参数或者解锁实验特性的JVM参数,升级JDK到10+,我们可以解决这个问题(也许吧~.~)。

首先Docker容器本质是是宿主机上的一个进程,它与宿主机共享一个/proc目录,也就是说我们在容器内看到的/proc/meminfo/proc/cpuinfo
与直接在宿主机上看到的一致,如下。

  • Hostcat /proc/meminfo MemTotal: 197869260 kB MemFree: 3698100 kB MemAvailable: 62230260 kB
  • 容器docker run -it --rm alpine cat /proc/meminfo MemTotal: 197869260 kB MemFree: 3677800 kB MemAvailable: 62210088 kB

那么Java是如何获取到Host的内存信息的呢?没错就是通过/proc/meminfo来获取到的。

默认情况下,JVM的Max Heap Size是系统内存的1/4,假如我们系统是8G,那么JVM将的默认Heap≈2G。

Docker通过CGroups完成的是对内存的限制,而/proc目录是已只读形式挂载到容器中的,由于默认情况下Java
压根就看不见CGroups的限制的内存大小,而默认使用/proc/meminfo中的信息作为内存信息进行启动,
这种不兼容情况会导致,如果容器分配的内存小于JVM的内存,JVM进程会被理解杀死。

内存限制不兼容

我们首先来看一组测试,这里我们采用一台内存为188G的物理机。

#free -g
              total        used        free      shared  buff/cache   available
Mem:            188         122           1           0          64          64

以下的测试中,我们将包含openjdk的hotspot虚拟机,IBM的openj9虚拟机。

以下测试中,我们把正确识别到限制的jdk,称之为安全(即不会超出容器限制不会被kill),反之称之为危险。

测试用例1(OPENJDK)

这一组测试我们使用最新的openjdk8-12,给容器限制内存为4G,看JDK默认参数下的最大堆为多少?看看我们默认参数下多少版本的JDK是安全的

  • 命令如下,如果你也想试试看,可以用一下命令。
   docker run -m 4GB  --rm  openjdk:8-jre-slim java  -XshowSettings:vm  -version
   docker run -m 4GB --rm  openjdk:9-jre-slim java  -XshowSettings:vm  -version
   docker run -m 4GB --rm  openjdk:10-jre-slim java -XshowSettings:vm  -version
   docker run -m 4GB --rm  openjdk:11-jre-slim java -XshowSettings:vm  -version
   docker run -m 4GB --rm  openjdk:12 java -XshowSettings:vm  -version
  • OpenJDK8(并没有识别容器限制,26.67G) 危险
[root@xiaoke-test ~]# docker run -m 4GB --rm  openjdk:8-jre-slim java  -XshowSettings:vm  -version

VM settings:
    Max. Heap Size (Estimated): 26.67G
    Ergonomics Machine Class: server
    Using VM: OpenJDK 64-Bit Server VM

openjdk version "1.8.0_181"
OpenJDK Runtime Environment (build 1.8.0_181-8u181-b13-2~deb9u1-b13)
OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)
  • OpenJDK8 -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap (正确的识别容器限制,910.50M)安全
[root@xiaoke-test ~]# docker run -m 4GB --rm  openjdk:8-jre-slim java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XshowSettings:vm  -version
VM settings:
    Max. Heap Size (Estimated): 910.50M
    Ergonomics Machine Class: server
    Using VM: OpenJDK 64-Bit Server VM

openjdk version "1.8.0_181"
OpenJDK Runtime Environment (build 1.8.0_181-8u181-b13-2~deb9u1-b13)
OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)
  • OpenJDK 9(并没有识别容器限制,26.67G)危险
[root@xiaoke-test ~]# docker run -m 4GB --rm  openjdk:9-jre-slim java  -XshowSettings:vm  -version
VM settings:
    Max. Heap Size (Estimated): 29.97G
    Using VM: OpenJDK 64-Bit Server VM

openjdk version "9.0.4"
OpenJDK Runtime Environment (build 9.0.4+12-Debian-4)
OpenJDK 64-Bit Server VM (build 9.0.4+12-Debian-4, mixed mode)
  • OpenJDK 9 -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap (正确的识别容器限制,1G)安全
[root@xiaoke-test ~]# docker run -m 4GB --rm  openjdk:9-jre-slim java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XshowSettings:vm  -version
VM settings:
    Max. Heap Size (Estimated): 1.00G
    Using VM: OpenJDK 64-Bit Server VM

openjdk version "9.0.4"
OpenJDK Runtime Environment (build 9.0.4+12-Debian-4)
OpenJDK 64-Bit Server VM (build 9.0.4+12-Debian-4, mixed mode)
  • OpenJDK 10(正确的识别容器限制,1G)安全
[root@xiaoke-test ~]# docker run -m 32GB --rm  openjdk:10-jre-slim java -XshowSettings:vm -XX:MaxRAMFraction=1  -version
VM settings:
    Max. Heap Size (Estimated): 1.00G
    Using VM: OpenJDK 64-Bit Server VM

openjdk version "10.0.2" 2018-07-17
OpenJDK Runtime Environment (build 10.0.2+13-Debian-2)
OpenJDK 64-Bit Server VM (build 10.0.2+13-Debian-2, mixed mode)
  • OpenJDK 11(正确的识别容器限制,1G)安全
[root@xiaoke-test ~]# docker run -m 4GB --rm  openjdk:11-jre-slim java -XshowSettings:vm  -version
VM settings:
    Max. Heap Size (Estimated): 1.00G
    Using VM: OpenJDK 64-Bit Server VM

openjdk version "11.0.1" 2018-10-16
OpenJDK Runtime Environment (build 11.0.1+13-Debian-3)
OpenJDK 64-Bit Server VM (build 11.0.1+13-Debian-3, mixed mode, sharing)
  • OpenJDK 12(正确的识别容器限制,1G)安全
[root@xiaoke-test ~]# docker run -m 4GB --rm  openjdk:12 java -XshowSettings:vm  -version
VM settings:
    Max. Heap Size (Estimated): 1.00G
    Using VM: OpenJDK 64-Bit Server VM

openjdk version "12-ea" 2019-03-19
OpenJDK Runtime Environment (build 12-ea+23)
OpenJDK 64-Bit Server VM (build 12-ea+23, mixed mode, sharing)

测试用例2(IBMOPENJ9)

docker run -m 4GB --rm  adoptopenjdk/openjdk8-openj9:alpine-slim  java -XshowSettings:vm  -version
docker run -m 4GB --rm  adoptopenjdk/openjdk9-openj9:alpine-slim  java -XshowSettings:vm  -version
docker run -m 4GB --rm  adoptopenjdk/openjdk10-openj9:alpine-slim  java -XshowSettings:vm  -version
docker run -m 4GB --rm  adoptopenjdk/openjdk11-openj9:alpine-slim  java -XshowSettings:vm  -version
  • openjdk8-openj9 (正确的识别容器限制,3G)安全
    [root@xiaoke-test ~]# docker run -m 4GB --rm  adoptopenjdk/openjdk8-openj9:alpine-slim  java -XshowSettings:vm  -version
    VM settings:
        Max. Heap Size (Estimated): 3.00G
        Ergonomics Machine Class: server
        Using VM: Eclipse OpenJ9 VM
    
    openjdk version "1.8.0_192"
    OpenJDK Runtime Environment (build 1.8.0_192-b12_openj9)
    Eclipse OpenJ9 VM (build openj9-0.11.0, JRE 1.8.0 Linux amd64-64-Bit Compressed References 20181107_95 (JIT enabled, AOT enabled)
    OpenJ9   - 090ff9dcd
    OMR      - ea548a66
    JCL      - b5a3affe73 based on jdk8u192-b12)
  • openjdk9-openj9 (正确的识别容器限制,3G)安全
    [root@xiaoke-test ~]# docker run -m 4GB --rm  adoptopenjdk/openjdk9-openj9:alpine-slim  java -XshowSettings:vm  -version
    VM settings:
        Max. Heap Size (Estimated): 3.00G
        Using VM: Eclipse OpenJ9 VM
    
    openjdk version "9.0.4-adoptopenjdk"
    OpenJDK Runtime Environment (build 9.0.4-adoptopenjdk+12)
    Eclipse OpenJ9 VM (build openj9-0.9.0, JRE 9 Linux amd64-64-Bit Compressed References 20180814_248 (JIT enabled, AOT enabled)
    OpenJ9   - 24e53631
    OMR      - fad6bf6e
    JCL      - feec4d2ae based on jdk-9.0.4+12)
  • openjdk10-openj9 (正确的识别容器限制,3G)安全
    [root@xiaoke-test ~]# docker run -m 4GB --rm  adoptopenjdk/openjdk10-openj9:alpine-slim  java -XshowSettings:vm  -version
    VM settings:
        Max. Heap Size (Estimated): 3.00G
        Using VM: Eclipse OpenJ9 VM
    
    openjdk version "10.0.2-adoptopenjdk" 2018-07-17
    OpenJDK Runtime Environment (build 10.0.2-adoptopenjdk+13)
    Eclipse OpenJ9 VM (build openj9-0.9.0, JRE 10 Linux amd64-64-Bit Compressed References 20180813_102 (JIT enabled, AOT enabled)
    OpenJ9   - 24e53631
    OMR      - fad6bf6e
    JCL      - 7db90eda56 based on jdk-10.0.2+13)
  • openjdk11-openj9(正确的识别容器限制,3G)安全
    [root@xiaoke-test ~]# docker run -m 4GB --rm  adoptopenjdk/openjdk11-openj9:alpine-slim  java -XshowSettings:vm  -version
    VM settings:
        Max. Heap Size (Estimated): 3.00G
        Using VM: Eclipse OpenJ9 VM
    
    openjdk version "11.0.1" 2018-10-16
    OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.1+13)
    Eclipse OpenJ9 VM AdoptOpenJDK (build openj9-0.11.0, JRE 11 Linux amd64-64-Bit Compressed References 20181020_70 (JIT enabled, AOT enabled)
    OpenJ9   - 090ff9dc
    OMR      - ea548a66
    JCL      - f62696f378 based on jdk-11.0.1+13)

分析

分析之前我们先了解这么一个情况:

JavaMemory (MaxRAM) = 元数据+线程+代码缓存+OffHeap+Heap...

一般我们都只配置Heap即使用-Xmx来指定JVM可使用的最大堆。而JVM默认会使用它获取到的最大内存的1/4作为堆的原因也是如此。

安全性(即不会超过容器限制被容器kill)

OpenJdk

OpenJdk8-12,都能保证这个安全性的特点(8和9需要特殊参数,-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap)。

OpenJ9

IbmOpenJ9所有的版本都能识别到容器限制。

资源利用率

OpenJdk

自动识别到容器限制后,OpenJdk把最大堆设置为了大概容器内存的1/4,对内存的浪费不可谓不大。

当然可以配合另一个JVM参数来配置最大堆。-XX:MaxRAMFraction=int。下面是我整理的一个常见内存设置的表格,
从中我们可以看到似乎JVM默认的最大堆的取值为MaxRAMFraction=4,随着内存的增加,堆的闲置空间越来越大,在16G容器内存时,java堆只有不到4G。

MaxRAMFraction取值堆占比容器内存=1G容器内存=2G容器内存=4G容器内存=8G容器内存=16G
1≈90%910.50M1.78G3.56G7.11G14.22G
2≈50%455.50M910.50M1.78G3.56G7.11G
3≈33%304.00M608.00M1.19G2.37G4.74G
4≈25%228.00M455.50M910.50M1.78G3.56G

OpenJ9

关于OpenJ9的的详细介绍你可以从这里了解更多
对于内存利用率OpenJ9的策略是优于OpenJdk的。以下是OpenJ9的策略表格

容器内存<size>最大Java堆大小
小于1 GB50%<size>
1 GB – 2 GB<size>– 512 MB
大于2 GB大于2 GB

结论

  • 注意:这里我们说的是容器内存限制,和物理机内存不同,

自动档

  • 如果你想要的是,不显示的指定-Xmx,让Java进程自动的发现容器限制。

1.如果你想要的是jvm进程在容器中安全稳定的运行,不被容器kiil,并且你的JDK版本小于10(大于等于JDK10的版本不需要设置,参考前面的测试)
你需要额外设置JVM参数-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap,即可保证你的Java进程不会因为内存问题被容器Kill。
当然这个方式使用起来简单,可靠,缺点也很明显,资源利用率过低(参考前面的表格MaxRAMFraction=4)。

2.如果想在基础上我还想提高一些内存资源利用率,并且容器内存为1 GB – 4 GB,我建议你设置-XX:MaxRAMFraction=2,在大于8G的可以尝试设置-XX:MaxRAMFraction=1(参考上表格)。

手动挡

  • 如果你想要的是手动挡的体验,更加进一步的利用内存资源,那么你可能需要回到手动配置时代-Xmx。
  • 手动挡部分,请可以完全忽略上面我的BB。
    1.上面的我们说到了自动挡的配置,用起来很简单很舒服,自动发现容器限制,无需担心和思考去配置-Xmx。
    2.比如你有内存1G那么我建议你的-Xmx750M,2G建议配置-Xmx1700M,4G建议配置-Xmx3500-3700M,8G建议设置-Xmx7500-7600M,
    总之就是至少保留300M以上的内存留给JVM的其他内存。如果堆特别大,可以预留到1G甚至2G。
    3.手动挡用起来就没有那么舒服了,当然资源利用率相对而言就更高了。

a tiny but valid `init` for containers

tini

Using Tini has several benefits:

  • It protects you from software that accidentally creates zombie processes, which can (over time!) starve your entire system for PIDs (and make it unusable).
  • It ensures that the default signal handlers work for the software you run in your Docker image. For example, with Tini, SIGTERM properly terminates your process even if you didn’t explicitly install a signal handler for it.
  • It does so completely transparently! Docker images that work without Tini will work with Tini without any changes.

In Docker, you will want to use an entrypoint so you don’t have to remember to manually invoke Tini:

# Add Tini
ENV TINI_VERSION v0.19.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
RUN chmod +x /tini
ENTRYPOINT ["/tini", "--"]

# Run your program under Tini
CMD ["/your/program", "-and", "-its", "arguments"]
# or docker run your-image /your/program ...

find 之 prune

在查找某个目录的时候,如果要排除其中某个子目录可以用-path pathname -prune

例:查找根目录下24小时内修改过的文件,但是不要查询proc目录可用如下命令

find / -path /proc -prune -mtime -1 -type f
#排除多个目录
find / \( -path /proc -o -path /run \) -prune -mtime -1 -type f

例2:系统被病毒攻击,会产生很多可执行文件,如果发现被攻击时间是2天前

#全局查找命令如下
find / -mtime -3 -perm /111 -type -f 
#查找并显示详细信息
find / -mtime -3 -perm /111 -type -f -exec ls -la {} \;
#查找并删除文件
find / -mtime -3 -perm /111 -type -f -exec rm -f {} \;
#查找并删除文件 xargs
find / -mtime -3 -perm /111 -type -f  | xargs rm -f 

【3】Python之Click 库 命令行参数解析

Click是Flask的作者开发的一个第三方模块,用于快速创建命令行。它的作用与Python标准库argparse相同,但是使用更加简单。
click相对于argparse,就好比requests相对于urllib

Click使用分两步:
1)使用@click.command() 装饰一个函数,使之成为命令行接口;
2)使用@click.option() 等装饰函数,为其添加命令行选项等。

##Click 官方例子1
import click
@click.command()              //使函数hello成为命令行接口
@click.option('--count', defaut=1, help='Number of greetings.')
@click.option('--name', prompt='Your name', help='The person to greet.')
def hello(count, name):
    """Simple program that greets NAME for a total of COUNT times."""
    for x in range(count):
        click.echo('Hello %s! % name')

if __name__ == '__main__':
    hello()     
##option常用的设置参数
default: 设置命令行参数的默认值
help:    参数说明
type:    参数类型,可以是string, int, float等
prompt:  命令行提示信息,可输入参数
nargs:   指定命令行参数接受的值的个数
##Click 官方例子2
##通过nargs设定参数个数,type设置参数类型
@click.command()
@click.optoin('--pos', nargs=2, type=float)
def findme(pos):
    click.echo('%s / %s' % pos)

###
@click.command()
@click。option('--hash-type', type=click.Choice(['md5', 'sha1']))
def digest(hash_type):
    click.echo(has_type)

【2】python之ConfigParse配置文件解析

典型的配置文件包含一到多个章节(section),每个章节下可以包含一个到多个的选项(option)。如下就是一个典型的MySQL配置文件:

[client]
port           = 3306
user           = mysql
password       = mysql
host           = 127.0.0.1

[mysqld]
basedir            = /usr
datadir            = /var/lib/mysql
tmpdir             = /tmp
skip-external-locking

Python 标准库的configparser模块用以接卸配置文件。
ConfigParse模块包含一个ConfigParser类,一个ConfigParser对象,可同时解析多个配置文件。

import ConfigParser

##ConfigParser方法
###读取配置
sections           //返回一个包含所有章节的列表
has_section         //判断章节是否存在
items              // 元组的形式返回所有选项
options            // 返回一个包含章节下所有选项的列表
has_option         // 判断某个选项是否存在
get getboolean getint  getfloat   // 获取选项的值
###修改配置
remove_section      // 删除一个章节
add_section         // 添加一个章节
remote_option       // 删除一个选项
set                 // 添加一个选项
write               // 将ConfigParser对象中的数据保存到文件中

cf = ConfigParser.ConfigParser(allow_no_value=True)  //allow_no_value 默认为false,表示允许选项没有值,选项存在就表示取值为真,不存在取值为假
In [4]: cf.read('my.cnf')
Out[4]: ['my.cnf']

In [5]: cf.sections()
Out[5]: ['client', 'mysqld']

In [6]: cf.has_section('client')
Out[6]: True

In [7]: cf.options("client")
Out[7]: ['port', 'user', 'password', 'host']

In [8]: cf.has_option("client", "user")
Out[8]: True

In [9]: cf.get("client","host")
Out[9]: '127.0.0.1'

In [10]: cf.getint("client" ,"port")
Out[10]: 3306


In [11]: cf.remove_section('client')
Out[11]: True

In [12]: cf.add_section('mysql')

In [13]: cf.set('mysql','host','127.0.0.1')

In [14]: cf.set('mysql','port',3306)

In [15]: cf.write(open('my_copy.cnf', 'w'))

【1】python之操作 excel 库openpyxl 速查

import openpyxl
#打开文件
wb = oepnpyxl.load_workbook('example.xlsx')

#workbook
##workbook对象属性
wb.active    //获取活跃的worksheet
wb.read_only
wb.encoding
wb.properties  //文档元数据,如标题、创建者、创建日期
##workbook对象方法
wb.sheetnames //获取所有表格名称
ws = wb['sheetname']   //获取worksheet对象
wb.remove_sheet         //删除工作表
wb.create_sheet         //创建工作表
wb.copy_worksheet
wb.save('sample.xlsx')   //保存工作簿

#worksheet
##worksheet对象属性
ws.title       //表格标题
ws.dimensions //表格大小区域  ,A1:E11
ws.max_row     //最大行
ws.min_row     //最小行
ws.max_column   //最大列
ws.min_column   //最小列
ws.rows        //按行获取单元格(cell对象)
ws.columns     //按列获取单元格(cell对象)
ws.values       //按行获取表格内容
ws.freeze_panes  //冻结窗格,冻结第一行-A2;冻结第一列B1;冻结第一行列B2
##columns rows values 通过生成器返回数据
##worksheet对象方法
iter_rows        //按行获取所有单元格,可以指定起点、终点
list(ws.iter_rows(min_row=2, max_row=4, min_col=1, max_col=3))  //使用例子 
iter_columns
append           //在表格末尾加数据
merged_cell      //合并多个单元格
unmerged_cell    //移除合并的单元格

#Cell对象
ws['A2']   //cell对象
ws.cell(row=1, column=2)
##cell属性
row        //单元格所在行
column     //单元格所在列
cordinate  //单元格的坐标,行和列

##打印表格内容
###Example 1
for row in ws.values;
    print(*row)

###Example 2
for row in ws.rows:
    print(*[cell.value for cell in row])

###Example 3
for row in ws.iter_rows():
    print(*[cell.value for cell in row])

示例代码1

#!/usr/bin/python
#-*- coding: utf-8 -*-
import openpyxl

##计算表中学生的总成绩和平均成绩

def process_worksheet(sheet):
    avg_column = sheet.max_column + 1
    sum_column = sheet.max_column + 2

    for row in sheet.iter_rows(min_row=2, min_col=3):
        scores = [cell.value for cell in row]
        sum_scores = sum(scores)
        avg_scores = sum_scores / len(scores)

        #计算平均分和总分,并且保存到最后两列
        sheet.cell(row=row[0].row, column=avg_column).value = avg_scores
        sheet.cell(row=row[0].row, column=sum_column).value = sum_scores
    #设置平均分和总分的标题部分
    sheet.cell(row=1, column=avg_column).value = 'avg'
    sheet.cell(row=1, column=sum_column).value = 'sum'

def main():
    wb = openpyxl.load_workbook('example.xlsx')
    sheet = wb['student']
    process_worksheet(sheet)
    wb.save('example_copy.xlsx')

if __name__ == '__main__':
    main()

示例代码2

#!/usr/bin/python
#-*- coding: utf-8 -*-
import os 
import glob

import openpyxl

##合并多个excle到一个

def merge_xlsx_files(xlsx_files):
    wb = openpyxl.load_workbook(xlsx_files[0])
    ws = wb.active
    ws.title = "merged result"

    for filename in xlsx_files[1:]:
        workbook = openpyxl.load_workbook(filename)
        sheet = workbook.active
        for row in sheet.iter_rows(min_row=2):
            value = [cell.value for cell in row]
            ws.append(value)

    return wb

def get_all_xlsx_files(path):
    xlsx_files = glob.glob(os.path.join(path, '*.xlsx'))
    sorted(xlsx_files, key=str.lower)
    return xlsx_files

def main():
    xlsx_files = get_all_xlsx_files(os.path.expanduser('~lmx'))
    wb = merge_xlsx_files(xlsx_files)
    wb.save('merged_form.xlsx')

if __name__ == '__main__':
    main()

linux ssh 暴力破解 拦截方案

一 、背景介绍

正常机器如果开启ssh可能会被暴力破解用户密码,可以配置ssh的pam限制登录失败时可以锁定用户一段时间,就算密码输入正确也无法登录,等恢复之后才可以再次进入。

二、具体配置

具体的pam配置在/etc/pam.d下,对ssh服务的位置是:/etc/pam.d/sshd,打开第一行就可以发现引入了password-auth,然后可以直接编辑/etc/pam.d/password-auth,在最上面添加一行:
auth required pam_tally2.so deny=6 unlock_time=300 even_deny_root root_unlock_time=300

even_deny_root表示root用户也会限制

保存后,重启sshd服务即可生效 systemctl restart sshd

查看登录失败统计和清除次数同样使用下面的命令:

pam_tally2 --user root
# 或者简写-u
pam_tally2 -u root
# 清除次数
pam_tally2 --user root --reset

三、类似方案介绍

1、另外ssh还有个通用的配置就是连续尝试几次密码登录失败的话,可以直接断开数据包,这样也可以防止连接一次后不断尝试,编辑配置文件:/etc/ssh/sshd_config,修改下面配置:

MaxAuthTries 3

2、更高级的功能可以引入第三方软件——fail2ban,它可以更精确的拦截来源IP