Blog Archives

小技巧-Suse Linux下设置Cron job简便方法

0
本文是专题:建站日记中的第6篇,共12篇

 很多时候设置Cron job,也就是自动执行的脚本,来定时做一些重复劳动的事情,一般都是采用导入或者修改Crontab的方法来实现。最近发现我的SuseLinux下面,有个很偷懒的做法,就是把待执行的脚本,直接放在/etc/下面的cron.daily/ cron.hourly/ cron.monthly/ cron.weekly/几个文件夹之一当中,就可以自动执行了。具体那个是每天一次,每小时一次,每月一次,每周一次,不用我说,大家都能看出来了吧。

具体的执行策略,据我观察,就是从脚本放入文件夹开始差不多计时的。比如现在放入一个脚本到cron.daily差不多以后每天这个时候就会执行一遍。(不计cron本身醒来去读该文件夹的时间误差啦)

注意,是直接把需要执行的脚本或者程序放进去就可以啦,一点不需要在crontab的格式上烦神了。

Apache优化限制内存占用,防止当机

0
本文是专题:建站日记中的第7篇,共12篇

Linux Apache服务器架构应该以稳定著称, 前一篇日志提到有人抱怨soso spider把自己的网站搞死了,这个其实不能全怪spider.想想看,如果有足够多的用户,正常访问网站,人多的像soso的spider一样,apache也不可能挂了? 关键在于Apache配置, 以及配置之后一定要进行压力测试.。

先说说配置, 第一是不要加载不必要的apache模块, 这样可以限制每个进程的内存占用量(对prefork而言,worker没用过,因为php的原因). 然后就要注意下面这个性能配置部分。

View Code MYSQL
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
<ifmodule prefork.c="">          
	# number of server processes to start           
	# http://httpd.apache.org/docs/2.2/mod/mpm_common.html#startservers  	
	# 服务器启动时,产生的服务进程         
	StartServers       8          
	# minimum number of server processes which are kept spare          
	# http://httpd.apache.org/docs/2.2/mod/prefork.html#minspareservers  	
	# 系统空闲态,至少要保留的服务进程数,也就是相当于,饭店里没人吃饭,也要至少站6个服务员等顾客来         
	MinSpareServers    6          
	# maximum number of server processes which are kept spare          
	# http://httpd.apache.org/docs/2.2/mod/prefork.html#maxspareservers  	
	# 系统空闲态,至多保留的服务进程数,也就是相当于,饭店里要是没有顾客,数一数站着没事的服务员,多于10个的话,就是让他们放假回家.         
	MaxSpareServers    10          
	# highest possible MaxClients setting for the lifetime of the Apache process.          
	# http://httpd.apache.org/docs/2.2/mod/mpm_common.html#serverlimit  	
	# 服务器允许配置的进程数上限,设置了MaxClients最大允许配置的数值.必须重启服务器才生效的值.         
	ServerLimit       40          
	# maximum number of server processes allowed to start          
	# http://httpd.apache.org/docs/2.2/mod/mpm_common.html#maxclients  	
	# 服务器允许连接的进程数上限,也就是饭店里正常情况下最大允许进入的人数.此值不需要重启服务器即可修改生效,但不能超过ServerLimit,及时配置超过,也只能最大运行ServerLimit个进程. 
       	MaxClients        20          
	# maximum number of requests a server process serves          
	# http://httpd.apache.org/docs/2.2/mod/mpm_common.html#maxrequestsperchild          
	MaxRequestsPerChild  10000  
</ifmodule>

关于其他参数,就搜索一下吧,我就不再重复了.

关键在于,一定要测试自己服务器的负载,是不是能承受的住最糟糕的情况. 使用命令:

ab2 –n 1000 –c 100 http://yourdomain.com/index.php

这条命令模拟并发连接数为100的情况,而上面的配置最大只允许20个并发,所以有一些请求会在队列里等待服务,但不会耗光你的内存。你可以尝试加大自我攻击的力度,如果服务器在这样糟糕的情况下还能剩余一些内存,系统就肯定不会崩溃。 请注意,这里说的内存是物理内存,别把swap算进来。一旦用上swap,因为硬盘的速度和内存无法相提并论,造成服务器的响应就会非常慢。这时候应该减小MaxClients到自己能承受的值。

监控剩余内存,自动重启Apache和Mysql,使用Crontab和Daemon方法.

0
本文是专题:建站日记中的第8篇,共12篇

写下文本,源于我最近一次失败的尝试。我的VPS是限定最高内存用量的,上限为2G,如果内存用完了,就会出现Cannot allocate memory无法获取可用内存的故障,导致SSH无法远程登录,也网站性能也急剧下降。这个问题可以通过限制Apache和Mysql的配置来预防。可以做保守配置来杜绝这样的问题。但是由于我的配置比较乐观,可能在某些木马攻击或者劣质网站爬虫的骚扰下,前几天出现过一次内存不足问题,导致不得不请求服务商帮我重启了一下运行了60多天的服务器,让我非常伤心。所以我尝试了一下,可否通过建立脚本,监控运行状况来自动重启Apache和Mysql来释放内存,避免重启服务器,好让我的uptime千秋万代地积累下去?

最容易想到的就是采用Crontab来做了,下面是我第一次的尝试。脚本如下

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
#check free memory and decide how to maintain system.
#Albert Zhu 朱文昊 V0.1 http://zhuwenhao.com
MinFreeMem='100000' #only restart apache below this number
BadFreeMem='10000'  #retart apache and mysql below this number
CurrentMem=$(cat /proc/meminfo | grep -i MemFree | cut -d ':' -f2 | cut -d 'k' -f1)
CurrentMem=$(($CurrentMem+0))
#echo "CurrentMem="$CurrentMem
#echo "MinFreeMem="$MinFreeMem
#echo "BadFreeMem="$BadFreeMem
if [ $BadFreeMem -gt $CurrentMem ];
then
        echo `date "+%Y-%m-%d-%H-%M-%S"`
        echo "CurrentMem="$CurrentMem
        echo "restarted two service"
        service apache2 restart;
        service mysql   restart;
else
 
        if [ $MinFreeMem -gt $CurrentMem ];
        then
                echo `date "+%Y-%m-%d-%H-%M-%S"`
                echo "CurrentMem="$CurrentMem
                echo "restarted apache"
                service apache2 restart;
        fi
        echo `date "+%Y-%m-%d-%H-%M-%S"`
        echo "Free Memory is Good!"
fi

然后使用cron job来自动运行 crontab –e 后加入

1
* * * * * ./memmonitor.sh >> ./memmonitor.log

这样我的脚本会每分钟运行一下,怎么样?感觉很爽吧!于是压力测试,Apache在强大的并发连接下,很快内存飙升,2G内存立马没了。结果,当Cron job醒来后,内存不足,自己都运行不起来,崩溃~~~

分析一下,感觉是cron job每分钟运行一次,太慢!造成对内存感觉不灵敏,等到发现,已经晚了。cron设计最快也就是每分钟运行。于是改用死循环来做,也就是做成守护进程Daemon,对内存每秒钟检查一次,够好了吧?

继续压力测试,依然崩溃~~~~~

于是review脚本,发现 service apache2 restart这样的语句,本身需要较大的内存,而且貌似要等到apache的子进程把当前服务提供完后,才终止(这点我不是很确定,不要太相信)。如果在DDOS下,哪里有空等服务结束?应当直接kill掉。修改脚本为如下

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#check free memory and decide how to maintain system.
#Albert Zhu 朱文昊 V0.2 http://zhuwenhao.com
KillAllApacheSon ()
{
ListPIDtoKill=$(ps  -u wwwrun | grep httpd | cut -d ' ' -f1)
echo "List PID to Kill "$ListPIDtoKill
i=1
while [ true ];
do
        GetPIDtoKill=$(echo ${ListPIDtoKill} | cut -d ' ' -f${i})
        GetPIDtoKill=$(($GetPIDtoKill+0))
        if [ $GetPIDtoKill -gt 0 ];
        then
                kill $GetPIDtoKill
                echo "kill "$GetPIDtoKill
                i=$(($i+1))
        else
                break;
        fi
done
echo "Killed Apache Son Num: "$i
}
KillMysql ()
{
GetPIDtoKill=$(ps -u mysql | cut -d ' ' -f1)
GetPIDtoKill=$(($GetPIDtoKill+0))
if [ $GetPIDtoKill -gt 0 ];
then
        kill $GetPIDtoKill
        echo "kill mysql and PID is "$GetPIDtoKill
fi
}
CheckMem ()
{
MinFreeMem='100000' #only restart apache below this number
BadFreeMem='10000'  #retart apache and mysql below this number
CurrentMem=$(cat /proc/meminfo | grep -i MemFree | cut -d ':' -f2 | cut -d 'k' -f1)
CurrentMem=$(($CurrentMem+0))
#echo "CurrentMem="$CurrentMem
#echo "MinFreeMem="$MinFreeMem
#echo "BadFreeMem="$BadFreeMem
if [ $BadFreeMem -gt $CurrentMem ];
then
        echo `date "+%Y-%m-%d-%H-%M-%S"`
        echo "CurrentMem="$CurrentMem
        echo "restarted two service"
        KillAllApacheSon
        KillMysql
        service mysql   restart
else
 
        if [ $MinFreeMem -gt $CurrentMem ];
        then
                echo `date "+%Y-%m-%d-%H-%M-%S"`
                echo "CurrentMem="$CurrentMem
                echo "restarted apache"
                KillAllApacheSon
        fi
        echo `date "+%Y-%m-%d-%H-%M-%S"`
        echo "Free Memory is Good!"
fi
}
renice -15 $$ >> ./second.log
#echo $(nice)
while [ true ];
do
#       sleep 1
        usleep 100
        CheckMem>>./second.log
done

这次修改比较幸苦,感觉一个小脚本写到这份上,对我来说也算得上是高级bash编程了吧?呵呵。拉出来溜溜?惨不忍睹。依然无法实现预期功能。为什么?难道1秒钟也太漫长?

于是请出usleep,每隔100毫秒就检查内存一次。我的cpu 10%都用在这个脚本上了,结果怎么样?没用! 写到这里,我心灰意冷了,彻底放弃。亲爱的朋友,有谁能帮帮我呢?

我写出上面的文字来,除了期待高手来解救我之外,还有一个原因。仔细想想看,我的这些脚本不能在VPS上实现功能,但应该可以在独立服务器或者PC上工作,为什么呢?因为VPS一旦接近耗尽内存,那真的是一点memory都allocate不处理,所以脚本本身就无法继续执行.但是对于独立服务器或者PC, 都有swap机制. 在物理内存耗尽的情况下, 会拿硬盘来充数,虽然速度慢很多,但以上的两个版本的脚本,都有可能正常工作.所以如果你测试以上脚本可用,请告诉我,抚慰一下我受伤的心吧 :)

Hello, IPv6!

0
本文是专题:建站日记中的第9篇,共12篇

I just moved my sites to a brand new server with IPv6 enabled. You can ping6 zhuwenhao.com or host zhuwenhao.com to test.
My IPv6 address is [2607:f2f8:3340::1eee]
Welcome to my blog via IPv6 network!

自动备份数据库并发送到电子邮箱的脚本

0
本文是专题:建站日记中的第10篇,共12篇

将网站数据库备份后留在本地硬盘上,并不是一个可靠的方案。我就把压缩后的文件发送到电子邮件信箱里。Gmail的附件目前最大25兆,QQ邮箱是50兆,所以本方法不适合大型商业网站,个人独立博客比较合适的说。

下面贴出脚本,本方法需要先安装mutt邮件客户端。
请注意,有些老点的文章中给出的示例,在邮件地址前面没有 — 符号,这会造成新版本的mutt提示 No recipients specified. 只要加上 — 符号就可以了。
还有一个注意的地方,如果连续发送很多数据库文件并保存在Sent文件中,很快就会消耗大量的本地硬盘空间。让mutt默认不保存已发送邮件的方法是修改 /etc/Muttrc文件,或者在当前用户home目录下,修改或建立一个隐藏文件 .muttrc (注意这两个M的大小写), 修改或增加这样一行 set record=”/dev/null” (一般默认为 set record=”~/Sent”),就可以让Mutt不保存已发送邮件从而节省空间了。

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
#!/bin/sh
sendfiletogmail ()
{
        FilePath=$1
        FileName=$2".bz2"
        mutt -s "Database Backup File ${FileName}" -a${FilePath}"/"${FileName} -- yourMailBox@gmail.com < "/path/to/emailbody.txt"
}
 
 
backup ()
{
        DBName=$@
        BackupPath="/path/to/"${DBName}
        BackupName=${DBName}-`date "+[%z%Z]%Y-%m-%d-%H-%M-%S"`".sql"
                if [[ -d "${BackupPath}" ]] || mkdir ${BackupPath};
                then
                                if        mysqldump -uroot -pYourPasswd \
                                                --default-character-set=utf8 --opt --master-data=1 \
                                                --single-transaction --flush-logs \
                                                ${DBName} > ${BackupPath}"/"${BackupName};
                                then
                                                echo ${BackupName}"Backup success!"
                                                bzip2 -q -s  ${BackupPath}"/"${BackupName};
                                                sendfiletogmail ${BackupPath} ${BackupName}
                                else
                                                echo ${BackupName}"Backup Failed@@@@@@@@@@@@@@@@@@@@@@@@"
                                fi
                fi
                find ${BackupPath}"/" -ctime +7 -exec rm {} \;
}
#Call the function to backup database assigned below
backup  yourDBnamd_db
Go to Top