我爱linux

我是一个linux运维从业者,这个网站记录一些平时调试linux相关文档及生活随笔

Linux 服务器根据CPU负载及内存占用自动重启服务脚本

with one comment

最近发现我的vps服务器经常无故cpu负载超过2,甚至达到4,影响网站访问,具体原因可能是php5-cgi的问题,但深层次的原因还没找到,为了让服务器能稳定运行,所以做个脚本能自动检测系统负载,但复杂很高的时候,自动重启有问题的程序
主要用于监控 linux 服务器负载及内存占用,如 MySQl、php-fpm,当负载或内存占用达到设置值后,便自动重启该进程以避免宕机。

# 设置最大内存占用百分比
PID_MEM_MAX=”85″

# 设置最大系统负载
SYS_LOAD_MAX=”1″

# 设置需要监控的服务名称
NAME_LIST=”php5-cgi mysql”

for NAME in $NAME_LIST
do
# 初始化内存统计
PID_MEM_SUM=0

# 获取该程序总进程数
PID_NUM_SUM=`ps aux | grep $NAME | wc -l`

# 列出每个进程内存占用百分比
PID_MEM_LIST=`ps aux | grep $NAME | awk ‘{print $4}’`

# 计算所有进程总内存占用
for PID_MEM in $PID_MEM_LIST
do
PID_MEM_SUM=`echo $PID_MEM_SUM + $PID_MEM | bc`
done

# 获取最近一分钟系统负载
SYS_LOAD=`uptime | awk ‘{print $(NF-2)}’ | sed ‘s/,//’`

# 比较内存占用和系统负载是否超过阀值
MEM_VULE=`awk ‘BEGIN{print(‘”$PID_MEM_SUM”‘>=’”$PID_MEM_MAX”‘?”1″:”0″)}’`
LOAD_VULE=`awk ‘BEGIN{print(‘”$SYS_LOAD”‘>=’”$SYS_LOAD_MAX”‘?”1″:”0″)}’`

# 如果系统内存占用和系统负载超过阀值,则进行下面操作。
if [ $MEM_VULE = 1 ] || [ $LOAD_VULE = 1 ] ;then
# 写入日志
echo $(date +”%y-%m-%d %H:%M:%S”) “killall $NAME” “(MEM:$PID_MEM_SUM,LOAD:$SYS_LOAD)”>> /var/log/autoreboot.log
# 正常停止服务
/etc/init.d/$NAME stop
sleep 3
# 强制关闭
pkill $NAME

# 重启
/etc/init.d/$NAME start
#写入日志
echo $(date +”%y-%m-%d %H:%M:%S”) “start $NAME” “(MEM:$PID_MEM_SUM,LOAD:$SYS_LOAD)” >> /var/log/autoreboot.log
else
echo “$NAME very health!(MEM:$PID_MEM_SUM,LOAD:$SYS_LOAD)” > /dev/null
fi
done
以上代码保存为一个文件,例如:auto_reboot.sh

添加计划任务,设置每分钟检查一次

crontab -e
* * * * * /bin/bash/root/auto_reboot.sh

注意文件的位置要搞正确。

请确保您的Linux系统中已经安装了bc,否则会出现错误。查看是否安装了bc可以使用命令:

1
bc -v
如果没有安装,centos可以用 yum -y install bc 安装它

可以使用命令

1
sh /bin/bash/root/auto_reboot.sh
测试以上脚本,如果出现 syntax error near unexpected token `do 这样的错误请查看本站文章《Linux 下sh脚本执行时出现 syntax error near unexpected token `do 错误的解决方法 》一文。

CentOS VPS服务器根据CPU负载及内存占用自动重启的bash shell脚本:
#!/bin/sh
#usage: */2 * * * * root /root/checkload.sh
# [CentOS]VPS服务器根据CPU负载及内存占用自动重启脚本
# 设置最小剩余内存,一般至少要剩余50M可用(单位兆)
FREE_MEM_MIN=”50″
# 设置最大系统负载
SYS_LOAD_MAX=”3″
# 设置重启服务的最小剩余内存(单位兆)
RESTART_FREE_MEM_MIN=”500″
# 设置需要监控的服务名称
NAME_LIST=”httpd mysqld”
for NAME in $NAME_LIST
do
# 获得剩余内存(单位兆)
FREE_MEM=`free -m|grep Mem|awk ‘{print $4}’`
# 获得已用内存(单位兆)
#FREE_MEM=`free -m|grep Mem|awk ‘{print $3}’`
# 获取最近一分钟系统负载
SYS_LOAD=`uptime | awk ‘{print $(NF-2)}’ | sed ‘s/,//’`
# 比较内存占用和系统负载是否超过阀值
MEM_VULE=`awk ‘BEGIN{print(‘”$FREE_MEM”‘<’”$FREE_MEM_MIN”‘?”1″:”0″)}’`
LOAD_VULE=`awk ‘BEGIN{print(‘”$SYS_LOAD”‘>=’”$SYS_LOAD_MAX”‘?”1″:”0″)}’`

# 测试结果
#LOAD_VULE=”1″
#echo $(date +”%y-%m-%d %H:%M:%S”) “DEBUG $NAME” “(FREE_MEM:$FREE_MEM|$MEM_VULE,LOAD:$SYS_LOAD|$LOAD_VULE)”>> /var/log/autoreboot_debug.log

# 如果系统内存占用和系统负载超过阀值,则进行下面操作。
if [ $MEM_VULE = 1 ] || [ $LOAD_VULE = 1 ] ;then
# 写入日志
echo $(date +”%y-%m-%d %H:%M:%S”) “killall $NAME” “(FREE_MEM:$FREE_MEM,LOAD:$SYS_LOAD)”>> /var/log/autoreboot.log
# 正常停止服务
service $NAME stop
sleep 3
# 强制关闭
skill $NAME
# 重启
sleep 10
for i in 1 2 3
do
FREE_MEM=`free -m|grep Mem|awk ‘{print $4}’`
MEM_VULE=`awk ‘BEGIN{print(‘”$FREE_MEM”‘>=’”$RESTART_FREE_MEM_MIN”‘?”1″:”0″)}’`
if [ `pgrep $NAME | wc -l` -le 0 ] && [ $MEM_VULE = 1 ]
then
service $NAME start
sleep 15
echo “AutoStart:” $(date +”%y-%m-%d %H:%M:%S”) “start $NAME” `ps -ef | grep $NAME | wc -l` > /var/log/autoreboot.log
fi
done

# 写入日志
echo $(date +”%y-%m-%d %H:%M:%S”) “start $NAME” “(FREE_MEM:$FREE_MEM,LOAD:$SYS_LOAD)” >> /var/log/autoreboot.log
else
MEM_VULE=`awk ‘BEGIN{print(‘”$FREE_MEM”‘>=’”$RESTART_FREE_MEM_MIN”‘?”1″:”0″)}’`
if [ `pgrep $NAME | wc -l` -le 0 ] && [ $MEM_VULE = 1 ]
then
service $NAME start
sleep 15
echo “AutoStart:” $(date +”%y-%m-%d %H:%M:%S”) “start $NAME” `ps -ef | grep $NAME | wc -l` > /var/log/autoreboot.log
else
echo “$NAME very health!(FREE_MEM:$FREE_MEM,LOAD:$SYS_LOAD)” > /dev/null
fi
fi
done

Written by zhangweibo

四月 18th, 2012 at 1:33 下午

Posted in linux

Tagged with , ,

抢了个buyvm

with 4 comments

一直说buyvm的口碑还行,性价比很好,但一直没货,终于等到要放货的消息,时间锁定在3月23日晚上10点,可惜我9点上去的时候,已经发现buyvm被ddos攻击,网站根本没法访问,真是树大招风,上twrite和IRC也证实了这事,特逗的是IRC上到处都是国人站长,都快被我们中国人占领了,哈哈

攻击一直在持续,直到11点,还没放货的任何消息,我也觉得希望不大,就洗洗睡了

凌晨4点左右,恍惚听到一个短信声音,迷迷糊糊看一下,发现居然是我的自动脚本提示我buyvm放货了,这才想起几个月前做了自动脚本,只要侦测到库存有货就发短信给我,我怎么把这事给忘了,哈

赶紧起床,可惜我的笔记本不争气,太老了,都陪伴我6年了,启动了将近5分钟

咳,还是错过了15$的那款,估计就差那么几分钟,看看256M的还有,赶紧下手,幸亏前几天我已经通过了帐号验证,购物很顺利,对了,buyvm结算都是按按月来的,所以24日下单,多出的几天就折算出美金,第一次一起算了,以后都是每月1日结帐。

 

下单完成,pp付款,一气呵成。

上午大概10点的时候,服务器就激活了,客服速度还行,离我付款就间隔了4小时

Written by zhangweibo

三月 26th, 2012 at 8:49 上午

Posted in vps

Tagged with

充分利用linode的4核cpu

without comments

我的Linode十分繁忙,在跑一些密集操作数据库的Rake任务时尤其如此。但我观察发现,Linode服务器的4核CPU,只有第1个核心(CPU#0)非常忙,其他都处于idle状态。

不了解Linux是如何调度的,但在Linode的这种状态下,显然有优化的余地。除了处理正常任务,CPU#0还需要处理各种中断。因此,若能将CPU#0分担的任务摊派到其他CPU核心上,可以预见,系统的处理能力将有更大的提升。

两个名词

SMP (Symmetrical Multi-Processing):指在一个计算机上汇集了一组处理器(多CPU),各CPU之间共享内存子系统以及总线结构。

CPU affinity:中文唤作“CPU亲和力”,是指在CMP架构下,能够将一个或多个进程绑定到一个或多个处理器上运行。

一、在Linux上修改进程的“CPU亲和力”

在Linux上,可以通过 taskset 命令进行修改。以Ubuntu为例,运行如下命令可以安装taskset工具。

# apt-get install schedutils

对运行中的进程,文档上说可以用下面的命令,把CPU#1 #2 #3分配给PID为2345的进程:

# taskset -cp 1,2,3 2345

但我尝试没奏效,于是我关掉了MySQL,并用taskset将它启动:

# taskset -c 1,2,3 /etc/init.d/mysql start

对于其他进程,也可如此处理(nginx除外,详见下文)。之后用top查看CPU的使用情况,原来空闲的#1 #2 #3,已经在辛勤工作了。

4颗CPU全在跑

二、配置nginx绑定CPU

刚才说nginx除外,是因为nginx提供了更精确的控制。

在conf/nginx.conf中,有如下一行:

worker_processes  1;

这是用来配置nginx启动几个工作进程的,默认为1。而nginx还支持一个名为worker_cpu_affinity的配置项,也就是说,nginx可以为每个工作进程绑定CPU。我做了如下配置:

worker_processes  3;
worker_cpu_affinity 0010 0100 1000;

这里0010 0100 1000是掩码,分别代表第2、3、4颗cpu核心。

重启nginx后,3个工作进程就可以各自用各自的CPU了。

三、刨根问底

  1. 如果自己写代码,要把进程绑定到CPU,该怎么做?可以用sched_setaffinity函数。在Linux上,这会触发一次系统调用。
  2. 如果父进程设置了affinity,之后其创建的子进程是否会有同样的属性?我发现子进程确实继承了父进程的affinity属性(其实用taskset启动进程就是一次fork+exec)。

Written by zhangweibo

三月 20th, 2012 at 8:20 下午

Posted in linux,nginx,vps

Tagged with , ,

让ecshop能根据智能手机自动区分web和wap访问方式

without comments

众所周知,ecshop在2.7.x版本,引入了mobile目录,并在首页进行判断,如果来访为手机用户,则自动把链接跳转到 www.xxx.com/mobile ,用wap方式来引导。

但这两年手机技术发展也很快,大屏化、高速化、智能化是明显的改变。智能机3.5寸以上的屏幕到处都是,分辨率大部分都在 720*480以上,很多高端用户希望在手机屏幕上得到与电脑一样的体验。

同时为了兼顾低端低网速的用户群,又不能完全关闭wap方式。

今天闲着无事,做了一点尝试,供各位参考。

修改index.php

找到 $ua = strtolower($_SERVER['HTTP_USER_AGENT']);

做如下代码修改(增加了普通手机的ua代码,增加了智能手机的ua变量)
$uachar = “/(nokia|sony|ericsson|mot|samsung|sgh|lg|philips|panasonic|alcatel|lenovo|cldc|midp|coolpad|k-touch|tcl|oppo|doov|amoi|bbk|cect|amoi|zte|huawei)/i”;

$smartuachar = “/(iphone|ipad|android|smartphone|windows)/i”;

//判别是iphone ipad android smartphone windows类手机就按普通web方式处理,其他手机按wap处理

if(!(preg_match($smartuachar, $ua)) && ($ua == ” || preg_match($uachar, $ua))&& !strpos(strtolower($_SERVER['REQUEST_URI']),’wap’))
经测试,我的iphone、ipad无论3G还是wifi都以web方式正常浏览。而一台旧huawei手机就自动按wap方式访问了。由于环境所限,各种流行的 android及SM、WP手机都没有测试。各位自行核对web http日志找到的UA来优化代码吧。

好了,测试一下我的商城 www.applezone.cn

 

Written by zhangweibo

三月 8th, 2012 at 9:06 下午

Posted in ecshop

Tagged with