#!/usr/bin/env tclsh # snapshot - use rsync to rsync a snapshot of a directory to a remote machine # via rsync and ssh. # # Usage: snapshot directory [interval] # where interval is: one of hourly, daily, weekly, monthly # source ssh.tcl package require ssh # account@machine to run the remote set remote user@machine # location on remote to store snapshots set root /var/backup # schedule of snapshots - how many for each category array set schedule { hourly 24 daily 7 weekly 4 monthly 3 } if {[info exists argv0] && ($argv0 == [info script])} { if {[llength $argv] < 2} { puts stderr "Usage: [info script] <interval> <directory>\nwhere interval is: one of hourly, daily, weekly, monthly" exit 1 } set interval [lindex $argv 0] connect $remote # send remote our globals remotes [subst { array set schedule [list [array get schedule]] set root [file normalize $root] array get schedule }] # rotate according to schedule remote { proc rotate {interval} { global schedule global root if {![file exists $root]} { file mkdir $root } set stem [file join $root $interval] if {![file exists ${stem}.0]} { # brand new file mkdir ${stem}.0 return } # delete oldest snapshots if {[file exists $stem.$schedule($interval)]} { file delete -force $stem.$schedule($interval) } # age snapshot names for {set i $schedule($interval)} {$i > 0} {incr i -1} { if {[file exists $stem.$i]} { file rename $stem.$i $stem.[expr {$i + 1}] } } # age/link files from most recent snapshot to .1 exec /bin/cp -al $stem.0/ $stem.1/ } } remote "rotate $interval" ;# first rotate this interval's snapshot remote exit ;# clean up the rotation set stem [file join $root $interval] # rsync the local dirs to the appropriate snapshot foreach dir [lrange $argv 1 end] { set dir [file normalize $dir] set dest [file join ${stem}.0 [string map {/ @} $dir]]/ exec sudo /usr/bin/rsync -a -P -S -z --delete --numeric-ids ${dir}/ ${remote}:${dest} >@stdout 2>@stderr } }
.tclshrc in remote user's home directory.
# This goes into the remote user's home directory. Note the sudo if {[info exists argv]} { if {[lindex $argv 0] == "-c"} { fconfigure stdin -buffering none -encoding binary -translation {binary binary} fconfigure stdout -buffering none -encoding binary -translation {binary binary} eval exec sudo [lindex $argv 1] >@stdout <@stdin 2>/tmp/snapshot.err exit } }
mzgcoco: My simple backup tool on windows platform Tackup