#!/bin/bash # vim: set fileencoding=utf-8 ts=4 sw=4 noexpandtab PORTICRON_VERSION="0.7.2" version() { echo "porticron ${PORTICRON_VERSION}" echo "Copyright (c) 2008-2009 Benedikt Böhm " exit 0 } usage() { echo "Usage: porticron [-hvn] [-c ]" echo echo " -h print this help text" echo " -v enable verbose output" echo " -V print version number" echo " -n do not send upgrade mails" echo " -c use configuration in " echo exit 0 } log() { [[ ${VERBOSE} -eq 1 ]] && echo "$@" >&2 } send_mail() { if [[ ${NOMAIL} -eq 1 ]]; then if [[ ${VERBOSE} -eq 1 ]]; then cat else cat > /dev/null fi else ${SENDMAIL:-/usr/sbin/sendmail} -t fi } mkhash() { echo "${1}" | md5sum | cut -f1 -d' ' } save_msg() { HASH_FILE="${TMP}${1}" log "creating hash file ${HASH_FILE}" mkhash "${2}" > "${HASH_FILE}" } # Test if msg with id $1 and body $2 is equal to previous saved msg # Returns: 1 - if msg is equal, 0 - if msg is different, unknown, etc check_msg() { if [[ ${CHECK_DUP_MSG} -eq 0 ]]; then return 0 fi if [[ ${NOMAIL} -eq 1 ]]; then return 0 fi HASH_FILE="${TMP}${1}" if [ ! -f "${HASH_FILE}" ]; then log "no previous hash file ${HASH_FILE} exists" save_msg "$1" "$2" return 0 fi OLD_HASH=$(cat "${HASH_FILE}") NEW_HASH=$(mkhash "${2}") if [[ "${OLD_HASH}" == "${NEW_HASH}" ]]; then log "hash matched for hash file ${HASH_FILE}" return 1 else save_msg "$1" "$2" log "hash unmatched for hash file ${HASH_FILE}" return 0 fi } # parse command line while getopts "hvVnc:" opt; do case $opt in h) usage;; v) VERBOSE=1;; V) version;; n) NOMAIL=1;; c) PORTICRON_CONF=${OPTARG};; ?) exit 1;; esac done # defaults, more below : ${VERBOSE:=0} : ${NOMAIL:=0} : ${PORTICRON_CONF:=/etc/porticron.conf} : ${TMP:="/var/tmp/porticron."} : ${CHECK_DUP_MSG:=1} : ${SUBJECT:=Gentoo package updates on {FQDN\} [ {IP\} ]} : ${SUBJECT_WARN:=WARNING: Gentoo security updates on {FQDN\} [ {IP\} ]} : ${EMERGE:=/usr/bin/emerge} log "using PORTICRON_CONF=${PORTICRON_CONF}, NOMAIL=${NOMAIL}, VERBOSE=${VERBOSE}" # load config if [[ ! -r ${PORTICRON_CONF} ]]; then echo "could not open configuration file ${PORTICRON_CONF}" exit 1 else source ${PORTICRON_CONF} fi # detect some common variables SCRIPT_NAME=$(basename $0) : ${FQDN:=$(hostname --fqdn)} : ${HOST:=$(hostname -s)} IP=$(getent hosts ${FQDN} | cut -d ' ' -f 1) : ${DATE:=$(date -R)} : ${PORTDIR:=$(portageq get_repo_path $(portageq envvar EROOT) gentoo)} # defaults, second half : ${RCPT:=root} : ${FROM:=root@${FQDN}} : ${SYNC_CMD:=${EMERGE} --sync} : ${SYNC_OVERLAYS_CMD:=/bin/true} : ${GLSA_CHECK:=/usr/bin/glsa-check} # replace variables for var in FQDN HOST IP DATE; do SUBJECT=${SUBJECT/\{$var\}/${!var}} SUBJECT_WARN=${SUBJECT_WARN/\{$var\}/${!var}} done # sync if desired log "running SYNC_CMD: ${SYNC_CMD}" ${SYNC_CMD} &>/dev/null log "running SYNC_OVERLAY_CMD: ${SYNC_OVERLAYS_CMD}" ${SYNC_OVERLAYS_CMD} &>/dev/null # run emerge once to perform global updates while not cluttering mail output ${EMERGE} --info &>/dev/null # GLSA check log "running GLSA_AFFECTED: ${GLSA_CHECK} --test --nocolor --verbose affected" GLSA_AFFECTED=$(${GLSA_CHECK} --test --nocolor --verbose affected 2>/dev/null) log "running GLSA_UPGRADES: ${GLSA_CHECK} --nocolor --pretend affected" GLSA_UPGRADES=$(${GLSA_CHECK} --nocolor --pretend affected | grep '^ ') if [[ -n ${GLSA_AFFECTED} ]]; then if check_msg GLSA_AFFECTED "${GLSA_AFFECTED}"; then GLSA_MSG=" ${SCRIPT_NAME} has detected that this system is affected by the following GLSAs: $(echo "${GLSA_AFFECTED}" | sed 's/^20/ 20/') ======================================================================== The following updates should be performed for these GLSAs: ${GLSA_UPGRADES} " cat </dev/null) fi if [[ -n ${DIFF} ]]; then DIFF_MSG="${SCRIPT_NAME} has detected the following changes to ${PORTDIR}: ${DIFF} ======================================================================== " fi # build list of upgrades : ${UPGRADE_OPTS:=--deep --update} log "running UPGRADE_CMD: ${EMERGE} ${UPGRADE_OPTS} --quiet --pretend world" UPGRADE=$(${EMERGE} ${UPGRADE_OPTS} --quiet --pretend world 2>/dev/null) if [[ -n ${UPGRADE} ]]; then UPGRADE_MSG=" ${SCRIPT_NAME} has detected that some packages need upgrading: $(echo "${UPGRADE}" | sed 's/^\[/ [/') ======================================================================== You can perform the upgrade by issuing the command: emerge ${UPGRADE_OPTS} world as root on ${FQDN} It is recommended that you pretend the upgrade first to confirm that the actions that would be taken are reasonable. The upgrade may be pretended by issuing the command: emerge ${UPGRADE_OPTS} --pretend world " fi # send mail if [[ -z ${UPGRADE_MSG} && -z ${DIFF_MSG} ]]; then log "no upgrades found, exiting." exit 0 fi # We need to execute both check_msg actually to save hash files check_msg UPGRADE_MSG "${UPGRADE_MSG}" UPGRADE_MSG_CODE=$? # TODO: Output of DIFF_MSG can contain dates and status of currently installed packages. # This will trigger e-mail sending even if e.g. eix cache is not changed. check_msg DIFF_MSG "${DIFF_MSG}" DIFF_MSG_CODE=$? if [[ ${UPGRADE_MSG_CODE} -eq 1 && ${DIFF_MSG_CODE} -eq 1 ]]; then log "no new upgrades found, exiting." exit 0 fi cat <