通过pam.d限制linux登入

想设置一下Linux下系统登录用户密码输错次数的限制。由于知道是/etc/pam.d/system-auth文件来进行控制的,所以就查看了一下这个文件。

 

system-auth是由以下几个部分组成的

auth,account,password,session。每个部分又都有不同的方法,针对方法的使用也有不同的控制选项,一般有这些控制选项:required,requisite,sufficient,optional,include 这5种

 

具体内容man pam.d就都能看到,而很明显的,验证登录是通过auth这个部分来的。


account
this module type performs non-authentication based account management. It is typically used to restrict/permit access to a service
based on the time of day, currently available system resources (maximum number of users) or perhaps the location of the applicant
user -- ’root’ login only on the console.

auth
this module type provides two aspects of authenticating the user. Firstly, it establishes that the user is who they claim to be, by
instructing the application to prompt the user for a password or other means of identification. Secondly, the module can grant
group membership or other privileges through its credential granting properties.

password
this module type is required for updating the authentication token associated with the user. Typically, there is one module for
each ’challenge/response’ based authentication (auth) type.

session
this module type is associated with doing things that need to be done for the user before/after they can be given service. Such
things include the logging of information concerning the opening/closing of some data exchange with a user, mounting directories,
etc.

The third field, control, indicates the behavior of the PAM-API should the module fail to succeed in its authentication task. There
are two types of syntax for this control field: the simple one has a single simple keyword; the more complicated one involves a
square-bracketed selection of value=action pairs.

For the simple (historical) syntax valid control values are:

required
failure of such a PAM will ultimately lead to the PAM-API returning failure but only after the remaining stacked modules (for this
service and type) have been invoked.

requisite
like required, however, in the case that such a module returns a failure, control is directly returned to the application. The
return value is that associated with the first required or requisite module to fail. Note, this flag can be used to protect against
the possibility of a user getting the opportunity to enter a password over an unsafe medium. It is conceivable that such behavior
might inform an attacker of valid accounts on a system. This possibility should be weighed against the not insignificant concerns
of exposing a sensitive password in a hostile environment.

sufficient
success of such a module is enough to satisfy the authentication requirements of the stack of modules (if a prior required module
has failed the success of this one is ignored). A failure of this module is not deemed as fatal to satisfying the application that
this type has succeeded.

optional
the success or failure of this module is only important if it is the only module in the stack associated with this service+type.

include
include all lines of given type from the configuration file specified as an argument to this control.

而所有的pam的方法都在/lib64/security/ 目录下,查询到登录验证是通过pam_tally2这个来进行的。通过man pam_tally2找到了很多对应的方法。因为之前查了很多网上的方法都是只针对普通用户的,不针对root用户的。root的方法跟普通的是不一样的。从这个来看以后还是得多看man帮助。

 

下面这个就是修改的system-auth,这是修改了auth部分的第2行而已。


cat /etc/pam.d/system-auth
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth        required      pam_env.so
auth       required     pam_tally2.so deny=3 onerr=fail no_magic_root even_deny_root unlock_time=120 root_unlock_time=120
auth        sufficient    pam_unix.so nullok try_first_pass
auth        requisite     pam_succeed_if.so uid >= 500 quiet
auth        required      pam_deny.so

account     required      pam_unix.so
account     sufficient    pam_succeed_if.so uid < 500 quiet
account     required      pam_permit.so

password    requisite     pam_cracklib.so try_first_pass retry=3
password    sufficient    pam_unix.so md5 shadow nullok try_first_pass use_authtok
password    required      pam_deny.so

session     optional      pam_keyinit.so revoke
session     required      pam_limits.so
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required      pam_unix.so

近日linux记录

最近忙于部署一些应用,发现自己对于一些centos的基础不是很了解,主要是init.d下的一些脚本和bash的一些信号了解点了。

1

自己写init.d下的启动脚本的时候必须有下面2行

# chkconfig: 345 85 15
# description: Nginx is an HTTP(S) server, HTTP(S) reverse

本来一直以为只是简单的注释,但是发现其实并没有那么简单,这2行是必须的。
chkconfig 这行是为了在 chkconfig nginx on/off指定的时候用的。

其中345表示在哪些运行级别启用,一般就是都是345这3个级别。

85的意义是当你chkconfig nginx on的时候,它在对应的运行级别下的启动顺序是85,在这里就是S85nginx。这个是从0开始,最终到99,一般99是rc.local

15的意义是当你chkconfig nginx off的时候,它在对应的运行级别下的停止顺序是15,在这里就是K15nginx。

description 就是描述这个应用程序的。

2
在stop方法中我们经常用到killproc这个方法。但是在系统中其实没有killproc这个方法,只有kill和killall。其实这个方法是在/etc/rc.d/init.d/functions这里进行定义的。

这也是为什么要在开头source进去的原因之一。

3
在启动和关闭应用程序中返回的[success]和[failure]其实直接通过echo出来的,而是通过获取返回信号再进行echo的


echo -e "33[1;32;1m[success]33[0m"

出来的。而是 daemon 方法返回的结果。这就是为什么start方法中启动应用程序之前都加上 daemon,而#?就是返回的信号。当然daemon也是在/etc/rc.d/init.d/functions中定义的。当然返回的内容其实也是上面说的echo的那个。

4

kill 的各种信号。之前我常用的几个信号是0,9,15.

0 表示测试这个进程是否活着

9 表示强制关闭

15 表示正常的关闭,默认不加信号就是指代15

但是发现有些应用程序还有USR1这样的信号,比如在nginx中reopen log,这个用在轮询日志的时候使用。

关于更多Nginx中的各种信号请参考http://wiki.nginx.org/CommandLine

下面是1-31所有信号的解释,来源是soso上的问答,原始来源找不到了,不过还是很感谢。

但是现在有增加了很多信号,通过kill -l可以查看

kill -l

1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP

6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1

11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM

16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP

21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ

26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR

31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3

38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8

43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13

48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12

53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7

58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2

63) SIGRTMAX-1 64) SIGRTMAX

下面我们对编号小于SIGRTMIN的信号进行讨论。

1) SIGHUP

本信号在用户终端连接(正常或非正常)结束时发出, 通常是在终端的控制进程结束时, 通知同一session内的各个作业, 这时它们与控制终端不再关联。

登录Linux时,系统会分配给登录用户一个终端(Session)。在这个终端运行的所有程序,包括前台进程组和后台进程组,一般都属于这个 Session。当用户退出Linux登录时,前台进程组和后台有对终端输出的进程将会收到SIGHUP信号。这个信号的默认操作为终止进程,因此前台进 程组和后台有终端输出的进程就会中止。不过可以捕获这个信号,比如wget能捕获SIGHUP信号,并忽略它,这样就算退出了Linux登录,wget也 能继续下载。

此外,对于与终端脱离关系的守护进程,这个信号用于通知它重新读取配置文件。

2) SIGINT

程序终止(interrupt)信号, 在用户键入INTR字符(通常是Ctrl-C)时发出,用于通知前台进程组终止进程。

3) SIGQUIT

和SIGINT类似, 但由QUIT字符(通常是Ctrl-\)来控制. 进程在因收到SIGQUIT退出时会产生core文件, 在这个意义上类似于一个程序错误信号。

4) SIGILL

执行了非法指令. 通常是因为可执行文件本身出现错误, 或者试图执行数据段. 堆栈溢出时也有可能产生这个信号。

5) SIGTRAP

由断点指令或其它trap指令产生. 由debugger使用。

6) SIGABRT

调用abort函数生成的信号。

7) SIGBUS

非法地址, 包括内存地址对齐(alignment)出错。比如访问一个四个字长的整数, 但其地址不是4的倍数。它与SIGSEGV的区别在于后者是由于对合法存储地址的非法访问触发的(如访问不属于自己存储空间或只读存储空间)。

8) SIGFPE

在发生致命的算术运算错误时发出. 不仅包括浮点运算错误, 还包括溢出及除数为0等其它所有的算术的错误。

9) SIGKILL

用来立即结束程序的运行. 本信号不能被阻塞、处理和忽略。如果管理员发现某个进程终止不了,可尝试发送这个信号。

10) SIGUSR1

留给用户使用

11) SIGSEGV

试图访问未分配给自己的内存, 或试图往没有写权限的内存地址写数据.

12) SIGUSR2

留给用户使用

13) SIGPIPE

管道破裂。这个信号通常在进程间通信产生,比如采用FIFO(管道)通信的两个进程,读管道没打开或者意外终止就往管道写,写进程会收到SIGPIPE信号。此外用Socket通信的两个进程,写进程在写Socket的时候,读进程已经终止。

14) SIGALRM

时钟定时信号, 计算的是实际的时间或时钟时间. alarm函数使用该信号.

15) SIGTERM

程序结束(terminate)信号, 与SIGKILL不同的是该信号可以被阻塞和处理。通常用来要求程序自己正常退出,shell命令kill缺省产生这个信号。如果进程终止不了,我们才会尝试SIGKILL。

17) SIGCHLD

子进程结束时, 父进程会收到这个信号。

如果父进程没有处理这个信号,也没有等待(wait)子进程,子进程虽然终止,但是还会在内核进程表中占有表项,这时的子进程称为僵尸进程。这种情 况我们应该避免(父进程或者忽略SIGCHILD信号,或者捕捉它,或者wait它派生的子进程,或者父进程先终止,这时子进程的终止自动由init进程来接管)。

18) SIGCONT

让一个停止(stopped)的进程继续执行. 本信号不能被阻塞. 可以用一个handler来让程序在由stopped状态变为继续执行时完成特定的工作. 例如, 重新显示提示符…

19) SIGSTOP

停止(stopped)进程的执行. 注意它和terminate以及interrupt的区别:该进程还未结束, 只是暂停执行. 本信号不能被阻塞, 处理或忽略.

20) SIGTSTP

停止进程的运行, 但该信号可以被处理和忽略. 用户键入SUSP字符时(通常是Ctrl-Z)发出这个信号

21) SIGTTIN

当后台作业要从用户终端读数据时, 该作业中的所有进程会收到SIGTTIN信号. 缺省时这些进程会停止执行.

22) SIGTTOU

类似于SIGTTIN, 但在写终端(或修改终端模式)时收到.

23) SIGURG

有”紧急”数据或out-of-band数据到达socket时产生.

24) SIGXCPU

超过CPU时间资源限制. 这个限制可以由getrlimit/setrlimit来读取/改变。

25) SIGXFSZ

当进程企图扩大文件以至于超过文件大小资源限制。

26) SIGVTALRM

虚拟时钟信号. 类似于SIGALRM, 但是计算的是该进程占用的CPU时间.

27) SIGPROF

类似于SIGALRM/SIGVTALRM, 但包括该进程用的CPU时间以及系统调用的时间.

28) SIGWINCH

窗口大小改变时发出.

29) SIGIO

文件描述符准备就绪, 可以开始进行输入/输出操作.

30) SIGPWR

Power failure

31) SIGSYS

非法的系统调用。

在以上列出的信号中,程序不可捕获、阻塞或忽略的信号有:SIGKILL,SIGSTOP

不能恢复至默认动作的信号有:SIGILL,SIGTRAP

默认会导致进程流产的信号有:SIGABRT,SIGBUS,SIGFPE,SIGILL,SIGIOT,SIGQUIT,SIGSEGV,SIGTRAP,SIGXCPU,SIGXFSZ

默认会导致进程退出的信号有:SIGALRM,SIGHUP,SIGINT,SIGKILL,SIGPIPE,SIGPOLL,SIGPROF,SIGSYS,SIGTERM,SIGUSR1,SIGUSR2,SIGVTALRM

默认会导致进程停止的信号有:SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU

默认进程忽略的信号有:SIGCHLD,SIGPWR,SIGURG,SIGWINCH

此外,SIGIO在SVR4是退出,在4.3BSD中是忽略;SIGCONT在进程挂起时是继续,否则是忽略,不能被阻塞。

###########################################
Best regards Timo Seven
blog:http://www.timoseven.com
twitter: http://twitter.com/zauc
Linux System Admin & MySQL DBA

grep用法

grep是一个常用的命令。
以前只知道^$.+?*这些用法。以及-E的正则表达式。

今天偶然发现还有一些更高级的匹配模式。具体如下:

[:alnum:]    字母与数字字符
[:alpha:]    字母
[:ascii:]    ASCII字符
[:blank:]    空格或制表符
[:cntrl:]    ASCII控制字符
[:digit:]    数字
[:graph:]    非控制,非空格字符
[:lower:]    小写字母
[:print:]    可打印字符
[:punct:]    标点符号字符
[:space:]    空白字符,包括垂直制表符
[:upper:]    大写字母
[:xdigit:]    十六进制数字

还有一些常用的就是
{n}            必须匹配n次
{n,}        必须匹配n次或n次以上
{n,m}        必须匹配n到m次,包含n和m

下面我们进行简单的测试下就知道了
文本内容如下test.txt

A novel is a book of long narrative in literary prose

The genre has historical roots both in the fields of the medieval and early modern romance and in the tradition of the novella

The latter supplied the present generic term in the late 18th century.

Further definition of the genre is historically difficult.

The construction of the narrative, the plot, the way reality is created in the works of fiction.

Most of these requirements were introduced in the 16th and 17th  centuries in order to give fiction a justification outside the field of  factual history.

The individualism of the presentation makes the  personal memoir and the autobiography the two closest relatives among  the genres of modern histories.
grep a[[:blank:]] test.txt

5561066808_a504984507_z.jpg

grep -E [a-z]\{10\} test.txt

5561066804_ae4c0ebe60_z.jpg

grep Th.[[:space:]] test.txt

5561066798_fb5625ab54_z.jpg

###########################################

Best regards
Timo Seven
blog:http://www.timoseven.com
twitter: http://twitter.com/zauc
Linux System Admin  & MySQL DBA

MySQL服务器的linux性能优化和扩展技巧

MySQL服务器的linux性能优化和扩展技巧

作者:Yoshinori Matsunbu

作者现在是DeNA公司的数据库和基础设施架构师。之前在SUN公司工作。他也是HandlerSocket的作者。这个是MySQL的NoSQL插件。

本文是根据他的PPT整理而成的,如有不正确敬请指教。

本文有可以直接点击下载:linux性能优化技巧

本文主要的内容有如下:

  1. 内存和SWAP空间管理
  2. 同步I/O,文件系统和I/O调度
  3. 有用的命令和工具:iostat, mpstat, oprofile, SystemTap, gdb

第一部分:内存和SWAP空间管理

内存也就是随机访问内存

内存是最重要的硬件部件对于RDBMS(relation database management system)。

内存的访问速度远远超过HDD(普通硬盘)/SSD(固态硬盘)

内存:60ns, 但是还没达到每秒10W

HDD:5ms

SSD:100-500us

他们之间的关系为:

1s = 1000ms

1ms = 1000us

1us = 1000ns

所以16GB-64GB对于现在是非常合适的。(好像之前在人人的时候都是72G)

热点应用的数据都需要缓存在内存中

当然最小化热点数据大小也是很重要的,主要有以下几种措施:

使用紧凑长度的数据类型(SMALLINT来替代VARCHAR/BIGINT, TIMESTAMP来替代DATETIME等等)

不要创建无用的索引

删除不必要的数据或者将这些数据移到存档表中,来保证热点的表尽量的小

下面这个测试就是针对不同内存大小服务器的一个测试,测试数据在20-25GB(200个数据仓库,运行一小时),使用的是DBT-2测试,这是一 种密集写的测试,服务器的配置为Nehalem 2.93 * 8 cores, MySQL 5.5.2, 4 RAID 1+0 HDDs

从上面这个表格中我们可以很明显看到巨大的差异当数据全部缓存到内存中。

内存大小会影响所有操作,不管是SELECT,还是INSERT/UPDATE/DELETE操作。

INSERT:当往一个随机排序的索引中插入数据的时候会造成随机的读/写

UPDATE/DELETE: 当更改数据的时候会导致磁盘的读/

还有一个提高性能的方法是使用直接I/O(Direct I/O)

从上图中我们可以看到Direct I/O就是直接跳过了文件系统的cache。

Direct I/O对于完全利用内存是非常重要的。我们可以通过设置innodb_flush_method=O_DIRECT来运行。

注:文件I/O必须是512byte为一个单位,同时O_DIRECT不能用在InnoDB日志文件,二进制日志文件,MyISAM引擎,PostgreSQL数据文件等等。

不要分配太多的内存

这个其实只要分配到足够其它应用程序使用,而不要最后导致系统没有内存可用。

上图中我们可以看到总共系统32G内存,而Mysqld已经使用了30G,而系统居然还只有150M可用,这样是非常危险。

当系统没有内存可用时会发生什么事情呢?

减少文件系统缓存来分配内存空间,这个文件系统缓存就是上图中cached部分

替换掉一些进行来分配内存空间。也就是将一些内存空间移动到SWAP

SWAP是坏的

进程空间会写入到磁盘上(swap out),而这些进程空间本应该是写入到内存中的。

当访问磁盘上的进程空间会导致磁盘读写(swap in)

同时会产生巨量的随机磁盘读写

那也许有些人会想到把swap大小设置为0,但是这样其实是非常危险的。

因为当内存和SWAP都不可用的时候的,OOM Killer(out of memory)就会被启用。OOM Killer会杀掉任何进程来分配内存空间。

最耗费内存的进程会被最先杀掉,在mysql服务器上这个一般是mysqld进程

mysqld会被中止关闭,而在重启时候会进行崩溃修复。

OOM Killer的策略是根据/proc/<pid>/oom_score来进行倒序排列,也就是oom_score最大的会被第一个干掉

通常mysqld会拥有最高的值,因为oom_score是根据内存大小,CPU时间,运行时间来判断。

OOM Killer杀死进程会花费很长的时间,而这期间我们不能干任何事情。

所以不要设置swap为0

上图中我们看到swap被设置为了0,而一旦没有内存可用OOM Killer就会被启用。

一些CPU核心会耗尽100%的系统资源。在上图中我们就看到的就是一个CPU核使用100%的CPU资源。而这个时候连接终端(SSH)就会断掉。

所以swap是不好的,但是OOM Killer更不好。

如果/proc/<PID>/oom_adj被设置为-17,OOM Killer就不会杀掉这个进程。所以给SSHD进程设置为-17是一个有效防止断线的方法。

echo -17 > /proc/<PID>/oom_adj

但是不要给mysqld设置为-17,因为如果最耗内存的进程没被杀死,linux依然没有任何可用的内存。而我们就会在很长很长很长的时间内没法干任何事情。

因此,对于一个生产环境的系统SWAP是必须的。但是我们同样不希望Mysql进行swap out。

我们就需要知道mysql中哪些东西耗费内存

RDBMS:主要的进程空间是被使用的(innodb_buffer_pool, key_buffer, sort_buffer等等),有时候文件系统的cache也会被使用(MyISAM引擎的文件等等)

管理操作:(备份等等),这个时候主要是文件系统cache会被使用

我们要让mysql在内存中,也不要分配大量的文件系统cache。

要特别注意备份操作

因为在备份的时候往往会拷贝大文件,而拷贝大文件就会使用到swap

这个时候我们可以设置/etc/sysctl.conf中vm.swappiness=o来避免这个,而默认值是60

我们看看下图就知道前后的区别了

我们看到,同样是拷贝大文件,下面这个swap才之用了216K

这是因为当物理内存耗尽的时候,linux内核会减少文件系统cache作为最高优先级(低优先级就增加那个值)

当文件系统cache也没有可用的时候,就会开始使用swap。而这个OOM Killer也不会被启用,因为还有足够的swap空间呢。这样才是安全的。

内存分配

mysqld使用malloc()/mmap()方法来进行内存分配

如果要使用更快更多并发的内存就要用tcmalloc()这样的方法

安装Google Perftools(tcmalloc被包含在了里面)

yum install libunwind

cd google-perftools-1.5 ; ./configure –enable-frame-pointers; make; make install

export LD_PRELOAD=/usr/local/lib/tcmalloc_minimal.so;

mysqld_safe &

而对于InnoDB来说它会使用它自己的内存分配器

这个可以在InnoDB Plugin中进行更改

如果innodb_use_sys_malloc=1(默认为1),InnoDB就会使用操作系统的内存分配器

这样tcmalloc通过设置LD_PRELOAD就会被使用。

下面这个是对2种不同的内存分配器进行测试,从中可以看到在内存越大时候,这个差距也越明显。平台还是Nehalem 2.93 * 8 cores, MySQL 5.5.2, 数据量也是20-25GB(200个仓库运行1个小时)

要个别注意分配给每个session的内存

不要分配超过需求过多的的内存大小(特别是针对每个session的内存)

因为分配2MB内存比分配128KB内存会花更多的时间。当分配内存小于等于512MBLinux malloc()方法内部会调用brk()方法,其它时候会调用mmap()。

在一些情况下,分配给每个session过多的内存回到反向的性能影响。

从上面我们可以很明显的看到差距。

在大部分情况都不要分配超过需要过多的内存,当然也有特别的场景(比如:MyISAM + LIMIT + FullScan)

第二部分:同步I/O,文件系统和I/O调度

文件i/O和同步写

RDBMS会经常调用fsync()方法(每一次事务提交,检查点等等)

确认使用RAID卡上的电池备份写缓存(BBWC Battery Backed up Write Cache)

10000+次的fsync()每秒,而不用BBWC会减少200次左右。这个都是在磁盘的情况下。

为了安全的原因需要关闭写缓存。

不要在文件系统中设置“写隔离”(在很多情况下默认都是打开的)

就算使用了BBWC,写入到磁盘还是会非常慢。这是因为一旦打开写隔离,那只有把所有数据写入到磁盘才会关闭隔离。

Ext3中通过mount -o barrier=0,在xfs中是mount -o nobarrier,而在drbd中是在drbd.conf文件中写入no-disk-barrier。

写隔离技术对于防止脏页是非常有作用的,但是在mysql服务器上我们可以关闭,因为都是内部通过事务来提交了。对于其它应用的服务器我们要审慎对待。

复写还是追加写

一些文件是复写的(固定文件大小的),其它的是追加写的(增长的文件长度的)

复写:InnoDB日志文件

追加写: 二进制日志文件

追加写+fsync()比复写+fsync()要慢的多,这是因为追加写每次都要分配文件需要的空间,同时元数据需要通过每个fsync()来刷新到磁盘上。

对于复写可以达到10000+每秒的fsync,而追加写只有3000次左右。

追加写的速度依赖于文件系统。

copy-on-write的文件系统如Solaris的ZFS就会对于追加写足够快,可以达到7000+次。

特别小心设置sync-binlog=1为二进制日志,设置为1的时候会每个事务写入一次就会自动同步硬盘一次。这样效率会非常差

这个时候可以考虑ZFS

检查“预分配二进制日志”的工作日志。Http://forge.mysql.com/worklog/task.php?id=4925

不要太频繁的更新文件

innodb_autoextend_increment=20(默认为8),这个表示表空间文件每次扩展空间都到20M

快速文件I/O健康检测

启用BBWC,并且写隔离是关闭的。

复写+fsync()测试:运行mysqlslap插入(InnoDB, 单线程, innodb_flush_log_at_trx_commit=1 log buffer每次事务提交都会写入log file,并且将数据刷新到磁盘中去);检查的qps超过了1000.

具体使用方法可以参考http://dev.mysql.com/doc/refman/5.1/en/mysqlslap.html

缓冲区和异步写

一些文件I/O操作既不是使用Direct I/O,也不是使用同步写,如:文件复制,MyISAM, mysqldump, innodb_flush_log_at_trx_commit=2等等

在文件系统缓存的脏页最终都要被刷新到磁盘上去。pdflush用作刷新到磁盘上的,它最大可以8个线程同时进行。

这个是高度依赖于vm.dirty_background_ratio和vm.dirty_ratio这2个系统参数的。当脏页数量达到 dirty_background_ratio(默认是10%,64GB内存的话就是当cache达到6.4GB)的时候就会开始刷新到磁盘上。

当达到dirty_ratio的时候就会强制进行刷新到磁盘,默认是40%

强制和粗鲁的脏页刷新是有问题的。当大幅增加传输延迟时间,会导致所有的buffer的写操作都变成了同步的。

过分的刷新脏页到磁盘

执行刷新,会产生大量的写操作

减少vm.dirty_background_ratio的值

升级内核到2.6.22或者更高版本

pdflush线程会给每个设备进行分配,刷新一个慢设备的时候不会阻碍其它设备的pdflush线程。

文件系统—EXT3

这是一种现在最广泛使用的文件系统,但是它明显不是最好的。

首先它在删除大文件的会花费很长的时间:在执行的时候内部会有很多随机的磁盘I/O(HDD)。而对于mysql来说,当执行DROP table的时候,所有open/lock表的客户端线程都会被block掉(LOCK_open mutex)。还有要特别注意使用MyISAM,使用innodb_file_per_table的InnoDB,以及PBXT引擎等。

写文件是串行化的

串行化是通过i-mutex(互斥),分配给每个inode

有时候它比分配单个大文件会快。

对于快速的存储设备缺少优化(如PCI-E接口的SSD)

使用“dir_index”来加快搜索文件,这个需要在文件系统中增加这个属性,tune2fs -O +dir_index/dev/hda5

关闭barrier。

文件系统—XFS/EXT2/BTRFS

xfs的特点

快速删除文件

当使用O_DIRECT可以进行并发写入到一个文件

在RHEL中没有官方支持

可以设置“nobarrier”来关闭写隔离

ext2

更快速的写,因为它不支持日志,所以出现问题不能进行恢复

fsck的时间很长

在active-active的冗余环境下使用(比如MySQL的replication)

在一些情况下,ext2拥有更好的性能

btrfs(开发中)

这是一种跟ZFS一样的copy-on-write的文件系统

支持事务(没有half-block更新)

snapshot备份无需额外的开销

下图就是ext3和xfs在不同的磁盘上的随机写的一个对比图。HDD就是普通磁盘,Intel应该是普通的SATA接口的SSD,而FUSION应该是pci-e接口的SSD

上面的HDD是4块SAS RAID1。

I/O调度器

注:RDBMS(特别是InnoDB)都会调度I/O请求,所以理论上Linux I/O调度器并不是必须的。

Linux的I/O调度器可以有效的控制I/O请求,I/O调度器类型和队列大小都是要考虑的问题。

Linux I/O调度器的类型(根据RHEL5,内核2.6.10)

noop:排序进入的I/O请求通过逻辑block地址,其实就是FIFO,先进先出。

Deadline:读请求(sync)的请求比写请求(async)拥有更高的优先级。其它的就是FIFO,这样就能避免I/O请求饥饿的问题。

cfg(默认):对于每个I/O线程公平的策略I/O,它会对所有的I/O请求进行逻辑block地址重新进行排序,这样减少了查找block地址的时间。

Anticipatory:在2.6.33内核中已经删除,所以请不要再进行使用了。

下面会并发运行2个压力测试程序

多线程的随机磁盘读(默认RDBMS读)

单线程的复写+fsync()(模拟redo日志写)

从上面图中我们可以很容易的看到cfq和noop的差距。操作为RHEL5.3和SUSE11,4 HDD的RAID 1+0。

在RDBMS中,写的IOPS通常都非常高,因为HDD写cache每秒需要控制成千上万的事务提交(write+fsync)

写入的IOPS会被调整为每个线程读IOPS,所以很明显的减少总的IOPS。

下面这个是4个不同的I/O策略的测试图,使用的DBT-2测试,引擎为InnoDB

可以看到noop和deadline差距还是很少的,但是比cfq还是高出30%的样子。

下面这个图是更改了I/O策略的队列大小后的对比图,所以用的MyISAM引擎的比较结果

queue size=N, I/O调度器就会排序N个请求来优化磁盘查找。

MyISAM引擎不会在内部优化I/O请求,它高度依赖OS和存储。当对索引进行插入会导致巨量的随机磁盘读写。

增加I/O队列大小可以减少磁盘查找的开销。Echo 100000 > /sys/block/sdX/queue/nr_requests

这种操作对于InnoDB没有影响,InnoDB会在内部进行排序I/O请求。

有用的命令和工具

iostat

mpstat

oprofile

SystemTap(stap)

gdp

作者讲了这5种命令和工具,但是我这边只说到前面3个命令和工具。

iostat

每个设备的详细的I/O统计数据,对于RDBMS非常重要,因为它经常成为I/O瓶颈。

Iostat -xm 10每10秒执行一次。主要注意r/s和w/s,svctm是平均服务时间(milliseconds),而util就是(r/s+w/s)*svctm

svctm越低意味着r/s和w/s越高。所以我们不要太相信util,我们主要关注的是r/s,w/s和svctm这几个值。如果你的IOPS是1000,那如果svctm是1ms的话,那util就是100。所以当svctm大于1的话就算是有问题了。

Mpstat

以前我一直用vmstat,但是vmstat是显示的所有CPU的一个平均数,后来发现mpstat是能显示每个CPU核的统计。经常会发现某个 CPU核会占满100%的资源,而其它CPU核却还空闲着。而如果你使用vmstat/top/iostat/sar你却无法发现难个CPU的瓶颈。

你也可以用mpstat来检查网络的瓶颈。

从上面VMSTAT的图中我们看CPU的空闲度达到了88%,但是通过MPSTAT图中发现是一个CPU满了,而其它CPU都完全空闲了,这个就是 CPU资源分配不均。这个在之前我们nginx cache服务器上也发现了类似的问题,最终解决后发现性能提升了30%以上。

Oprofile

oprofile是可以查看运行进程的CPU使用状况的概括。你可以很容易的确认那些方法用掉了这些CPU资源。这个工具同时支持系统空间和用户空 间。这个工具主要是用于数据库的内部开发者。如果发现有特别的方法占用了大部分的资源,程序员最好跳过这些方法的调用。对于检查低cpu活动,IO限制和 互斥等情况没有用处。

如何使用呢?

Opcontrol –start –no-vmlinux

benchmarking

opcontrol –dump

opcontrol –shutdown

opreport -l /usr/local/bin/mysqld

执行完如下结果

###########################################

Best regards
Timo Seven
blog:http://www.timoseven.com
twitter: http://twitter.com/zauc
Linux System Admin & MySQL DBA

vmstat信息解读

本文参考了ibm press的《Linux 服务器性能调整》,这本书全面介绍了性能调整的方方面面,但是把很多无用的显示信息放到正文中,这样很不爽

vmstat是在xnix我们常用的性能监控工具。常用的命令有vmstat 5 5,这个表示每5秒统计一次,共统计5次。

[root@ns ~]# vmstat 5 5
procs ———–memory———- —swap– —–io—- –system– —–cpu——
r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
0  0 1968768  83276 206644 965036    0    0    96   296    1    0 25  0 73  2  0
0  0 1968768  83276 206644 965036    0    0     0    10 1021  760  0  0 100  0  0
0  0 1968768  83284 206644 965036    0    0     0     3 1030  725  2  1 98  0  0
0  0 1968768  83276 206644 965036    0    0     0    22 1048  790  0  0 100  0  0
1  0 1968768  82268 206644 965048    0    0     0   190 1054  842  0  0 99  0  0

前面一个5表示间隔多少秒,后面一个5表示统计几次。

第一列是procs,这个提供了生成报告时正在运行的进程数目(r)以及被阻塞的进程数目(b)。这2个值通常是越低越好,越低说明cpu空闲度高。
第二列是memory,这个提供了换出内存(swpd),空闲内存(free), I/O数据结构的缓冲区的缓存大小(buff),以及从磁盘读取文件的内存缓存(cache)的大小,单位都是KB。swpd的取值反映了kswapd的活动情况。
第三列是swap部分,这里提供了从磁盘上换入的内存容量(si)以及换出到磁盘上内存量(so),单位为KB/s。so反映了当数据被换出到交换分区时kswapd的活动情况,而si则反映了当页面被换回到物理内存时发生页面错误的情况。这两个值在系统内存够大或者负载较轻的情况下应该都为0.
第四列是io部分,这个部分反映了从设备读入块数(bi)以及写出到设备上的块数(bo),单位为KB/s,当I/O操作特别频繁的时候要特别注意这2个值的变化。
第五列是system部分,显示了每秒钟的中断数目(in)和上下文切换数目(cs)。中断和上下文切换是每个程序都肯定存在的,所以必须要 有所前后文比对才能确定是否系统出了问题,程序有问题肯定会导致频繁的中断和上下文切换,这样非常消耗系统资源。
第六列是cpu部分,这里提供了用户(us),系统(sy),真正空闲(id)以及等待I/O完成(wa)在CPU总时间中所站的百分比,若wa值过大,则应该检查I/O子系统。
而在linux2.6.11后还会多出(st)列,这个表示虚拟线程占有cpu。现在还不知道这个值具体有什么作用,是不是只有在装了KVM或者XEN的情况下才有用呢?

Linux密碼長度限制

在linux中我們可以設置密碼最短為多少,只需要修改/etc/login.defs文件中的PASS_MIN_LEN 參數就可以了。
但是最近我發現了另外一個問題,我明明設置了10幾位的密碼,但是最終系統登錄的時候只是查看前面的8位。查找了半天原因,原來是/etc/pam.d/system-auth的問題。
在老的版本默認password居然是使用shadow進行驗證的。而它所使用的算法是DES加密算法,這是一種64位加密算法,只能識別到前面八位。修改方法就是把system-auth修改成如下形式:

#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth        required      pam_env.so
auth        sufficient    pam_unix.so nullok try_first_pass
auth        requisite     pam_succeed_if.so uid >= 500 quiet
auth        required      pam_deny.so

account     required      pam_unix.so
account     sufficient    pam_succeed_if.so uid < 500 quiet
account     required      pam_permit.so

password    requisite     pam_cracklib.so try_first_pass retry=3
password    sufficient    pam_unix.so md5 shadow nullok try_first_pass use_authtok
password    required      pam_deny.so

session     optional      pam_keyinit.so revoke
session     required      pam_limits.so
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required      pam_unix.so

這個修改完成后理論上是立刻生效的。但是我在實際使用過程中發現還是要把所有密碼重新設置一遍才會生效。
其實也可以通過修改/etc/pam.d/login來解決的,但是很多pam其實最終都是調用的system-auth的,所以修改system-auth還是一個比較好的方式。

使用kickstarts来安装Linux

kickstar是redhat的一种安装方式。使用起来非常简单。只需要修改redhat所有版本的第一个Iso文件里的isolinux/isolinux.cfg文件,修改完成后重新打包好iso就可以了。 修改这个文件主要是确认这个新装的LINUX在安装时候来定义一个IP。

我自己定义的isolinux.cfg文件定义如下。

default linux ip=172.16.1.253 netmask=255.255.255.0 gateway=172.16.1.1 ks=http://192.168.1.254:8080/ks.cfg
prompt 1
timeout 8
display boot.msg
label linux
kernel vmlinuz
append initrd=initrd.img

这里default linux ip=172.16.1.253 netmask=255.255.255.0 gateway=172.16.1.1 定义的是这个linux机器安装时候所使用的IP和子网掩码以及网关。当然如果你内网有DHCP服务器的话那也可以通过DHCP来获取IP,但是一般机房内我们不会单独设置一个DHCP服务器,所以这里使用的固定IP,这种方法更可靠。

ks=http://192.168.1.254:8080/ks.cfg 这个是定义ks.cfg文件的下载地址。

ks.cfg文件里包含了所有你需要的安装选项,如果没有这个文件,那系统安装也无法继续进行了。任何redhat机器安装完成都会在用户主目录下包含有ks.cfg这个文件。一般我们使用的使用的ks.cfg文件还会根据自己的要求来修改。主要修改的是%post后面的内容。

但是需要注意这里最好使用完整的路径

install
text
url --url http://192.168.1.254:8080/rhel
key 2515dd4e215225dd
lang en_US.UTF-8
keyboard us
#xconfig --startxonboot
skipx
network --device eth0 --bootproto static --ip 172.16.1.10 --netmask 255.255.0.0 --gateway 172.16.0.254 --nameserver 202.96.209.6 --hostname kickstart.test.com
#123456
rootpw --iscrypted $1$jTyfIbbE$aSiDPkLNeVs7hQaFljqgS1
firewall --enabled --port=22:tcp
authconfig --enableshadow --enablemd5
selinux --enforcing
timezone Asia/Shanghai
bootloader --location=mbr --driveorder=sda --append="rhgb quiet"
# The following is the partition information you requested
# Note that any partitions you deleted are not expressed
# here so unless you clear all partitions first, this is
# not guaranteed to work
clearpart  --linux
#part /boot --size  2048  --fstype=ext3
part /     --size  50480  --fstype=ext3 --asprimary
part swap  --size   256
%packages
@admin-tools
@base
@base-x
@core
@development-libs
@development-tools
@dialup
@editors
@gnome-desktop
@gnome-software-development
@graphical-internet
@java
@text-internet
kernel-devel
%post
/sbin/chkconfig --level 345 sshd on
/sbin/chkconfig --level 0123456  kudzu off
/sbin/chkconfig --level 0123456  cups off
/sbin/chkconfig --level 0123456  autofs off
/sbin/chkconfig --level 0123456  sendmail off
/sbin/chkconfig --level 0123456  atd off
/sbin/chkconfig --level 0123456  iptables off
/sbin/chkconfig --level 0123456  xinetd off
/sbin/chkconfig --level 0123456  portmap off
/sbin/chkconfig --level 0123456  pcmcia off
/sbin/chkconfig --level 0123456  gpm off
/sbin/chkconfig --level 0123456  rhnsd off
/sbin/chkconfig --level 0123456  isdn off
/sbin/chkconfig --level 0123456  nfslock off
/sbin/chkconfig --level 0123456  rawdevices off
/sbin/chkconfig --level 0123456  keytable off
/sbin/chkconfig --level 0123456  apmd off
/sbin/chkconfig --level 0123456  anacron off
/sbin/chkconfig --level 0123456  xfs off
/sbin/chkconfig --level 0123456  netfs off
/sbin/chkconfig --level 0123456  ip6tables off
/sbin/chkconfig --level 0123456  arptables_jf off
/sbin/chkconfig --level 0123456  microcode_ctl off
/sbin/chkconfig --level 0123456  irqbalance off
/sbin/chkconfig --level 0123456  mdmonitor off
/sbin/chkconfig --level 0123456  hpoj off
/sbin/chkconfig --level 0123456  sgi_fam off
/sbin/chkconfig --level 0123456  audit off
/sbin/chkconfig --level 0123456  firstboot off
/sbin/chkconfig --level 0123456  vsftpd off
cd /usr/local/
/usr/bin/wget http://192.168.1.254:8080/source.tar.gz
/bin/tar zxvf source.tar.gz
/usr/local/source/scripts/sys-init.sh >>/tmp/sys-alert 2>&

url –url http://192.168.21.254:8080/rhel 这里定义的安装时候需要相关一些包的地址,所以由于centos这样的系统有很多包,rhel目录下是包含了disk1下所有的内容,同时要把其它盘里Server目录下的内容复制到rhel/Server/目录下。

这里定义的IP就是系统完成后的IP了。这个ks.cfg由于是在服务器端设置的,所以根据不同的需求来进行改变。而%post之后完全可以根据自己的要求来定义。而这里的路径请使用绝对路径。