save-config: Adjust for working with current Grml versions [Testing: issue1188]
[grml-autoconfig.git] / bin / save-config
1 #!/bin/zsh
2 # Filename:      save-config
3 # Purpose:       generate grml configuration archive and store it anywhere
4 # Authors:       grml-team (grml.org), (c) Michael Prokop <mika@grml.org>
5 # Bug-Reports:   see http://grml.org/bugs/
6 # License:       This file is licensed under the GPL v2.
7 ################################################################################
8
9 # some zsh-stuff {{{
10   autoload colors ; colors
11   setopt nonomatch
12   . /etc/grml/sh-lib
13   . /etc/grml/script-functions
14 # }}}
15
16 # set variables  {{{
17   LANG=C
18   LC_ALL=C
19   [[ $UID != 0 ]] && runas='sudo' # important for /etc
20
21   if [ -d /live/overlay ] ; then
22     CHANGE_DIR='/live/overlay'
23   elif [ -d /live/image ] ; then # old version
24     CHANGE_DIR='/live/image'
25   else
26     echo "Error: no overlay directories found (neither /live/overlay nor /live/image)." >&2
27     bailout; exit 1
28   fi
29
30   if [ -d /live/rofs ] ; then
31     ORIG_DIR="$(find /live/rofs/ -maxdepth 1 -name \*.squashfs | head -1)"
32   else # old version
33     ORIG_DIR="/GRML"
34   fi
35
36   check4progs mutt &>/dev/null || echo "Warning, mutt not available for mail handling.">&2
37   check4progs tar || { echo "Sorry, can't continue. Exiting.">&2 ; bailout ; exit 1 }
38
39   CONFIG=/etc/grml/saveconfig
40   [ -r "$CONFIG" ] && . $CONFIG
41
42   PROGRAMNAME=${0##*/}
43   HOSTNAME=$(hostname)
44   DATE=$(date)
45   GRML_VERSION=$(awk '{print $1}' /etc/grml_version 2>/dev/null || print "not a grml system")
46   KERNEL=$(uname -a)
47
48   TMPDIR='/tmp'
49   MAILFILE="${TMPDIR}/mail.txt"
50
51   [ -n "$FILELIST" ] || FILELIST=$(mktemp $TMPDIR/filelist.XXXXXX)
52 # }}}
53
54 # functions {{{
55 debug(){
56   if [[ $DEBUG -gt 0 ]] ; then
57     echo "debug: $*"
58   fi
59 # setopt xtrace
60 # set -x
61 }
62
63 bailout(){
64   rm -f "$FILELIST"
65   rm -f "$MAILFILE"
66 }
67
68 trap bailout 1 2 3 15
69
70 findchanged() {
71   if [ -d "$1" ]; then
72     for i in `(cd "$1"; find . -type f 2>/dev/null | sed 's,^\./,,g' | grep -v ' ' )`; do
73       cmp -s "$1/$i" "$2/$i" || echo "$1/$i"
74     done
75   elif [ -e "$1" ]; then
76     cmp -s "$1" "$2" || echo "$1"
77   fi
78 }
79 # }}}
80
81 # usage information {{{
82 usage()
83 {
84   print 1>&2 "
85 $bg[black]$fg[green]${boldcolor}${PROGRAMNAME} - save configuration of grml system${reset_color}
86
87 $bg[black]$fg[blue]${boldcolor}Usage:${reset_color}
88   $PROGRAMNAME [-target_options] -{all,home,etc,configdir}
89
90 $bg[black]$fg[blue]${boldcolor}Target options:${reset_color}
91   -ssh user@host:/path/to/file  copy configuration via ssh/scp to remote host
92   -mail <recipient>             send configuration via mail
93   -file foo_bar_config.tbz      save configuration in specified file
94
95   Notice: if no option is specified the default is assumed:
96           create file config.tbz in current directory
97
98 $bg[black]$fg[blue]${boldcolor}Files-to-store options:${reset_color}
99   -home                         store hidden files from \$HOME (\$HOME/.*)
100   -grmlhome                     store hidden files from \$HOME (\$HOME/.*) of user grml [use as user root]
101   -etc                          store modified files from /etc
102   -configdir                    store \$HOME/config
103   -all                          store all configuration files (:= -home, -configdir and -etc)
104
105   Notice: it is also possible to use environment variables:
106           \$SAVE_HOME, \$SAVE_GRMLHOME, \$SAVE_ETC, \$SAVE_CONFIGDIR and \$SAVE_ALL
107
108 $bg[black]$fg[blue]${boldcolor}Usage examples:${reset_color}
109   $PROGRAMNAME -all                                  => store all configuration files in config.tbz in current dir
110   $PROGRAMNAME -home -mail  devnull@grml.org         => store \$HOME/.* in config.tbz and send it via mail
111   $PROGRAMNAME -etc  -ssh   devnull@grml.org:/path/  => store /etc in config.tbz and scp it to specified host
112   $PROGRAMNAME -all  -file  foo.tbz                  => store all configuration files in foo.tbz
113   SAVE_ALL=yes $PROGRAMNAME -file /path/foo.tbz      => store all configuration files in /path/foo.tbz
114
115 More information on save-config can be found in the manual page: man save-config
116
117 See also: restore-config(1), bootoptions: myconfig=/dev/ice, extract=PATH,
118           netconfig=server.tld/path/to/config.tbz
119
120 Report bugs, send wishes and feedback to the grml team:
121 http://grml.org/bugs/ - contact (at) grml.org
122 "
123 }
124 # }}}
125
126 # what do we want to store? {{{
127 save_home(){
128   debug "save home"
129   for i in $HOME/.* ; do findchanged "$i" /etc/skel/$(basename "$i"); done >> $FILELIST
130   debug "debug: $FILELIST"
131 }
132
133 save_grmlhome(){
134   debug "save grmlhome"
135   if [ -d /home/grml/ ] ; then
136      for i in /home/grml/.* ; do findchanged "$i" /etc/skel/$(basename "$i"); done >> $FILELIST
137   fi
138   debug "debug: $FILELIST"
139 }
140
141 save_etc(){
142   debug "save etc"
143   if [ -n "$NEWLAYOUT" ] ; then
144      $runas find "${CHANGE_DIR}/etc" | sed -e "s#${CHANGE_DIR}## ; /etc$/d" >> $FILELIST
145   else
146      $runas findchanged /etc "${ORIG_DIR}/etc" >> $FILELIST
147   fi
148 }
149
150 save_configdir(){
151   debug "save configdir"
152   if [ -d $HOME/config ] ; then
153      ls $HOME/config/*  >> $FILELIST 2>/dev/null
154      ls $HOME/config/.* >> $FILELIST 2>/dev/null
155   fi
156 }
157 # }}}
158
159 # create configuration file {{{
160 create_config(){
161   if ! [ -r "$FILELIST" ]; then
162     echo "Filelist $FILELIST could not be read." >&2
163     echo "Error when generating $FILENAME." >&2
164     bailout ; exit 1
165   else
166     # GNU tar sucks so much, really. Avoid the "file changed as we read it":
167     tar cf /dev/null /etc
168     # now really execute the according tar command:
169     if BZIP2=-9 $runas tar -T - -cpPjf "$FILENAME" <"$FILELIST" ; then
170       echo "Successfully stored configuration in file $FILENAME"
171     else
172       echo "Error when generating $FILENAME." >&2
173       bailout ; exit 1
174     fi
175   fi
176 }
177 # }}}
178
179 # commandline parsing {{{
180 parse_options()
181 {
182    zparseopts -K -- help=o_help mail:=o_mail \
183                     file:=o_file home=o_home grmlhome=o_grmlhome etc=o_etc \
184                     configdir=o_configdir all=o_all ssh:=o_ssh
185
186    if [[ "$#" == 0 || "$o_help" != "" || "$1" == '-h' || "$1" == '--help' ]]; then
187       usage ; exit
188    fi
189
190    if [[ "$o_file" != "" ]]; then
191      FILENAME="$o_file[2]"
192    else
193      FILENAME="config.tbz"
194    fi
195
196    if [[ "$o_home" != "" ]]; then
197       debug "home is set"
198       SAVE_HOME="yes"
199    fi
200
201    if [[ "$o_grmlhome" != "" ]]; then
202       debug "grmlhome is set"
203       SAVE_GRMLHOME="yes"
204    fi
205
206    if [[ "$o_etc" != "" ]]; then
207       debug "etc is set"
208       SAVE_ETC="yes"
209    fi
210
211    if [[ "$o_configdir" != "" ]]; then
212       debug "configdir is set"
213       SAVE_CONFIGDIR="yes"
214    fi
215
216    if [[ "$o_all" != "" ]]; then
217       debug "home, grmlhome, etc and configdir are set"
218       SAVE_HOME="yes"
219       SAVE_GRMLHOME="yes"
220       SAVE_ETC="yes"
221       SAVE_CONFIGDIR="yes"
222    fi
223
224    if [[ "$o_ssh" != "" ]]; then
225       debug "scp $FILENAME $o_ssh[2]"
226       scp $FILENAME $o_ssh[2]
227    fi
228
229    if [[ "$o_mail" != "" ]]; then
230       check4progs mutt || { echo "Sorry, mutt not available for sending mail. Exiting.">&2 ; exit 1 }
231       recipient=$o_mail[2]
232       debug "send mail to $recipient"
233       echo "Created on $DATE on host $HOSTNAME running grml $GRML_VERSION" > $MAILFILE
234       mutt -s "configuration of $HOSTNAME ($DATE)" -a $FILENAME $recipient < $MAILFILE
235    fi
236 }
237 parse_options $*
238 # }}}
239
240 # execution wrapper {{{
241 runit(){
242    if [[ $SAVE_HOME == "yes" ]]; then
243      debug "running save_home"
244      save_home
245      SETSAVE=1
246    fi
247    if [[ $SAVE_GRMLHOME == "yes" ]]; then
248      debug "running save_grmlhome"
249      save_grmlhome
250      SETSAVE=1
251    fi
252    if [[ $SAVE_ETC == "yes" ]] ; then
253      debug "running save_etc"
254      save_etc
255      SETSAVE=1
256    fi
257    if [[ $SAVE_CONFIGDIR == "yes" ]] ; then
258      debug "running save_configdir"
259      save_configdir
260      SETSAVE=1
261    fi
262    if [ -z $SETSAVE ] ; then
263      echo "Sorry, you did not select any configuration which should be saved. Exiting."
264      bailout ; exit 1
265    fi
266 }
267 # }}}
268
269 # now run it
270   runit
271   create_config
272   bailout
273
274 ## END OF FILE #################################################################
275 # vim:foldmethod=marker