在寻找应用程序内存泄漏的解决方案时,我正在尝试贴上临时创可贴。我写的是一个小bash
脚本,放在服务器的根目录中。这就是脚本应该做的事情:
- 获取它运行的位置
- 检查脚本是否是 crontab
- 如果 crontab 中没有,请添加到 crontab 以每 5 分钟运行一次
- 测试内存并检查%是否高于percent_allowed
- 如果以上测试,则重新启动 nginx 和 php-fmp 服务
memory_protect.sh
:
#!/bin/sh
cronfile=memory_protect.sh #NOTE THIS SHOULD DETECT IT'S SELF
path=pwd #this is the path to the file
percent_allowed=80 #this should be max memory before action
has_cron(){
#is the file in the cron?
return [[ crontab -l | egrep -v '^$|^#' | grep -q $cronfile ]] && return 1 || return 0
}
test_memory(){
memusage=`top -n 1 -b | grep "Mem"`
MAXMEM=`echo $memusage | cut -d" " -f2 | awk '{print substr($0,1,length($0)-1)}'`
USEDMEM=`echo $memusage | cut -d" " -f4 | awk '{print substr($0,1,length($0)-1)}'`
USEDMEM1=`expr $USEDMEM \* 100`
PERCENTAGE=`expr $USEDMEM1 / $MAXMEM`
#if it's above 80% alert
return [[ $PERCENTAG>$percent_allowed ]] && return 1 || return 0
}
if [[ has_cron -eq 0 ]]
then
#was not here so add
#run this script every 5 mins
*/5 * * * $path/$cronfile
fi
if [[ test_memory ]]
then
#clear some memory
/etc/init.d/nginx restart
/etc/init.d/php-fpm restart
fi
当我自行运行内存测试时,内存测试似乎有效,但这似乎不起作用。
更新
我需要dos2unix
在文件上运行,但我也意识到我最终对每个函数的条件都有返回..所以这是行不通的。现在好像说没有找到声明[[
。if
更新2 看起来很接近,它正在运行服务的重新启动,但它没有将 cron 作业放入..所以我没有看到它正在运行
#!/bin/bash
cronfile=memory_protect.sh #NOTE THIS SHOULD DETECT IT'S SELF
path=pwd #this is the path to the file
percent_allowed=80 #this should be max memory before action
has_cron(){
#is the file in the cron?
#return 0 #returning this just to test should
#be the next line but it's not working
return 0
[[ crontab -l | egrep -v '^$|^#' | grep -q $cronfile ]] && return 1 || return 0
}
test_memory(){
memusage=`top -n 1 -b | grep "Mem"`
MAXMEM=`echo $memusage | cut -d" " -f2 | awk '{print substr($0,1,length($0)-1)}'`
USEDMEM=`echo $memusage | cut -d" " -f4 | awk '{print substr($0,1,length($0)-1)}'`
USEDMEM1=`expr $USEDMEM \* 100`
PERCENTAGE=`expr $USEDMEM1 / $MAXMEM`
#if it's above 80% alert
[[ $PERCENTAG -gt $percent_allowed ]] && return 1 || return 0
}
if [[ has_cron -eq 0 ]]
then
#was not here so add
#run this script every 5 mins
#crontab -e */5 * * * $path/$cronfile
cat <(crontab -l) <(echo "*/5 * * * $path/$cronfile") | crontab -
else
echo "cron present"
fi
if [ test_memory ]
then
#clear some memory
sudo /etc/init.d/nginx restart
sudo /etc/init.d/php-fpm restart
fi
我想现在已经接近被纠正了。
答案1
要通过 Bash 脚本创建 crontab 条目,您需要更改此行:
*/5 * * * * $path/$cronfile
对于这样的事情:
# Write out current crontab
crontab -l > mycron
# Echo new cron into cron file
echo "*/5 * * * * $path/$cronfile" >> mycron
# Install new cron file
crontab mycron
rm mycron
你也可以用这个衬垫来完成这一切:
cat <(crontab -l) <(echo "*/5 * * * $path/$cronfile") | crontab -
你的脚本
这是对我有用的脚本的修改版本。
#!/bin/sh
cronfile=memory_protect.sh #NOTE THIS SHOULD DETECT IT'S SELF
path=$(pwd) #this is the path to the file
percent_allowed=80 #this should be max memory before action
has_cron(){
#is the file in the cron?
#return 0 #returning this just to test should
#be the next line but it's not working
if crontab -l | egrep -v '^$|^#' | grep -q $cronfile; then
return 1
else
return 0
fi
}
test_memory(){
memusage=$(top -n 1 -b | grep "Mem")
MAXMEM=$(echo $memusage | cut -d" " -f2 | awk '{print substr($0,1,length($0)-1)}')
USEDMEM=$(echo $memusage | cut -d" " -f4 | awk '{print substr($0,1,length($0)-1)}')
USEDMEM1=$(expr $USEDMEM \* 100)
PERCENTAGE=$(expr $USEDMEM1 / $MAXMEM)
#if it's above 80% alert
[[ $PERCENTAG>$percent_allowed ]] && return 1 || return 0
}
if has_cron;
then
#was not here so add
#run this script every 5 mins
#crontab -e */5 * * * $path/$cronfile
#cat <(crontab -l) <(echo "*/5 * * * $path/$cronfile") | crontab -
crontab -l > mycron
# Echo new cron into cron file
echo "*/5 * * * * $path/$cronfile" >> mycron
# Install new cron file
crontab mycron
rm mycron
else
echo "cron present"
fi
if test_memory;
then
#clear some memory
echo "/etc/init.d/nginx restart"
echo "/etc/init.d/php-fpm restart"
fi
例子
$ ./memory_protect.sh
/etc/init.d/nginx restart
/etc/init.d/php-fpm restart
$ crontab -l
*/5 * * * * /home/saml/tst/91789/memory_protect.sh
该脚本需要修改这两行,以便它实际上重新启动nginx
和php-fpm
服务。
更改这些行: echo "/etc/init.d/nginx restart" echo "/etc/init.d/php-fpm restart"
对于这些:
/etc/init.d/nginx restart
/etc/init.d/php-fpm restart
我这样做只是为了看到脚本运行正确。注意:sudo
如果此脚本以 root 以外的任何人身份运行,则这些重新启动行应以前缀!
sudo /etc/init.d/nginx restart sudo /etc/init.d/php-fpm restart
此用途可能需要NOPASSWD
至少拥有这两个脚本的权限,否则它将等待拥有 cron 的用户提供密码。
crontab 条目不存在?
当您的 crontab 尚未在目录 中创建时,您将遇到此问题/var/sppol/cron
。当你crontab -l
像这样运行时你会遇到它:
$ crontab -l
no crontab for saml
再检查一遍:
$ sudo ls -l /var/spool/cron/
total 0
-rw------- 1 root root 0 Sep 16 23:47 root
因此,只需简单地假设您要编辑它,然后保存空文件即可创建它:
$ crontab -e
# now you're in the vim editor, add a empty line
# type "i", hit return, hit Escape,
# and do a Shift + Z + Z to save!
现在你应该看到这个:
$ crontab -l
$
和这个:
$ sudo ls -l /var/spool/cron/
total 0
-rw------- 1 root root 0 Sep 16 23:47 root
-rw------- 1 saml root 0 Sep 21 16:20 saml
重新启动服务
您将遇到的另一个问题是,如果此 crontab 条目以用户 user1 身份运行,则 user1 将需要sudo
重新启动它们的权限。
答案2
我会用监控为了这
这是 monit 脚本示例,满足您的要求
check process nginx with pidfile /var/run/nginx.pid
start program = "/etc/init.d/nginx start"
stop program = "/etc/init.d/nginx stop"
if memory usage > 95% then restart
group www-data
if 5 restarts within 5 cycles then timeout
尝试重启5次;如果 monit 无法重新启动网络服务器 5 次;只是超时以避免竞争状况。