summarylogtreecommitdiffstats
path: root/system_image.sh
blob: 710dbc9dfeba5455c211f8eed45acdfb09c857f4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
#!/bin/bash
# welcome to system_image_backup(sib)-source-code
# do you want to run with colors? recommended

USECOLOR="yes"

# some functions from archlinux' /etc/rc.d/functions, gives us nice colors and layout
# width:
STAT_COL=80
if [ ! -t 1 ]; then
  USECOLOR=""

# stty will fail when stdin isn't a terminal
elif [ -t 0 ]; then
  STAT_COL="$(/bin/stty size)"
  # stty gives "rows cols"; strip the rows number, we just want columns
  STAT_COL="${STAT_COL##* }"

else
  # is /usr/share/terminfo already mounted, and TERM recognized?
  /bin/tput cols &>/dev/null
  if [ $? -eq 0 ]; then
    STAT_COL=$(/bin/tput cols)
  fi
fi
if [ "0$STAT_COL" -eq 0 ]; then
  # if output was 0 (serial console), set default width to 80
  STAT_COL=80
  USECOLOR=""
fi

# we use 13 characters for our own stuff
STAT_COL=$(($STAT_COL - 13))

# disable colors on broken terminals
TERM_COLORS="$(/bin/tput colors 2>/dev/null)"
if [ $? = 3 ]; then
        TERM_COLORS=8
elif [ -n "${TERM_COLORS}" ]; then
        case "${TERM_COLORS}" in
                *[!0-9]*)
                        USECOLOR=""
                        ;;
                *)
                        [ "${TERM_COLORS}" -lt 8 ] && USECOLOR=""
                        ;;
        esac
else
        USECOLOR=""
fi
unset TERM_COLORS

# colors:
if [ "$USECOLOR" = "YES" -o "$USECOLOR" = "yes" ]; then
        C_MAIN="\033[1;37;40m"      # main text
        C_OTHER="\033[1;34;40m"     # prefix & brackets
        C_SEPARATOR="\033[1;30;40m" # separator

        C_BUSY="\033[0;36;40m"      # busy
        C_FAIL="\033[1;31;40m"      # failed
        C_DONE="\033[1;37;40m"      # completed

        C_H1="\033[1;37;40m"        # highlight text 1
        C_H2="\033[1;36;40m"        # highlight text 2
	C_OK="\033[01;32m"	    # green text
        C_CLEAR="\033[1;0m"	    # clear color
fi

if [ -t 1 ]; then
        SAVE_POSITION="\033[s"
        RESTORE_POSITION="\033[u"
        DEL_TEXT="\033[$(($STAT_COL+4))G"
else
        SAVE_POSITION=""
        RESTORE_POSITION=""
        DEL_TEXT=""
fi

# prefixes:
PREFIX_REG=":::"
PREFIX_HL="(O)"

# different little functions:
deltext() {
        printf "${DEL_TEXT}"
}

printhl() {
        printf "${C_OTHER}${PREFIX_HL} ${C_H1}${1}${C_CLEAR} \n"
}

printsep() {
        printf "\n${C_SEPARATOR}   ------------------------------  ------------------------------\n"
}

stat_busy() {
        printf "${C_OTHER}${PREFIX_REG} ${C_MAIN}${1}${C_CLEAR} "
        printf "${SAVE_POSITION}"
        deltext
        printf "   ${C_OTHER}[${C_BUSY}BUSY${C_OTHER}]${C_CLEAR} "
}

stat_done() {
        deltext
        printf "   ${C_OTHER}[${C_DONE}DONE${C_OTHER}]${C_CLEAR} \n"
}

stat_fail() {
        deltext
        printf "   ${C_OTHER}[${C_FAIL}FAIL${C_OTHER}]${C_CLEAR} \n"
}
input_err() {
	printf "   ${C_FAIL}Wrong input! ${1}${C_CLEAR}\n"
}
prompt() {
	printf "=> "
}
cancel() {
	cd /
	sleep 1
	umount /dev/disk/by-label/$SOURCE 2> /dev/null
	sleep 1
	umount /dev/disk/by-label/$AIM 2> /dev/null
	stat_fail
	exit 1
}
#regular expression, integer only
RE='^[0-9]+$'
# coordinates our input for $SOURCE
input_source() {
	DEV_NR=$[$DEV_NR-1]
	prompt
	read SOURCE || cancel
	if ( [[ $SOURCE =~ $RE ]]  && [ $SOURCE -ge 0 ] && [ $SOURCE -le $DEV_NR ] ); then
	  SOURCE=${DEV[$SOURCE]}
	  DEV_NR=$[$DEV_NR+1]
	else
	  input_err "Choose between 0 and $DEV_NR!"
	  DEV_NR=$[$DEV_NR+1]
	  input_source
	fi || cancel
}
# coordinates our input for $AIM
input_aim() {
	DEV_NR=$[$DEV_NR-1]
	prompt
	read AIM || cancel
	if ( [[ $AIM =~ $RE ]]  && [ $AIM -ge 0 ] && [ $AIM -le $DEV_NR ] ); then
	  AIM=${DEV[$AIM]}
	  if [[ $AIM = $SOURCE ]]; then
	    input_err "Choose between 0 and $DEV_NR, but not '$SOURCE'!${C_CLEAR}"
	    DEV_NR=$[$DEV_NR+1]
	    input_aim
	  fi
	else
	  input_err "Choose between 0 and $DEV_NR, but not '$SOURCE'!${C_CLEAR}"
	  DEV_NR=$[$DEV_NR+1]
	  input_aim
	fi || cancel
	DEV_NR=$[$DEV_NR+1]
}
# function which runs, when we call "image-creation"
backup() {
	clear
	echo " "
	stat_busy "[1/3] Configuring System Backup"
	echo " "
	echo " "
	echo "   Enter the number of device-label you want to backup as image:"
	dev_list
	echo " "
	input_source
	printf "  ${C_SEPARATOR}"
	mount | grep $SOURCE | grep "on / type"
	if [ $? = 0 ]; then
	  printf "   ${C_FAIL}For System-Backups You need to be root from live-CD${C_CLEAR}"
	  cancel
	fi
	printf "  ${C_CLEAR}"
	echo " "  
	echo "   Enter the number of the device-label where you want to store the image:"
	dev_list
	echo " "
	input_aim
	stat_done
	printf "\n\n\n\n"
	stat_busy "[2/3] Preparing Backup and Processing Image"
	printf "${C_SEPARATOR}"
	mkdir $MNT_SYSTEM 2> /dev/null
	mkdir $MNT_BACKUP  2> /dev/null
	printf "${C_CLEAR}"
	mount -o ro -L $SOURCE $MNT_SYSTEM || cancel
	mount -L $AIM $MNT_BACKUP || cancel
	printf "${C_SEPARATOR}"
	echo " "
	echo " "
	ls -d $MNT_BACKUP/system > /dev/null 2> /dev/null
	if [ $? != 0 ]; then
	  echo "   Creating folder for backup-images..."
	  mkdir $MNT_BACKUP/system > /dev/null 2> /dev/null
	fi
	printf "${C_CLEAR}"
	cd $MNT_SYSTEM || cancel
	printf "\n   Create backup-image of /dev/disk/by-label/${C_H2}${SOURCE}${C_CLEAR} at /dev/disk/by-label/${C_H2}${AIM}${C_CLEAR}/system/${SOURCE}-${DATE}.tar.bz2 ?\n"
	backup_command() {
	    echo "   Packing tarball, this can take a long time..."
	    printf "${C_SEPARATOR}tar cpflv ${MNT_BACKUP}/system/${SOURCE}-${DATE}.tar --index-file=${MNT_BACKUP}/system/${SOURCE}-${DATE}.log --wildcards --verify --xattrs --anchored --exclude=\"home/*/.config/Slack\" --exclude=\"home/*/Eigene_Dateien\" --exclude=\"home/*/.cache\" --exclude=\"var/tmp/*\" --exclude=\"proc/*\" --exclude=\"sys/*\" --exclude=\"tmp/*\" *${C_CLEAR}\n"
	    tar cpflv $MNT_BACKUP/system/$SOURCE-$DATE.tar --index-file=$MNT_BACKUP/system/$SOURCE-$DATE.log --wildcards --verify --xattrs --anchored --exclude="home/*/.config/Slack" --exclude="home/*/Eigene_Dateien" --exclude="home/*/.cache" --exclude="var/tmp/*" --exclude="proc/*" --exclude="sys/*" --exclude="tmp/*" *  || cancel
	    if [ $? = 0 ]; then
	      echo "   Tarball created and verified successfully."
	      echo " "
	      echo "   Compressing Tarball, this can take a long time on single core cpu..." && which pbzip2 > /dev/null 2> /dev/null
	      case "$?" in
		0)
		  printf "${C_SEPARATOR}"
		  pbzip2 -z -m768 -v --best $MNT_BACKUP/system/$SOURCE-$DATE.tar || cancel
		;;
		1)
		  printf "${C_SEPARATOR}"
		  bzip2 -z -v --best $MNT_BACKUP/system/$SOURCE-$DATE.tar || cancel
		;;
	      esac
	      printf "${C_CLEAR}"
	      echo "   Tarball compressed successfully, now verifying..."
	      printf "${C_SEPARATOR}"
	      which pbzip2 > /dev/null 2> /dev/null
	      case "$?" in
		0)
		  printf "${C_SEPARATOR}"
		  pbzip2 -t -m768 -v $MNT_BACKUP/system/$SOURCE-$DATE.tar.bz2 || cancel
		;;
		1)
		  printf "${C_SEPARATOR}"
		  bzip2 -t -v $MNT_BACKUP/system/$SOURCE-$DATE.tar.bz2 || cancel
		;;
	      esac
	      printf "${C_CLEAR}"
	      echo "   ...successful!"
	    else
	      cancel
	    fi
	}
	PROGRAM=backup_command
	case_program
	stat_done
	printf "\n\n\n\n"
	stat_busy "[3/3] Creating Checksum and Cleaning System"
	cd $MNT_BACKUP/system/ || cancel
	md5sum $SOURCE-$DATE.tar.bz2 > $SOURCE-$DATE.md5 || cancel
	echo " "
	printf "${C_SEPARATOR}\n   $(cat $SOURCE-$DATE.md5 || cancel)${C_CLEAR}\n"
	echo " "
	echo "   Created Files:"
	echo "   --------------"
	printf "$(ls -ash $MNT_BACKUP/system/ | grep $SOURCE-$DATE || cancel)"
	cd / || cancel
}
# function which runs, when we call "restore"
restore () {
	clear
	echo " "
	stat_busy "[1/3] Configuring System Restore"
	echo " "
	echo " "
	echo "   Enter the number of the device-label where an 'system'-folder (backup) is located:"
	dev_list
	echo " "
	source_device () {
	      input_source
	      mkdir $MNT_BACKUP 2> /dev/null
	      mount -o ro -L $SOURCE $MNT_BACKUP || cancel
	      ls -d $MNT_BACKUP/system > /dev/null 2> /dev/null
	      if [[ $? != 0 ]]; then
		input_err "No backup-image folder $MNT_BACKUP/system found!"
		sleep 1
		umount /dev/disk/by-label/$SOURCE || cancel
		rmdir $MNT_BACKUP 2> /dev/null
		source_device
	      fi
	}
	source_device
	echo " "
	echo "   Enter the number of the backup you want to restore:"
	declare -a FILE
	FILE=( $(ls $MNT_BACKUP/system|grep tar.bz2) )
	FILE_NR=$(echo ${FILE[@]} | wc -w)
	NR=0
	until [ $NR = $FILE_NR ]; do
	printf "   ${C_H2}$NR${C_SEPARATOR}:${C_CLEAR}${FILE[$NR]} "
	NR=$[$NR+1]
        done
	echo " "
	FILE_NR=$[$FILE_NR-1]
	input_aimfile() {
	      prompt
	      read AIMFILE || cancel
	      if [[ $AIMFILE = [0-$FILE_NR] ]]; then
		AIMFILE=${FILE[$AIMFILE]}
	      else
		input_err "Choose between 0 and $FILE_NR!"
		input_aimfile
	      fi || cancel
	}
	input_aimfile
	echo " "  
	echo "   Enter the number of the device-label where you want to extract the image:"
	dev_list
	echo " "
	input_aim
	printf "  ${C_SEPARATOR}"
	mount | grep $AIM | grep "on / type" > /dev/null 2> /dev/null
	if [ $? = 0 ]; then
	  printf " ${C_FAIL}You want to extract to /${C_CLEAR}\n"
	  PROGRAM=$(printf "")
	  case_program
	fi
	printf "  ${C_CLEAR}"
	echo " "  
	stat_done
	printf "\n\n\n\n"
	stat_busy "[2/3] Checking MD5-sum and Processing Image"
	echo " "
	mkdir $MNT_SYSTEM  2> /dev/null
	mount -L $AIM $MNT_SYSTEM || cancel
	cd $MNT_BACKUP/system || cancel
	AIMFILE=$(echo $AIMFILE|cut --delimiter="." -f1)
	printf "${C_SEPARATOR}"
	md5sum -c $AIMFILE.md5 || cancel
	printf "${C_CLEAR}"
	echo " "
	printf "\n   Restore backup-image of /dev/disk/by-label/${SOURCE}/system/${C_H2}$AIMFILE.tar.bz2${C_CLEAR} at /dev/disk/by-label/${C_H2}${AIM}${C_CLEAR}?\n"
	restore_command() {
		echo "   Unpacking tarball, this can take a long time..."
		printf "${C_SEPARATOR}tar xpjfv --xattrs ${MNT_BACKUP}/system/${AIMFILE}.tar.bz2 --index-file=${MNT_SYSTEM}/system_restore-${DATE}.log --directory ${MNT_SYSTEM}${C_CLEAR}\n"
		tar xpjfv --xattrs $MNT_BACKUP/system/$AIMFILE.tar.bz2 --index-file=$MNT_SYSTEM/system_restore-$DATE.log --directory $MNT_SYSTEM || cancel
		if [ $? = 0 ]; then
		  echo "   Tarball extracted successfully."
		  echo " "
		fi
	  }
	  PROGRAM=restore_command
	  case_program
	  stat_done
	printf "\n\n\n\n"
	stat_busy "[3/3] Cleaning System"
	echo " "
	echo "   If you unpacked an image on another PC you have to check/adjust:"
	echo "   - /etc/xorg.conf (X11-Server, another graphics card?)"
	echo "   - /etc/fstab (devices you mount while booting, changed uuid, device-label,other devices?)"
	echo "   - /boot/grub/menu.lst or /etc/lilo.conf (same as above, bootloader has to find /)"
	cd / || cancel
}
# asks if we want to continue with a special function
case_program() {
	printf "   ${C_SEPARATOR}Continue? [${C_H2}y${C_SEPARATOR}es/${C_H2}n${C_SEPARATOR}o]${C_CLEAR}\n"
	prompt
	read INPUT
	echo " "
	case "$INPUT" in
	  y)
	    $PROGRAM
	  ;;
	  n)
	    printf "   ${C_SEPARATOR}Aborted by user $(whoami)${C_CLEAR}"
	    cancel
	  ;;
	  *)
	    input_err "Type 'y' for Yes or 'n' for No"
	    case_program
	esac
}
# here starts the program with functions from above
if [[ $(whoami) != root ]]; then
  printf "${C_FAIL}You need to be root!${C_CLEAR}\n"
  exit 1
fi
DATE=$(date -I);
MNT_BACKUP="/mnt/sib_backup"
MNT_SYSTEM="/mnt/sib_system"
declare -a DEV
DEV=( $(ls /dev/disk/by-label/) )
dev_list () {
	DEV_NR=$(echo ${DEV[@]} | wc -w)
	NR=0
	until [ $NR = $DEV_NR ]; do
	printf "   ${C_H2}$NR${C_SEPARATOR}:${C_CLEAR}${DEV[$NR]} "
	NR=$[$NR+1]
        done
}
echo " "
printhl "${C_H2}System Backup (image)"
printhl "Copyright 2010-2011 Manuel Conzelmann"
printhl "Distributed under the GNU General Public License (GPL)"
printhl ""
printhl "using $(tar --version | head -1)"
printsep
printf "${C_CLEAR}   For creating an image type ${C_H2}1${C_CLEAR}."
printf "   For restoring an image type ${C_H2}2${C_CLEAR}.\n"
abfrage () {
prompt
read INPUT
echo " "
case "$INPUT" in
  1)
      printf "   ${C_SEPARATOR}For System-Backups You need to be root from live-CD\n"
      printf "   Hidden files in the root-directory of the imaged system won't be backed up${C_CLEAR}\n"
      PROGRAM=backup
      case_program
      echo " "
  ;;
  2)
      printf "   ${C_SEPARATOR}For System-Restore You need to be root from live-CD\n"
      printf "   Remember: you need enough space on your target-device${C_CLEAR}\n"
      PROGRAM=restore
      case_program
      echo " "
  ;;
  *)
    input_err "Type '1' for image-creation or '2' for extracting an existing one."
    abfrage
esac
}
abfrage
umount /dev/disk/by-label/$SOURCE || cancel
umount /dev/disk/by-label/$AIM || cancel
rmdir $MNT_SYSTEM || cancel
rmdir $MNT_BACKUP || cancel
echo " "
printf "${C_OK}${PROGRAM} ran successfully!${C_CLEAR}"
stat_done


#exclude.lst ?
#/usr/src