Nginx写IO占用高故障处理

故障现象

 

突然收到一台服务器负载过高告警,紧接着网站打开缓慢。

 

故障分析

 

  • 1、登录服务器,使用top命令看到Cpu行的iowait达到了70%以上,所以断定是IO负载过高的原因;
  • 2、接着使用iotop -o命令发现,Nginx的写IO特别大,并且在上一步的top命令看到Nginx的进程状态为D,表示Nginx在等待IO已经为僵死状态;
  • 3、这时候是清楚知道是Nginx在对文件系统进行大量的写操作导致的系统负载过高了,但还是不能知道具体Nginx在写什么文件导致的负载压力,所以我们还需要继续追查下去;
  • 4、我们找到其中一个nginx worker进程的pid,使用lsof -p pid列出来的文件发现除了一些系统库文件及日志文件,还有相当多的fastcgi_temp/xxx文件,有可能与这些文件有关联;
  • 5、再次使用strace -p pid追踪,发现nginx进程对某个fd进行大量的写操作,与lsof命令列出来的文件刚好符合;
  • 6、使用iostat 1输出的大量写io的分区也与fastcgi_temp所在分区相符合;
  • 7、猜测可能是外部正在上传大量的大文件给php-fpm,于是通过EZHTTP的小工具来查看实时流量,发现入站流量其实不大。

 

分析结果

 

根据以上的故障分析,非常有可能是本机的某些程序通过http上传大量大文件。因为对程序逻辑不熟悉,也只是猜测。为了尽快恢复服务,决定实施以下解决方案。

 

解决方案

 

既然清楚知道了fastcgi_temp io压力大,目前也无法短时间从根本上解决问题,所以决定把fastcgi_temp指向/dev/shm,也就是映射到了内存,重启nginx之后服务恢复了正常。最终原因还需要开发配合解决。

ubuntu apt-file解决依赖的利器

刚才安装Spynner模块,使用的是easy_install spynner安装,各种文件缺失啊,无意中发现apt-file命令,从此再也不用担心编译软件缺少某个文件而不知所措了。
1、首先得安装apt-file命令

  1. apt-get install apt-file

2、接着更新apt-file的缓存

  1. apt-file update

3、现在你可以使用apt-file搜索缺失的文件了,比如编译过程中提示缺少

  1. root@test:~# apt-file search XTest.h
  2. libbcprov-java-doc: /usr/share/doc/libbcprov-java-doc/api/org/bouncycastle/jce/provider/test/PKIXTest.html
  3. libreoffice-dev-doc: /usr/share/doc/libreoffice-dev/docs/common/ref/com/sun/star/test/XTest.html
  4. libsvgsalamander-java-doc: /usr/share/doc/libsvgsalamander-java-doc/api/com/kitfox/svg/xml/cpx/CPXTest.html
  5. libsvgsalamander-java-doc: /usr/share/doc/libsvgsalamander-java-doc/api/com/kitfox/svg/xml/cpx/class-use/CPXTest.html
  6. libxtst-dev: /usr/include/X11/extensions/XTest.h

4、显然libxtst-dev包正是我们需要安装的

  1. apt-get install libxtst-dev

linux文件名编码转换工具convmv

今天介绍个文件名转码的工具–convmv,convmv能帮助我们很容易地对一个文件,一个目录下所有文件进行编码转换,比如gbk转为utf8等。
语法:
convmv [options] FILE(S) … DIRECTORY(S)
主要选项:
1、-f ENCODING
指定目前文件名的编码,如-f gbk
2、-t ENCODING
指定将要转换成的编码,如-t utf-8
3、-r
递归转换目录下所有文件名
4、–list
列出所有支持的编码
5、–notest
默认是只打印转换后的效果,加这个选项才真正执行转换操作。
更多选项请man convmv。
例子:
递归转换centos目录下的目前文件名编码gbk为utf-8:

  1. convmv -f gbk -t utf-8 –notest -r  centos

Web压力测试工具-http_load

介绍个http_load压力测试工具,http_load,类似的工具还有webbench、ab、Siege。

1、下载

官方网站:http://acme.com/software/http_load/

  1. cd /root
  2. wget http://acme.com/software/http_load/http_load-12mar2006.tar.gz
  3. tar xzf http_load-12mar2006.tar.gz

2、安装

  1. cd http_load-12mar2006
  2. make

执行完make,会在当前目录生成一个http_load二进制文件。

3、使用方法

  1. root@www:~/http_load-12mar2006# ./http_load –help
  2. usage:  ./http_load [-checksum] [-throttle] [-proxy host:port] [-verbose] [-timeout secs] [-sip sip_file]
  3.             -parallel N | -rate N [-jitter]
  4.             -fetches N | -seconds N
  5.             url_file
  6. One start specifier, either -parallel or -rate, is required.
  7. One end specifier, either -fetches or -seconds, is required.

主要参数说明:
-parallel 简写-p :含义是并发的用户进程数。
-rate 简写-r :含义是每秒的访问频率
-fetches 简写-f :含义是总计的访问次数
-seconds简写-s :含义是总计的访问时间

选择参数时,-parallel和-rate选其中一个,-fetches和-seconds选其中一个。
示例:

  1. http_load -parallel 50 -s 10 urls.txt

这段命令行是同时使用50个进程,随机访问urls.txt中的网址列表,总共访问10秒。

  1. http_load -rate 50 -f 5000 urls.txt

每秒请求50次,总共请求5000次停止。

expect spawn、linux expect 用法小记

使用expect实现自动登录的脚本,网上有很多,可是都没有一个明白的说明,初学者一般都是照抄、收藏。可是为什么要这么写却不知其然。本文用一个最短的例子说明脚本的原理。
  脚本代码如下:

  1.   ##############################################
  2.   #!/usr/bin/expect
  3.   set timeout 30
  4.   spawn ssh -l username 192.168.1.1
  5.   expect "password:"
  6.   send "ispassr"
  7.   interact
  8.   ##############################################

  1. [#!/usr/bin/expect]
  这一行告诉操作系统脚本里的代码使用那一个shell来执行。这里的expect其实和linux下的bash、windows下的cmd是一类东西。
  注意:这一行需要在脚本的第一行。
  2. [set timeout 30]
  基本上认识英文的都知道这是设置超时时间的,现在你只要记住他的计时单位是:秒
  3. [spawn ssh -l username 192.168.1.1]
  spawn是进入expect环境后才可以执行的expect内部命令,如果没有装expect或者直接在默认的SHELL下执行是找不到spawn命令的。所以不要用 “which spawn“之类的命令去找spawn命令。好比windows里的dir就是一个内部命令,这个命令由shell自带,你无法找到一个dir.com 或 dir.exe 的可执行文件。
  它主要的功能是给ssh运行进程加个壳,用来传递交互指令。
  4. [expect “password:”]
  这里的expect也是expect的一个内部命令,有点晕吧,expect的shell命令和内部命令是一样的,但不是一个功能,习惯就好了。这个命令的意思是判断上次输出结果里是否包含“password:”的字符串,如果有则立即返回,否则就等待一段时间后返回,这里等待时长就是前面设置的30秒
  5. [send “ispassr”]
  这里就是执行交互动作,与手工输入密码的动作等效。
  温馨提示: 命令字符串结尾别忘记加上“r”,如果出现异常等待的状态可以核查一下。
  6. [interact]
  执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。如果你只是登录过去执行

  1.   #!/usr/bin/expect #注意安装的路径,不确定 whereis expect 一下
  2.   # Change a login shell to bash
  3.   set user [lindex $argv 0]
  4.   spawn bash $user
  5.   expect "]:"
  6.   send "/bin/bash "
  7.   expect eof
  8.   exit

转自:http://sysop.blogbus.com/logs/70787883.html

设置centos6 yum源为光盘

1、挂载光盘

  1. mount /dev/cdrom /media/cdrom

2、设置CentOS-Media.repo

检查/etc/yum.repos.d/目录是否存在里文件,如存在,此步略过,如果不存在,手动建立,代码如下:

  1. [c6-media]
  2. name=CentOS-$releasever – Media
  3. baseurl=file:///media/CentOS/
  4.         file:///media/cdrom/
  5.         file:///media/cdrecorder/
  6. gpgcheck=1
  7. enabled=0
  8. gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

3、开始安装软件

  1. yum –disablerepo=* –enablerepo=c6-media install kernel-devel

grub rescue下手动引导系统

今天把测试服务器的另外两块硬盘撤下,不能开机,又装上,发现启动不了ubuntu系统了,出现grub rescue的画面。现在让我们来学习手动来引导系统。
1、执行ls命令会出现所有的系统分区,如下

  1. grub rescue> ls
  2. (hd0,1),(hd0,2),(hd1,1),(hd2,1)

2、一个人ls查看,看能否看到/boot分区

  1. grub rescue> ls (hd0,1)/
  2.    grub      lost+found    memtest86+_multiboot.bin     vmlinuz-3.2.0-29-generic
  3. config-3.2.0-29-generic  initrd.img-3.2.0-29-generic  memtest86+.bin  System.map-3.2.0-29-generic

如果出现类似如上文件列表,表明此hd0,1为boot分区;如果出现unkonw system,继续ls下一分区。
3、设置root和prefix

  1. grub rescue>set root=(hd0,1)
  2. grub rescue>set root=(hd0,1)/grub

4、载入模块并启动

  1. grub rescue>insmod /grub/normal.mod
  2. grub rescue>normal

5、这时候顺利的话会成功引导进系统,下一步就是正常的修复grub了。
进入系统后,执行如下命令修复(以ubuntu为例)

  1. sudo update-grub
  2. sudo grub-install /dev/sda

注:/dev/sda根据bios设置的第一硬盘设置。如果重启之后还出现grub rescue,重复以上步骤,把sda换成其它硬盘,直到成功为止。
centos的grub修复请参考http://devops.webres.wang/2012/06/centos-install-repair-grub/

I/O监视器-iotop

iotop 是一个用来监视磁盘 I/O 使用状况的 top 类工具。如下图所示,Iotop 具有与 top 相似的 UI,其中包括 PID、用户、I/O、进程等相关信息。
1、安装

  1. ubuntu:apt-get install iotop
  2. centos:yum install iotop

2、使用方法
iotop [OPTIONS]

主要选项有:
-o :只显示有io操作的进程
-b :批量显示,无交互。主要用作记录到文件。
-n NUM:显示NUM次,主要用于非交互式模式。
-d SEC:间隔SEC秒显示一次。
-p PID:监控的进程pid
-u USER:监控的进程用户。

系统管理

使用expect实现scp ssh自动输入密码登录

expect是一种自动交互语言,能实现在shell脚本中为scp和ssh等自动输入密码自动登录。
下面给出scp和ssh的使用示例:
1、scp

  1. expect -c "
  2.   spawn scp [email protected]:/root/1.log /root
  3.   expect {
  4.     "*assword" {set timeout 300; send "passwordr";}
  5.     "yes/no" {send "yesr"; exp_continue;}
  6.   }
  7.   expect eof"

2、ssh

  1. #!/bin/bash
  2. expect -c "
  3. spawn ssh [email protected] "ls;"
  4. expect {
  5.     "*assword" {set timeout 300; send "passwordr";}
  6.     "yes/no" {send "yesr"; exp_continue;}
  7.       }
  8. expect eof
  9.             "