Difference between revisions of "SwapClean"
From James Dooley's Wiki
(→Script) |
|||
| (9 intermediate revisions by 2 users not shown) | |||
| Line 1: | Line 1: | ||
| + | [[Category:Scripts]] | ||
==Overview== | ==Overview== | ||
Script that is run via cron every ~10 minutes. Main purpose is to clear any swap usage if the system has the enough free ram and load is below a set value. | Script that is run via cron every ~10 minutes. Main purpose is to clear any swap usage if the system has the enough free ram and load is below a set value. | ||
==Script== | ==Script== | ||
| − | |||
| + | <source lang='bash'> | ||
#!/bin/bash | #!/bin/bash | ||
#Swap Cleaner | #Swap Cleaner | ||
#Watches swap usage | #Watches swap usage | ||
#If there is swapping going on and there is enough free (+cache) ram, then turn swap off and back on. | #If there is swapping going on and there is enough free (+cache) ram, then turn swap off and back on. | ||
| − | + | #Created by James Dooley | |
| + | #Feature / Bug requests jdooley@lw | ||
| + | |||
#User Assigned Variables | #User Assigned Variables | ||
| − | + | ||
| − | swapthresh=0 #Swap threshold for clearing swap. Will not clear until this value is hit | + | swapthresh=0 #Swap threshold for clearing swap. Will not clear until this value is hit. Good for servers that normally allocates small amounts of swap for some reason. |
| − | freethresh=0 #Real free (free+cached) - current swap threshold. Ensures that atleast x bytes are free before clearing | + | freethresh=0 #Real free (free+cached) - current swap threshold. Ensures that atleast x bytes are free before clearing. |
loadthresh=0 #Load threshold, will not clear if above this value (unless 0) | loadthresh=0 #Load threshold, will not clear if above this value (unless 0) | ||
logrotate=1000 #Max number of lines in the log file | logrotate=1000 #Max number of lines in the log file | ||
#### | #### | ||
| − | + | ||
function plog { | function plog { | ||
echo "[ `date` ][ $curswap; $curfree; $realload ] $1" >> /var/log/swapclean | echo "[ `date` ][ $curswap; $curfree; $realload ] $1" >> /var/log/swapclean | ||
| Line 24: | Line 27: | ||
sed -i -e "1d" /var/log/swapclean | sed -i -e "1d" /var/log/swapclean | ||
fi | fi | ||
| + | return | ||
} | } | ||
| + | function clearswap { | ||
| + | plog "Clearing swap" | ||
| + | touch /var/run/.swapoff | ||
| + | echo $$ > /var/run/.swapoff | ||
| + | /sbin/swapoff -a && /sbin/swapon -a | ||
| + | rm -f /var/run/.swapoff | ||
| + | plog "Swap Cleared" | ||
| + | return | ||
| + | } | ||
| + | |||
function checkswap { | function checkswap { | ||
| − | + | ||
curswap=`free | fgrep "Swap:" | awk '{print $3}'` | curswap=`free | fgrep "Swap:" | awk '{print $3}'` | ||
curfree=`free | fgrep "buffers/cache:" | awk '{print $4}'` | curfree=`free | fgrep "buffers/cache:" | awk '{print $4}'` | ||
| − | realload=` | + | realload=`cat /proc/loadavg | awk '{print $1}'` |
curload=`echo "$realload * 100" | bc | sed 's/[.].*//'` | curload=`echo "$realload * 100" | bc | sed 's/[.].*//'` | ||
loadthresh=`echo "$loadthresh *100" | bc | sed 's/[.].*//'` | loadthresh=`echo "$loadthresh *100" | bc | sed 's/[.].*//'` | ||
swapdif=`expr $curfree - $curswap` | swapdif=`expr $curfree - $curswap` | ||
| − | + | ||
if [ "$swapthresh" -lt "$curswap" ] | if [ "$swapthresh" -lt "$curswap" ] | ||
then | then | ||
| Line 44: | Line 58: | ||
then | then | ||
#Load is below threshold | #Load is below threshold | ||
| − | if [ ! -e ".swapoff" ] | + | if [ ! -e "/var/run/.swapoff" ] |
then | then | ||
| − | + | clearswap | |
| − | + | else | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | else | ||
plog "Lock file found, swap may be already clearing" | plog "Lock file found, swap may be already clearing" | ||
| + | opid=`cat /var/run/.swapoff` | ||
| + | if [ ! "`ps ax | grep $opid | grep ${0##*/}`" ] | ||
| + | then | ||
| + | plog "PID not active or not owned by swapclean, clearing pid file" | ||
| + | rm -f /var/run/.swapoff | ||
| + | clearswap | ||
| + | else | ||
| + | plog "Swap already being cleared, PID active" | ||
| + | fi | ||
fi | fi | ||
else | else | ||
| Line 62: | Line 80: | ||
fi | fi | ||
fi | fi | ||
| − | + | return | |
} | } | ||
function enablecron { | function enablecron { | ||
| − | + | if [ -e "/etc/cron.d/swapclean.sh" ] | |
| − | |||
| − | |||
| − | |||
| − | |||
then | then | ||
| − | crontime="*/10 * * * *" | + | echo "Cron already enabled, use change to set new time" |
| + | else | ||
| + | echo "What time would you like to set the cron to" | ||
| + | echo "[IE: */10 * * * * ]" | ||
| + | read crontime; | ||
| + | if [ ! $crontime ] | ||
| + | then | ||
| + | crontime="*/10 * * * *" | ||
| + | fi | ||
| + | echo "SHELL=/bin/bash" > /etc/cron.d/swapclean.sh | ||
| + | echo "$crontime root $(readlink -f $0)" >> /etc/cron.d/swapclean.sh | ||
| + | chmod 0644 /etc/cron.d/swapclean.sh | ||
| + | echo "Cron enabled [$crontime root $(readlink -f $0)]" | ||
| + | return | ||
fi | fi | ||
| − | + | return | |
| − | |||
| − | |||
| − | |||
} | } | ||
| − | + | ||
function disablecron { | function disablecron { | ||
| − | + | if [ -e "/etc/cron.d/swapclean.sh" ] | |
| − | rm -f /etc/cron.d/swapclean.sh | + | then |
| − | echo "Cron | + | rm -f /etc/cron.d/swapclean.sh |
| − | + | echo "Cron disabled" | |
| + | else | ||
| + | echo "Cron not enabled" | ||
| + | fi | ||
| + | return | ||
} | } | ||
| − | + | ||
| − | + | ||
case $1 in | case $1 in | ||
--cron) | --cron) | ||
| Line 96: | Line 124: | ||
off) | off) | ||
disablecron | disablecron | ||
| + | ;; | ||
| + | change) | ||
| + | disablecron | ||
| + | enablecron | ||
;; | ;; | ||
esac | esac | ||
| Line 101: | Line 133: | ||
--help) | --help) | ||
echo "Check swap usage:" | echo "Check swap usage:" | ||
| − | echo " --cron [on, off]" | + | echo " --cron [on, change, off]" |
echo " on: Turns on cron job and asks for time" | echo " on: Turns on cron job and asks for time" | ||
| + | echo " change: Changes the cron time" | ||
echo " off: Turns off the cron job" | echo " off: Turns off the cron job" | ||
;; | ;; | ||
| Line 109: | Line 142: | ||
;; | ;; | ||
esac | esac | ||
| − | </ | + | </source> |
==What to change== | ==What to change== | ||
| Line 120: | Line 153: | ||
===loadthresh=== | ===loadthresh=== | ||
This is the load level threshold at which the script will allow swap to be cleaned. | This is the load level threshold at which the script will allow swap to be cleaned. | ||
| + | |||
| + | You will probably want to set this value to a sane number, otherwise an already stressed system may lock up. | ||
===logrotate=== | ===logrotate=== | ||
This is the number of lines that will be stored in the log file. When reached the top line will be deleted. | This is the number of lines that will be stored in the log file. When reached the top line will be deleted. | ||
Latest revision as of 14:33, 25 March 2014
Contents
Overview
Script that is run via cron every ~10 minutes. Main purpose is to clear any swap usage if the system has the enough free ram and load is below a set value.
Script
#!/bin/bash
#Swap Cleaner
#Watches swap usage
#If there is swapping going on and there is enough free (+cache) ram, then turn swap off and back on.
#Created by James Dooley
#Feature / Bug requests jdooley@lw
#User Assigned Variables
swapthresh=0 #Swap threshold for clearing swap. Will not clear until this value is hit. Good for servers that normally allocates small amounts of swap for some reason.
freethresh=0 #Real free (free+cached) - current swap threshold. Ensures that atleast x bytes are free before clearing.
loadthresh=0 #Load threshold, will not clear if above this value (unless 0)
logrotate=1000 #Max number of lines in the log file
####
function plog {
echo "[ `date` ][ $curswap; $curfree; $realload ] $1" >> /var/log/swapclean
if [ "`wc -l /var/log/swapclean | awk '{print $1}'`" -gt "$logrotate" ]
then
sed -i -e "1d" /var/log/swapclean
fi
return
}
function clearswap {
plog "Clearing swap"
touch /var/run/.swapoff
echo $$ > /var/run/.swapoff
/sbin/swapoff -a && /sbin/swapon -a
rm -f /var/run/.swapoff
plog "Swap Cleared"
return
}
function checkswap {
curswap=`free | fgrep "Swap:" | awk '{print $3}'`
curfree=`free | fgrep "buffers/cache:" | awk '{print $4}'`
realload=`cat /proc/loadavg | awk '{print $1}'`
curload=`echo "$realload * 100" | bc | sed 's/[.].*//'`
loadthresh=`echo "$loadthresh *100" | bc | sed 's/[.].*//'`
swapdif=`expr $curfree - $curswap`
if [ "$swapthresh" -lt "$curswap" ]
then
#Server has swapped and is above its threshold
if [ "$freethresh" -lt "$swapdif" ]
then
#Free - Swap is greater then freethresh
if [ "$curload" -lt "$loadthresh" -o "$loadthresh" -eq 0 ]
then
#Load is below threshold
if [ ! -e "/var/run/.swapoff" ]
then
clearswap
else
plog "Lock file found, swap may be already clearing"
opid=`cat /var/run/.swapoff`
if [ ! "`ps ax | grep $opid | grep ${0##*/}`" ]
then
plog "PID not active or not owned by swapclean, clearing pid file"
rm -f /var/run/.swapoff
clearswap
else
plog "Swap already being cleared, PID active"
fi
fi
else
plog "High load, waiting to clear swap"
fi
else
plog "Not enough free memory, waiting to clear swap"
fi
fi
return
}
function enablecron {
if [ -e "/etc/cron.d/swapclean.sh" ]
then
echo "Cron already enabled, use change to set new time"
else
echo "What time would you like to set the cron to"
echo "[IE: */10 * * * * ]"
read crontime;
if [ ! $crontime ]
then
crontime="*/10 * * * *"
fi
echo "SHELL=/bin/bash" > /etc/cron.d/swapclean.sh
echo "$crontime root $(readlink -f $0)" >> /etc/cron.d/swapclean.sh
chmod 0644 /etc/cron.d/swapclean.sh
echo "Cron enabled [$crontime root $(readlink -f $0)]"
return
fi
return
}
function disablecron {
if [ -e "/etc/cron.d/swapclean.sh" ]
then
rm -f /etc/cron.d/swapclean.sh
echo "Cron disabled"
else
echo "Cron not enabled"
fi
return
}
case $1 in
--cron)
case $2 in
on)
enablecron
;;
off)
disablecron
;;
change)
disablecron
enablecron
;;
esac
;;
--help)
echo "Check swap usage:"
echo " --cron [on, change, off]"
echo " on: Turns on cron job and asks for time"
echo " change: Changes the cron time"
echo " off: Turns off the cron job"
;;
*)
checkswap
;;
esac
What to change
swapthresh
This value allows swap to get to a certain level before looking to swap.
freethresh
This is the level of extra free ram the script will require before attempting to clean swap
loadthresh
This is the load level threshold at which the script will allow swap to be cleaned.
You will probably want to set this value to a sane number, otherwise an already stressed system may lock up.
logrotate
This is the number of lines that will be stored in the log file. When reached the top line will be deleted.