如何实现lftp自动mirror

如何实现lftp自动mirror

如何实现lftp自动mirror
lftp有一个mirror的命令,可以镜像远程ftp上的目录,用这个来实现数据同步.
要求是,用脚本实现自动登录,登录后,然后执行mirror命令.
然后运行crontab,实现每天数据同步

perl如何实现呢?
之前用expect来实现,失败了
expect 为什么会失败? expect 为什么会失败?
出错提示?
就用Expect.
就用Expect
这个是perl网络编程书中例子的源代码
#!/usr/bin/perl -w
# file: ftp_mirror.pl
# Figure 6.2: Recursively mirroring an FTP directory

use strict;
use Net::FTP;
use File::Path;
use Getopt::Long;

use constant USAGEMSG => <<USAGE;
Usage: ftp_mirror.pl [options] host:/path/to/directory
Options:
--user <user> Login name
--pass <pass> Password
--hash Progress reports
--verbose Verbose messages
USAGE

my ($USERNAME,$PASS,$VERBOSE,$HASH);

die USAGEMSG unless GetOptions('user=s' => \$USERNAME,
'pass=s' => \$PASS,
'hash' => \$HASH,
'verbose' => \$VERBOSE);
die USAGEMSG unless my ($HOST,$PATH) = $ARGV[0]=~/(.+):(.+)/;

my $ftp = Net::FTP->new($HOST) or die "Can't connect: $@\n";
$ftp->login($USERNAME,$PASS) or die "Can't login: ",$ftp->message;
$ftp->binary;
$ftp->hash(1) if $HASH;

do_mirror($PATH);

$ftp->quit;
exit 0;

# top-level entry point for mirroring.
sub do_mirror {
my $path = shift;

return unless my $type = find_type($path);

my ($prefix,$leaf) = $path =~ m!^(.*?)([^/]+)/?$!;
$ftp->cwd($prefix) if $prefix;

return get_file($leaf) if $type eq '-'; # ordinary file
return get_dir($leaf) if $type eq 'd'; # directory

warn "Don't know what to do with a file of type $type. Skipping.";
}

# mirror a file
sub get_file {
my ($path,$mode) = @_;
my $rtime = $ftp->mdtm($path);
my $rsize = $ftp->size($path);
$mode = (parse_listing($ftp->dir($path)))[2] unless defined $mode;

my ($lsize,$ltime) = stat($path) ? (stat(_))[7,9] : (0,0);
if ( defined($rtime) and defined($rsize)
and ($ltime >= $rtime)
and ($lsize == $rsize) ) {
warn "Getting file $path: not newer than local copy.\n" if $VERBOSE;
return;
}

warn "Getting file $path\n" if $VERBOSE;
$ftp->get($path) or (warn $ftp->message,"\n" and return);
chmod $mode,$path if $mode;
}

# mirror a directory, recursively
sub get_dir {
my ($path,$mode) = @_;
my $localpath = $path;
-d $localpath or mkpath $localpath or die "mkpath failed: $!";
chdir $localpath or die "can't chdir to $localpath: $!";
chmod $mode,'.' if $mode;

my $cwd = $ftp->pwd or die "can't pwd: ",$ftp->message;
$ftp->cwd($path) or die "can't cwd: ",$ftp->message;

warn "Getting directory $path/\n" if $VERBOSE;

foreach ($ftp->dir) {
next unless my ($type,$name,$mode) = parse_listing($_);
next if $name =~ /^(\.|\.\.)$/; # skip . and ..
get_dir ($name,$mode) if $type eq 'd';
get_file($name,$mode) if $type eq '-';
make_link($name) if $type eq 'l';
}

$ftp->cwd($cwd) or die "can't cwd: ",$ftp->message;
chdir '..';
}

# subroutine to determine whether a path is a directory or a file
sub find_type {
my $path = shift;
my $pwd = $ftp->pwd;
my $type = '-'; # assume plain file
if ($ftp->cwd($path)) {
$ftp->cwd($pwd);
$type = 'd';
}
return $type;
}

# Attempt to mirror a link. Only works on relative targets.
sub make_link {
my $entry = shift;
my ($link,$target) = split /\s+->\s+/,$entry;
return if $target =~ m!^/!;
warn "Symlinking $link -> $target\n" if $VERBOSE;
return symlink $target,$link;
}

# parse directory listings
# -rw-r--r-- 1 root root 312 Aug 1 1994 welcome.msg
sub parse_listing {
my $listing = shift;
return unless my ($type,$mode,$name) =
$listing =~ /^([a-z-])([a-z-]{9}) # -rw-r--r--
\s+\d* # 1
(?:\s+\w+){2} # root root
\s+\d+ # 312
\s+\w+\s+\d+\s+[\d:]+ # Aug 1 1994
\s+(.+) # welcome.msg
$/x;
return ($type,$name,filemode($mode));
}

# turn symbolic modes into octal
sub filemode {
my $symbolic = shift;
my (@modes) = $symbolic =~ /(...)(...)(...)$/g;
my $result;
my $multiplier = 1;
while (my $mode = pop @modes) {
my $m = 0;
$m += 1 if $mode =~ /[xsS]/;
$m += 2 if $mode =~ /w/;
$m += 4 if $mode =~ /r/;
$result += $m * $multiplier if $m > 0;
$multiplier *= 8;
}
$result;
}
看看这个有没有用
use Net::Telnet ();
$telnet = new Net::Telnet (Timeout => 30,
Prompt => '/\>/'); #注意prompt 设置
$telnet->open("address");
$telnet->login("user","passwd");
$telnet->cmd("mirror");
$telnet->cmd("crontab");