Skip to content
42 changes: 28 additions & 14 deletions time-machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

__license__ = 'GNU GPL v2'
__copyright__ = '2016, Chen Wei <weichen302@gmail.com>'
__version__ = '0.0.2'
__version__ = '0.0.3'

import os
import sys
Expand Down Expand Up @@ -52,6 +52,9 @@
'--itemize-changes',
'--progress',
'--relative',
'--perms',
'--owner',
'--group'
)
# '--perms',
# '--partial',
Expand Down Expand Up @@ -178,28 +181,29 @@ def take_snapshot():

elif len(snapshots) > 0 and not os.path.exists(latest):
if os.path.lexists(latest):
logger('Error, the "latest" symbol link is broken. Remove'
' "latest" and recreate that link by run:\n'
'ln -fs yyyy-mm-dd_HH:MM:SS_GMT latest')
os.remove(latest)
logger('Error, the "latest" symbol link is broken and will be recreated empty for next backup...')
else:
logger('Error, cannot find the last snapshot, maybe the "latest" '
'symbol link has been deleted. Please create that link by '
'run:\nln -s yyyy-mm-dd_HH:MM:SS_GMT latest')
'symbol link has been deleted. We will recreate it empty for next backup...')
os.mkdir(backup_dst)
os.symlink(backup_dst, latest)
exit(2)

else: # len(snapshots) == 0
if os.path.lexists(latest):
os.remove(latest)

if not os.path.exists(backup_dst):
os.mkdir(backup_dst)

args.extend(cfg['sources'])
args.append(backup_dst)

ret = run_rsync(args)
if ret == 0:
if os.path.exists(latest):
os.remove(latest)

os.symlink(backup_dst, latest)
if os.path.exists(latest):
os.remove(latest)
os.symlink(backup_dst, latest)

return now

Expand Down Expand Up @@ -414,10 +418,10 @@ def get_config(conf):
source_paths = config.get('source', 'path')

if source_host and source_user: # ssh remote
cfg['sources'] = ['%s@%s:%s' % (source_user, source_host, p)
cfg['sources'] = ['%s@%s:%s/' % (source_user, source_host, p)
for p in source_paths]
elif source_host and not source_user: # ssh username in .ssh/config
cfg['sources'] = ['%s:%s' % (source_host, p)
cfg['sources'] = ['%s:%s/' % (source_host, p)
for p in source_paths]
else: # local path
cfg['sources'] = source_paths
Expand Down Expand Up @@ -497,6 +501,11 @@ def print_fs_stat(stat):
logger(' free inodes: %s, %.1f%% used' % (
humanize_inodes(inodes_free), inodes_used))

def size_dir(dir):
return int(subprocess.check_output(['du','-s', dir]).split()[0].decode('utf-8')) * 1024

def print_snaps_stat(stat):
logger(' used space by snapshot(s): %s' % (humanize_bytes(stat)))

def check_freespace(stat):
''' abort backup if not enough free space or inodes '''
Expand Down Expand Up @@ -537,6 +546,7 @@ def main():
sys.exit(2)

stat_before = os.statvfs(cfg['dest_path'])
#stat_snaps_before = size_dir(cfg['dest_path'])
check_freespace(stat_before)

t_start = datetime.now()
Expand All @@ -550,13 +560,17 @@ def main():

# report
stat_after = os.statvfs(cfg['dest_path'])
#stat_snaps_after = size_dir(cfg['dest_path'])
logger('Filesystem before backup:')
print_fs_stat(stat_before)
#print_snaps_stat(stat_snaps_before)
logger('Filesystem after backup:')
print_fs_stat(stat_after)

#print_snaps_stat(stat_snaps_after)
t_used = datetime.now() - t_start
#s_used_diff = stat_snaps_after - stat_snaps_before
logger('Backup runtime: %s' % str(t_used).split('.')[0])
#logger('Backup snapshots(s) space diff before/after: %s' % str(humanize_bytes(s_used_diff)))
flock_release(fd)


Expand Down