lnbackup 2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/lnbackup +187 -0
- data/bin/lnmount +16 -0
- data/bin/lnstat +4 -0
- data/bin/lnumount +4 -0
- data/bin/pc_backup +66 -0
- data/bin/sql_backup.sh +123 -0
- data/lib/lnbackup/backup.rb +1938 -0
- data/lib/lnbackup/freespace.rb +73 -0
- data/lib/lnbackup/util.rb +123 -0
- data/lib/lnbackup/version.rb +3 -0
- data/lib/lnbackup.rb +21 -0
- metadata +63 -0
data/bin/lnbackup
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'lnbackup'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
def go
|
7
|
+
debug_levels = {
|
8
|
+
:debug => Logger::DEBUG,
|
9
|
+
:info => Logger::INFO,
|
10
|
+
:warn => Logger::WARN,
|
11
|
+
:error => Logger::ERROR,
|
12
|
+
:fatal => Logger::FATAL,
|
13
|
+
}
|
14
|
+
backup_name = 'localhost'
|
15
|
+
log_level = Logger::INFO
|
16
|
+
test_mode = false
|
17
|
+
config_dir = LnBackup::CONFIG_D
|
18
|
+
log_file = LnBackup::LOG_FILE
|
19
|
+
status_file_pref = LnBackup::STATUS_FILE_PREF
|
20
|
+
status = false
|
21
|
+
mount = false
|
22
|
+
mountrw = false
|
23
|
+
umount = false
|
24
|
+
no_mirror = false
|
25
|
+
nagios = false
|
26
|
+
nagios_all = false
|
27
|
+
source_prefix = nil
|
28
|
+
target_dir_name = nil
|
29
|
+
mirror_only = nil
|
30
|
+
backup = nil
|
31
|
+
pc_test = nil
|
32
|
+
pc_backup = nil
|
33
|
+
init_crypto = nil
|
34
|
+
crypto_size = 0
|
35
|
+
pcs_status_f = LnBackup::PCS_STATUS
|
36
|
+
pcs_status = nil
|
37
|
+
delay = nil
|
38
|
+
delay_denom = nil
|
39
|
+
no_delete = nil
|
40
|
+
no_acl = nil
|
41
|
+
bin_log = nil
|
42
|
+
max_iter = 5
|
43
|
+
|
44
|
+
ARGV.options do |p|
|
45
|
+
p.banner = "Usage: #{$0} [options]\n"
|
46
|
+
p.on( '--backup-name=NAME', String, "name of backup configuration (#{backup_name})") { |nam| backup_name = nam }
|
47
|
+
p.on('-l', '--log-file=FILE', String, "file for logging (#{log_file})") { |lf| log_file = lf }
|
48
|
+
p.on( '--status-file-pref=FILE', String, "prefix for file to store backup status (#{status_file_pref}), backup name will be added") { |pref| status_file_pref = pref }
|
49
|
+
p.on('-v', '--log-level=LEVEL', String, 'set log level: debug,[info],warn,error,fatal') { |lvl|
|
50
|
+
symb = lvl.downcase.intern
|
51
|
+
if debug_levels.key?(symb)
|
52
|
+
log_level = debug_levels[symb]
|
53
|
+
else
|
54
|
+
puts p
|
55
|
+
puts "Invalid log level #{lvl}"
|
56
|
+
exit(1)
|
57
|
+
end
|
58
|
+
}
|
59
|
+
p.on('-c', '--config-dir=PATH', String, 'configuration directory') { |cd| config_dir = cd }
|
60
|
+
p.on('-t', '--test', 'dry run (test mode)') { |tm| test_mode = tm }
|
61
|
+
p.on('-m', '--no-mirror', 'skip creation of bootable mirror after backup') { |no_mirror| }
|
62
|
+
p.on('-s', '--status', 'display lnbackup status information including list of available backups') { status = true }
|
63
|
+
p.on( '--backup', 'run backup') { backup = true }
|
64
|
+
p.on( '--mount', 'mount backup device ro') { mount = true }
|
65
|
+
p.on( '--mountrw', 'mount backup device rw') { mountrw = true }
|
66
|
+
p.on( '--umount', 'umount backup device') { umount = true }
|
67
|
+
p.on( '--nagios', 'run as nagios plugin') { nagios = true }
|
68
|
+
p.on( '--dump-log=FILE', String, 'parse bin. log and dump to STDOUT') { bin_log = true }
|
69
|
+
p.on( '--nagios-all' 'run as nagios plugin for all backups config directory') { nagios_all = true }
|
70
|
+
p.on( '--source-prefix=DIR', String, 'prefix the source directory given by configuration') { |sp| source_prefix = sp }
|
71
|
+
p.on( '--target-dir-name=NAME', String, 'set backup target directory under backup root ([backup-name] if not given)') { |td| target_dir_name = td }
|
72
|
+
p.on( '--mirror-only', 'only create bootable mirror from last backup') { mirror_only = true }
|
73
|
+
|
74
|
+
#p.on( '--pc-backup', 'run backup of PCs') { |pc_backup| }
|
75
|
+
#p.on( '--pc-mount-test', 'test if PCs configured for backup are accessible') { |pc_test| }
|
76
|
+
#p.on( '--pc-status', 'display PCs backup status') { |pcs_status| }
|
77
|
+
#p.on( '--pc-status-file=FILE', String, 'PCs backup status file') { |pcs_status_f| }
|
78
|
+
|
79
|
+
p.on('--init-crypto[=SIZE]', 'initialize crypto loop device, optional SIZE in MB (ignored if block device)') { |crypto_size| init_crypto = true }
|
80
|
+
p.on('--delay=FLOAT', 'delay (sec) between processing objects') { |delay| delay = delay.to_f }
|
81
|
+
p.on('--delay-denom=N', 'apply delay every N objects') { |delay_denom| delay_denom = delay_denom.to_i }
|
82
|
+
p.on('--no-delete', 'don\'t remove old backups, return error when out of space') { |no_delete| no_delete = true }
|
83
|
+
p.on('--no-acl', 'don\'t restore ACL, don\'t generate fstab with ACL options') { |no_acl| no_acl = true }
|
84
|
+
p.on('--version', 'version info') { puts LnBackup::VERSION; exit(1) }
|
85
|
+
p.on('--help', 'display help') { puts p; exit(1) }
|
86
|
+
p.on('--search-iter=NUMBER', 'number of backups to search for files not contained in the last backup (0 for unlimited, default 5)') { |mi| max_iter = mi.to_i }
|
87
|
+
begin
|
88
|
+
p.parse!(ARGV)
|
89
|
+
#rescue => e
|
90
|
+
# puts e.backtrace.join("\n")
|
91
|
+
# puts p
|
92
|
+
# exit(1)
|
93
|
+
end
|
94
|
+
if ( not status and not backup and not mount and not mountrw and not umount and not nagios and not nagios_all and
|
95
|
+
not pc_test and not pc_backup and not init_crypto and not pcs_status and not mirror_only and not bin_log )
|
96
|
+
puts p
|
97
|
+
exit(1)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
if bin_log
|
102
|
+
Marshal.restore( File.read(bin_log) ).each { |st| st.each_pair { |k,v| puts "#{k+' '*(30-k.length)}:\t#{v}" if k }; puts }
|
103
|
+
exit
|
104
|
+
end
|
105
|
+
|
106
|
+
target_dir_name = backup_name unless target_dir_name
|
107
|
+
|
108
|
+
lnbackup = LnBackup::LnBackup.new( :log_level => log_level,
|
109
|
+
:log_file => log_file,
|
110
|
+
:test_mode => test_mode,
|
111
|
+
:config_dir => config_dir,
|
112
|
+
:status_file_pref => status_file_pref,
|
113
|
+
:source_prefix => source_prefix,
|
114
|
+
:target_dir_name => target_dir_name,
|
115
|
+
:delay => delay,
|
116
|
+
:delay_denom => delay_denom,
|
117
|
+
:no_delete => no_delete,
|
118
|
+
:no_acl => no_acl,
|
119
|
+
:max_iter => max_iter
|
120
|
+
)
|
121
|
+
|
122
|
+
res = 0
|
123
|
+
if status
|
124
|
+
# display status
|
125
|
+
lnbackup.backup_status( backup_name, status_file_pref )
|
126
|
+
|
127
|
+
elsif nagios
|
128
|
+
# run nagios check
|
129
|
+
res, message = lnbackup.nagios_check( backup_name )
|
130
|
+
puts message
|
131
|
+
|
132
|
+
elsif nagios_all
|
133
|
+
# run nagios check
|
134
|
+
res, message = lnbackup.nagios_check_all
|
135
|
+
puts message
|
136
|
+
|
137
|
+
elsif mount
|
138
|
+
# mount backup ro
|
139
|
+
return res if (res = lnbackup.config_init(backup_name)) != 0
|
140
|
+
lnbackup.mount_backup(false)
|
141
|
+
|
142
|
+
elsif mountrw
|
143
|
+
# mount backup rw
|
144
|
+
return res if (res = lnbackup.config_init(backup_name)) != 0
|
145
|
+
lnbackup.mount_backup
|
146
|
+
|
147
|
+
elsif umount
|
148
|
+
# umount backup
|
149
|
+
return res if (res = lnbackup.config_init(backup_name)) != 0
|
150
|
+
lnbackup.umount_backup(true)
|
151
|
+
|
152
|
+
elsif mirror_only
|
153
|
+
# create only bootable mirror
|
154
|
+
return res if (res = lnbackup.config_init(backup_name)) != 0
|
155
|
+
return lnbackup.mirror_only( backup_name )
|
156
|
+
|
157
|
+
elsif backup
|
158
|
+
# run backup
|
159
|
+
res = lnbackup.go_backup( backup_name, no_mirror )
|
160
|
+
|
161
|
+
elsif pc_backup
|
162
|
+
# run PCs backup -- backup PCs over cifs
|
163
|
+
lnbackup.backup_pcs( pcs_status_f, no_delete )
|
164
|
+
|
165
|
+
elsif pc_test
|
166
|
+
# run PCs backup test -- test if shares for backup are accessible
|
167
|
+
lnbackup.backup_pcs_test
|
168
|
+
|
169
|
+
elsif init_crypto
|
170
|
+
# initialize crypto device
|
171
|
+
lnbackup.crypto_init(crypto_size)
|
172
|
+
|
173
|
+
elsif pcs_status
|
174
|
+
lnbackup.backup_pcs_status( pcs_status_f )
|
175
|
+
|
176
|
+
else
|
177
|
+
puts "Ups, we should never get here!"
|
178
|
+
exit(1)
|
179
|
+
end
|
180
|
+
|
181
|
+
return res
|
182
|
+
end
|
183
|
+
|
184
|
+
if $0 == __FILE__
|
185
|
+
exit go
|
186
|
+
end
|
187
|
+
|
data/bin/lnmount
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
if [ "$1" == "--help" ]; then
|
4
|
+
echo "usage: $0 [--rw] [lnbackup arguments]"
|
5
|
+
echo
|
6
|
+
echo "shortcut for mounting lnbackup backups"
|
7
|
+
exit 0
|
8
|
+
fi
|
9
|
+
|
10
|
+
if [ "$1" == "--rw" -o "$1" == "--mountrw" ]; then
|
11
|
+
shift
|
12
|
+
/usr/sbin/lnbackup --mountrw --log-file - "$@"
|
13
|
+
else
|
14
|
+
/usr/sbin/lnbackup --mount --log-file - "$@"
|
15
|
+
fi
|
16
|
+
|
data/bin/lnstat
ADDED
data/bin/lnumount
ADDED
data/bin/pc_backup
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
. /etc/default/lnbackup-pc
|
4
|
+
|
5
|
+
if [ -z "$BACKUP_HOSTS" ]; then
|
6
|
+
exit
|
7
|
+
fi
|
8
|
+
|
9
|
+
echo -n 'starting at '
|
10
|
+
date
|
11
|
+
|
12
|
+
if [ -z "$1" ]; then
|
13
|
+
echo "running in FULL mode"
|
14
|
+
|
15
|
+
for HOST in $BACKUP_HOSTS; do
|
16
|
+
umount $MOUNTS_ROOT/$HOST >/dev/null 2>&1
|
17
|
+
mkdir -p $MOUNTS_ROOT/$HOST
|
18
|
+
echo -n "trying $HOST ... "
|
19
|
+
|
20
|
+
#echo mount -t smb -o username=$BACKUP_USER,password=$BACKUP_PASSWORD,workgroup=$BACKUP_WORKGROUP //$HOST/$BACKUP_SHARE $MOUNTS_ROOT/$HOST
|
21
|
+
if mount -t smb -o username=$BACKUP_USER,password=$BACKUP_PASSWORD,workgroup=$BACKUP_WORKGROUP //$HOST/$BACKUP_SHARE $MOUNTS_ROOT/$HOST >/dev/null 2>&1 &&
|
22
|
+
ls /mnt/pc_backups/$HOST >/dev/null 2>&1; then
|
23
|
+
|
24
|
+
echo "passed"
|
25
|
+
#mkdir -p $BACKUPS_ROOT/$HOST/
|
26
|
+
$LNBACKUP --backup -l $LOG_DIR/$HOST-lnbackup.log \
|
27
|
+
--source-prefix=$MOUNTS_ROOT/$HOST/ \
|
28
|
+
--target-dir-name=windows/$HOST --backup-name=windows \
|
29
|
+
--status-file-pref=$STATUS_DIR/$HOST.status
|
30
|
+
# --force-target=$BACKUPS_ROOT/$HOST/ --backup-name=windows \
|
31
|
+
else
|
32
|
+
echo "failed"
|
33
|
+
fi
|
34
|
+
umount $MOUNTS_ROOT/$HOST >/dev/null 2>&1
|
35
|
+
done
|
36
|
+
else
|
37
|
+
# echo "running in TEST mode"
|
38
|
+
#
|
39
|
+
# for HOST in $BACKUP_HOSTS; do
|
40
|
+
# echo -n "trying $HOST ... "
|
41
|
+
# if mount -t smb -o username=backup,password=luroj3op,workgroup=is //$HOST/is /mnt/pc_backups/$HOST >/dev/null 2>&1 &&
|
42
|
+
# ls /mnt/pc_backups/$HOST >/dev/null 2>&1; then
|
43
|
+
# echo "passed"
|
44
|
+
# else
|
45
|
+
# echo "failed"
|
46
|
+
# fi
|
47
|
+
# umount /mnt/pc_backups/$HOST >/dev/null 2>&1
|
48
|
+
# done
|
49
|
+
#fi
|
50
|
+
echo "running in TEST mode"
|
51
|
+
|
52
|
+
for HOST in $BACKUP_HOSTS; do
|
53
|
+
echo -n "trying $HOST ... "
|
54
|
+
#echo smbclient -c "''" -W $BACKUP_WORKGROUP //$HOST/$BACKUP_SHARE -U $BACKUP_USER%$BACKUP_PASSWORD
|
55
|
+
if smbclient -c '' -W $BACKUP_WORKGROUP //$HOST/$BACKUP_SHARE -U $BACKUP_USER%$BACKUP_PASSWORD 1>/dev/null 2>&1; then
|
56
|
+
echo "passed"
|
57
|
+
else
|
58
|
+
echo "failed"
|
59
|
+
fi
|
60
|
+
done
|
61
|
+
fi
|
62
|
+
|
63
|
+
|
64
|
+
echo -n 'finished at '
|
65
|
+
date
|
66
|
+
|
data/bin/sql_backup.sh
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
###################################### DEFINICE FUNKCI ##############################################
|
4
|
+
|
5
|
+
###################################### FUNKCE NAPOVEDA ##############################################
|
6
|
+
|
7
|
+
napoveda() {
|
8
|
+
|
9
|
+
echo "sql_backup [volby]";
|
10
|
+
echo "Volby:";
|
11
|
+
echo " --mysql Zalohovani MySQL";
|
12
|
+
echo " --postgresql Zalohovani PostgreSQL";
|
13
|
+
echo " --help Napoveda";
|
14
|
+
return 0;
|
15
|
+
}
|
16
|
+
|
17
|
+
|
18
|
+
###################################### FUNKCE ZALOHA ##############################################
|
19
|
+
|
20
|
+
zaloha() {
|
21
|
+
#kontrola a includovani souboru s vyjimkami DB ktere se nebudou zalohovat
|
22
|
+
if [ -e /etc/default/lnbackup_databases ]; then
|
23
|
+
. /etc/default/lnbackup_databases
|
24
|
+
else
|
25
|
+
SKIP_MYSQL=""; # mysql DB ktere se nebudou zalohovat
|
26
|
+
SKIP_POSTGRESQL=""; # postgre DB ktere se nebudou zalohovat
|
27
|
+
fi;
|
28
|
+
|
29
|
+
|
30
|
+
#nastaveni promenne ZALOHOVAT_DB a vlozeni template0 do SKIP_POSTGRESQL (zalohovani teto DB se defaultne preskakuje)
|
31
|
+
if [ $DUMP == "/usr/bin/pg_dump" ]; then
|
32
|
+
#pridavam defaultne template0 databazi protoze jeji zalohovani vzdy skonci s chybou (testovano na serverech emilka a hosting)
|
33
|
+
SKIP_POSTGRESQL="$SKIP_POSTGRESQL template0";
|
34
|
+
ZALOHOVAT_DB=$(diff <(printf "%s\n" ${databases[@]} | sort) <(printf "%s\n" ${SKIP_POSTGRESQL[@]} | sort) | egrep '^(<|>)' | tr -d '<> ') #vsechny DB - vzjimky DB = DB ktere se budou zalohovat
|
35
|
+
fi
|
36
|
+
|
37
|
+
|
38
|
+
#nastaveni promenne ZALOHOVAT_DB
|
39
|
+
if [ $DUMP == "/usr/bin/mysqldump" ]; then
|
40
|
+
ZALOHOVAT_DB=$(diff <(printf "%s\n" ${databases[@]} | sort) <(printf "%s\n" ${SKIP_MYSQL[@]} | sort) | egrep '^(<|>)' | tr -d '<> ') #vsechny DB -
|
41
|
+
fi
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
for database in $ZALOHOVAT_DB;do
|
46
|
+
if [ $DUMP == "/usr/bin/mysqldump" ]; then
|
47
|
+
$DUMP $database | grep -v 'Dump completed on ' | gzip --no-name > $TMP_DIR/$database.sql.gz # DUMP DB, vyjme se 'Dump completed on '(datum)pro pripad ze by byly soucasna i predchozi stejna a lisily se jen v datu
|
48
|
+
elif [ $DUMP == "/usr/bin/pg_dump" ]; then
|
49
|
+
su postgres -c "$DUMP $database | gzip --no-name > $TMP_DIR/$database.sql.gz" # su postgres je tam proto aby se dump provadel pod uzivatelem postgres
|
50
|
+
fi
|
51
|
+
|
52
|
+
#zjistit zda existuje vubec predchozi zaloha - v pripade ze ano tak porovnavat, v pripade ze ne tak to tam rovnou nahrnout
|
53
|
+
if [ -f $DST_DIR/$database.sql.gz ];then # test predchozi a soucasne DB, v pripade zmeny je stara DB prepsana, v pripade ze je stejna tak je ponechana
|
54
|
+
#ls -l $TMP_DIR/$database.sql.gz $DST_DIR/$database.sql.gz
|
55
|
+
if ! /usr/bin/diff -q $TMP_DIR/$database.sql.gz $DST_DIR/$database.sql.gz > /dev/null; then # pokud DB nejsou stejne tak prepis posledni zalohu
|
56
|
+
echo "prepisuji soubor $DST_DIR/$database.sql.gz novejsi verzi"
|
57
|
+
mv $TMP_DIR/$database.sql.gz $DST_DIR/$database.sql.gz
|
58
|
+
else
|
59
|
+
echo "mazu $TMP_DIR/$database.sql.gz" #
|
60
|
+
rm $TMP_DIR/$database.sql.gz # pokud jsou stejne tak smaze docas. adr. ktery slouzi pro porovnavani soucasne a minule DB
|
61
|
+
fi
|
62
|
+
else
|
63
|
+
mv $TMP_DIR/$database.sql.gz $DST_DIR/$database.sql.gz # pripad kdy neexistovala predchozi DB
|
64
|
+
echo "predchozi $DST_DIR/$database.sql.gz neexistovala, ukladam aktualni"
|
65
|
+
fi
|
66
|
+
done
|
67
|
+
|
68
|
+
rmdir $TMP_DIR
|
69
|
+
|
70
|
+
return 0;
|
71
|
+
}
|
72
|
+
|
73
|
+
|
74
|
+
####################################### SPUSTENI S ARGUMENTEM --mysql ###############################
|
75
|
+
if [ "${1}" == "--mysql" ]; then
|
76
|
+
if [ -x /usr/bin/mysql ]; then
|
77
|
+
|
78
|
+
MYSQL=/usr/bin/mysql
|
79
|
+
DUMP=/usr/bin/mysqldump
|
80
|
+
#TYPE=mysql
|
81
|
+
#MD5SUM=/usr/bin/md5sum
|
82
|
+
GREP=/bin/grep
|
83
|
+
DST_DIR=/var/backups/mysql
|
84
|
+
TMP_DIR=/tmp/sql
|
85
|
+
|
86
|
+
|
87
|
+
mkdir -p $TMP_DIR
|
88
|
+
mkdir -p $DST_DIR
|
89
|
+
|
90
|
+
databases=`$MYSQL -B -e 'show databases;' | $GREP -v '^Database'` # do pro menne databazes se zapisi DB ktere jsou na serveru
|
91
|
+
zaloha
|
92
|
+
else
|
93
|
+
echo "na serveru neni nainstalovano mysql";
|
94
|
+
exit 1
|
95
|
+
fi
|
96
|
+
####################################### SPUSTENI S ARGUMENTEM --postgresql ###############################
|
97
|
+
elif [ "${1}" == "--postgresql" ]; then
|
98
|
+
if [ -x /usr/bin/psql ]; then
|
99
|
+
POSTGRES=/usr/bin/psql
|
100
|
+
DUMP=/usr/bin/pg_dump
|
101
|
+
#TYPE=postgres
|
102
|
+
#MD5SUM=/usr/bin/md5sum
|
103
|
+
GREP=/bin/grep
|
104
|
+
DST_DIR=/var/backups/postgres
|
105
|
+
TMP_DIR=/tmp/postgres
|
106
|
+
|
107
|
+
mkdir -p $TMP_DIR
|
108
|
+
#pridani prav aby uzivatel postgres mohl zapisovat do cilove slozky
|
109
|
+
chmod o+w $TMP_DIR
|
110
|
+
mkdir -p $DST_DIR
|
111
|
+
#pridani prav aby uzivatel postgres mohl zapisovat do cilove slozky
|
112
|
+
chmod o+w $DST_DIR
|
113
|
+
|
114
|
+
databases=`su postgres -c "psql -l | egrep -v '(Name.*Owner.*Encoding|List of databases|----------|. rows|^$)' | cut -f 2 -d ' '"` #do databases se zapisi DB ktere jsou na serveru
|
115
|
+
zaloha
|
116
|
+
else
|
117
|
+
echo "na serveru neni nainstalovan postgresql";
|
118
|
+
exit 1
|
119
|
+
fi
|
120
|
+
######################################## SPUSTENI S NAPOVEDY (ARGUMENTEM --help) ###############################
|
121
|
+
else
|
122
|
+
napoveda
|
123
|
+
fi
|