Blog Archives
小技巧-Suse Linux下设置Cron job简便方法
0很多时候设置Cron job,也就是自动执行的脚本,来定时做一些重复劳动的事情,一般都是采用导入或者修改Crontab的方法来实现。最近发现我的SuseLinux下面,有个很偷懒的做法,就是把待执行的脚本,直接放在/etc/下面的cron.daily/ cron.hourly/ cron.monthly/ cron.weekly/几个文件夹之一当中,就可以自动执行了。具体那个是每天一次,每小时一次,每月一次,每周一次,不用我说,大家都能看出来了吧。
具体的执行策略,据我观察,就是从脚本放入文件夹开始差不多计时的。比如现在放入一个脚本到cron.daily差不多以后每天这个时候就会执行一遍。(不计cron本身醒来去读该文件夹的时间误差啦)
注意,是直接把需要执行的脚本或者程序放进去就可以啦,一点不需要在crontab的格式上烦神了。
Apache优化限制内存占用,防止当机
0Linux Apache服务器架构应该以稳定著称, 前一篇日志提到有人抱怨soso spider把自己的网站搞死了,这个其实不能全怪spider.想想看,如果有足够多的用户,正常访问网站,人多的像soso的spider一样,apache也不可能挂了? 关键在于Apache配置, 以及配置之后一定要进行压力测试.。
先说说配置, 第一是不要加载不必要的apache模块, 这样可以限制每个进程的内存占用量(对prefork而言,worker没用过,因为php的原因). 然后就要注意下面这个性能配置部分。
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写下文本,源于我最近一次失败的尝试。我的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!
0I 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将网站数据库备份后留在本地硬盘上,并不是一个可靠的方案。我就把压缩后的文件发送到电子邮件信箱里。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 |