#!/bin/zsh # Filename: save-config # Purpose: generate grml configuration archive and store it anywhere # Authors: grml-team (grml.org), (c) Michael Prokop # Bug-Reports: see http://grml.org/bugs/ # License: This file is licensed under the GPL v2. ################################################################################ # some zsh-stuff {{{ autoload colors ; colors setopt nonomatch . /etc/grml/sh-lib . /etc/grml/script-functions # }}} # set variables {{{ LANG=C LC_ALL=C [[ $UID != 0 ]] && runas='sudo' # important for /etc if [ -d /lib/live/mount/overlay ] ; then # since around December 2012 CHANGE_DIR='/lib/live/mount/overlay' elif [ -d /live/overlay ] ; then # until around December 2012 CHANGE_DIR='/live/overlay' elif [ -d /live/image ] ; then # old version CHANGE_DIR='/live/image' else echo "Error: no overlay directories found (like /lib/live/mount/overlay or /live/overlay)." >&2 bailout; exit 1 fi if [ -d /live/rofs ] ; then ORIG_DIR="$(find /live/rofs/ -maxdepth 1 -name \*.squashfs | head -1)" else # old version ORIG_DIR="/GRML" fi check4progs mutt &>/dev/null || echo "Warning, mutt not available for mail handling.">&2 check4progs tar || { echo "Sorry, can't continue. Exiting.">&2 ; bailout ; exit 1 } CONFIG=/etc/grml/saveconfig [ -r "$CONFIG" ] && . $CONFIG PROGRAMNAME=${0##*/} HOSTNAME=$(hostname) DATE=$(date) GRML_VERSION=$(awk '{print $1}' /etc/grml_version 2>/dev/null || print "not a grml system") KERNEL=$(uname -a) TMPDIR='/tmp' MAILFILE="${TMPDIR}/mail.txt" [ -n "$FILELIST" ] || FILELIST=$(mktemp $TMPDIR/filelist.XXXXXX) # }}} # functions {{{ debug(){ if [[ $DEBUG -gt 0 ]] ; then echo "debug: $*" fi # setopt xtrace # set -x } bailout(){ rm -f "$FILELIST" rm -f "$MAILFILE" } trap bailout 1 2 3 15 findchanged() { if [ -d "$1" ]; then for i in `(cd "$1"; find . -type f 2>/dev/null | sed 's,^\./,,g' | grep -v ' ' )`; do cmp -s "$1/$i" "$2/$i" || echo "$1/$i" done elif [ -e "$1" ]; then cmp -s "$1" "$2" || echo "$1" fi } # }}} # usage information {{{ usage() { print 1>&2 " $bg[black]$fg[green]${boldcolor}${PROGRAMNAME} - save configuration of grml system${reset_color} $bg[black]$fg[blue]${boldcolor}Usage:${reset_color} $PROGRAMNAME [-target_options] -{all,home,etc,configdir} $bg[black]$fg[blue]${boldcolor}Target options:${reset_color} -ssh user@host:/path/to/file copy configuration via ssh/scp to remote host -mail send configuration via mail -file foo_bar_config.tbz save configuration in specified file Notice: if no option is specified the default is assumed: create file config.tbz in current directory $bg[black]$fg[blue]${boldcolor}Files-to-store options:${reset_color} -home store hidden files from \$HOME (\$HOME/.*) -grmlhome store hidden files from \$HOME (\$HOME/.*) of user grml [use as user root] -etc store modified files from /etc -configdir store \$HOME/config -all store all configuration files (:= -home, -configdir and -etc) Notice: it is also possible to use environment variables: \$SAVE_HOME, \$SAVE_GRMLHOME, \$SAVE_ETC, \$SAVE_CONFIGDIR and \$SAVE_ALL $bg[black]$fg[blue]${boldcolor}Usage examples:${reset_color} $PROGRAMNAME -all => store all configuration files in config.tbz in current dir $PROGRAMNAME -home -mail devnull@grml.org => store \$HOME/.* in config.tbz and send it via mail $PROGRAMNAME -etc -ssh devnull@grml.org:/path/ => store /etc in config.tbz and scp it to specified host $PROGRAMNAME -all -file foo.tbz => store all configuration files in foo.tbz SAVE_ALL=yes $PROGRAMNAME -file /path/foo.tbz => store all configuration files in /path/foo.tbz More information on save-config can be found in the manual page: man save-config See also: restore-config(1), bootoptions: myconfig=/dev/ice, extract=PATH, netconfig=server.tld/path/to/config.tbz Report bugs, send wishes and feedback to the grml team: http://grml.org/bugs/ - contact (at) grml.org " } # }}} # what do we want to store? {{{ save_home(){ debug "save home" for i in $HOME/.* ; do findchanged "$i" /etc/skel/$(basename "$i"); done >> $FILELIST debug "debug: $FILELIST" } save_grmlhome(){ debug "save grmlhome" if [ -d /home/grml/ ] ; then for i in /home/grml/.* ; do findchanged "$i" /etc/skel/$(basename "$i"); done >> $FILELIST fi debug "debug: $FILELIST" } save_etc(){ debug "save etc" if [ -n "$NEWLAYOUT" ] ; then $runas find "${CHANGE_DIR}/etc" | sed -e "s#${CHANGE_DIR}## ; /etc$/d" >> $FILELIST else $runas findchanged /etc "${ORIG_DIR}/etc" >> $FILELIST fi } save_configdir(){ debug "save configdir" if [ -d $HOME/config ] ; then ls $HOME/config/* >> $FILELIST 2>/dev/null ls $HOME/config/.* >> $FILELIST 2>/dev/null fi } # }}} # create configuration file {{{ create_config(){ if ! [ -r "$FILELIST" ]; then echo "Filelist $FILELIST could not be read." >&2 echo "Error when generating $FILENAME." >&2 bailout ; exit 1 else # GNU tar sucks so much, really. Avoid the "file changed as we read it": tar cf /dev/null /etc # now really execute the according tar command: if BZIP2=-9 $runas tar -T - -cpPjf "$FILENAME" <"$FILELIST" ; then echo "Successfully stored configuration in file $FILENAME" else echo "Error when generating $FILENAME." >&2 bailout ; exit 1 fi fi } # }}} # commandline parsing {{{ parse_options() { zparseopts -K -- help=o_help mail:=o_mail \ file:=o_file home=o_home grmlhome=o_grmlhome etc=o_etc \ configdir=o_configdir all=o_all ssh:=o_ssh if [[ "$#" == 0 || "$o_help" != "" || "$1" == '-h' || "$1" == '--help' ]]; then usage ; exit fi if [[ "$o_file" != "" ]]; then FILENAME="$o_file[2]" else FILENAME="config.tbz" fi if [[ "$o_home" != "" ]]; then debug "home is set" SAVE_HOME="yes" fi if [[ "$o_grmlhome" != "" ]]; then debug "grmlhome is set" SAVE_GRMLHOME="yes" fi if [[ "$o_etc" != "" ]]; then debug "etc is set" SAVE_ETC="yes" fi if [[ "$o_configdir" != "" ]]; then debug "configdir is set" SAVE_CONFIGDIR="yes" fi if [[ "$o_all" != "" ]]; then debug "home, grmlhome, etc and configdir are set" SAVE_HOME="yes" SAVE_GRMLHOME="yes" SAVE_ETC="yes" SAVE_CONFIGDIR="yes" fi if [[ "$o_ssh" != "" ]]; then debug "scp $FILENAME $o_ssh[2]" scp $FILENAME $o_ssh[2] fi if [[ "$o_mail" != "" ]]; then check4progs mutt || { echo "Sorry, mutt not available for sending mail. Exiting.">&2 ; exit 1 } recipient=$o_mail[2] debug "send mail to $recipient" echo "Created on $DATE on host $HOSTNAME running grml $GRML_VERSION" > $MAILFILE mutt -s "configuration of $HOSTNAME ($DATE)" -a $FILENAME $recipient < $MAILFILE fi } parse_options $* # }}} # execution wrapper {{{ runit(){ if [[ $SAVE_HOME == "yes" ]]; then debug "running save_home" save_home SETSAVE=1 fi if [[ $SAVE_GRMLHOME == "yes" ]]; then debug "running save_grmlhome" save_grmlhome SETSAVE=1 fi if [[ $SAVE_ETC == "yes" ]] ; then debug "running save_etc" save_etc SETSAVE=1 fi if [[ $SAVE_CONFIGDIR == "yes" ]] ; then debug "running save_configdir" save_configdir SETSAVE=1 fi if [ -z $SETSAVE ] ; then echo "Sorry, you did not select any configuration which should be saved. Exiting." bailout ; exit 1 fi } # }}} # now run it runit create_config bailout ## END OF FILE ################################################################# # vim:foldmethod=marker