-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbefore_rsnapshot.py
executable file
·157 lines (134 loc) · 5.32 KB
/
before_rsnapshot.py
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
#!/usr/bin/env python3
"""
Install using a Terminal:
1. Run linux-preinstall/everyone/linuxpreinstall-rsnapshot.py
2. Add the following to rsnapshot.conf (comment any existing cmd_preexec line first then):
cmd_preexec /opt/bin/before_rsnapshot.sh
# (rsnapshot requires a tab character between the setting name and value)
- and comment any existing cmd_preexec line
"""
# formerly before-backup.sh
import os
import subprocess
import time
import sys
if __name__ == "__main__":
SCRIPTS_DIR = os.path.dirname(os.path.realpath(__file__))
REPO_DIR = os.path.dirname(SCRIPTS_DIR)
sys.path.insert(0, REPO_DIR)
from generate_exclude import main as generate_exclude_main
from linuxpreinstall import (
echo0,
)
from linuxpreinstall.logging2 import getLogger
from linuxpreinstall.more_rsnapshot import (
LOG,
settings,
IS_ROOT_MODE,
)
from linuxpreinstall.sysdirs import (
sysdirs,
)
logger = getLogger(__name__)
_, me = os.path.split(__file__)
def run_command(command, log=None):
"""Run a command and optionally log the output. Returns the
returncode of the process."""
print("[{}] Running: {}".format(command, me))
# ^ Only use stderr on error, since may be running as cron
try:
output = subprocess.check_output(command, shell=True,
stderr=subprocess.STDOUT)
if log:
with open(log, 'a') as logfile:
logfile.write(output.decode())
return 0 # Success
except subprocess.CalledProcessError as e:
if log:
with open(log, 'a') as logfile:
logfile.write("Error: {}\n".format(e.output.decode()))
return e.returncode # Return the error code
def main():
# Write date to log
with open(LOG, 'w') as logfile:
logfile.write(time.strftime('%Y-%m-%d %H:%M:%S\n'))
# Log /etc/default/cron
with open(LOG, 'a') as logfile:
logfile.write("* /etc/default/cron:\n")
with open('/etc/default/cron', 'r') as cron_file:
cron_content = cron_file.read()
for line in cron_content.splitlines():
if 'EXTRA_OPTS' in line:
logfile.write(line + '\n')
# Log syslog configuration
with open(LOG, 'a') as logfile:
logfile.write("* {}:\n".format(sysdirs['SYSLOG_CONF']))
with open(sysdirs['SYSLOG_CONF'], 'r') as syslog_file:
for line in syslog_file:
if 'cron.*' in line:
logfile.write(line)
# Check and manage mount point
subs = []
if IS_ROOT_MODE and os.path.isdir(sysdirs['PROFILES']):
subs = list(os.listdir(sysdirs['PROFILES']))
for sub in subs:
# Unmount fuse mounts of the backup drive that do not match the
# destination mountpoint.
if "{}" in settings['backup_unused_fuse_mountpoint_fmt']:
backup_unused_fuse_mountpoint = \
settings['backup_unused_fuse_mountpoint_fmt'].format(sub)
else:
backup_unused_fuse_mountpoint = \
settings['backup_unused_fuse_mountpoint_fmt']
if backup_unused_fuse_mountpoint == settings['backup_drive']:
# The fuse mountpoint is the backup drive, so don't unmount it.
continue
if os.path.isdir(os.path.join(backup_unused_fuse_mountpoint,
settings['rsnapshot_flag_dir'])):
result = run_command('umount {}'
.format(backup_unused_fuse_mountpoint),
log=LOG)
if result == 0:
with open(LOG, 'a') as logfile:
logfile.write("OK\n")
else:
with open(LOG, 'a') as logfile:
logfile.write(
"FAILED (umount {})\n"
.format(backup_unused_fuse_mountpoint))
time.sleep(1)
if subs:
time.sleep(1) # This seems to be necessary for drive to be available
if not os.path.isdir(settings['snapshot_root']):
result = run_command('mount {}'.format(settings['backup_drive']),
log=LOG)
if result != 0:
with open(LOG, 'a') as logfile:
logfile.write("[before-backup.sh] Error: mount {} failed.\n"
.format(settings['backup_drive']))
return result
# Verify rsnapshot directory
if not os.path.isdir(settings['snapshot_root']):
logger.error(
"{} is missing."
.format(settings['snapshot_root']))
return 1
# Run generate_exclude.py scripts
# sys.argv = ['generate_exclude.py', '--user']
# generate_exclude_main()
usr_cmd = 'sudo -u owner python3 /opt/bin/generate_exclude.py --user'
code = run_command(usr_cmd, log=LOG)
if code != 0:
logger.error("Failed with code {}: {}".format(code, usr_cmd))
echo0("See \"{}\"".format(LOG))
return code
print("OK: {}".format(usr_cmd))
# ^ Only use stderr on error, since may be running as cron
# run_command('sudo python3 /opt/bin/generate_exclude.py', log=LOG)
sys.argv = ['generate_exclude.py']
generate_exclude_main()
print("OK: generate_exclude_main")
# ^ Only use stderr on error, since may be running as cron
return 0
if __name__ == "__main__":
sys.exit(main())