<?php

Archive for the ‘linux’ Category

proftp安装配置,虚拟账号便于管理

首先下载安装:

wget ftp://mirror.wrpn.net/proftpd/distrib/source/proftpd-1.3.2.tar.bz2
tar jxf proftpd-1.3.2.tar.bz2
cd proftpd-1.3.2
./configure --prefix=/home/proftpd --disable-ipv6
make && make install

vi /etc/rc.local

vi /home/proftpd/etc/proftpd.conf
修改端口,
# Port 21 is the standard FTP port.
Port                            2121

# standalone 模式下耗费资源多一点,但配置简单
ServerType                      standalone

#注释掉 编译时已经disable-ipv6,这里如果不注释掉,启动时会报错
#UseIPv6                                off

#修改执行账号
User                            nobody
Group                           nobody

#去掉下面这一行的注释 “#”,这一行是把ftp用户限定在自己的目录下,禁止切换到上层目录
DefaultRoot ~

默认情况下proftpd是通过系统账号做认证的,或许你也跟我一样 不愿意用这种方式。那么有什么方式呢?查阅资料之后发现有另外两种方式。
一,采用mysql方式存储虚拟用户,如此一来用户容量巨大。比较适合公开ftp server,对于我的应用过于夸张了。这里也不做详细介绍了,有兴趣的可以去搜索一下,资料很多。下面说一下资料并不多的方法。
二,文件形式的虚拟用户存储方案。
首先在proftpd.conf中添加以下两行:

AuthUserFile /home/proftpd/etc/ftp.passwd	# 指定认证文件的存储路径
AuthOrder mod_auth_file.c mod_auth_unix.c	# 这两个文件是proftpd认证是的先后次序, mod_auth_file.c是我们要用的文件认证形式,mod_auth_unix.c是以系统账号认证

然后要做的就是创建认证文件(/home/proftpd/etc/ftp.passwd),这里需要用到proftp提供的一个工具:ftpasswd,可以在proftp源文件中contrib目录下找到:

#复制到指定目录
cp contrib/ftpasswd /home/proftpd/sbin/

最后就是添加账号:

./contrib/ftpasswd --file /home/proftpd/etc/ftp.passwd --name ftpusername --passwd  --home=/data/htdocs --shell=/sbin/nologin

执行后会提示输入账号密码,确认之后创建完毕

最最后,启动proftpd

/home/proftpd/sbin/proftpd start

接下来就可以用指定的端口、账号密码连接新proftpd了~

Notice:
proftpd默认情况下是不支持断点续传的,但是你又需要此功能?哈哈,很简单,只需要在proftpd.conf中添加以下两行,然后重启就ok

# break point
AllowRetrieveRestart on
AllowStoreRestart on

如果想允许ftp用户修改文件的权限设置,可以修改以下设置

  <Limit SITE_CHMOD>
    DenyAll	#禁用; AllowAll 启用全部用户; AllowUser abc 只允许abc用户
  </Limit>

参考:http://www.proftpd.org/docs/howto/Limit.html

增加一些可能用到的命令:

#立即关闭的命令
/usr/local/proftpd/sbin/ftpshut +0

#关闭命令为
/usr/local/proftpd/sbin/ftpshut

ftpshut [ -l min ] [ -d min ] time [ warning-message ... ]

-l min: 在ftp关闭服务之前的几分钟内,尝试建立新的ftp连接均不被接受
-d min: 在ftp关闭服务之前的几分钟内,已经建立的ftp连接将被中止
time: 在多少时间后,服务器将关闭ftp服务,格式有两种
+number 经过number分钟后关闭
MMHH 在今天MM:HH服务器将关闭

举例:
在半小时后,将FTP服务关闭,在这之前的20分钟不可接受任何新的ftp连接,已经建立的在服务关闭前10分钟强制断线,并在客户端显示“FTP Server Will shutdown at time”

ftpshut -l 20 -d 10 +30 "FTP Server Will shutdown at time"

其实ftpshut就是产生/etc/shutmsg ,你只要删除这个文件ftp又可以重新服务,或者
直接用

ftpshut -R

比较多的应用是Limit,Limit大致有以下动作,基本能覆盖全部的权限

CMD:Change Working Directory 改变目录
MKD:MaKe Directory 建立目录的权限
RNFR: ReName FRom 更改目录名的权限
DELE:DELEte 删除文件的权限
RMD:ReMove Directory 删除目录的权限
RETR:RETRieve 从服务端下载到客户端的权限
STOR:STORe 从客户端上传到服务端的权限
READ:可读的权限,不包括列目录的权限,相当于RETR,STAT等
WRITE:写文件或者目录的权限,包括MKD和RMD
DIRS:是否允许列目录,相当于LIST,NLST等权限,还是比较实用的
ALL:所有权限
LOGIN:是否允许登陆的权限

针对上面这个Limit所应用的对象,又包括以下范围
AllowUser 针对某个用户允许的Limit
DenyUser 针对某个用户禁止的Limit
AllowGroup 针对某个用户组允许的Limit
DenyGroup 针对某个用户组禁止的Limit
AllowAll 针对所有用户组允许的Limit
DenyAll 针对所有用户禁止的Limit

关于限制速率的参数为:
TransferRate STOR|RETR 速度(Kbytes/s) user 使用者

nginx中的文件检查”缺陷”

接上一篇 nginx启用sendfile之高级篇,还是同一个项目,按照前文的配置已经都很正常,只是发现有些目标文件明明是已经存在的,但为什么还是走到了后端处理呢? 查看了十几个URL之后发现了一个共性:文件或目录名包含 “+”。
比如 用户请求http://yourdomain/ab+c.ext,经过测试之后发现nginx实际读取的文件名是 ab%2bc.ext ,注意:这是在经过location匹配和rewrite处理的情况下,如果是直接访问一个静态文件 ab+c.ext 且文件存在,是没有问题的。经过我测试发现加号和空格会有这个问题,其他符号都是不会被encode的。
如此一来就很好解释“有些目标文件明明是已经存在的,但为什么还是走到了后端处理呢?”,nginx检查文件是否存在时使用的是 ab%2bc.ext,但文件系统上实际保存的文件是 ab+c.ext,因此会将请求rewrite到后端程序处理。

既然知道了问题,解决办法自然就有了。有两种解决办法:
1,不要使用包含加号和空格的文件、目录名;
2,如果必须使用,应该encode后在做为文件、目录名

注意,在 location 文档说明有这么一句话“It is important to know that nginx does the comparison against decoded URIs.”

nginx启用sendfile之高级篇

什么是sendfile?
nginx官方只是一句带过,如果你需要了解详细的请参考: http://celebnamer.celebworld.ws/stuff/mod_xsendfile/

为什么要用sendfile?
原因很简单,项目中有个需求是后端程序负责把源文件打包加密生成目标文件,然后程序读取目标文件返回给浏览器;这种做法有个致命的缺陷就是占用大量后端程序资源,如果遇到一些访客下载速度巨慢,就会造成大量资源被长期占用得不到释放,很快后端程序就会因为没有资源可用而无法正常提供服务。通常表现就是nginx报502错误!其次在nginx内部我还想实现“由nginx检查目标文件是否存在,如果存在的话就直接返回给浏览器而无需经过后端程序的处理”,这样一来后端程序只是负责生成目标文件,一单目标文件被生成,基本上就不再提供服务,而nginx则提供全静态的文件浏览服务。可想而知,性能的提升还是大很多的!

怎么启用sendfile?
详细配置步骤就不说了,官方wiki已经说明的比较清楚。只提一下注意点吧:
1,location 必须 被定义为 internal;
2,如果在location中使用alias 一定要注意目录结尾的“/”;
3,要注意location 匹配时尽量只用目录名。 我在测试中遇到抓狂的问题。

先说一下我最终的方案:
1,增加一个location作为目标文件的检查,如果存在 就发给internal的location继续处理,如果不存在就rewrite到后端程序处理;

location ~ ^/vdir/(.*)\.ext$
{
	set $obj_file "$1.ext";
	if (!-f /path/to/obj/dir/$obj_file)
	{
		rewrite ^  /backend/app last;
	}
	rewrite ^ /revdir/$obj_file last;
}

以上代码可实现“由nginx检查目标文件是否存在,如果存在的话就直接返回给浏览器而无需经过后端程序的处理”。
接下来看下sendfile相关的location

location /revdir
{
	internal;
	alias /another/dir/;
	#rewrite (.*) /$1 redirect;	# 用于测试匹配到的数据是否正确,也可以使用 add_header  xxx  $1  来代替
}

程序里送出的header是 :

X-Accel-Redirect: /revdir/a/b/xxx.ext

需要再原本的文件路径前加一个虚拟目录 /revdir/

下面讲一下访客在浏览 http://yourdomain/vdir/d/i/r/xxx.ext时的一些处理过程:
1,nginx会先去检查是否存在目标文件”/path/to/obj/dir/d/i/r/xxx.ext”
2.1,如果文件不存在,就会发起一个rewrite ,将请求发往后端程序处理生成文件,然后后端程序只送出”X-Accel-Redirect”header之后完成处理,nginx接受X-Accel-Redirect会被 location /revdir 匹配到,继而发送该文件;
2.1,如果文件存在,也会发起一个rewrite ,然后会被 location /revdir 匹配到,继而直接发送该文件无需经过后端程序;
3,over.

提醒注意:
如果你在测试中发现nginx报500,首先一个考虑下是不是重复匹配次数达到nginx内部预设的10次上限,然后报500错误。有方法可以验证,适当的location添加:

log_subrequest on;

详细请点击参考官方wiki

最后再提一点,远程文件怎么使用这个功能来转发呢? 不是proxy喔~~
有兴趣的可以参考这里:Nginx-Fu: X-Accel-Redirect From Remote Servers

QQ潮流概念版初体验

今天看到QQ出了个潮流概念版,下载地址,如果打不开请尝试搜索
试用之前需要申请登录许可,申请地址
下面贴几张我的截图吧, 启动中:
loading

登录窗口:
login

登录后的QQ主界面:
QQ

被拖拽到桌面的好友,这个功能挺好的。不过也不算QQ的首创了,我记得当初UC(现在的新浪UC)出来时就有了这个功能。
drag

点击被拖拽出来的图标会有几个菜单供选择,看样子以后会加入数量更多的菜单,这个形式很容易扩展。
menu

其他地方值得一提的就是操作的体验吧,一个字“炫”,或许这个就是潮流概念的所指? 整体没有发现什么新功能,多tab聊天比较适合玩NP的聊天狂人,我是用不上了。。
更多的是不足,比如说对我很重要的聊天记录。在这个版本中居然没有导入历史记录的工具。

另外 这个版本目前还没有广告, 免于广告的骚扰是一种幸福。。。

下面看一下官方给出的whats new:
1.个性化登录界面
悠悠飘动的白云,随风摇摆的叶子,极富生命力。

2.头像动感相框
多款富有动感的相框,给自己的头像增添新的趣味。

3.动态背景
清新自然的竹叶,活力四射的霓虹灯,好友列表不再单调。

4.好友动态滚动显示
个性签名、音乐状态、QZone 等更新信息滚动显示,随时随地了解好友动态。

5.桌面好友
把好友拖放到桌面,实时关注好友的最新状态,即时快聊,实现无缝沟通和互动。

6.好友管理
富有质感的界面,好友卡片自由拖放,支持多点触摸,好友男女比例统计,给您全新的好友管理体验。

7.多TAB聊天功能
拖拽会话窗口上的头像可以合并和拆分会话窗口,管理会话更方便。

8.表情选择器
圆盘卡片式的表情选择器,自动排列常用表情。

9.超级表情
给好友发送特殊的表情,让您的心情跃然好友屏幕之上,与好友一起感受不一样的互动形式。

10.全新的聊天记录查看体验
带有加速度和富有弹性的滚动及翻页体验,操作更自然。

11.系统设置
系统设置位于主面板背面,可用鼠标右键手势进行3D翻转,修改设置更快捷。

通过shell+crontab实现自动分割nginx日志

最近有几个朋友问这个事情,干脆写出来吧。。
nginx自身不能按天分割日志,因此还是自己动手来吧~
本文提供的这个脚本会把当前的log文件打包为当前日期为文件名的tgz包,并保存到指定目录。

首先把下面的脚本copy保存为/root/daily_logs.sh

#! /bin/bash

nginx_app=/home/nginx/sbin/nginx #设置nginx的目录
logs_dir=/data/logs/ #log目录
bak_dir=/data/logs/bak/ #log备份目录

#先把现有的log文件挪到备份目录临时存放
cd $logs_dir
echo "moving logs"
/bin/mv *.log $bak_dir
sleep 3

#重建nginx log
echo "rebuild logs"
echo "$nginx_app -s reopen"
$nginx_app -s reopen

#按天打包log文件
echo "begining of tar"
cd $bak_dir
/bin/tar czf `date +%Y%m%d`.tgz *.log

#删除备份目录的临时文件
echo "rm logs"
rm -f *.log
echo "done"

并添加执行权限:

chmod +x /root/daily_logs.sh

然后增加crontab,这里以每晚0点执行为例:

[root@localhost ~]# crontab -e
0 0 * * * /root/daily-task.sh > /dev/null 2>&1

保存后退出,以后就可以自动分割nginx的日志啦~

收工。。

linux下erlang之OTP编译安装

在安装otp时遇到了一点问题,整体的安装过程比较简单。

wget http://erlang.org/download/otp_src_R13B04.tar.gz
tar xzf otp_src_R13B04.tar.gz
cd otp_src_R13B04
./configure --prefix=/home/erlang

configure之后发现有以下提示信息:
[code lang="code"]
*********************************************************************
********************** APPLICATIONS DISABLED **********************
*********************************************************************

odbc : ODBC library - link check failed
jinterface : No Java compiler found

*********************************************************************
*********************************************************************
********************** APPLICATIONS INFORMATION *******************
*********************************************************************

wx : wxWidgets not found, wx will NOT be usable

*********************************************************************
*********************************************************************
********************** DOCUMENTATION INFORMATION ******************
*********************************************************************
[/code]

我们只需要关注APPLICATIONS DISABLED部分的提示信息,至于其他提示信息需要根据使用情况酌情处理。
这里我只需要解决APPLICATIONS DISABLED部分的问题:
1,安装unixODBC和unixODBC-devel,解决第一个问题;
2,因为我这里用不上java编译了,因此可以在configure时增加 –disable-javac 避免第二个错误;

yum install unixODBC unixODBC-devel
./configure --prefix=/home/erlang --without-javac
make && make install

ok, 安装成功了。
下面给erl做一个软连接到/usr/local/bin/,以方便使用

ln -s /home/erlang/bin/erl /usr/local/bin/erl

测试一下:

bash-3.2# erl
Erlang R13B04 (erts-5.7.5) [source] [64-bit] [smp:4:4] [rq:4] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.5  (abort with ^G)
1> EvenN = lists:filter (fun (N) -> N rem 2 == 0 end, lists:seq (1,100)).
[2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,
 44,46,48,50,52,54,56,58|...]
2> halt().
bash-3.2#

注:以上操作在centOS5下完成。

解决cacti大量sleep连接占用mysql资源的问题

最近发现msyql的进程数经常保持在20个并发连接,感觉非常奇怪。show processlist 之后才发现原来全都是cacti的连接,而且全部是sleep状态。因此考虑到有可能是连接数据库时使用了持久连接,或mysql_connect 的bool new_link 参数为false了。
接下来就有了查找目标,首先进入到cacti程序的根目录。

[root@localhost htdocs]# cd cacti
[root@localhost cacti]# grep -r mysql_pconnect .
./lib/adodb/drivers/adodb-mysql.inc.php:                        $this->_connectionID = @mysql_pconnect($argHostname,$argUsername,$argPassword,$this->clientFlags);
./lib/adodb/drivers/adodb-mysql.inc.php:                        $this->_connectionID = @mysql_pconnect($argHostname,$argUsername,$argPassword);

接下来再去找./lib/adodb/drivers/adodb-mysql.inc.php文件内查找mysql_pconnect找到所属的方法名。我这里找到的是_pconnect
然后再查找:

grep -rw _pconnect .
./lib/adodb/drivers/adodb-sqlite.inc.php:       function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
./lib/adodb/drivers/adodb-sybase.inc.php:       function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
./lib/adodb/drivers/adodb-oracle.inc.php:               function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
./lib/adodb/drivers/adodb-ado.inc.php:  function _pconnect($argHostname, $argUsername, $argPassword, $argProvider='MSDASQL')
./lib/adodb/drivers/adodb-postgres64.inc.php:  27 Nov 2000 jlim - added changes to _connect/_pconnect from ideas by "Lennie" <leen@wirehub.nl>
./lib/adodb/drivers/adodb-postgres64.inc.php:   function _pconnect($str,$user='',$pwd='',$db='')
./lib/adodb/drivers/adodb-csv.inc.php:  function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
./lib/adodb/drivers/adodb-mssql.inc.php:        function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
./lib/adodb/drivers/adodb-mysqli.inc.php:       function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
./lib/adodb/drivers/adodb-ibase.inc.php:        function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
./lib/adodb/drivers/adodb-pdo.inc.php:  function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
./lib/adodb/drivers/adodb-oci8.inc.php: function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
./lib/adodb/drivers/adodb-fbsql.inc.php:        function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
./lib/adodb/drivers/adodb-mysql.inc.php:        function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
./lib/adodb/drivers/adodb-ado5.inc.php: function _pconnect($argHostname, $argUsername, $argPassword, $argProvider='MSDASQL')
./lib/adodb/drivers/adodb-odbc.inc.php: function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
./lib/adodb/drivers/adodb-odbc_oracle.inc.php:  function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
./lib/adodb/drivers/adodb-odbtp.inc.php:        function _pconnect($HostOrInterface, $UserOrDSN='', $argPassword='', $argDatabase='')
./lib/adodb/drivers/adodb-informix72.inc.php:   function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
./lib/adodb/adodb.inc.php:              if ($this->_pconnect($this->host, $this->user, $this->password, $this->database)) return true;

这次会找到很多结果 看上去有点无从下手。没关系,看一看文件名就知道了,这些基本上都是针对其他数据库的代码,与msyql无关。
注意,其中的./lib/adodb/adodb.inc.php,没错,这个就是我们要找的。
在该文件内查找包含_pconnect的函数名,只有一个函数:PConnect
再接下来就是查找调用PConnect函数的地方:

[root@localhost cacti]# grep -rw PConnect .
./lib/adodb/adodb-pear.inc.php:         if($persist) $ok = $obj->PConnect($dsninfo['hostspec'], $dsninfo['username'],$dsninfo['password'],$dsninfo['database']);
./lib/adodb/drivers/adodb-postgres64.inc.php:   //      $db->PConnect("host=host1 user=user1 password=secret port=4341");
./lib/adodb/drivers/adodb-postgres64.inc.php:   //      $db->PConnect('host1','user1','secret');
./lib/adodb/drivers/adodb-odbc.inc.php:                 ADOConnection::outp("For odbc PConnect(), $argDatabasename is not used. Place dsn in 1st parameter.");
./lib/adodb/adodb.inc.php:      var $autoRollback = false; // autoRollback on PConnect().
./lib/adodb/adodb.inc.php:      function PConnect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "")
./lib/adodb/adodb.inc.php:                                      $ok = $obj->PConnect($dsna['host'], $dsna['user'], $dsna['pass'], $dsna['path']);
./lib/database.php:             if ($cnn_id->PConnect($hostport,$user,$pass,$db_name)) {

OK, 这下找到我们的终极目标了:./lib/database.php
打开该文件浏览一遍代码,马上就会发现cacti默认使用的是PConnect, 至于有没有地方可以配置选择 我还不太清楚,因为没有使用长连接的需求,干脆直接改掉这里吧。把PConnect改成Connect,保存退出。
最后就是等待观察,经过十几分钟的观察一切正常了,再也看不到令人厌烦的sleep连接啦~
oh my lady gaga…
收兵

linux下根据/proc/stat计算CPU使用情况算法详解

本文是介绍在Linux/unix下如何根据/proc/stat文件的信息计算得到CPU使用率。大多情况下自己做系统监控时都会用到这个文件

首先找来一段扫盲文字“在linux下,CPU利用率分为用户态,系统态和空闲态,分别表示CPU处于用户态执行的时间,系统内核执行的时间,和空闲系统进程执行的时间。平时所说的CPU利用率是指:CPU执行非系统空闲进程的时间 / CPU总的执行时间。在内核中,有一个全局变量:Jiffies。 Jiffies代表时间。它的单位随硬件平台的不同而不同。系统里定义了一个常数HZ,代表每秒种最小时间间隔的数目。这样jiffies的单位就是1/HZ。Intel平台jiffies的单位是1/100秒,这就是系统所能分辨的最小时间间隔了。每个CPU时间片,Jiffies都要加1。 CPU的利用率就是用执行用户态+系统态的Jiffies除以总的Jifffies来表示。”

下面我们看一下/proc/stat 的内容结构

/bin/cat /proc/stat
cpu  3783155 5336 947214 78774537 115679 6 89497 0
cpu0 871159 806 194940 19851524 8176 0 2221 0
cpu1 918820 1900 203290 19794976 7834 1 1980 0
cpu2 922359 882 213789 19715943 61418 2 14503 0
cpu3 1070815 1747 335193 19412092 38250 1 70791 0
intr 284814153 209329067 3 0 0 4 0 0 0 1 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 252 0 0 0 0 0 0 0 2664133 0 0 0 0 0 0 0 72820689 0 0 0 0 0
ctxt 1591477835
btime 1268412588
processes 1346557
procs_running 1
procs_blocked 1

咋一看去相当的晕,完全不知从何下手。有关文件格式的介绍可以参考:http://www.linuxhowtos.org/System/procstat.htm
下面对输出信息做解释:

CPU时间=user+system+nice+idle+iowait+irq+softirq
“intr”这行给出中断的信息,第一个为自系统启动以来,发生的所有的中断的次数;然后每个数对应一个特定的中断自系统启动以来所发生的次数。

“ctxt”给出了自系统启动以来CPU发生的上下文交换的次数。
“btime”给出了从系统启动到现在为止的时间,单位为秒。
“processes (total_forks) 自系统启动以来所创建的任务的个数目。
“procs_running”:当前运行队列的任务的数目。
“procs_blocked”:当前被阻塞的任务的数目。
那么CPU利用率可以使用以下两个方法。先取两个采样点,然后计算其差值:

[code lang="code"]
cpu usage=(idle2-idle1)/(cpu2-cpu1)*100 cpu usage=[(user_2 +sys_2+nice_2) - (user_1 + sys_1+nice_1)]/(total_2 - total_1)*100
[/code]

以下用分别用bash和perl做的一个cpu利用率的计算:
原作者注:以下代码则采用公式为:
[code lang="code"]
total_0USER[0]+NICE[0]+SYSTEM[0]+IDLE[0]+IOWAIT[0]+IRQ[0]+SOFTIRQ[0] total_1=USER[1]+NICE[1]+SYSTEM[1]+IDLE[1]+IOWAIT[1]+IRQ[1]+SOFTIRQ[1] cpu usage=(IDLE[0]-IDLE[1]) / (total_0-total_1) * 100
[/code]

bash 代码:

#!/bin/sh
##echo user nice system idle iowait irq softirq
CPULOG_1=$(cat /proc/stat | grep 'cpu ' | awk '{print $2" "$3" "$4" "$5" "$6" "$7" "$8}')
SYS_IDLE_1=$(echo $CPULOG_1 | awk '{print $4}')
Total_1=$(echo $CPULOG_1 | awk '{print $1+$2+$3+$4+$5+$6+$7}')

sleep 5

CPULOG_2=$(cat /proc/stat | grep 'cpu ' | awk '{print $2" "$3" "$4" "$5" "$6" "$7" "$8}')
SYS_IDLE_2=$(echo $CPULOG_2 | awk '{print $4}')
Total_2=$(echo $CPULOG_2 | awk '{print $1+$2+$3+$4+$5+$6+$7}') 

SYS_IDLE=`expr $SYS_IDLE_2 - $SYS_IDLE_1`

Total=`expr $Total_2 - $Total_1`
SYS_USAGE=`expr $SYS_IDLE/$Total*100 |bc -l`

SYS_Rate=`expr 100-$SYS_USAGE |bc -l`

Disp_SYS_Rate=`expr "scale=3; $SYS_Rate/1" |bc`
echo $Disp_SYS_Rate%

perl 代码:

#!/usr/bin/perl
use warnings;

$SLEEPTIME=5;

if (-e "/tmp/stat") {
	unlink "/tmp/stat";
}
open (JIFF_TMP, ">>/tmp/stat") || die "Can't open /proc/stat file!\n";
open (JIFF, "/proc/stat") || die "Can't open /proc/stat file!\n";
@jiff_0=<JIFF>;
print JIFF_TMP $jiff_0[0] ;
close (JIFF);

sleep $SLEEPTIME;

open (JIFF, "/proc/stat") || die "Can't open /proc/stat file!\n";  @jiff_1=<JIFF>;
print JIFF_TMP $jiff_1[0];
close (JIFF);
close (JIFF_TMP);

@USER=`awk '{print \$2}' "/tmp/stat"`;
@NICE=`awk '{print \$3}' "/tmp/stat"`;
@SYSTEM=`awk '{print \$4}' "/tmp/stat"`;
@IDLE=`awk '{print \$5}' "/tmp/stat"`;
@IOWAIT=`awk '{print \$6}' "/tmp/stat"`;
@IRQ=`awk '{print \$7}' "/tmp/stat"`;
@SOFTIRQ=`awk '{print \$8}' "/tmp/stat"`;

$JIFF_0=$USER[0]+$NICE[0]+$SYSTEM[0]+$IDLE[0]+$IOWAIT[0]+$IRQ[0]+$SOFTIRQ[0];
$JIFF_1=$USER[1]+$NICE[1]+$SYSTEM[1]+$IDLE[1]+$IOWAIT[1]+$IRQ[1]+$SOFTIRQ[1];
$SYS_IDLE=($IDLE[0]-$IDLE[1]) / ($JIFF_0-$JIFF_1) * 100;  $SYS_USAGE=100 - $SYS_IDLE;

printf ("The CPU usage is %1.2f%%\n",$SYS_USAGE);

参考原文:http://server.51cto.com/sCollege-188250.htm

一个简单的由perl实现的端口监控脚本,邮件通知+手机短信通知

先说一下原理,1,根据端口的响应时间来判断是否宕掉;2,如果宕掉了就发一封邮件到指定邮箱(注意:需要用到sendmail, 要安装配置好)
另一个,如果需要手机短信通知。其实不需要搞什么飞信接口了,直接去注册一个139邮箱,免费的邮件到达短信通知,包括邮件内容的! 如果不想用139邮箱,也可以选择qq邮箱的短信通知服务。或其他服务商,任你选择了。

#!/usr/bin/perl -X

use IO::Socket;

##############################
# Constant define (configure)
##############################
# mail config
use constant MAIL_ADDR          => ('to'=>'zhys9@139.com', 'from'=>'nginx.org@gmail.com');
# common config
use constant MD5SUM_FILE        => '/tmp/__monitor_md5sum_hash';
# apache
use constant WEBSERVER_PORT        => 80;
use constant WEBSERVER_HOSTS     => ('localhost');
# mysql
use constant MYSQL_PORT         => 3306;
use constant MYSQL_HOSTS      => ('localhost');
# memcache
use constant PHPFCGI_PORT      => 9000;
use constant PHPFCGI_HOSTS   => ('localhost');

##############################
# Server port is alive check
##############################
sub check_server_alive {
    my($server, $port) = @_;

    $sock = IO::Socket::INET->new(PeerAddr=>$server, PeerPort=>$port, Proto=>'tcp', Timeout=>1);
    if (!$sock){
        return 0;
    }
    $sock->close();
    return 1;
}

##############################
# Send notice mail
##############################
sub send_mail {
    my ($subject, $content) = @_;;
    my %mailaddr = MAIL_ADDR;

    open(MAIL, "|/usr/sbin/sendmail -t");

    ## Mail Header
    print MAIL "To: $mailaddr{'to'}\n";
    print MAIL "From: $mailaddr{'from'}\n";
    print MAIL "Subject: $subject\n\n";

    ## Mail Body
    print MAIL "$content\n";

    close(MAIL);

}

##############################
# Check server alive main
##############################
sub monitor_main {
    # check apache
    foreach $item (WEBSERVER_HOSTS) {
        if (!check_server_alive($item, WEBSERVER_PORT)) {
            send_mail("$item web server is down", "$item web server is down. please timely restoration");
        }
    }
    # check mysql
    foreach $item (MYSQL_HOSTS) {
        if (!check_server_alive($item, MYSQL_PORT)) {
        print("mysql is down.");
            send_mail("$item mysql server is down", "$item mysql server is down. please timely restoration");
        }
    }
    # check fast-cgi
    foreach $item (PHPFCGI_HOSTS) {
        if (!check_server_alive($item, PHPFCGI_PORT)) {
            send_mail("$item fast-cgi is down", "$item fast-cgi is down. please timely restoration");
        }
    }
}

##############################
# Main running
##############################

monitor_main();

本脚本参考文档:
http://blog.csdn.net/re_think/archive/2009/06/25/4296833.aspx
perl发送邮件:http://www.cyberciti.biz/faq/sending-mail-with-perl-mail-script/

系统监控配置之cacti+rrdtool+netsnmp

一,安装rrdtool 官网: http://oss.oetiker.ch/rrdtool/

/usr/bin/wget http://oss.oetiker.ch/rrdtool/pub/rrdtool-1.4.2.tar.gz
/bin/tar xzf rrdtool-1.4.2.tar.gz
cd rrdtool-1.4.2
./configure --prefix=/home/rrdtool

提示以下warning信息:
configure: WARNING:
—————————————————————————-
* I found a copy of pkgconfig, but there is no pangocairo.pc file around.
  You may want to set the PKG_CONFIG_PATH variable to point to its
  location.
—————————————————————————-

configure: WARNING:
—————————————————————————-
* I could not find a working copy of pangocairo. Check config.log for hints on why
  this is the case. Maybe you need to set LDFLAGS and CPPFLAGS appropriately
  so that compiler and the linker can find libpango-1.0 and its header files. If
  you have not installed pangocairo, you can get it either from its original home on

     http://ftp.gnome.org/pub/GNOME/sources/pango/1.17

  You can find also find an archive copy on

     http://oss.oetiker.ch/rrdtool/pub/libs

  The last tested version of pangocairo is 1.17.

       LIBS=-lm  -lglib-2.0 
   LDFLAGS= -L/lib64   
  CPPFLAGS= -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include 

—————————————————————————-
               
checking for xmlParseFile in -lxml2… yes
checking libxml/parser.h usability… yes
checking libxml/parser.h presence… yes
checking for libxml/parser.h… yes
configure: error: Please fix the library issues listed above and try again.

信息表明缺了pango的头文件,因此要先安装pango-devel

/usr/bin/yum install pango-devel

接下来重新编译

./configure --prefix=/home/rrdtool

这次编译通过:
Config is DONE!

make && make install

做一个软连接

/bin/ln -s /home/rrdtool/bin/* /usr/local/bin/
cd ..

这样就完成了rrdtool的安装,

 

二,安装net-snmp 官网: http://www.net-snmp.org/

先下载net-snmp的最新版本5.5

/usr/bin/wget http://downloads.sourceforge.net/project/net-snmp/net-snmp/5.5/net-snmp-5.5.tar.gz?use_mirror=nchc
/bin/tar xzf net-snmp-5.5.tar.gz
cd net-snmp-5.5
./configure #一切按照默认值来编译(默认安装到/usr/loca/)
make && make install

运行以下snmpget,检查是否安装成功

/usr/loca/bin/snmpget

我这里就遇到了问题,提示信息是:
/usr/local/bin/snmpget: error while loading shared libraries: libnetsnmp.so.20: cannot open shared object file: No such file or directory
先通过ldd查看snmpget需要加载哪些库

[root@test_server net-snmp-5.5]# /usr/bin/ldd /usr/local/bin/snmpget
        libnetsnmp.so.20 => not found
        libcrypto.so.6 => /lib64/libcrypto.so.6 (0×0000003c1fc00000)
        libc.so.6 => /lib64/libc.so.6 (0×0000003c1d000000)
        libdl.so.2 => /lib64/libdl.so.2 (0×0000003c1d400000)
        libz.so.1 => /usr/lib64/libz.so.1 (0×0000003c1ec00000)
        /lib64/ld-linux-x86-64.so.2 (0×0000003c1cc00000)
可见需要加载的库文件大都放在/lib64/下的;
再查一下libnetsnmp.so.20是在什么位置

/usr/bin/whereis libnetsnmp.so.20
libnetsnmp.so: /usr/local/lib/libnetsnmp.so /usr/local/lib/libnetsnmp.so.20

ok, 至此我们就知道怎么解决问题了:

/bin/ln -s /usr/local/lib/libnetsnmp.so.20 /lib64/libnetsnmp.so.20

再执行一次snmpget

/usr/local/bin/snmpget
Created directory: /var/net-snmp
Created directory: /var/net-snmp/mib_indexes
No hostname specified.
USAGE: snmpget [OPTIONS] AGENT OID [OID]...

  Version:  5.5
  Web:      <a href="http://www.net-snmp.org/">http://www.net-snmp.org/</a>
  Email:    <a href="mailto:net-snmp-coders@lists.sourceforge.net">net-snmp-coders@lists.sourceforge.net</a>

OPTIONS:
  -h, --help            display this help message
...

一切OK

三, 安装cacti 官网: http://www.cacti.net/
值得注意的是cacti的环境需求:
RRDTool 1.0.49 or 1.2.x or greater
MySQL 4.1.x or 5.x or greater
PHP 4.3.6 or greater, 5.x greater highly recommended for advanced features
A Web Server e.g. Apache or IIS

先确认是否满足,然后:

cd ..
/usr/bin/wget http://www.cacti.net/downloads/cacti-0.8.7e.tar.gz
/bin/tar xzf cacti-0.8.7e.tar.gz
/bin/mv cacti-0.8.7e cacti

然后就可以把cacti转移到web目录下

/bin/mv cacti /data/htdocs/cacti
cd /data/htdocs/cacti
/home/mysql/bin/mysql cacti &lt; cacti.sql #导入数据库结构
/bin/chown www:www -R .
/bin/vi include/config.php

修改数据库连接信息:
$database_default = “cacti”;
$database_hostname = “localhost”;
$database_username = “root”;
$database_password = “”;
$database_port = “3306″;

增加后台任务,每两分钟搜集一次数据

*/5 * * * * /usr/local/bin/php /usr/local/apche2/htdocs/cacti/poller.php > /dev/null 2>&1

接下来就从前台访问cacti的安装目录
http://zhys9.com/cacti/install/
按照以下图片中的标红提示完成配置

1

2

3
最后通过默认账号密码: admin/admin 登录,然后系统会提示修改密码;

 

接下来的事情就只是用了 ;)