#!/bin/sh # $FreeBSD: ports/Tools/portbuild/scripts/cleanup-chroots,v 1.11 2010/06/25 22:49:56 linimon Exp $ # To be run on the client, this script looks for chroot directories # that have not been used in 60 minutes, as well as directories listed # as 'in use' that have not been touched in 5 days (corresponding to # port builds that have timed out or shut down uncleanly) and prunes # them to reclaim space. pbd=${PORTBUILD_DATA:-/a/portbuild} # XXX TODO promote # all times are in minutes REMOVE_EMPTY_BUILD_TIME=10080 REMOVE_INUSE_CHROOT_TIME=7200 REMOVE_NOTINUSE_CHROOT_TIME=60 REMOVE_NOTINUSE_CLAIM_CHROOT_TIME=60 #VERBOSE=1 # cleanup all mounts (old NFS, devfs, linux), as well as mds cleanup_all() { chroot=$1 chrootnb=${chroot##*/} #chroot dir branch=${chroot%/*} #buildid dir branch=${branch%/*} #branch dir branch=${branch%/*} #branch name branch=${branch##*/} jname=${branch}-${chrootnb} # Stop the jail if running jls -qj ${jname} > /dev/null 2>&1 && jail -r ${jname} # umounting normal device for MNT in $( mount | awk -v mnt="${chroot}/" 'BEGIN{ gsub(/\//, "\\\/", mnt); } { if ($3 ~ mnt && $1 !~ /\/dev\/md/ ) { print $3 }}' | sort -r ); do umount -f ${MNT} done # umount md device if any for unit in $(mount | awk -v mnt="${chroot}" 'BEGIN{ gsub(/\//, "\\\/", mnt); } { if ($3 ~ mnt && $1 ~ /\/dev\/md/ ) { sub(/\/dev\/md/, "", $1); print $1 }}' | sort -r); do umount -f /dev/md${unit} mdconfig -d -u ${unit} done } # note: uname is not being overridden (should not need client.conf here) arch=$(uname -m) # note: if any are missing, the script exits here. . ${pbd}/${arch}/client.conf . ${pbd}/${arch}/portbuild.conf . ${pbd}/${arch}/portbuild.$(hostname) if [ "${use_zfs}" = "1" ]; then old_chroots=$(find ${scratchdir}/*/*/* -prune -mmin +${REMOVE_NOTINUSE_CHROOT_TIME} 2> /dev/null) else old_chroots=$(find ${scratchdir}/*/*/chroot/* -prune -mmin +${REMOVE_NOTINUSE_CHROOT_TIME} 2> /dev/null) fi if [ ! -z "${old_chroots}" ]; then echo "cleanup-chroots: non-empty chroots > 1 hr old found on $(hostname):" echo ${old_chroots} echo else if [ $VERBOSE ]; then echo "cleanup-chroots: no non-empty chroots > 1 hr old found on $(hostname)." echo fi fi if [ ! -z "${old_chroots}" ]; then # Flag non-empty chroots with no active builds for chroot in ${old_chroots}; do if [ ! -d ${chroot}/used ]; then stale_chroots="${chroot} ${stale_chroots}" # Also flag "in use" chroots that were set up more than N days ago elif [ ! -z "`find ${chroot}/used -prune -mmin +${REMOVE_INUSE_CHROOT_TIME}`" ]; then echo "cleanup-chroots: Found old files on $(hostname):" ls -l ${chroot}/tmp ${chroot}/used echo "${chroot} allegedly in use but > N days old" stale_chroots="${chroot} ${stale_chroots}" echo fi done fi if [ ! -z "${stale_chroots}" ]; then echo "cleanup-chroots: non-empty, > 1 hr old stale chroots found on $(hostname):" echo ${stale_chroots} echo else if [ $VERBOSE ]; then echo "cleanup-chroots: no non-empty, > 1 hr old stale chroots found on $(hostname)." echo fi fi # save off non-empty, stale chroots for possible examination if [ -z "${stale_chroots}" ]; then mkdir -p ${scratchdir}/old for chroot in ${stale_chroots}; do mv ${chroot} ${scratchdir}/old done rm -rf ${scratchdir}/old 2> /dev/null if [ -d ${scratchdir}/old ]; then chflags -R noschg ${scratchdir}/old rm -rf ${scratchdir}/old fi fi # cleanup old NFS and devfs mounts for stale chroots if [ ! -z "${stale_chroots}" ]; then for chroot in ${stale_chroots}; do cleanup_all ${chroot} done fi # now look for empty stale builds if [ "${use_zfs}" = "1" ]; then # XXX MCL zfs case not yet tested; is this the right command? builds=$(find ${scratchdir}/[0-9]*/* -prune -mmin +${REMOVE_EMPTY_BUILD_TIME} 2> /dev/null) else builds=$(find ${scratchdir}/[0-9]*/* -prune -mmin +${REMOVE_EMPTY_BUILD_TIME} 2> /dev/null) fi for build in ${builds}; do if [ -e ${build} ]; then stale_builds="${build} ${stale_builds}" fi done if [ ! -z "${stale_builds}" ]; then echo "cleanup-chroots: empty stale builds found on $(hostname):" echo ${stale_builds} echo else if [ $VERBOSE ]; then echo "cleanup-chroots: no empty stale builds found on $(hostname)." echo fi fi # cleanup old NFS and devfs mounts for vanished chroots in stale builds if [ ! -z "${stale_builds}" ]; then for build in ${stale_builds}; do # XXX MCL HACK! what I really want is "give me the next 2 subdirs after $build" mounts=$(mount | grep "${build}" | awk '{print $3}' | grep -E "/dev$") if [ $VERBOSE ]; then echo "cleanup-chroots: suspected stale mounts on $(hostname):" echo ${mounts} echo fi if [ ! -z "${mounts}" ]; then for mount in ${mounts}; do target=`echo ${mount} | sed -e "s@/dev@@"` cleanup_all ${target} done fi rm -rf ${build} done fi # cleanup claim-chroots that failed (usually due to ssh timeout after # copy to client) # XXX MCL assuming that mktemp using /tmp in claim-chroot stale_claim_chroots=$(find /tmp -name claim-chroot.* -prune -mmin +${REMOVE_NOTINUSE_CLAIM_CHROOT_TIME} 2> /dev/null) if [ ! -z "${stale_claim_chroots}" ]; then if [ $VERBOSE ]; then echo "cleanup-chroots: suspected stale claim_chroots on $(hostname):" echo ${stale_claim_chroots} echo fi for claim_chroot in ${stale_claim_chroots}; do rm -rf ${claim_chroot} done fi