syslog-ng详解——日志备份

目录
  1. logrotate开源软件
    1. logrotate配置文件
    2. logrotate源码获取
  2. syslog-ng-ctl
  3. 使用logrotate对syslog-ng进行日志备份

logrotate开源软件

logrotate为日志备份开源软件,其开源license为GPL。在Linux系统下,一般都默认安装好,配合syslog使用,可以使用man logrotate查看帮助信息:

NAME
   logrotate - rotates, compresses, and mails system logs

SYNOPSIS
   logrotate [-dv] [-f|--force] [-s|--state file] config_file ..

logrotate使用的主要在于掌握其配置文件语法,命令中常用选项为-f,表示强制执行备份动作(忽略触发备份的条件)

logrotate配置文件

一个典型示例配置文件如下:

# sample logrotate configuration file
   compress

   /var/log/messages {
          prerotate
                  sh  prerotate.sh #"execute prerotate script"
          endscript
          compress #compress the log
          create mode owner group #specify the log's owner and file mode
       rotate 5  #max rotate count
       size 100k #rotate begin when the file size excess 100k
       postrotate
           sh  postrotate.sh #"execute prerotate script"
       endscript
   }

其中,prerotate和postrotate用于指定当触发备份时执行的动作(相当于初始化和退出清理动作);
更多的选项可以参考man

logrotate源码获取

可以从Logrotate-3.11.0下载,依赖popt
logrotate的源码不多,也比较容易看懂,有兴趣的可以自行了解,一般在需要增加另外的配置选项时才会去修改源码。

syslog-ng-ctl

syslog-ng-ctl是和syslog-ng配套的软件,其源码也在syslog-ng源码包中,其使用unix-socket和syslog-ng进行通信,用于控制syslog-ng的一些行为,比如重新加载配置文件(syslog-ng-ctl reload,适用于在配置文件发生变化时,通知syslog-ng重新解析配置文件并用新的配置运行)等,具体可以通过syslog-ng-ctl -h查看。

使用logrotate对syslog-ng进行日志备份

有了logrotate和syslog-ng-ctl工具,下面说说如何对syslog-ng进行日志备份:
1、 写个小程序(类似cron定时任务的),定时执行下logrotate
其中logrotate配置中可以使用文件大小或者时间条件,当日志满足条件的时候触发备份;
记得在logrotate配置文件(logrotate.conf)中的加上

postrotate
    syslog-ng-ctl reload
endscript

让syslog-ng重新加载下配置。这是因为当触发日志备份时,syslog-ng的输出文件被移除了,需要重新reload下,syslog-ng才会重新生成输出文件。

syslog-ng详解——运行syslog-ng

目录
  1. 安装目录结构介绍
  2. 配置syslog-ng
  3. 运行syslog-ng

安装完syslog-ng后,就是如何使用的问题了。在https://syslog-ng.org 上可以下载syslog-ng的说明文档syslog-ng-ose-guide-admin.pdf,文档中介绍了syslog-ng的用法,很详细。下面介绍下如何使用syslog-ng。

安装目录结构介绍

在syslog-ng安装目录下,文件夹及作用如下:

  • bin 存放一些用于测试syslog-ng的工具,如loggen, pdbtool
  • etc 存放syslog-ng的配置文件,⚠主要为syslog-ng.conf
  • include 头文件
  • lib syslog-ng相关库文件,如libsyslog-ng.so已经syslog-ng的各种plugin
  • sbin syslog-ng可执行程序syslog-ng及交互程序syslog-ng-ctl
  • share 帮助文档
  • var存放syslog-ng运行时的一些信息

配置syslog-ng

在使用syslog-ng前,需要先对其进行配置,其对应的配置文件为syslog-ng.conf(位于syslog-ng安装目录etc下面),默认配置如下(为了能更好的描述配置文件,我加了个filter语法):

@version: 3.4
@include "scl.conf"

source s_local {
    system();
    internal();
};

source s_network {
    udp();
};

destination d_local {
    file("/var/log/messages");
};

filter f_level {
    "${LEVEL_NUM}" > "5";
};

log {
    source(s_local);
    # uncomment this line to open port 514 to receive messages
    #source(s_network);
    filter(f_level);
    destination(d_local);
};

上边配置了两个日志源:s_local及s_network, 一个日志目的地:d_local;
然后定义了日志收集语法 log {source(s_xxx); filter(f_xxx); destination(d_xxx);};.
即收集system(指送往/dev/log及/proc/kmsg的日志)及internal(指syslog-ng进程本身的日志),然后日志经过filter,将日志级别小于等于7(debug)级别的日志输出到/var/log/messages目录。

配置完syslog-ng后,便可以运行syslog-ng了。

运行syslog-ng

进入sbin目录,执行./syslog-ng运行syslog-ng.如果用上面的配置文件,会发现运行时报错:

system(): /proc/kmsg is not readable, please check permissions if this is     unintentional.; error='Permission denied (13)'
Error binding socket; addr='AF_UNIX(/dev/log)', error='Address already in     use (98)'
Error initializing message pipeline;

这是因为我们现在是以非root用户运行的,所以无法读取/proc/kmsg文件;另外/dev/log这个socket,当前rsyslogd进程正在使用,你也无法使用;
所以先将system这个语法用’#’注释掉,换成file(“…/syslog-ng-3.4.2/syslog-ng.in”);
还有d_local中的目的文件可以改成…/syslog-ng-3.4.2/syslog-ng.out,方便我们分析(这边我们也没有操作/var/log/messages的权限)。
其中…为软件的安装上级目录,且配置文件中的路径要使用绝对路径。

修改后的配置文件如下:

@include "scl.conf"

source s_local {
    #system();
    file("/home/user/software/syslog-ng-3.4.2/syslog-ng.in");
    internal();
};

source s_network {
    udp();
};

destination d_local {
    #file("/var/log/messages");
    file("/home/user/software/syslog-ng-3.4.2/syslog-ng.out");
};

filter f_level {
    "${LEVEL_NUM}" <= "7";
};

log {
    source(s_local);
    # uncomment this line to open port 514 to receive messages
    #source(s_network);
    filter(f_level);
    destination(d_local);
};

再次运行syslog-ng,可见在安装目录下生成了syslog-ng.out文件,cat看一下,输出:

Sep 13 22:17:28 localhost syslog-ng[84496]: syslog-ng starting up;     version='3.4.2'

这说明syslog-ng已经成功运行起来了。用ps命令看下:

$ps -elf|grep syslog-ng 
1 S user        84495      1  0  80   0 -  6150 wait   22:17 ?            00:00:00 supervising syslog-ng
1 S user        84496  84495  0  80   0 -  8832 ep_pol 22:17 ?            00:00:00 ./syslog-ng

其中,主进程为./syslog-ng

这时,我们可以试下往/home/user/software/syslog-ng-3.4.2/syslog-ng.in文件中输入一条信息,syslog-ng将会把此信息一起收集到syslog-ng.out文件中。

$echo "Hello, syslog-ng"  > syslog-ng.in
$cat syslog-ng.out
Sep 13 22:46:49 localhost Hello, syslog-ng

这样,我们就大概清楚了syslog-ng运行的原理:即将某个日志源的信息进行收集,然后对日志进行一些处理(如果过滤,文本替换等),然后输出到指定的目的地(本地或者网络)。

红黑树

目录
  1. 树的旋转
  2. 红黑树的插入
  3. 红黑树的删除

红黑树的5条性质:
1)每个结点要么是红的,要么是黑的。
2)根结点是黑的。
3)每个叶结点(叶结点即指树尾端NIL指针或NULL结点)是黑的。
4)如果一个结点是红的,那么它的俩个儿子都是黑的。
5)对于任一结点而言,其到叶结点树尾端NIL指针的每一条路径都包含相同数目的黑结点。
这决定了红黑树是相对平衡的二叉树,其查找,删除和插入的的时间复杂度为O(log n)

树的旋转

树的旋转,分为左旋和右旋,下面介绍下左旋(右旋的原理类似)
左旋是指以某个结点current和他的右子结点right为“支轴”,使right结点成为current子树新的根结点。即将right结点成为current结点的父结点,right结点的左子结点成为current结点的右子结点。其原理图如下:
left-rotate

左旋操作的伪代码如下(x为上图的pivot结点):

LEFT-ROTATE(T, x)  
y ← right[x] //Set y.  
right[x] ← left[y]      //Turn y's left subtree into x's right subtree.  
p[left[y]] ← x  
p[y] ← p[x]             //Link x's parent to y.  
if p[x] = nil[T]        //Set P's child node
   then root[T] ← y  
   else if x = left[p[x]]  
           then left[p[x]] ← y  
           else right[p[x]] ← y  
 left[y] ← x             //Put x on y's left.  
 p[x] ← y

红黑树的插入

1、 先按照二叉查找树插入的方式插入节点,然后把插入节点的左右孩子都置为叶结点nil,将插入节点涂色成红色。

2、在插入节点后,对节点进行旋转并重新着色,使整棵树保持红黑树的性质

这时会有下面几种情况:

  • 如果插入的是根结点,因为原树是空树,此情况只会违反性质2,所以直接把此结点涂为黑色。
  • 如果插入的结点的父结点是黑色,由于此不会违反性质2和性质4,红黑树没有被破坏,所以此时也是什么也不做。

但遇到下述三种情况时:

  • 插入修复情况1:如果当前结点的父结点是红色且祖父结点的另一个子结点(叔叔结点)是红色
  • 插入修复情况2:当前结点的父结点是红色,叔叔结点是黑色,当前结点是其父结点的右子
  • 插入修复情况3:当前结点的父结点是红色,叔叔结点是黑色,当前结点是其父结点的左子

对于插入修复情况1,对策:将当前结点的父结点和叔叔结点涂黑,祖父结点涂红,把当前结点指向祖父结点,从新的当前结点重新开始算法
对于插入修复情况2,对策:当前结点的父结点做为新的当前结点,以新当前结点为支点左旋,把当前结点指向祖父结点,从新的当前结点重新开始算法 ,。
对于插入修复情况3,对策:父结点变为黑色,祖父结点变为红色,在祖父结点为支点右旋

可以将上面5种情况看成状态机的5种状态,包括红黑树(已经调整到位,终止状态)共6种状态。红黑树的插入就是状态机几种状态的转移。

红黑树的删除

先按照二叉查找树删除结点的方式删除结点,然后再对整棵树进行调整,使其保持红黑树的性质
也是分为几种情况分别处理(其中可能发生情况的转化),略

socket通信服务端编程

目录
  1. 多进程
  2. 多线程
  3. 线程池(进程池)技术

当开发一个Unix服务器程序时,需要处理的1对多或者多对更多的问题,我们有如下类型的进程控制可供选择:

多进程

通过调用fork派生出一个子进程来处理客户端请求,但子进程的最大数目受限于由于操作系统对用户可以派生的子进程数的限制(这种情况可以使用预先派生子进程的进程池技术)。
缺点:执行fork是一个耗时操作,且最多数目有限制
整体流程图如下:
tcpip_sever_fork

编程注意点:

  1. 父进程需要处理子进程的SIGCHLD信号,做一些子进程结束后的清理工作,释放资源(调用waitpid等待子进程退出,防止出现僵尸进程及关闭accept的套接字)。

    1
    2
    3
    4
    5
    6
    7
    8
    void sig_chld(int signo)
    {
    pid_t pid;
    int status;
    while((pid=waitpid(-1, &status, WNOHANG)) > 0) //WNOHANG 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若结束,则返回该子进程的ID。
    printf("child %d terminated\n", pid);
    return;
    }
  2. 由于fork的写时复制特性,子进程执行fork后需要关闭父进程listen的描述符,然后再处理客户端的请求,处理完后关闭该socket

多线程

多线程技术相比多进程来说,由于线程是轻量级的进程,创建线程的速度和效率要高很多(需要指出的是,有的操作系统不支持多线程)。其流程和多进程一致(只是fork换成了pthread_create),代码框架如下(摘自unp源码):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/* include serv06 */
#include "unpthread.h"
int
main(int argc, char **argv)
{
int listenfd, connfd;
void sig_int(int);
void *doit(void *);
pthread_t tid;
socklen_t clilen, addrlen;
struct sockaddr *cliaddr;
if (argc == 2)
listenfd = Tcp_listen(NULL, argv[1], &addrlen);
else if (argc == 3)
listenfd = Tcp_listen(argv[1], argv[2], &addrlen);
else
err_quit("usage: serv06 [ <host> ] <port#>");
cliaddr = Malloc(addrlen);
Signal(SIGINT, sig_int);
for ( ; ; ) {
clilen = addrlen;
connfd = Accept(listenfd, cliaddr, &clilen);
Pthread_create(&tid, NULL, &doit, (void *) connfd); }
}
void *
doit(void *arg)
{
void web_child(int);
Pthread_detach(pthread_self());
web_child((int) arg);
Close((int) arg);
return(NULL);
}
/* end serv06 */
void
sig_int(int signo)
{
void pr_cpu_time(void);
pr_cpu_time();
exit(0);
}

编程注意点:
子线程要调用pthread_detach,由自己释放资源,避免资源泄露。

线程池(进程池)技术

线程池技术的原理:类似于某企业的客服系统,假设共有10个客服(相当于线程池中有10个线程),当业务繁忙时(服务人数大于10),则后面来的只能等待,直到有客服人员处理完业务后才能处理

  • 进程池技术
    对应于多进程并发服务器,可以使用预先派生子进程的方法,然后将客户端的请求交给子进程处理。
    程序流程:父进程在调用listen后,fork出一一定数量的子进程,然后可以执行下面的1)或2) :
    1) 各个子进程在函数体内循环调用accept等待客户端连接,并处理客户端请求
    2) 由父进程监听描述符,然后传递给各个子进程
    方法1)存在accept惊群现象:当有客户端连接时,所有N个子进程均被唤醒(因为他们监听的同一个listen socket);尽管所有N个子进程均被唤醒,但只有最先运行的子进程获得此客户端连接,其余子进程继续恢复睡眠(accept执行过程中发现accept队列长度为0),可以通过对accept调用加锁或者信号量来减少该问题带来的性能影响
    方法2) 需要增加对子进程的管理和调度,监控各个子进程的状态,然后通过描述符传递机制(可以通过socketpair机制来实现)将该描述符传递给空闲的子进程(同时也涉及accept fd队列管理,毕竟可能存在所有子进程都满载的情况)

  • 线程池技术
    类似进程池技术,但由于线程可以访问进程的全局变量空间,主程序可以维持一个队列,然后各个子进程从队列中获取connfd然后进行处理(需要添加互斥变量控制),不用进行父子进程间的描述符传递操作,更加实用。

综上,如果系统支持多线程的话,使用多线程技术可以获得更高的效率。

tips:

  1. 如何修改用户能fork的最大子进程数?
  • 通过ulimit -a查看用户能fork的最大子进程数目:
    max user processes (-u) 3810
  • 通过修改/etc/sercurity/limits.conf,增加用户限制条目:
    @user hard nproc 65535
  • 由于操作系统对系统最多pid数有限制,如果要突破该限制的话需要更改kernel.pid_max参数
    sysctl kernel.pid_max #查看
    sysctl -w kernel.pid_max=num #修改,其中num为进程数
  1. 如何获取进程耗费的cpu时间?
    使用getrusage函数,设置第一个参数为RUSAGE_SELF和RUSAGE_CHILDREN分别获取父子进程的cpu使用情况,在分别统计用户态耗时(ru_utime结构)及内核态耗时(ru_stime结构)

信息安全技术

目录
  1. 加密算法
  2. 数字签名
  3. 防火墙,路由等

加密算法

加密算法分为对称加密算法及非对称加密算法
对称加密算法
DES 、AES、 3DES、RC4

非对称加密算法
RSA D-H

数字签名

数字签名中使用的技术为RSA加密及报文摘要算法,其步骤如下:
1 Jack对消息明文PLAIN_TEXT进行报文摘要算法(如MD5,SHA),得到报文摘要,对报文摘要使用己方的RSA私钥进行加密,得到报文摘要密文MD_CIPHER,然后将消息明文PLAIN_TEXT和报文摘要密文一起发送给对方
2 Rose接收到消息明文PLAIN_TEXT和摘要密文MD_CIPHER后,使用对方(Jack)的RSA公钥对对摘要密文解密,得到报文摘要明文A;同时对收到的消息明文进行报文摘要算法,得到接收消息对应的报文摘要B;然后将B和A进行对比,如果一致的话说吗消息没有被篡改过,且这个消息确实是来自Jack
数字签名的原理:由于RSA私钥只由发送方持有,因此用此私钥加密过的报文摘要具有不可篡改和不可抵赖性。而对于不同消息具有不同的报文摘要,所以通过对比报文摘要能保证消息的有效性。
上述步骤中由于传输的消息为明文,能被第三方截获并加以利用。使用时经常是对消息明文进行AES加密,然后将AES密钥和报文摘要一起经过RAS加密,然后再转发给对方;
对方收到消息后,进行RAS解密,得到AES密钥和报文摘要,然后再利用AES密钥解密消息密文。 从而增强系统的安全性。

防火墙,路由等

可以由路由器或者某一个主机充当,来对经过其的数据包进行一定的操作(过滤,拦截等),主要是宽出严入(通常认为外网是非安全环境,内网是安全环境),起隔离内外网络的作用,保障内网安全。
软件防火墙:iptable
NAT其实也可以作为一种防火墙来使用

python argparser解析

目录
  1. 创建
  2. 添加参数
  3. 解析参数

parser是python标准库的一个参数解析模块,通过使用’import argparse’即可导入使用,可方便编写命令行接口。当命令有错时其会自动产生错误提示信息。

创建

1
>>> parser = argparse.ArgumentParser(description='Process some integers.')

添加参数

通过使用add_argument函数可以添加参数信息,其原型为:

1
ArgumentParser.add_argument(name or flags…[, action][, nargs][, const][, default][, type][, choices][, required][, help][, metavar][, dest])

示例如下

1
2
3
4
5
>>> parser.add_argument('integers', metavar='N', type=int, nargs='+',
... help='an integer for the accumulator')
>>> parser.add_argument('--sum', dest='accumulate', action='store_const',
... const=sum, default=max,
... help='sum the integers (default: find the max)')

函数中的参数说明如下:

  • type
    type 指出了参数的类型,如int, double
    parser.add_argument(‘intergers’, type=int, nargs=’+’)
  • nargs
    表示参数的个数,’+’表示1个以上,’*’表示0个以上
  • action
    action 参数指出了解析参数的动作, 如count表示计数,store_const
  • help
    为该参数的帮助信息
  • default
    默认值或者默认行为
  • metavar
    usage提示信息中的参数名
  • const
    常量或者固定的行为,通过匹配参数选项来决定,但不能通过输入指定,如例子中的const=sum
  • dest
    parse_args的返回值名称

解析参数

1
2
>>> args = parser.parse_args()
>>> print args.accumulate(args.integers)

运行上面的例子:

1
2
3
4
5
$ python prog.py 1 2 3 4
4
$ python prog.py 1 2 3 4 --sum
10

parser支持更多选项,请查阅其官网文档argparse — Parser for command-line options, arguments and sub-commands

入门资料:
Argparse Tutorial

python 爬虫初窥

目录

github下了个crawel入门的python 源码,我fork了一份,研究下看看:
Mini-Spider

代码调用关系:
入口(执行方式):
test_all.sh

1
python3 mini-spider -a http://bbs.fengniao.com/forum/9373824.html jpg html

先由main.py中调用parser.parse_args解析参数,match规则为:

1
2
3
# Add arguments.
analysis_help = 'Analysis a URL.'
parser.add_argument('-a', help=analysis_help, nargs='+', dest='analysis_url', metavar='[URL]')

进一步调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Parse analysis url.
if args.analysis_url:
if len(args.analysis_url) == 1: #需要至少指定两个参数,指定需要获取的资源类型
print('Error: Please input what resource you are looking for!')
return False
timeout = 2.0
if args.time_out:
timeout = args.time_out[0]
if args.similarity:
spider = MiniSpider(args.analysis_url[0], search=args.analysis_url[1:],
similarity_threshold=args.similarity[0], timeout=timeout)
spider.analysis_url()
else:
spider = MiniSpider(args.analysis_url[0], search=args.analysis_url[1:], similarity_threshold=0.6,
timeout=timeout)
spider.analysis_url()

解析args

最后调用spider.analysis_url做实际性的工作(解析url并获取资源).

来看下MiniSpider这个类(scheduler.py):

  1. 调用init函数解析url及资源类型列表
  2. 调用analysis_url函数下载资源,具体如下:
  • 调用_url_read下载网页
  • 使用python正则表达式查找匹配的资源match = re.findall(i, content)
  • 使用_handle_match处理结果self._handle_match(match_list)
  • 使用_save_temp保存结果

进阶:

Python网络爬虫实战项目代码大全(长期更新,欢迎补充) – Python中文社区 – 知乎专栏

Wi-Fi

目录
  1. 使用wpa_cli连接Wi-Fi
  2. wpa_supplicant
  3. WI-FI用户及内核调用分析
  4. 报文分析

使用wpa_cli连接Wi-Fi

wpa_cli -h
Connect to password protected wifi network using adb shell

wpa_supplicant

帮助文档

WI-FI用户及内核调用分析

Analysis of Open Source Drivers for IEEE 802.11 WLANs

https://vm.thekkedam.org/assets/docs/thesis/Analysis_of_Open_Source_Drivers_for_IEEE_802.11_WLANs_Vipin_Madhavanunni.pdf

报文分析

实战无线网络分析(篇一)无线监听

wireshark中无线帧的类型、子类型对照表

软件:

window: wireshark omnipeek

linux:aircrack-ng

mac:

本站总访问量