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
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# Copyright 2011 Justin Santa Barbara
# All Rights Reserved.
# Copyright (c) 2010 Citrix Systems, Inc.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.
import 
smtplib
import 
os,sys,time,fcntl,struct
import 
ConfigParser
import 
commands
import 
traceback
import 
socket
import 
shutil
import 
sys
import 
re
try
:
    
from 
email.mime.multipart 
import 
MIMEMultipart
except
:
    
from 
email.MIMEMultipart 
import 
MIMEMultipart
try
:
    
from 
email.mime.text 
import 
MIMEText
except
:
    
from 
email.MIMEText 
import 
MIMEText
try
:
    
from 
hashlib 
import 
md5
except
:
    
from 
md5 
import 
md5
CONFIG_PATH 
= 
"/etc/rsyncd.conf"
def 
_load_cfg(section 
= 
None
):
    
'''
    
load config section from CONFIG_PATH
    
'''
    
global 
CONFIG_PATH
    
config 
= 
ConfigParser.ConfigParser()
    
if 
os.path.isfile(CONFIG_PATH):
        
config.read(CONFIG_PATH)
        
sections 
= 
config.sections()
        
if 
section 
and 
section 
in 
sections:
            
return 
dict
(config.items(section))
        
elif 
not 
section:
            
rst 
= 
dict
()
            
for 
sec 
in 
sections:
                
rst[sec] 
= 
dict
(config.items(sec))
            
return 
rst
        
else
:
            
return 
dict
()
def 
load_cfg(sections 
= 
[]):
    
'''
    
from cfg format to dict
    
:params sections The section list in cfg
    
return a dict with all options
    
'''
    
rst 
= 
dict
()
    
if 
not 
sections:
        
return 
_load_cfg()
    
for 
sec 
in 
sections:
        
rst[sec] 
= 
_load_cfg(sec)
    
return 
rst
def 
logging(item,level,mes):
    
logpath 
= 
'/var/log/kxtools/'
    
if 
not 
os.path.exists(logpath):
        
os.makedirs(logpath)
    
fp 
= 
open
(
'%s/kxbackup.log'
%
logpath,
'a'
)
    
fp.write(
'%s - %s - %s - %s \n'
%
(time.ctime(),item,level,mes))
    
fp.close()
"""Access file md5 value"""
def 
MD5(fname):
    
filemd5 
= 
""
    
try
:
        
file 
= 
open
(fname, 
"rb"
)
        
md5f 
= 
md5()
        
strs 
= 
""
        
while 
True
:
            
strs 
= 
file
.read(
8096
)
            
if 
not 
strs:
                
break
            
md5f.update(strs)
        
filemd5 
= 
md5f.hexdigest()
        
file
.close()
        
return 
filemd5
    
except
:
        
logging(
'MySQL Check'
,
'ERROR'
,traceback.format_exc())
def 
get_em_ipaddr(dev):
    
= 
socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    
IP 
= 
socket.inet_ntoa(fcntl.ioctl(
           
s.fileno(),
           
0x8915
,  
# SIOCGIFADDR
           
struct.pack(
'24s'
,dev)
    
)[
20
:
24
])
    
return 
IP
def 
ipaddr():
    
"""
    
Get host name, ip
    
return(hostname, ip)
    
"""
    
def 
_get_ipaddr():
        
try
:
            
= 
socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            
s.connect((
"8.8.8.8"
8000
))
            
return 
s.getsockname()[
0
]
        
except
:
            
logging(
'MySQL Check'
,
'ERROR'
,traceback.format_exc())
        
s.close()
    
return 
(socket.gethostname(), _get_ipaddr())
def 
tracert(ip):
    
count 
= 
0
    
for 
in 
range
(
10
):
        
sock
=
socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        
sock.settimeout(
10
)
        
try
:
            
sock.connect((ip,
873
))
            
count 
+
= 
1
        
except 
socket.error,e:
            
pass
        
time.sleep(
1
)
    
if 
count >
= 
6
:
        
return 
0
    
else
:
        
return 
1
class  
SendMail(
object
):
    
def 
__init__ (
self
):
        
self
.smtpserver 
= 
'smtp.163.com'
        
self
.fro 
= 
'kxbackup@163.com'
        
self
.c_code 
= 
'UTF-8'
        
self
.port 
= 
25
        
self
.auth 
= 
'kxbackup@163.com'
        
self
.pawd 
= 
'11111111@123'
    
''' Send Email'''
    
def 
sendmail(
self
,to,subject,content,cc
=
'',files
=
[]):
        
msg 
= 
MIMEMultipart()
        
msg[
'Subject'
= 
subject
        
txt 
= 
MIMEText(content)
        
msg.attach(txt)
        
hd 
= 
smtplib.SMTP(
self
.smtpserver,
self
.port)
        
hd.ehlo()
        
hd.starttls()
        
hd.ehlo()
        
if 
self
.auth 
and 
self
.pawd:
            
hd.login(
self
.auth,
self
.pawd)
        
for 
in 
to.split(
","
):
            
hd.sendmail(
self
.fro,t, msg.as_string())
        
if 
cc:
            
for 
in 
cc.split(
","
):
                
hd.sendmail(
self
.fro,t, msg.as_string())
        
hd.close()
class 
CheckMySQL(
object
):
    
def 
__init__(
self
):
        
version 
= 
1.0
    
def 
checkRsyncConfig(
self
):
        
# Rsync configuration check
        
fp 
= 
open
(
'/etc/rsyncd.conf'
,
'r'
).readlines()
        
for 
n,s 
in 
enumerate
(fp):
            
if 
=
= 
0
:
                
if 
s[
0
] !
= 
'['
:
                    
fp.insert(
0
,
'[global]\n'
)
        
= 
open
(
'/etc/rsyncd.conf'
,
'w'
)
        
f.writelines(fp)
        
f.close()
    
def 
checkFile(
self
):
        
# Directory traversal, find today compared with yesterday's file
        
backupPath  
= 
load_cfg()[
'yttx'
][
'path'
]
        
os.chdir(backupPath)
        
CTIME 
= 
time.strftime(
'%Y%m%d'
)
        
files
= 
dict
()
        
# Define the keys
        
for 
in 
os.listdir(backupPath):
            
stamp_time, file_kyes 
= 
self
._get_file_ctime(f)
            
if 
(time.time() 
- 
stamp_time) <
= 
86400
:
                
files[file_kyes] 
= 
list
()
        
# According to the date of classified documents
        
for 
in 
os.listdir(backupPath):
            
stamp_time , file_ctime 
= 
self
._get_file_ctime(f)
            
stamp_ctime 
= 
time.time()
            
for 
tm 
in 
files.keys():
                
#print file_ctime,f
                
if 
tm 
=
= 
file_ctime 
and 
(stamp_ctime 
- 
stamp_time) <
= 
86400
:
                    
files[tm].append(f)
        
# Check the file MD5
        
today_file 
=
dict
()
        
ystday_file 
= 
dict
()
        
Ttime 
= 
time.strftime(
"%Y%m%d"
)
        
Ytime 
= 
time.strftime(
"%Y%m%d"
,time.localtime((time.time() 
- 
86400
)))
        
for 
f  
in 
os.listdir(backupPath):
            
if 
Ttime 
=
=
f.split(
'_'
)[
0
]:
                
ip 
= 
f.split(
'_'
)[
1
]
                
today_file[ip]
=
f
            
elif 
Ytime 
=
= 
f.split(
'_'
)[
0
]:
                
ip 
= 
f.split(
'_'
)[
1
]
                
ystday_file[ip] 
= 
f
            
else
:
                
pass
        
# Read the latest IP list
        
backup_list 
= 
'/data0/backup_mysql.txt'
        
if 
not 
os.path.exists(backup_list):
            
utils.COMM(
"touch %s" 
%
backup_list)
        
fp 
= 
open
(
'/data0/backup_mysql.txt'
,
'r'
).readlines()
        
ips 
= 
[i.strip() 
for 
in 
fp]
        
fail_ip 
= 
list
()
        
done_ip 
= 
list
()
        
# Call Func md5
        
for 
ip 
in 
ips:
            
if 
ip  
in 
today_file:
                
if 
not 
self
._checkMD5(backupPath,today_file[ip]):
                    
fail_ip.append(ip)
                
else
:
                    
done_ip.append(ip)
            
else
:
                
fail_ip.append(ip)
        
# Determine whether is empty,
        
# If not empty, calls the SendMail class
        
done_mes 
= 
str
()
        
if 
done_ip:
            
for 
ip 
in 
done_ip:
                
done_mes 
+
= 
"host %s MySQL backup is successful \n" 
%
ip
        
done_info 
= 
"\nBackup Successful: \n" 
+ 
done_mes
        
ret 
= 
str
()
        
if 
fail_ip:
            
for 
ip 
in 
fail_ip:
                
ret 
+
= 
"host %s MySQL backup is failure \n" 
%
ip
        
mess 
= 
"\nPlease check the specific reason for the error \n" 
+ 
"E-mail : 222@222.222.com, 3333@222.222.com,444@222.2222.com \n" 
+ 
"Q Q : 11111,2222222,33333 "
        
back_time 
= 
"\nCheck Time: %s \n" 
%
time.ctime()
        
mes 
= 
done_info  
+ 
"\nBackup Failure:\n"  
+ 
ret 
+ 
back_time 
+  
mess
        
send 
= 
SendMail()
        
# Subject
        
subject 
= 
"MySQL Backup %s information" 
%
ipaddr()[
1
]
        
cc 
= 
'2222@222.222.com,333@222.222.com,444@222.222.com'
        
send.sendmail(
'kxbackup@163.com'
,subject,mes,cc
=
'')
    
def 
_checkMD5(
self
,backupPath,files):
        
file 
= 
backupPath 
+ 
'/' 
+ 
files
        
try
:
            
md5sun 
= 
file
.split(
"_"
)[
-
1
].split(
'.'
)[
0
]
        
except
:
            
return 
False
        
fmd5sun 
= 
MD5(
file
)
        
if 
fmd5sun  
=
= 
md5sun:
            
return 
True
        
else
:
            
return 
False
    
def 
_get_file_ctime(
self
,f):
        
# return time stamp, YY-MM-DD
        
st_ctime 
= 
os.stat(f).st_mtime
        
return 
st_ctime , time.strftime(
'%Y%m%d'
,time.localtime(st_ctime))
    
def 
DeleteFile(
self
):
        
# Delete file from 8 day ago
        
reserve 
= 
'/data0/reserve/'
        
if 
not 
os.path.exists(reserve):
            
os.makedirs(reserve)
        
backuPath  
= 
load_cfg()[
'yttx'
][
'path'
]
        
keep_file 
= 
list
()
        
delete_file 
= 
list
()
        
os.chdir(backuPath)
        
ctimes 
= 
time.time()
        
keep_time  
= 
691200
        
for 
in 
os.listdir(backuPath):
            
create_time 
= 
os.stat(f).st_ctime
            
if 
ctimes 
- 
create_time >
= 
keep_time:
                
try
:
                    
shutil.move(f,reserve)
                
except
:
                    
shutil.move(f,
'/dev/null'
)
                
logging(
'MySQL Check'
,
'INFO'
,
"Delete file %s"
%
f)
if 
__name__ 
=
= 
"__main__"
:
    
sc 
= 
CheckMySQL()
    
sc.checkRsyncConfig()
    
sc.checkFile()
    
sc.DeleteFile()