#!/bin/bash usage() { >&2 echo 'usage: update-me [-s|-c] [-u[ ]$user]' >&2 echo ' -s: play it save' >&2 echo ' -c: clear for exit' >&2 echo ' -u$user: safety-file should be owned by $user' exit 1 } play_it_safe=false safety_file='/tmp/update-me.do-not-exit' flags="$*" while [ $# -gt 0 ]; do case "x$1" in 'x-s') play_it_safe=true ;; 'x-c') if [ -f "${safety_file}" ] && ps $(cat "${safety_file}") >/dev/null; then rm "${safety_file}" exit 0 fi if pgrep -x update-me | grep -vqxF $$; then exit 1 else exit 2 fi ;; 'x-u'*) user="${1#-u}" ;; *) usage ;; esac shift done preCmds=('uname -n') cmds=() postCmds=('sync') for mp in '/' '/boot'; do mountpoint -q "${mp}" || continue mount \ | cut -d' ' -f3,6 \ | grep "^${mp}\s" \ | cut -d' ' -f2 \ | grep -qwF 'ro' || continue [ "${mp}" = '/boot' ] && [ -d '#ETCDIR#/ports' ] && continue preCmds+=('mount -o remount,rw '"${mp}") if command -v shutdownasap >/dev/null; then if command -v screen >/dev/null; then postCmds+=('mount -o remount,ro '"${mp}"' || screen -d -m shutdownasap -R') else postCmds+=('mount -o remount,ro '"${mp}"' || shutdownasap -R') fi else postCmds+=('bash -c "mount -o remount,ro '"${mp}"' || reboot"') fi done if command -v check-kernel >/dev/null; then postCmds+=('check-kernel -r') fi if command -v checkservices >/dev/null; then postCmds+=(checkservices) fi command_needs_root() { local cmd cmd=$( printf '%s\n' "$1" \ | sed ' s@^bash -c "\(.*\)"$@\1@ s@ .*$@@ s@^.*/@@ ' ) if [ "${cmd}" = 'checkservices' ] \ || [ "${cmd}" = 'check-kernel' ] \ || [ "${cmd}" = 'mount' ] \ || [ "${cmd}" = 'report-installed-packages' ]; then return 0 else return 1 fi } opportunity_for_rescue_shell() { if "${play_it_safe}"; then printf '%s' "$$" >"${safety_file}" if [ -n "${user}" ] && [ "$(whoami)" != "${user}" ]; then chown "${user}" "${safety_file}" fi >&2 printf '%s: waiting for clearance ...' "$(uname -n)" while read -t 0.0001; do : done while [ -f "${safety_file}" ] && [ "$(cat "${safety_file}")" = "$$" ]; do if read -t 1; then >&2 printf ' rescue shell!\n' bash break fi done >&2 printf ' clear.\n' play_it_safe=false fi } exit_or_rescue_shell() { opportunity_for_rescue_shell if [ "$1" -eq 0 ]; then >&2 printf '%s: Erfolg\n' "$(uname -n)" else >&2 printf '%s: Fehler\n' "$(uname -n)" fi while read -t 0.0001; do : done read s if [ -n "${s}" ]; then bash fi exit "$1" } nochmal_versuchen() { >&2 printf '%s (%s): Fehler - nochmal versuchen?\n' "$(uname -n)" "${cmd}" while read -t 0.0001; do : done read s if [ -n "${s}" ]; then return 1 else return 0 fi } . #ETCDIR#/update-me.conf if ! command -v sudo >/dev/null; then hasSudo=false fi if [ ! "$(whoami)" == "root" ]; then if ! "${hasSudo}"; then uname -n err=1 maxCount=3 while [ ${err} -eq 1 ] && [ ${maxCount} -gt 0 ] do su -c "$(readlink -f "$0") ${flags} -u$(whoami) || exit 2" err=$? maxCount=$[${maxCount} - 1] done exit ${err} fi pre='sudo' else pre='' fi if [ ${#cmds[@]} -eq 0 ] then if [ -d '#ETCDIR#/pacman.d' ] then cmds=('pacman -Syu' 'pacdiff') elif [ -d '#ETCDIR#/ports' ] then cmds=('ports -u' 'prt-get --install-scripts sysup' 'rejmerge' 'revdep') elif [ -d '#ETCDIR#/apt' ] then cmds=('apt-get update' 'apt-get upgrade' 'apt-get dist-upgrade' 'apt-get autoremove') else >&2 echo 'Unknown distribution!' exit 1 fi fi for cmd in "${preCmds[@]}" do if command_needs_root "${cmd}"; then eval ${pre} ${cmd} else eval ${cmd} fi err=$? while [ ${err} -ne 0 ] && nochmal_versuchen; do if command_needs_root "${cmd}"; then eval ${pre} ${cmd} else eval ${cmd} fi err=$? done if [ ${err} -ne 0 ] then exit_or_rescue_shell ${err} fi done for cmd in "${cmds[@]}" do eval ${pre} ${cmd} err=$? while [ ${err} -ne 0 ] && nochmal_versuchen; do eval ${pre} ${cmd} err=$? done if [ ${err} -ne 0 ]; then exit_or_rescue_shell ${err} fi done opportunity_for_rescue_shell for cmd in "${postCmds[@]}" do if command_needs_root "${cmd}"; then eval ${pre} ${cmd} else eval ${cmd} fi err=$? while [ ${err} -ne 0 ] && nochmal_versuchen; do if command_needs_root "${cmd}"; then eval ${pre} ${cmd} else eval ${cmd} fi err=$? done if [ ${err} -ne 0 ] then exit_or_rescue_shell ${err} fi done exit_or_rescue_shell 0