Archives 七月 2019

supervisord supervisorctl 问题supervisor.sock refused connection

如果supervisord挂了的话,提示supervisor.sock refused connection。重新启动命令为supervisord

常用命令:

supervisord -c /etc/supervisord.conf   启动supervisord并使用配置

supervisorctl restart programe_name

vi /etc/supervisord.conf

ps -ef|grep super

如果出现 sock文件找不到, 或是没有***.sock文件, 请根据相对应的文件路径, 增长文件目录的权限

如: chmod 777 /var/run

chmod 777 /var/run/log


goquery的使用详解

概述

相信很多小伙伴对爬虫有着很大的兴趣,今天我们就来说下go语言的爬虫利器goquery,有使用过jquery的小伙伴是不是看着这个很眼熟?goquery类似jquery,它是jquery的go版本实现,使用它,可以很方便的对HTML进行处理。

goquery是基于 Go net/htm包和css选择器库 cascadia。由于net/htm解析器返回的是DOM节点,而不是完整的DOM树,因此, jQuery的状态操作函数没有实现(像height(), css(), detach)

注意:goquery只支持utf-8编码,其他编码需要转换。

image

安装

在终端输入命令安装goquery。

go get github.com/PuerkitoBio/goquery

简单使用

我们首先通过一个小例子来介绍goqery。

func main() {
    html := `<html>
            <body>
                <h1 id="title">春晓</h1>
                <p class="content1">
                春眠不觉晓,
                处处闻啼鸟。
                夜来风雨声,
                花落知多少。
                </p>
            </body>
            </html>
            `
dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html))
    if err!=nil{
        log.Fatalln(err)
    }

    dom.Find("p").Each(func(i int, selection *goquery.Selection) {
        fmt.Println(selection.Text())
    })
}

得到结果:

                春眠不觉晓,
                处处闻啼鸟。
                夜来风雨声,
                花落知多少。

NewDocumentFromReader() 返回了一个*Document和error。Document代表一个将要被操作的HTML文档。

Find()是获取当前匹配元素集中每个元素的子代,参数是x选择器 ,它返回一个包含这些匹配元素的新选择对象。在例子中我们使用的是元素选择器P,它会帮我们匹配出所有的p标签 。

Each() 是迭代器,它会循环遍历选择的节点,它的参数是一个匿名函数,匿名函数拥有2个参数,一个是元素的索引位置,还有一个就是选择的结果集匹配到的内容都在它的里面。

Text() 则是获取匹配元素集中的文本内容。

选择器

上面的例子中,我们使用了元素选择器,goquery跟jquery一样都支持很多选择器,我们简单的介绍下常用的选择器:

  1. 基于HTML Element 元素的选择器
    就是基于a,p等这些HTML的基本元素进行选择。

使用方法 :使用语法为 dom.Find("p"),匹配文档中所有的p标签。

  1. ID 选择器
    ID选择器是我们使用最频繁的,假如我们有2个p元素,其实我们只需要其中的一个,那么我们只需要给这个标记一个唯一的id即可,这样我们就可以使用id选择器,精确定位了。

使用方法 :id选择器以#开头,紧跟着元素id的值,使用语法为
dom.Find("#title") ,匹配文档中所有的 id=title的内容

如果多个标签的ID都是title,我们可以指定某一个标签,如dom.Find("p#title")

  1. Class选择器

类选择跟ID选择器一样都是使用很频繁的,我们可以通过类选择器快速筛选到需要的内容。

使用方法 : id选择器以.开头,紧跟着元素class的值,使用语法为dom.Find(".content1"),匹配文档中所有的 id=title的元素。

类选择权器跟ID选择器一样,也可以指定某一个标签dom.Find("div.content1")

  1. 属性选择器

一个HTML元素都有自己的属性以及属性值,所以我们也可以通过属性和值筛选元素。

使用方法 :我们可以通过元素的属性和属性值来筛选数据,使用语法为dom.Find("p[class=content1],匹配文档中所有的 p标签的class属性是content1的元素。

当然我们这里以class属性为例,还可以用其他属性,比如href等很多,自定义属性也是可以的。

刚刚我们使用的是完全相等的匹配方式,属性选择器还要很多匹配方式。

选择器说明
Find(“div[my]“)筛选含有my属性的div元素
Find(“div[my=zh]“)筛选my属性为zh的div元素
Find(“div[my!=zh]“)筛选my属性不等于zh的div元素
Find(“div[my¦=zh]“)筛选my属性为zh或者zh-开头的div元素
Find(“div[my*=zh]“)筛选my属性包含zh这个字符串的div元素
Find(“div[my~=zh]“)筛选my属性包含zh这个单词的div元素,单词以空格分开的
Find(“div[my$=zh]“)筛选my属性以zh结尾的div元素,区分大小写
Find(“div[my^=zh]“)筛选my属性以zh开头的div元素,区分大小写
  1. parent > child选择器

筛选出某个元素下的子元素。

使用方法:使用>符号连接,使用语法 dom.Find("div>p") , 筛选div标签下的p标签

  1. element + next 相邻选择器

如果要筛选的元素没有规律,但是该元素的上一个元素有规律,我们就可以使用这种下一个相邻选择器来进行选择。

如:

<div>
<p my="a">a</p>
<p>b</p>
<p>c</p>
<div>

我想筛选出b所在的标签

使用方法:dom.Find("p[my=a]+p")筛选出p标签属性my的值为a的相邻p标签。

  1. element~next 兄弟选择器

有时候我们需要筛选同一父元素下,不相邻的标签,可以使用兄弟选择器

比如我想筛选出 b 和c 所在标签
使用方法:dom.Find("p[my=a]~p"),筛选出p标签属性my的值为a的兄弟p标签。

过滤器

有时候我们选择出来的结果,并不是我们心目中的最优结果,我们希望对其进行过滤。

  1. :contains过滤器

筛选出的元素要包含指定的文本,比如我想筛选出包含a的p标签

使用方法:dom.Find("p:contains(a)"),筛选出内容包含a的p标签

Find(“:has(selector)”)和contains差不多,只不过这个是包含的是元素节点。

此外还有Find(“:empty”)表示筛选出的元素都不能有子元素(包括文本元素),只筛选那些不包含任何子元素的元素。

  1. :first-child过滤器 和:first-of-type过滤器
    筛选出的元素要是他们的父元素的第一个子元素,如果不是,则不会被筛选出来。

使用方法:语法为Find(“p:first-child”),筛选出第一个p标签

:first-child选择器限制的比较死,必须得是第一个子元素,如果该元素前有其他在前面,就不能用:first-child了,这时候:first-of-type就派上用场了,它要求只要是这个类型的第一个就可以。

  1. :last-child 和:last-of-type过滤器
    这两个正好和上面的:first-child、:first-of-type相反
  2. :nth-child(n) 过滤器

筛选出的元素是其父元素的第n个元素,n以1开始。所以我们可以知道:first-child和:nth-child(1)是相等的。通过指定n,我们就很灵活的筛选出我们需要的元素。

  1. :nth-of-type(n) 过滤器

:nth-of-type(n)和 :nth-child(n) 类似,只不过它表示的是同类型元素的第n个,所以:nth-of-type(1) 和 :first-of-type是相等的。

  1. :nth-last-child(n) 和:nth-last-of-type(n) 过滤器

这两个和上面的类似,只不过是倒序开始计算的,最后一个元素被当成了第一个

  1. :only-child 过滤器 和 :only-of-type 过滤器

筛选出父元素中,只有它自己的一个的元素。

常用方法

  1. 类似函数的位置操作
  • Find(selection) *Selection //根据选择器查找节点集
  • Eq(index int) *Selection //根据索引获取某个节点集
  • First() *Selection //获取第一个子节点集
  • Last() *Selection //获取最后一个子节点集
  • Next() *Selection //获取下一个兄弟节点集
  • NextAll() *Selection //获取后面所有兄弟节点集
  • Prev() *Selection //前一个兄弟节点集
  • Get(index int) *html.Node //根据索引获取一个节点
  • Index() int //返回选择对象中第一个元素的位置
  • Slice(start, end int) *Selection //根据起始位置获取子节点集
  1. 循环遍历选择的节点
  • Each(f func(int, *Selection)) *Selection //遍历
  • EachWithBreak(f func(int, *Selection) bool) *Selection //可中断遍历
  • Map(f func(int, *Selection) string) (result []string) //返回字符串数组
  1. 检测或获取节点属性值
  • Attr(), RemoveAttr(), SetAttr() //获取,移除,设置属性的值
  • AddClass(), HasClass(), RemoveClass(), ToggleClass()
  • Html() //获取该节点的html
  • Length() //返回该Selection的元素个数
  • Text() //获取该节点的文本值
  1. 在文档树之间来回跳转(常用的查找节点方法)
  • Children() //返回selection中各个节点下的孩子节点
  • Contents() //获取当前节点下的所有节点
  • Find() //查找获取当前匹配的元素
  • Next() //下一个元素
  • Prev() //上一个元素

Python的迭代、可迭代对象、迭代器与生成器详解

teration(迭代)

迭代是Python最强大的功能之一,是访问集合元素的一种方式。

只要是可迭代对象(Iterable),就可以通过for循环来遍历,这种遍历我们称为迭代。

也就是说所有可作用于for循环的对象都是可迭代对象(Iterable)。

那么,如何判断一个对象是可迭代对象呢?方法是通过collections模块的Iterable类型判断:

>>> from collections import Iterable
>>> isinstance(123,Iterable)            # Integer 不可迭代False>>> isinstance('abc',Iterable)          # String 可迭代True>>> isinstance([1,2,3],Iterable)        # List 可迭代True>>> isinstance(('a','b','c'),Iterable)  # Tuple 可迭代True>>> isinstance({'name':'Arno','Job':'Ops'},Iterable)    # Dictionary 可迭代Truepython

dict 迭代说明

默认情况下,dict迭代的是key:

>>> d = {'Name':'Arno','Born':1993,'Job':'Ops'}
>>> for k in d:...     print(k)... NameBornJobpython

如果要迭代value,可以用for value in d.values():

>>> for v in d.values():...     print(v)... Arno1993Opspython

如果要同时迭代key和value,可以用for k, v in d.items():

>>> for k,v in d.items():...     print('key:', k, '\t', 'value:', v)... key: Name      value: Arnokey: Born      value: 1993key: Job      value: Opspython

知识扩展

在Python中,List元素是有索引的,那么如何实现类似Java那样的下标循环?

方法一,通过len()方法取得列表长度,再结合range()方法实现索引下标循环:

>>> L = ['a','b','c']>>> for i in range(len(L)):...     print(i, L[i])... 0 a1 b2 cpython

方法二,Python内置的enumerate函数可以把一个list变成 索引-元素 对,这样就可以在for循环中同时迭代索引和元素本身:

>>> for i,v in enumerate(L):...     print(i, v)... 0 a1 b2 cpython

iterator(迭代器)

迭代器是一个可以记住遍历的位置的对象。

  • 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束;
  • 迭代器只能往前不会后退;

迭代器有两个基本的方法:

  • iter()
  • next()

可以通过 collections 模块的 Iterator 类型判断一个对象是否是迭代器:

>>> from collections import Iterator
>>> isinstance([1,2,3], Iterator)False
>>> isinstance({'Name':'Arno','Born':1993,'Job':'Ops'}, Iterator)False
>>> isinstance('abc', Iterator)False
>>> isinstance(iter([1,2,3]), Iterator)             # iter()创建迭代器对象True
>>> isinstance((x for x in range(10)), Iterator)    # 生成器Truepython

可以看出,生成器(generator)都是迭代器(Iterator)对象,但String、List、Tuple、Dict虽然是可迭代对象(Iterable),却不是迭代器(Iterator)。

当然,String、List、Tuple、Dict等可迭代对象都可用于创建迭代器:

>>> L = [1,2,3]
>>> it = iter(L)
>>> print(next(it))1
>>> print(next(it))2
>>> print(next(it))3
>>> print(next(it))     # 没有值可返回时,抛异常 StopIterationTraceback (most recent call last):  File "<stdin>", line 1, in <module>StopIteration
>>> python

迭代器对象常使用for语句进行遍历:

>>> L = [1,2,3]
>>> it = iter(L)
>>> for x in it:...     print(x, end=" ")... 1 2 3 python

也可以使用 next() 函数:

>>> import sys
>>> L = [1,2,3]
>>> it = iter(L)
>>> while True:...     try:...         print(next(it))...     except StopIteration:...         sys.exit()... 123python

generator(生成器)

创建生成器的方法:

  • 使用了 yield 语句的函数
    Generator 是一个用于创建迭代器的简单而强大的工具。 它们的写法类似标准的函数,但当它们要返回数据时会使用 yield 语句。 每次对生成器调用 next() 时,它会从上次离开位置恢复执行(它会记住上次执行语句时的所有数据值)。
  • 使用生成器表达式,就是把一个 列表生成式 的[]改成()
    某些简单的生成器可以写成简洁的表达式代码,所用语法类似列表推导式,将外层为圆括号而非方括号。 这种表达式被设计用于生成器将立即被外层函数所使用的情况。 生成器表达式相比完整的生成器更紧凑但较不灵活,相比等效的列表推导式则更为节省内存。

yield 函数生成器

在 Python 中,使用了 yield 的函数被称为生成器

跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。

在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回yield的值。并在下一次执行 next()方法时从当前位置继续运行。

实例,使用 yield 实现斐波那契数列:

import sysdef fibonacci(n): # 生成器函数 - 斐波那契    
a, b, counter = 0, 1, 0    
while True:        
if (counter > n):             
return        yield a        
a, b = b, a + b        
counter += 1f = fibonacci(10) # f 是一个迭代器,由生成器返回生成while True:    try:        
print (next(f), end=" ")    
except StopIteration:        
sys.exit()
awk

列表生成式

列表生成式(List Comprehensions)也叫列表推导式,提供了一个更简单的创建列表的方法。

常见的用法:

  • 是把某种操作应用于序列或可迭代对象的每个元素上,然后使用其结果来创建列表;
  • 或者通过满足某些特定条件元素来创建子序列;

例如,创建一个平方列表,像这样

>>> squares = []
>>> for x in range(10):...     squares.append(x**2)...
>>> squares[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]python

可以改为

>>> list(map(lambda x: x**2, range(10)))[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

等价于

# 列表推导式,更加简洁易读
>>> [x**2 for x in range(10)][0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

增加特定条件

>>> [x**2 for x in range(10) if x % 2 != 0][1, 9, 25, 49, 81]

创建为生成器

>>> (x**2 for x in range(10) if x % 2 != 0)<generator object <genexpr> at 0x7f076f06e990>

知识扩展

lambda 表达式

lambda 表达式(有时称为 lambda 构型)被用于创建匿名函数。

表达式 lambda parameters: expression 会产生一个函数对象 。 该未命名对象的行为类似于用以下方式定义的函数:

def <lambda>(parameters):    return expression

注意:通过 lambda 表达式创建的函数不能包含语句或标注。

map() 高阶函数

接收两个参数,一个是函数,一个是可迭代对象(Iterable),map将传入的函数依次作用到序列的每个元素,并把结果作为新的iterator(迭代器)返回。

总结

  • 迭代(iteration)是访问集合元素的一种方式;
  • 迭代器(iterator)对象一定是可迭代对象,反之则不一定;
  • 可迭代对象(Iterable)不一定是迭代器;
    例如list、dict、str等集合数据类型是可迭代对象,但不是迭代器,但是它们可以通过iter()函数生成一个迭代器对象。
  • 生成器(generator)对象既是可迭代对象也是迭代器;

遍历方式

  • 迭代器、生成器和可迭代对象都可以用for循环去迭代
  • 生成器和迭代器还可以被next()方函数调用并返回下一个值

《Kafka 核心技术与实战》机制与消息压缩与解压

一、Kafka 版本演进

Kafka 目前总共演进了 7 个大版本,分别是 0.7、0.8、0.9、0.10、0.11、1.0 和 2.0,其中的小版本和 Patch 版本很多。

  • 0.7 版本,是最早开源时的版本,这个版本只提供了最基础的消息队列功能,连副本机制都没有。
  • 0.8 版本正式引入了副本机制,至此 Kafka 成为了一个真正意义上完备的分布式高可靠消息队列解决方案。
  • 0.9 版本增加了基础的安全认证 / 权限功能,同时使用 Java 重写了新版本消费者 API,另外还引入了 Kafka Connect 组件用于实现高性能的数据抽取。
  • 0.10 是里程碑式的大版本,该版本引入了 Kafka Streams。从这个版本起,Kafka 正式升级成分布式流处理平台。
  • 0.11 版本,引入了两个重量级的功能变更:一个是提供幂等性 Producer API 以及事务(Transaction) API;另一个是对 Kafka 消息格式做了重构。
  • 1.0 和 2.0 版本,主要还是 Kafka Streams 的各种改进,在消息引擎方面并未引入太多的重大功能特性。

二、生产者消息分区机制原理

Kafka 的消息组织方式实际上是三级结构:主题 – 分区 – 消息。主题下的每条消息只会保存在某一个分区中,而不会在多个分区中被保存多份。

其实分区的作用就是提供负载均衡的能力,或者说对数据进行分区的主要原因,就是为了实现系统的高伸缩性(Scalability)。

值得注意的是,不同的分布式系统对分区的叫法也不尽相同。比如在 Kafka 中叫分区,在 MongoDB 和 Elasticsearch 中就叫分片 Shard,而在 HBase 中则叫 Region,在 Cassandra 中又被称作 vnode。从表面看起来它们实现原理可能不尽相同,但对底层分区(Partitioning)的整体思想却从未改变。

三、生产者压缩算法

1,怎么压缩

目前 Kafka 共有两大类消息格式,社区分别称之为 V1 版本和 V2 版本。V2 版本是 Kafka 0.11.0.0 中正式引入的。

不论是哪个版本,Kafka 的消息层次都分为两层:消息集合(message set)以及消息(message)。一个消息集合中包含若干条日志项(record item),而日志项才是真正封装消息的地方。Kafka 底层的消息日志由一系列消息集合日志项组成。Kafka 通常不会直接操作具体的一条条消息,它总是在消息集合这个层面上进行写入操作。

2,何时压缩

在 Kafka 中,压缩可能发生在两个地方:生产者端和 Broker 端。

有两种例外情况就可能让 Broker 重新压缩消息。

  • 情况一:Broker 端指定了和 Producer 端不同的压缩算法。
  • 情况二:Broker 端发生了消息格式转换。

所谓的消息格式转换主要是为了兼容老版本的消费者程序。

一般情况下这种消息格式转换对性能是有很大影响的,除了这里的压缩之外,它还让 Kafka 丧失了引以为豪的 Zero Copy 特性。

3,何时解压缩

每个压缩过的消息集合在 Broker 端写入时都要发生解压缩操作,目的就是为了对消息执行各种验证。我们必须承认这种解压缩对 Broker 端性能是有一定影响的,特别是对 CPU 的使用率而言。

4,各种压缩算法对比

在 Kafka 2.1.0 版本之前,Kafka 支持 3 种压缩算法:GZIP、Snappy 和 LZ4。从 2.1.0 开始,Kafka 正式支持 Zstandard 算法(简写为 zstd)。它是 Facebook 开源的一个压缩算法,能够提供超高的压缩比(compression ratio)。

看一个压缩算法的优劣,有两个重要的指标:一个指标是压缩比;另一个指标就是压缩 / 解压缩吞吐量。

在吞吐量方面:LZ4 > Snappy > zstd 和 GZIP;而在压缩比方面,zstd > LZ4 > GZIP > Snappy。

5,最佳实践

如果 Producer 运行机器本身 CPU 已经消耗殆尽了,那么启用消息压缩无疑是雪上加霜,只会适得其反。


vsftpd配置文件详解

vsftpd作为一个主打安全的FTP服务器,有很多的选项设置。下面介绍了vsftpd的配置文件列表,而所有的配置都是基于vsftpd.conf这个配置文件的。本文将提供完整的vsftpd.conf的中文说明。学习本文的内容将有助于你初步了解vsftpd的配置文件,但针对具体情况还需要制定具体的配置方法。

vsftpd的配置文件

/etc/vsftpd/vsftpd.conf主配置文件
/usr/sbin/vsftpdVsftpd的主程序
/etc/rc.d/init.d/vsftpd启动脚本
/etc/pam.d/vsftpdPAM认证文件(此文件中file=/etc/vsftpd/ftpusers字段,指明阻止访问的用户来自/etc/vsftpd/ftpusers文件中的用户)
/etc/vsftpd/ftpusers禁止使用vsftpd的用户列表文件。记录不允许访问FTP服务器的用户名单,管理员可以把一些对系统安全有威胁的用户账号记录在此文件中,以免用户从FTP登录后获得大于上传下载操作的权利,而对系统造成损坏。(注意:linux-4中此文件在/etc/目录下)
/etc/vsftpd/user_list禁止或允许使用vsftpd的用户列表文件。这个文件中指定的用户缺省情况(即在/etc/vsftpd/vsftpd.conf中设置userlist_deny=YES)下也不能访问FTP服务器,在设置了userlist_deny=NO时,仅允许user_list中指定的用户访问FTP服务器。(注意:linux-4中此文件在/etc/目录下)
/var/ftp匿名用户主目录;本地用户主目录为:/home/用户主目录,即登录后进入自己家目录
/var/ftp/pub匿名用户的下载目录,此目录需赋权根chmod 1777 pub(1为特殊权限,使上载后无法删除)
/etc/logrotate.d/vsftpd.logVsftpd的日志文件

vsftpd的主配置文件/etc/vsftpd/vsftpd.conf说明(修改前先备份)

和Linux系统中的大多数配置文件一样,vsftpd的配置文件中以#开始注释。

# 是否允许匿名登录FTP服务器,默认设置为YES允许
# 用户可使用用户名ftp或anonymous进行ftp登录,口令为用户的E-mail地址。
# 如不允许匿名访问则设置为NO
anonymous_enable=YES
# 是否允许本地用户(即linux系统中的用户帐号)登录FTP服务器,默认设置为YES允许
# 本地用户登录后会进入用户主目录,而匿名用户登录后进入匿名用户的下载目录/var/ftp/pub
# 若只允许匿名用户访问,前面加上#注释掉即可阻止本地用户访问FTP服务器
local_enable=YES
# 是否允许本地用户对FTP服务器文件具有写权限,默认设置为YES允许
write_enable=YES 
# 掩码,本地用户默认掩码为077
# 你可以设置本地用户的文件掩码为缺省022,也可根据个人喜好将其设置为其他值
#local_umask=022
# 是否允许匿名用户上传文件,须将全局的write_enable=YES。默认为YES
#anon_upload_enable=YES
# 是否允许匿名用户创建新文件夹
#anon_mkdir_write_enable=YES 
# 是否激活目录欢迎信息功能
# 当用户用CMD模式首次访问服务器上某个目录时,FTP服务器将显示欢迎信息
# 默认情况下,欢迎信息是通过该目录下的.message文件获得的
# 此文件保存自定义的欢迎信息,由用户自己建立
#dirmessage_enable=YES
# 是否让系统自动维护上传和下载的日志文件
# 默认情况该日志文件为/var/log/vsftpd.log,也可以通过下面的xferlog_file选项对其进行设定
# 默认值为NO
xferlog_enable=YES
# Make sure PORT transfer connections originate from port 20 (ftp-data).
# 是否设定FTP服务器将启用FTP数据端口的连接请求
# ftp-data数据传输,21为连接控制端口
connect_from_port_20=YES
# 设定是否允许改变上传文件的属主,与下面一个设定项配合使用
# 注意,不推荐使用root用户上传文件
#chown_uploads=YES
# 设置想要改变的上传文件的属主,如果需要,则输入一个系统用户名
# 可以把上传的文件都改成root属主。whoever:任何人
#chown_username=whoever
# 设定系统维护记录FTP服务器上传和下载情况的日志文件
# /var/log/vsftpd.log是默认的,也可以另设其它
#xferlog_file=/var/log/vsftpd.log
# 是否以标准xferlog的格式书写传输日志文件
# 默认为/var/log/xferlog,也可以通过xferlog_file选项对其进行设定
# 默认值为NO
#xferlog_std_format=YES
# 以下是附加配置,添加相应的选项将启用相应的设置
# 是否生成两个相似的日志文件
# 默认在/var/log/xferlog和/var/log/vsftpd.log目录下
# 前者是wu_ftpd类型的传输日志,可以利用标准日志工具对其进行分析;后者是vsftpd类型的日志
#dual_log_enable
# 是否将原本输出到/var/log/vsftpd.log中的日志,输出到系统日志
#syslog_enable
# 设置数据传输中断间隔时间,此语句表示空闲的用户会话中断时间为600秒
# 即当数据传输结束后,用户连接FTP服务器的时间不应超过600秒。可以根据实际情况对该值进行修改
#idle_session_timeout=600
# 设置数据连接超时时间,该语句表示数据连接超时时间为120秒,可根据实际情况对其个修改
#data_connection_timeout=120
# 运行vsftpd需要的非特权系统用户,缺省是nobody
#nopriv_user=ftpsecure
# 是否识别异步ABOR请求。
# 如果FTP client会下达“async ABOR”这个指令时,这个设定才需要启用
# 而一般此设定并不安全,所以通常将其取消
#async_abor_enable=YES
# 是否以ASCII方式传输数据。默认情况下,服务器会忽略ASCII方式的请求。
# 启用此选项将允许服务器以ASCII方式传输数据
# 不过,这样可能会导致由"SIZE /big/file"方式引起的DoS攻击
#ascii_upload_enable=YES
#ascii_download_enable=YES
# 登录FTP服务器时显示的欢迎信息
# 如有需要,可在更改目录欢迎信息的目录下创建名为.message的文件,并写入欢迎信息保存后
#ftpd_banner=Welcome to blah FTP service.
# 黑名单设置。如果很讨厌某些email address,就可以使用此设定来取消他的登录权限
# 可以将某些特殊的email address抵挡住。
#deny_email_enable=YES
# 当上面的deny_email_enable=YES时,可以利用这个设定项来规定哪些邮件地址不可登录vsftpd服务器
# 此文件需用户自己创建,一行一个email address即可
#banned_email_file=/etc/vsftpd/banned_emails
# 用户登录FTP服务器后是否具有访问自己目录以外的其他文件的权限
# 设置为YES时,用户被锁定在自己的home目录中,vsftpd将在下面chroot_list_file选项值的位置寻找chroot_list文件
# 必须与下面的设置项配合
#chroot_list_enable=YES
# 被列入此文件的用户,在登录后将不能切换到自己目录以外的其他目录
# 从而有利于FTP服务器的安全管理和隐私保护。此文件需自己建立
#chroot_list_file=/etc/vsftpd/chroot_list
# 是否允许递归查询。默认为关闭,以防止远程用户造成过量的I/O
#ls_recurse_enable=YES
# 是否允许监听。
# 如果设置为YES,则vsftpd将以独立模式运行,由vsftpd自己监听和处理IPv4端口的连接请求
listen=YES
# 设定是否支持IPV6。如要同时监听IPv4和IPv6端口,
# 则必须运行两套vsftpd,采用两套配置文件
# 同时确保其中有一个监听选项是被注释掉的
#listen_ipv6=YES
# 设置PAM外挂模块提供的认证服务所使用的配置文件名,即/etc/pam.d/vsftpd文件
# 此文件中file=/etc/vsftpd/ftpusers字段,说明了PAM模块能抵挡的帐号内容来自文件/etc/vsftpd/ftpusers中
#pam_service_name=vsftpd
# 是否允许ftpusers文件中的用户登录FTP服务器,默认为NO
# 若此项设为YES,则user_list文件中的用户允许登录FTP服务器
# 而如果同时设置了userlist_deny=YES,则user_list文件中的用户将不允许登录FTP服务器,甚至连输入密码提示信息都没有
#userlist_enable=YES/NO
# 设置是否阻扯user_list文件中的用户登录FTP服务器,默认为YES
#userlist_deny=YES/NO
# 是否使用tcp_wrappers作为主机访问控制方式。
# tcp_wrappers可以实现linux系统中网络服务的基于主机地址的访问控制
# 在/etc目录中的hosts.allow和hosts.deny两个文件用于设置tcp_wrappers的访问控制
# 前者设置允许访问记录,后者设置拒绝访问记录。
# 如想限制某些主机对FTP服务器192.168.57.2的匿名访问,编缉/etc/hosts.allow文件,如在下面增加两行命令:
# vsftpd:192.168.57.1:DENY 和vsftpd:192.168.57.9:DENY
# 表明限制IP为192.168.57.1/192.168.57.9主机访问IP为192.168.57.2的FTP服务器
# 此时FTP服务器虽可以PING通,但无法连接
tcp_wrappers=YES

下面的内容将对一些限制和权限控制的选项进行更进一步的说明。

除了上述那些基本设定,我们还可以在vsftpd.conf文件中添加更多的安全选项。其中几个常用的如下:

限制最大连接数和传输速率

在FTP服务器的管理中,无论对本地用户还是匿名用户,对于FTP服务器资源的使用都需要进行控控制,避免由于负担过大造成FTP服务器运行异常,可以添加以下配置项对FTP客户机使用FTP服务器资源进行控制:

  1. max_client设置项 用于设置FTP服务器所允许的最大客户端连接数,值为0时表示不限制。例如max_client=100表示FTP服务器的所有客户端最大连接数不超过100个。
  2. max_per_ip设置项 用于设置对于同一IP地址允许的最大客户端连接数,值为0时表示不限制。例如max_per_ip=5表示同一IP地址的FTP客户机与FTP服务器建立的最大连接数不超过5个。
  3. local_max_rate设置项 用于设置本地用户的最大传输速率,单位为B/s,值为0时表示不限制。例如local_max_rate=500000表示FTP服务器的本地用户最大传输速率设置为500KB/s.
  4. anon_max_rate设置项 用于设置匿名用户的最大传输速率,单位为B/s,值为0表示不限制。例如ano_max_rate=200000,表示FTP服务器的匿名用户最大传输速率设置为200KB/s.

指定用户的权限设置

vsftpd.user_list文件需要与vsftpd.conf文件中的配置项结合来实现对于vsftpd.user_list文件中指定用户账号的访问控制:

(1)设置禁止登录的用户账号

当vsftpd.conf配置文件中包括以下设置时,vsftpd.user_list文件中的用户账号被禁止进行FTP登录:

userlist_enable=YES
userlist_deny=YES 

userlist_enable设置项设置使用vsftpd.user_list文件,userlist_deny设置为YES表示vsftpd.user_list文件用于设置禁止的用户账号。

(2)设置只允许登录的用户账号

当vsftpd.conf配置文件中包括以下设置时,只有vsftpd.user_list文件中的用户账号能够进行FTP登录:

userlist_enable=YES
userlist_deny=NO 

userlist_enable设置项设置使用vsftpd.user_list文件,userlist _deny设置为NO表示vsftpd.usre_list文件用于设置只允许登录的用户账号,文件中未包括的用户账号被禁止FTP登录。

userlist_deny和userlist_enable选项限制用户登录FTP服务器(使用userlist_deny选项和user_list文件一起能有效阻止root,apache,www等系统用户登录FTP服务器,从而保证FTP服务器的分级安全性)。以下是两个选项的具体表现形式和两种搭配使用方式的效果:

Userlist_enable=YESFtpusers中用户允许访问
User_list中用户允许访问
Userlist_enable=NOFtpusers中用户禁止访问
User_list中用户允许访问
Userlist_deny=YESFtpusers中用户禁止访问(登录时可以看到密码输入提示,但仍无法访问)
user_list 中用户禁止访问
Userlist_deny=NOftpusers中用户禁止访问
user_list中用户允许访问
Userlist_enable=YES 并且
Userlist_deny=YES
Ftpusers中用户禁止访问
User_list中用户禁止访问(登录时不会出现密码提示,直接被服务器拒绝)
Userlist_enable=YES 并且
Userlist_deny=NO
Ftpusers中用户禁止访问
User_list中用户允许访问
 

修改默认端口

默认FTP服务器端口号是21,出于安全目的,有时需修改默认端口号,修改/etc/vsftpd/vsftpd.conf,添加语句(例):

listen_port=4449 

语句指定了修改后FTP服务器的端口号,应尽量大于4000。修改后访问

#ftp 192.168.57.2 4449

注意这里需加上正确的端口号了,否则不能正常连接。

设置用户组

有关FTP用户和用户组的重要性,我们在之前介绍vsftpd的时候便已经提到过。这里主要是简单的说明用户组的技术实现,至于具体如何应用,还是具体需求具体对待。

#mkdir -p /home/try  递归创建新目录
#groupadd try        新建组
#useradd -g try -d /home/try try1 新建用户try1并指定家目录和属组
#useradd -g try -d /home/try try2 新建用户try2并指定家目录和属组
#useradd -g try -d /home/try try3 新建用户try3并指定家目录和属组
#passwd try1  为新用户设密码
#passwd try2  为新用户设密码
#passwd try3  为新用户设密码
#chown try1 /home/try 设置目录属主为用户try1
#chown .try /home/try 设置目录属组为组try
#chmod 750 /home/try  设置目录访问权限try1为读,写,执行;try2,try3为读,执行

由于本地用户登录FTP服务器后进入自己主目录,而try1,try2 try3对主目录/home/try分配的权限不同,所以通过FTP访问的权限也不同,try1访问权限为:上传,下载,建目录;try2,try3访问权限为下载,浏览,不能建目录和上传。实现了群组中用户不同访问级别,加强了对FTP服务器的分级安全管理。

配置空闲的用户会话的中断时间:如下配置将在用户会话空闲5分钟后被中断,以释放服务器的资源

Idle_session_timeout=300

配置空闲的数据连接的中断时间:如下配置将在数据空闲连接1分钟后被中断,同样也是为了释放服务器的资源

Data_connection_timeout=60

配置客户端空闲时的自动中断和激活连接的时间:如下配置将使客户端空闲1分钟后自动中断连接,并在30秒后自动激活连接

Accept_timeout=60
Connect_timeout=30

接下来,我们将对vsftpd的日志进行介绍。

常见的vsftpd日志解决方案

在vsftpd.conf中有如下内容定义了日志的记录方式:

# 表明FTP服务器记录上传下载的情况
xferlog_enable=YES 
# 表明将记录的上传下载情况写在xferlog_file所指定的文件中,即xferlog_file选项指定的文件中
xferlog_std_format=YES 
xferlog_file=/var/log/xferlog 
# 启用双份日志。在用xferlog文件记录服务器上传下载情况的同时,
# vsftpd_log_file所指定的文件,即/var/log/vsftpd.log也将用来记录服务器的传输情况
dual_log_enable=YES
vsftpd_log_file=/var/log/vsftpd.log

vsftpd的两个日志文件分析如下:

/var/log/xferlog

记录内容举例

Thu Sep 6 09:07:48 2007 7 192.168.57.1 4323279 /home/student/phpMyadmin-2.11.0-all-languages.tar.gz b -i r student ftp 0 * c 

/var/log/vsftpd.log

记录内容举例

Tue Sep 11 14:59:03 2007 [pid 3460]    CONNECT: Client "127.0.0.1"
Tue Sep 11 14:59:24 2007 [pid 3459] [ftp] OK LOGIN;Client "127.0.0.1" ,anon password ”?"

/var/log/xferlog日志文件中数据的分析和参数说明

记录数据
 
参数名称
 
参数说明
 
Thu Sep 6 09:07:48 2007
 
当前时间
 
当前服务器本地时间,格式为: 
DDD MMM dd hh:mm:ss YYY
 
7
 
传输时间
 
传送文件所用时间,单位为秒
 
192.168.57.1
 
远程主机名称/IP
 
远程主机名称/IP
 
4323279
 
文件大小
 
传送文件的大小,单位为byte
 
/home/student/phpMyadmin-
2.11.0-all-languages.tar.gz
 
文件名
 
传输文件名,包括路径
 
b
 
传输类型
 
传输方式的类型,包括两种:
a以ASCII传输 b以二进制文件传输
 

 
特殊处理标志
 
特殊处理的标志位,可能的值包括:
_ 不做任何特殊处理
C 文件是压缩格式
U 文件是非压缩格式
T 文件是tar格式
 
i
 
传输方向
 
文件传输方向,包括两种:
o 从FTP服务器向客户端传输
i 从客户端向FTP服务器传输
 
r
 
访问模式
 
用户访问模式,包括:
a 匿名用户
g 来宾用户
r 真实用户,即系统中的用户
 
student
 
用户名
 
用户名称
 
ftp
 
服务名
 
所使用的服务名称,一般为FTP
 
0
 
认证方式
 
认证方式,包括:
0 无
1 RFC931认证
 
*
 
认证用户id
 
认证用户的id,如果使用*,则表示无法获得该id
 
c
 
完成状态
 
传输的状态:
c 表示传输已完成
i 表示传输示完成
 

最后,介绍常见的FTP命令,以及FTP数字代码的意义。

常见FTP命令及其功能

FTP命令
 
功能
 
FTP命令
 
功能
 
ls显示服务器上的目录
 
ls [remote-dir][local-file]
 
显示远程目录remote-dir,并存入本地文件local-file
 
get remote-file [local-file]从服务器下载指定文件到客户端 
 
mget remote-files
 
下载多个远程文件(mget命令允许用通配符下载多个文件)
 
put local-file [remote-file]从客户端上传指定文件到服务器
 
mput local-file
 
将多个文件上传至远程主机(mput命令允许用通配符上传多个文件)
 
open连接FTP服务器
 
mdelete [remote-file]
 
删除远程主机文件
 
close中断与远程服务器的ftp会话(与open对应)
 
mkdir dir-name
 
在远程主机中创建目录
 
open host[port]建立指定的ftp服务器连接,可指定连接端口
 
newer file-name
 
如果远程主机中file-name的修改时间比本地硬盘同名文件的时间更近,则重传该文件
 
cd directory改变服务器的工作目录
 
rename [from][to]
 
更改远程主机的文件名
 
lcd directory在客户端上(本地)改变工作目录
 
pwd
 
显示远程主机的当前工作目录
 
bye退出FTP命令状态
 
quit
 
同bye,退出ftp会话
 
ascii设置文件传输方式为ASCII模式
 
reget remote-file [local-file]
 
类似于get,但若local-file存在,则从上次传输中断处续传
 
binary设置文件传输方式为二进制模式
 
rhelp [cmd-name]
 
请求获得远程主机的帮助
 
![cmd [args]]在本地主机中交互shell后退回到ftp环境,如:!ls *.zip
 
rstatus [file-name]
 
若未指定文件名,则显示远程主机的状态,否则显示文件状态
 
accout [password]提供登录远程系统成功后访问系统资源所需的密码
 
hash
 
每传输1024字节,显示一个hash符号(#)
 
append local-file [remote-file]将本地文件追加到远程系统主机,若未指定远程系统文件名,则使用本地文件名
 
restart marker
 
从指定的标志marker处,重新开始get或put,如restart 130
 
bye退出ftp会话过程
 
rmdir dir-name
 
删除远程主机目录
 
case在使用mget命令时,将远程主机文件名中的大写转为小写字母
 
size file-name
 
显示远程主机文件大小,如:
size idle 7200
 
cd remote-dir进入远程主机目录
 
status
 
显示当前ftp状态
 
cdup进入远程主机目录的父目录
 
system
 
显示远程主机的操作系统
 
delete remote-file删除远程主机文件
 
user user-name [password][account]
 
向远程主机表明自己的身份,需要密码时,必须输入密码,如:user anonymous my@email
 
dir [remote-dir][local-file]显示远程主机目录,并将结果存入本地文件
 
help [cmd]
 
显示ftp内部命令cmd的帮助信息,如help get
 

FTP数字代码的意义

110 重新启动标记应答。
120 服务在多久时间内ready。
125 数据链路端口开启,准备传送。
150 文件状态正常,开启数据连接端口。
200 命令执行成功。
202 命令执行失败。
211 系统状态或是系统求助响应。
212 目录的状态。
213 文件的状态。
214 求助的讯息。
215 名称系统类型。
220 新的联机服务ready。
221 服务的控制连接端口关闭,可以注销。
225 数据连结开启,但无传输动作。
226 关闭数据连接端口,请求的文件操作成功。
227 进入passive mode。
230 使用者登入。
250 请求的文件操作完成。
257 显示目前的路径名称。
331 用户名称正确,需要密码。
332 登入时需要账号信息。
350 请求的操作需要进一部的命令。
421 无法提供服务,关闭控制连结。
425 无法开启数据链路。
426 关闭联机,终止传输。
450 请求的操作未执行。
451 命令终止:有本地的错误。
452 未执行命令:磁盘空间不足。
500 格式错误,无法识别命令。
501 参数语法错误。
502 命令执行失败。
503 命令顺序错误。
504 命令所接的参数不正确。
530 未登入。 
532 储存文件需要账户登入。
550 未执行请求的操作。
551 请求的命令终止,类型未知。
552 请求的文件终止,储存位溢出。  
553 未执行请求的的命令,名称不正确。

本文主要内容来源于: http://os.51cto.com/art/201008/221842_all.htm


Hello world!

Welcome to WordPress. This is your first post. Edit or delete it, then start writing!