Hide Show 38 lines of Pod
our
$VERSION
=
'1.7.0'
;
BEGIN {
Expect->
use
;
$Expect::Log_Stdout
= 0;
}
@EXPORT
=
qw(sync)
;
Hide Show 39 lines of Pod
sub
sync {
my
(
$source
,
$dest
,
$opt
) =
@_
;
my
$current_connection
= Rex::get_current_connection();
my
$server
=
$current_connection
->{server};
my
$cmd
;
my
$port
;
my
$servername
=
$server
->to_s;
(
$servername
,
$port
) =
Rex::Helper::IP::get_server_and_port(
$servername
, 22 );
my
$auth
=
$current_connection
->{conn}->get_auth;
if
( !
exists
$opt
->{download} &&
$source
!~ m/^\// ) {
$source
= Rex::Helper::Path::get_file_path(
$source
,
caller
() );
}
Rex::Logger::debug(
"Syncing $source -> $dest with rsync."
);
if
(
$Rex::Logger::debug
) {
$Expect::Log_Stdout
= 1;
}
my
$params
=
""
;
if
(
$opt
&&
exists
$opt
->{
'exclude'
} ) {
my
$excludes
=
$opt
->{
'exclude'
};
$excludes
= [
$excludes
]
unless
ref
(
$excludes
) eq
"ARRAY"
;
for
my
$exclude
(
@$excludes
) {
$params
.=
" --exclude="
.
$exclude
;
}
}
if
(
$opt
&&
exists
$opt
->{parameters} ) {
$params
.=
" "
.
$opt
->{parameters};
}
my
@rsync_cmd
= ();
if
(
$opt
&&
exists
$opt
->{
'download'
} &&
$opt
->{
'download'
} == 1 ) {
$dest
= resolv_path(
$dest
);
Rex::Logger::debug(
"Downloading $source -> $dest"
);
push
@rsync_cmd
,
"rsync -rl -e '\%s' --verbose --stats $params "
;
push
@rsync_cmd
,
"'"
.
$auth
->{user} .
"\@"
.
$servername
.
":"
.
$source
.
"'"
;
push
@rsync_cmd
,
"'$dest'"
;
}
else
{
$source
= resolv_path(
$source
);
Rex::Logger::debug(
"Uploading $source -> $dest"
);
push
@rsync_cmd
,
"rsync -rl -e '\%s' --verbose --stats $params '$source' "
;
push
@rsync_cmd
,
"'"
.
$auth
->{user} .
"\@$servername:$dest"
.
"'"
;
}
if
(Rex::is_sudo) {
push
@rsync_cmd
,
"--rsync-path='sudo rsync'"
;
}
$cmd
=
join
(
" "
,
@rsync_cmd
);
my
$pass
=
$auth
->{password};
my
@expect_options
= ();
my
$auth_type
=
$auth
->{auth_type};
if
(
$auth_type
eq
"try"
) {
if
(
$server
->get_private_key && -f
$server
->get_private_key ) {
$auth_type
=
"key"
;
}
else
{
$auth_type
=
"pass"
;
}
}
if
(
$auth_type
eq
"pass"
) {
$cmd
=
sprintf
(
$cmd
,
"ssh -o StrictHostKeyChecking=no -o PubkeyAuthentication=no -p $port"
,
);
push
(
@expect_options
,
[
qr{Are you sure you want to continue connecting}
,
sub
{
Rex::Logger::debug(
"Accepting key.."
);
my
$fh
=
shift
;
$fh
->
send
(
"yes\n"
);
exp_continue;
}
],
[
qr{password: ?$}
i,
sub
{
Rex::Logger::debug(
"Want Password"
);
my
$fh
=
shift
;
$fh
->
send
(
$pass
.
"\n"
);
exp_continue;
}
],
[
qr{password for.*:$}
i,
sub
{
Rex::Logger::debug(
"Want Password"
);
my
$fh
=
shift
;
$fh
->
send
(
$pass
.
"\n"
);
exp_continue;
}
],
[
qr{rsync error: error in rsync protocol}
,
sub
{
Rex::Logger::debug(
"Error in rsync"
);
die
;
}
],
[
qr{rsync error: remote command not found}
,
sub
{
Rex::Logger::info(
"Remote rsync command not found"
);
Rex::Logger::info(
"Please install rsync, or use Rex::Commands::Sync sync_up/sync_down"
);
die
;
}
],
);
}
else
{
if
(
$auth_type
eq
"key"
) {
$cmd
=
sprintf
(
$cmd
,
'ssh -i '
.
$server
->get_private_key
.
" -o StrictHostKeyChecking=no -p "
.
"$port"
,
$port
);
}
else
{
$cmd
=
sprintf
(
$cmd
,
'ssh -o StrictHostKeyChecking=no -p '
.
"$port"
);
}
push
(
@expect_options
,
[
qr{Are you sure you want to continue connecting}
,
sub
{
Rex::Logger::debug(
"Accepting key.."
);
my
$fh
=
shift
;
$fh
->
send
(
"yes\n"
);
exp_continue;
}
],
[
qr{password: ?$}
i,
sub
{
Rex::Logger::debug(
"Want Password"
);
my
$fh
=
shift
;
$fh
->
send
(
$pass
.
"\n"
);
exp_continue;
}
],
[
qr{Enter passphrase for key.*: $}
,
sub
{
Rex::Logger::debug(
"Want Passphrase"
);
my
$fh
=
shift
;
$fh
->
send
(
$pass
.
"\n"
);
exp_continue;
}
],
[
qr{rsync error: error in rsync protocol}
,
sub
{
Rex::Logger::debug(
"Error in rsync"
);
die
;
}
],
[
qr{rsync error: remote command not found}
,
sub
{
Rex::Logger::info(
"Remote rsync command not found"
);
Rex::Logger::info(
"Please install rsync, or use Rex::Commands::Sync sync_up/sync_down"
);
die
;
}
],
);
}
Rex::Logger::debug(
"cmd: $cmd"
);
eval
{
my
$exp
= Expect->spawn(
$cmd
) or
die
($!);
eval
{
$exp
->expect(
Rex::Config->get_timeout,
@expect_options
,
[
qr{total size is [\d,]+\s+speedup is }
,
sub
{
Rex::Logger::debug(
"Finished transfer very fast"
);
die
;
}
]
);
$exp
->expect(
undef
,
[
qr{total size is [\d,]+\s+speedup is }
,
sub
{
Rex::Logger::debug(
"Finished transfer"
);
exp_continue;
}
],
[
qr{rsync error: error in rsync protocol}
,
sub
{
Rex::Logger::debug(
"Error in rsync"
);
die
;
}
],
);
};
$exp
->soft_close;
$? =
$exp
->exitstatus;
};
if
($@) {
Rex::Logger::info($@);
}
}
1;