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