lnbackup 2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|