Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
liblongpath-rsync
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
liblongpath
liblongpath-rsync
Commits
76181461
Commit
76181461
authored
Oct 11, 2008
by
Wayne Davison
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added a fully atomic update if the user has setup a symlink
to a *-1 or *-2 directory. A few other minor improvements.
parent
2c11e80e
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
56 additions
and
24 deletions
+56
-24
atomic-rsync
support/atomic-rsync
+56
-24
No files found.
support/atomic-rsync
View file @
76181461
...
...
@@ -6,35 +6,49 @@
# more details and some important caveats!**
use
strict
;
use
warnings
;
use
Cwd
'abs_path'
;
my
$RSYNC_PROG
=
'/usr/bin/rsync'
;
my
$RM_PROG
=
'/bin/rm'
;
my
$dest_dir
=
$ARGV
[
-
1
];
usage
(
1
)
if
$dest_dir
eq
''
||
$dest_dir
=~
/^--/
;
&
usage
if
!
defined
$dest_dir
||
$dest_dir
=~
/(^-|^$)/
||
grep
(
/^--help/
,
@ARGV
);
$dest_dir
=~
s{(?<=.)/+$} {}
;
if
(
!-
d
$dest_dir
)
{
print
STDERR
"$dest_dir is not a directory.\n\n"
;
usage
(
1
);
die
"$dest_dir is not a directory.\nUse --help for help.\n"
;
}
if
(
@_
=
grep
(
/^--
(link|compare)-dest
/
,
@ARGV
))
{
if
(
@_
=
grep
(
/^--
[a-z]+-dest\b
/
,
@ARGV
))
{
$_
=
join
(
' or '
,
@_
);
print
STDERR
"You may not use $_ as an rsync option.\n\n"
;
usage
(
1
);
die
"You cannot use the $_ option with atomic-rsync.\nUse --help for help.\n"
;
}
my
$symlink_content
=
readlink
$dest_dir
;
# undef when a real dir
my
$dest_arg
=
$dest_dir
;
# This gives us the real destination dir, with all symlinks dereferenced.
$dest_dir
=
abs_path
(
$dest_dir
);
if
(
$dest_dir
eq
'/'
)
{
print
STDERR
'You must not use "/" as the destination directory.'
,
"\n\n"
;
usage
(
1
);
die
qq|You must not use "/" as the destination directory.\nUse --help for help.\n|
;
}
my
(
$old_dir
,
$new_dir
);
if
(
defined
$symlink_content
&&
$dest_dir
=~
/-([12])$/
)
{
my
$num
=
3
-
$1
;
$old_dir
=
undef
;
(
$new_dir
=
$dest_dir
)
=~
s/-[12]$/-$num/
;
$symlink_content
=~
s/-[12]$/-$num/
;
}
else
{
$old_dir
=
"$dest_dir~old~"
;
$new_dir
=
"$dest_dir~new~"
;
}
my
$old_dir
=
"$dest_dir~old~"
;
my
$new_dir
=
$ARGV
[
-
1
]
=
"$dest_dir~new~"
;
$ARGV
[
-
1
]
=
"$new_dir/"
;
system
(
$RM_PROG
,
'-rf'
,
$old_dir
)
if
-
d
$old_dir
;
system
(
$RM_PROG
,
'-rf'
,
$old_dir
)
if
defined
$old_dir
&&
-
d
$old_dir
;
system
(
$RM_PROG
,
'-rf'
,
$new_dir
)
if
-
d
$new_dir
;
if
(
system
(
$RSYNC_PROG
,
"--link-dest=$dest_dir"
,
@ARGV
))
{
if
(
$?
==
-
1
)
{
...
...
@@ -48,17 +62,30 @@ if (system($RSYNC_PROG, "--link-dest=$dest_dir", @ARGV)) {
exit
$?
;
}
if
(
!
defined
$old_dir
)
{
atomic_symlink
(
$symlink_content
,
$dest_arg
);
exit
;
}
rename
(
$dest_dir
,
$old_dir
)
or
die
"Unable to rename $dest_dir to $old_dir: $!"
;
rename
(
$new_dir
,
$dest_dir
)
or
die
"Unable to rename $new_dir to $dest_dir: $!"
;
exit
;
sub
atomic_symlink
{
my
(
$target
,
$link
)
=
@_
;
my
$newlink
=
"$link~new~"
;
unlink
(
$newlink
);
# Just in case
symlink
(
$target
,
$newlink
)
or
die
"Unable to symlink $newlink -> $target: $!\n"
;
rename
(
$newlink
,
$link
)
or
die
"Unable to rename $newlink to $link: $!\n"
;
}
sub
usage
{
my
(
$ret
)
=
@_
;
my
$fh
=
$ret
?
*
STDERR
:
*
STDOUT
;
print
$fh
<<EOT;
die
<<EOT;
Usage: atomic-rsync [RSYNC-OPTIONS] HOST:/SOURCE/DIR/ /DEST/DIR/
atomic-rsync [RSYNC-OPTIONS] HOST::MOD/DIR/ /DEST/DIR/
...
...
@@ -67,24 +94,29 @@ creating a new hierarchy (using hard-links to leverage the existing files),
and then swapping the new hierarchy into place. You must be pulling files
to a local directory, and that directory must already exist. For example:
mkdir /local/files-1
ln -s files-1 /local/files
atomic-rsync -av host:/remote/files/ /local/files/
This would make the transfer to the directory /local/files~new~ and then
swap out /local/files at the end of the transfer by renaming it to
/local/files~old~ and putting the new directory into its place. The
/local/files~old~ directory will be preserved until the next update, at
which point it will be deleted.
If /local/files is a symlink to a directory that ends in -1 or -2, the
copy will go to the alternate suffix and the symlink will be changed to
point to the new dir. This is a fully atomic update. If the destination
is not a symlink (or not a symlink to a *-1 or a *-2 directory), this
will instead create a directory with "~new~" suffixed, move the current
directory to a name with "~old~" suffixed, and then move the ~new~
directory to the original destination name (this double rename is not
fully atomic, but is rapid). In both cases, the prior destintaion
directory will be preserved until the next update, at which point it
will be deleted.
Do NOT
specify this command:
In all likelihood, you do NOT want to
specify this command:
atomic-rsync -av host:/remote/files /local/
... UNLESS you want the entire /local dir to be swapped out!
See the "rsync" command for its list of options. You may not use the
--link-dest or --compare-dest options (since this script uses --link-dest
to make the transfer efficient). Also, the destination directory cannot
be "/".
--link-dest, --compare-dest, or --copy-dest options (since this script
uses --link-dest to make the transfer efficient).
EOT
exit
$ret
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment