Skip to content

Instantly share code, notes, and snippets.

@iki
Last active August 29, 2015 13:58
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save iki/9932972 to your computer and use it in GitHub Desktop.
Cleanup VM for exporting to appliance
#!/bin/bash
#|Usage: <command> [OPTIONS]
#|
#|Clean development VM for exporting to appliance:
#|
#| - update system: apt-get update and upgrade
#| - install zerofree package
#| - remove user ssh keys
#| - stop foreman and django
#| - stop mongodb, compact database, purge journal
#| - purge /var/cache: <var-cache>
#| - purge /tmp
#| - disable, zero, recreate and reenable swap
#| - output steps to minify the vmdk disk image
#|
#|Options:
#|
#| -h, --help Show this help message and exit.
#| -n, --dry-run Preview, do not run anything.
#| -u, --no-update Do not update system.
#|
SSHKey="$HOME/.ssh/id_rsa"
VarCache=
# VarCache="apt apt-xapian-index cups man oracle-jdk-7-installer"
MongoDB=/var/lib/mongodb
main () {
local Name Base Force DryRun NoUpdate Output Swap Root
Name="${0##*/}"
# Base="`cd "${0%/*}"; pwd -P`"
if [ "$1" = -h -o "$1" = --help ]; then
usage "$0" command="$Name" var-cache="${VarCache:-*}"
return 2
fi
[ "$1" = -f -o "$1" = --force ] && Force=$1 && shift 1 || Force=
[ "$1" = -n -o "$1" = --dry-run ] && DryRun=$1 && shift 1 || DryRun=
[ "$1" = -u -o "$1" = --no-update ] && NoUpdate=$1 && shift 1 || NoUpdate=
II "update system: apt-get update and upgrade"
if [ -z "$NoUpdate" ]; then
run sudo apt-get update || return $?
run sudo apt-get upgrade || return $?
else
skip "disabled with option $NoUpdate"
fi
II "install zerofree package"
if Output="`dpkg -l zerofree | grep -i 'ii *zerofree'`"; then
skip "zerofree already installed:" $Output
# dpkg output is outside quotes to shrink spaces
else
run sudo apt-get install -y zerofree || return $?
fi
II "remove user ssh keys"
if [ -f "$SSHKey" ]; then
run rm -f "$SSHKey" || return $?
[ ! -f "$SSHKey.pub" ] || run rm -f "$SSHKey.pub" || return $?
else
skip "not found: $SSHKey"
fi
II "stop foreman and django"
log pgrep -l foreman && { run pkill foreman || return $?; }
log pgrep -fl runserver && { run pkill -f runserver || return $?; }
II "stop mongodb, compact database, purge journal"
if Output="`status mongodb | grep -i stop`"; then
skip "mongodb already stopped: $Output"
else
run sudo stop mongodb || return $?
fi
if [ -d "$MongoDB" ]; then
log du -sh "$MongoDB"
run sudo mongod --repair --dbpath "$MongoDB" || return $?
run sudo chown -R mongodb:mongodb "$MongoDB"/* || return $?
log du -sh "$MongoDB"
log du -sh "$MongoDB"/journal
run sudo rm -rf "$MongoDB"/journal/* || return $?
log du -sh "$MongoDB"/journal
log du -sh "$MongoDB"
else
skip "mongodb database path not found: $MongoDB"
fi
II "purge /var/cache: ${VarCache:-*}"
if [ -z "$VarCache" ]; then
log sudo du -sh /var/cache
log sudo du -sh /var/cache/*
run sudo rm -rf /var/cache/* # || return $?
log sudo du -sh /var/cache
else
for dir in $VarCache; do
dir="/var/cache/$dir"
if [ -d "$dir" ]; then
log du -sh "$dir"
run sudo rm -rf "$dir" || return $?
else
skip "not found: $dir"
fi
done
fi
II "purge /tmp"
log sudo du -sh /tmp
run sudo rm -rf /tmp/* # || return $?
log sudo du -sh /tmp
II "disable, zero, recreate and reenable swap"
log swapon -s
Swap="`swapon -s | tail -1 | cut -f1 -d ' '`"
if [ "${Swap#/dev/}" != "$Swap" ]; then
log echo "detected swap on $Swap"
run sudo swapoff "$Swap" || return $?
run sudo dd "if=/dev/zero" "of=$Swap" # || return $?
run sudo mkswap "$Swap" || return $?
run sudo swapon "$Swap" || return $?
else
skip "no swap detected"
fi
II "steps to minify the vmdk disk image"
Root="`mount | grep ' on / type ' | cut -f1 -d ' '`"
log echo "detected root on ${Root:-<not-detected>}"
cat <<EOF
Steps to clean free space on root partition:
1. sudo telinit 1
# switch to single user mode with / mounted readonly
# - if it hangs, then restart, press Esc to get into boot menu
# and boot to recovery mode
2. zerofree -v ${Root:-<root-partition>}
# run verbose /usr/sbin/zerofree on root partiton
# zerofree can only zero free space on ext2/3/4 partitions
3. shutdown -h now
Steps to minify the vmdk image (expects the VM to be stopped):
1. cd "<home>/Virtualbox VMs/<vm-folder>"
2. VBoxManage modifyhd --compact <vm-disk-image.vmdk>
EOF
}
II () { echo >&2; echo "=== $@" >&2; }
skip () { echo "--- $@" >&2; return 3; }
error () { echo "!!! $@" >&2; return 1; }
run () { echo ">>> $@" >&2; [ -n "$DryRun" ] || "$@"; }
log () {
## Usage: log command [OPTIONS]
## Runs command, and redirect indented output to stderr.
local O R;
[ "$1" = echo ] && shift && echo "... $@" >&2 && return
echo "... $@" >&2; O="`mktemp`" || { "$@"; return $?; }
"$@" >"$O" 2>&1; R=$?; sed 's/^/ /' "$O" >&2; rm "$O"; return $R
}
usage () { local R S I; S="${1:-$0}"; shift; R=; for I in "$@"; do I="${I//\\/\\}"; I="${I//\//\/}"; R="${R}s/<${I%%=*}>/${I#*=}/;"; done; sed -n "$R;/^#|/s/#|//p;" "$S"; }
## Usage: usage script [var=value]
## Extracts documentation from script.
is_sourced () { [ -z "$0" -o "$0" = "${SHELL##*/}" -o "$0" = 'sh' ] && [ $# = 0 ]; }
## Checks if current script is sourced from another script via '.' (command is empty or shell).
is_sourced || ! trap 'exit 10' 1 2 3 13 15 || main "$@" || exit $?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment