Introducing sysutils/swapmon.

This port attempts to monitor swap usage and dynamically add a swapfile as
neccessary.

PR:		ports/148711
Submitted by:	Alexander Kuehn <freebsd@nagilum.org>
Approved by:	wxs (mentor)
This commit is contained in:
Joseph S. Atkinson 2010-08-23 02:40:15 +00:00
parent bfdbff9375
commit 93ee365402
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/head/; revision=259788
6 changed files with 358 additions and 0 deletions

View file

@ -809,6 +809,7 @@
SUBDIR += su2
SUBDIR += superiotool
SUBDIR += swapd
SUBDIR += swapmon
SUBDIR += symlinks
SUBDIR += symon
SUBDIR += synergy

40
sysutils/swapmon/Makefile Normal file
View file

@ -0,0 +1,40 @@
# ports collection makefile for: swapmon
# Date Created: 27 July 2010
# Whom: Alexander Kuehn <freebsd@nagilum.org>
#
# $FreeBSD$
#
PORTNAME= swapmon
PORTVERSION= 1.4
CATEGORIES= sysutils
MASTER_SITES= # none
DISTFILES= # none
MAINTAINER= freebsd@nagilum.org
COMMENT= Add/remove swapspace as needed
LICENSE= BSD
NO_BUILD= yes
MAN1= ${PORTNAME}.1
USE_RC_SUBR= ${PORTNAME}
PLIST_FILES= sbin/${PORTNAME}
do-install:
@${SED} -e 's|%%PREFIX%%|${PREFIX}|g' ${FILESDIR}/${PORTNAME}.sh.in \
> ${WRKDIR}/${PORTNAME}.sh
${INSTALL_SCRIPT} ${WRKDIR}/${PORTNAME}.sh ${PREFIX}/sbin/${PORTNAME}
${INSTALL_MAN} ${FILESDIR}/${PORTNAME}.1 ${PREFIX}/man/man1
post-install:
@${ECHO_MSG} ""
@${ECHO_MSG} "To have swapmon run automatically after each boot"
@${ECHO_MSG} "execute the following command as root:"
@${ECHO_MSG} ""
@${ECHO_MSG} " echo '${PORTNAME}_enable=\"YES\"' >>/etc/rc.conf"
@${ECHO_MSG} ""
.include <bsd.port.mk>

View file

@ -0,0 +1,88 @@
.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples.
.\"See Also:
.\"man mdoc.samples for a complete listing of options
.\"man mdoc for the short list of editing options
.\"/usr/share/misc/mdoc.template
.Dd Wed Jul 20 2010 \" DATE
.Dt swapmon 1 \" Program name and manual section number
.Os FreeBSD
.Sh NAME \" Section Header - required - don't modify
.Nm swapmon
.\" The following lines are read in generating the apropos(man -k) database. Use only key
.\" words here as the database is built based on the words here and in the .ND line.
.Nd monitor swapusage, add swapspace as needed
.Sh SYNOPSIS \" Section Header - required - don't modify
.Nm
.Op Ar start|stop|-F
add/remove swapspace automatically as needed
.Sh DESCRIPTION \" Section Header - required - don't modify
.Nm
will check the current swapusage and if more than SWAP_HIGH percent of swapspace is in use it will create a new swapfile with a size of size of SWAP_STEP percent of the current swapspace and activate it.
If less than SWAP_LOW percent of swapspace is in use it will deactivate a previously added swapspace file and remove it.
.Pp \" Inserts a space
If called with
.Ar start
it will fork into the background and run as a daemon. It will check and then sleep for DELAY seconds before checking again. Messages about the operation will be piped to LOGGER. The pid of the daemon will be written to PIDFILE.
.Pp \" Inserts a space
If called with
.Ar stop
it stop a previously forked swapmon daemon.
.Pp \" Inserts a space
If called with
.Ar -F
it will run as a daemon but not detach from the terminal. Messages will still be piped to LOGGGER and not to the terminal by default. You may specify "/bin/cat" as LOGGER to get the messages on the terminal.
.Pp \" Inserts a space
Default values:
.Bl -tag -width -indent \" Begins a tagged list
.It SWAP_HIGH \" Each item preceded by .It macro
75
.It SWAP_LOW \" Each item preceded by .It macro
45
.It SWAP_STEP \" Each item preceded by .It macro
100-SWAP_HIGH (=25)
.It SM_HOME
"/usr/.swap/"
.It DELAY \" Each item preceded by .It macro
30
.It LOGGER \" Each item preceded by .It macro
/usr/bin/logger
.It PIDFILE \" Each item preceded by .It macro
/var/run/swapmon.pid
.El \" Ends the list
.Pp
swapmon can be called via cron(5). In that case you would receive messages about the swapspace being adjusted via e-mail. To use it that way add a crontab entry to the root crontab similar to this:
.Bl -tag -width -indent \" Differs from above in tag removed
.It * * * * * /usr/local/sbin/swapmon
.El \" Ends the list
.Pp
.\" .Sh ENVIRONMENT \" May not be needed
.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1
.\" .It Ev ENV_VAR_1
.\" Description of ENV_VAR_1
.\" .It Ev ENV_VAR_2
.\" Description of ENV_VAR_2
.\" .El
.Sh FILES \" File used or created by the topic of the man page
.Bl -tag -width "/usr/local/etc/swapmonrc" -compact
.It Pa /usr/local/etc/swapmonrc
optional configuration file for overwriting the defaults above
.It Pa $SM_HOME
The "homedirectory" of swapmon. In here the swapfiles as well as a lockfile and the swapfile list will be created.
.\" .Sh DIAGNOSTICS \" May not be needed
.\" .Bl -diag
.\" .It Diagnostic Tag
.\" Diagnostic informtion here.
.\" .It Diagnostic Tag
.\" Diagnostic informtion here.
.\" .El
.Sh SEE ALSO
.\" List links in ascending order by section, alphabetically within a section.
.\" Please do not reference files that do not exist without filing a bug report
.Xr swapctl 8 ,
.Xr mdconfig 8 ,
.Xr truncate 8 ,
.Xr logger 1 ,
.Xr crontab 5
.\" .Sh BUGS \" Document known, unremedied bugs
.\" .Sh HISTORY \" Document history if command behaves in a unique manner

View file

@ -0,0 +1,33 @@
#!/bin/sh
#
# swapmon - add / remove swap as needed
#
# PROVIDE: swapmon
# REQUIRE: LOGIN
# KEYWORD: shutdown
#
# Add the following lines to /etc/rc.conf to enable swapmon:
#
#swapmon_enable="YES"
#
. /etc/rc.subr
name=swapmon
rcvar=`set_rcvar`
command="%%PREFIX%%/sbin/${name}"
command_interpreter="/bin/sh"
CONFIG=%%PREFIX%%/etc/${name}rc
if [ -r "${CONFIG}" ]
then . "${CONFIG}"
fi
pidfile=${PIDFILE:-"/var/run/${name}.pid"}
swapmon_enable=${swapmon_enable:-"NO"}
load_rc_config ${name}
start_precmd='command_args="-F <&- 2>&1 >/dev/null &"'
stop_postcmd='rm $pidfile'
run_rc_command "$1"

View file

@ -0,0 +1,187 @@
#!/bin/sh
#
# swapmon - add / remove swap as needed
#
# Copyright (C) 2010 Alexander Kuehn. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
CONFIG=%%PREFIX%%/etc/swapmonrc
VERSION="1.4"
if [ -r "${CONFIG}" ]
then . "${CONFIG}"
fi
# where to create swapfiles
: ${SM_HOME=/usr/.swap}
# if the swap usage is higher than that (percentage) new swap will be added
: ${SWAP_HIGH=75}
# if the swap usage is lower than that then a previously added swapfile will be removed
: ${SWAP_LOW=45}
# if swap is running low we will increase the swapspace by this many percent
: ${SWAP_STEP=$(( 100 - ${SWAP_HIGH} ))}
# if running as daemon how long to wait between checks
: ${DELAY=30}
# if running as daemon where to log messages
: ${LOGGER=/usr/bin/logger}
# if running as daemon where to put pidfile
: ${PIDFILE=/var/run/swapmon.pid}
LOCKF=$SM_HOME/lock
SWAPFILE=$SM_HOME/swap.XXXX
SWAPLIST=$SM_HOME/swapfiles
MKTEMP=/usr/bin/mktemp
TRUNCATE=/usr/bin/truncate
TOUCH=/usr/bin/touch
CHMOD=/bin/chmod
MDCONFIG=/sbin/mdconfig
SWAPON=/sbin/swapon
SWAPOFF=/sbin/swapoff
SWAPCTL=/sbin/swapctl
RM=/bin/rm
SED=/usr/bin/sed
umask 0077
if [ $(/usr/bin/id -u) -gt 0 ]
then echo "I'm not running as root (uid=0) this probably wont work."
# exit 1
fi
if [ \! -d ${SM_HOME} ]
then /bin/mkdir -p ${SM_HOME} || { echo "Error creating ${SM_HOME}!" ; exit 1; }
fi
$TOUCH ${SWAPLIST} || { echo "Can't write to ${SWAPLIST} aborting." ; exit 1; }
# add a 1MB swapfile to check if we have the permissions to do so
NSWAP=$($MKTEMP ${SWAPFILE})
$TRUNCATE -s 1M "${NSWAP}" || { echo "Error creating swapfile ${NSWAP}, aborting." ; exit 1; }
$CHMOD 600 "${NSWAP}"
MDEV=$($MDCONFIG -a -t vnode -f "${NSWAP}")
if [ -n "$MDEV" ]
then
$SWAPON /dev/${MDEV} || { echo "error activating swapdevice /dev/${MDEV}."; exit 1; }
$SWAPOFF "/dev/${MDEV}"
$MDCONFIG -d -u ${MDEV} >/dev/null
$RM -f "${NSWAP}"
else
echo "error configuring memory disk ($MDCONFIG -a -t vnode -f \"${NSWAP}\")"
$RM -f "${NSWAP}"
exit
fi
if [ ${SWAP_LOW} -ge $(( $(($SWAP_HIGH * 100)) / $((100 + $SWAP_STEP)) )) ]
then echo "SWAP_LOW(${SWAP_LOW}) schould be lower than $(( $(($SWAP_HIGH * 100)) / $((100 + $SWAP_STEP)) )) to be useful."
echo "Swapmon $VERSION."
exit 1
fi
check_swap()
{
SWAPCTLSK=$($SWAPCTL -sk)
SWAPTOTAL=${SWAPCTLSK#* }
SWAPTOTAL=${SWAPTOTAL% *}
SWAPUSAGE=$(( ${SWAPCTLSK##* } * 100 / $SWAPTOTAL ))
if [ ${SWAPUSAGE} -gt ${SWAP_HIGH} ]
then NSWAP=$($MKTEMP ${SWAPFILE})
BLOCKS=$(( $(( ${SWAPTOTAL} * ${SWAP_STEP} +1023)) / 102400 ))
# make sure we can write to the swaplist
$TOUCH "${SWAPLIST}" || { echo "swapmon$VERSION[$$] Error modifying ${SWAPLIST} exiting."|$LOGGER; exit 1; }
$TRUNCATE -s ${BLOCKS}M "${NSWAP}"
$CHMOD 0600 "${NSWAP}"
if [ -s "${NSWAP}" ]
then MDEV=$($MDCONFIG -a -t vnode -f "${NSWAP}")
printf "${MDEV} ${NSWAP}\n" >>"${SWAPLIST}"
echo "swapmon$VERSION[$$] Swapusage ${SWAPUSAGE}%($((${SWAPCTLSK##* }/1024))/$(($SWAPTOTAL/1024)) M), activated new swapdevice ${MDEV} backed by ${NSWAP}."|$LOGGER
$SWAPON /dev/${MDEV}
$SWAPCTL -lh|$SED -e "s/^/swapmon$VERSION[$$] /g"|$LOGGER
else echo "swapmon$VERSION[$$] Creating swapfile ${NSWAP} failed! :("|$LOGGER
fi
fi
while [ \( ${SWAPUSAGE} -lt ${SWAP_LOW} \) -a -s "${SWAPLIST}" ]
do MDEV=$(/usr/bin/tail -1 "${SWAPLIST}")
SWAPF=${MDEV#* }
MDEV=${MDEV%% *}
if [ -s "${SWAPF}" ]
then if [ "${SWAPF}" = "$($MDCONFIG -l -u ${MDEV}|/usr/bin/awk '{print $4}')" ]
then if [ -n "$($SWAPCTL -l|$SED -n '1!p'|/usr/bin/grep '/dev/'${MDEV})" ]
then echo "swapmon$VERSION[$$] Swapusage ${SWAPUSAGE}%($((${SWAPCTLSK##* }/1024))/$(($SWAPTOTAL/1024)) M), deactivating swapdevice ${MDEV}."|$LOGGER
$SWAPCTL -lh|$SED -e "s/^/swapmon$VERSION[$$] /g"|$LOGGER
$SWAPOFF "/dev/${MDEV}"
fi
echo "swapmon$VERSION[$$] Detaching vnode ${MDEV}."|$LOGGER
$MDCONFIG -d -u ${MDEV} >/dev/null
$RM -f "${SWAPF}"
else echo "swapmon$VERSION[$$] Swapfile ${SWAPF} is not attached to ${MDEV} as it should be!?"|$LOGGER
for MDEV in $($MDCONFIG -l)
do echo "swapmon$VERSION[$$] $($MDCONFIG -l -u ${MDEV})"|$LOGGER
done
fi
else echo "swapmon$VERSION[$$] ${SWAPF} is not a valid swapfile."|$LOGGER
fi
$SED -I '' -n '$!p' "${SWAPLIST}"
SWAPCTLSK=$($SWAPCTL -sk)
SWAPTOTAL=${SWAPCTLSK#* }
SWAPTOTAL=${SWAPTOTAL% *}
SWAPUSAGE=$(( ${SWAPCTLSK##* } * 100 / $SWAPTOTAL ))
done
}
case "$1" in
start)
$0 -F <&- 2>&1 >/dev/null &
;;
stop)
if [ -s "${PIDFILE}" ]
then
PID=$(/bin/cat ${PIDFILE})
if ( /bin/ps -p $PID|grep -q $0 )
then /bin/kill $PID
fi
$RM "${PIDFILE}"
fi
;;
-F)
echo $$ >"${PIDFILE}"
echo "swapmon$VERSION[$$] Writing pid $$ to pidfile ${PIDFILE}."|$LOGGER
cd / || exit 1
while [ -f "${PIDFILE}" ]
do check_swap
sleep ${DELAY}
done
;;
'')
if [ -r "${LOCKF}" ]
then
echo "${LOCKF} exists"
exit 1;
else
echo $$ >"${LOCKF}"
LOGGER="|/bin/cat"
check_swap
fi
$RM -f "${LOCKF}"
;;
*)
echo "$* not supported"
;;
esac

View file

@ -0,0 +1,9 @@
swapmon will check the current swapusage and if more than SWAP_HIGH per-
cent of swapspace is in use it will create a new swapfile with a size of
size of SWAP_STEP percent of the current swapspace and activate it. If
less than SWAP_LOW percent of swapspace is in use it will deactivate a
previously added swapspace file and remove it.
WWW: http://www.nagilum.net/swapmon/
freebsd@nagilum.org