Dieses Perl-Skript lädt nur alle veränderten Dateien über FTP auf den Server hoch.
#!/usr/bin/perl -w
use strict;
use Digest::MD5;
use File::Find;
use Data::Dumper;
use Net::FTP;
use File::Temp;
use File::Basename;
use Term::ReadKey;
my $dir = "www"; # the directory
my $dir_replace = "felektro"; # how to replace $dir in remote path
my @exclude_regexp_list = (qr{/\.svn\b}, qr{~$}, qr{^#.*#$}, qr{\.sql$}, qr{\.pl$}, qr{\.pm$}, qr{\.log$}, qr{\.out$}, qr{\.txt$}, qr{\.svg$}, qr{\.dat$}, qr{\.xcf}); # a list of regexp that get excluded
my $host = "myhost.de"
my $username = "user123"
my $password = undef; # String or undef to ask everytime
my $filelistref; # to store the data
# File::Find provides a convenient way to process a directory recursively
find(sub {
my $match = 0;
my $regexp;
# search thru exclude list
foreach $regexp (@exclude_regexp_list) {
if ($File::Find::name =~ $regexp) {
$match = 1;
last;
}
}
if($match) {
# exclude
print "E: $File::Find::name\n";
}
else {
$filelistref->{$File::Find::name} = {};
}
}, $dir);
if(!defined $password) {
print "password: ";
ReadMode 2; # password
$password = ReadLine(0);
ReadMode 1; # normal
chomp($password);
print "\n";
}
# ftp connection
my $ftp = Net::FTP->new($host) or die "ftp connection failed, stopped at $!";
$ftp->login($username, $password) or die $!; # Hier Benutzername und Password eingeben
$ftp->binary;
my $attempt = 1;
my $attempt_file = "";
foreach my $file (sort keys %{$filelistref}) {
# read and write cache file for every processed file
my $cachefile = 'update_server_cache.dat';
my $cache; # like $cache->{$file}->{'md5'}, $cache->{$file}->{'type'}
if(-e $cachefile) {
$cache = do ($cachefile) or die $!;
}
# create data structure
if(-d $file) {
print "D: " . $file . "\n";
$filelistref->{$file}->{'type'} = 'directory';
$filelistref->{$file}->{'md5'} = 'na';
}
else {
my $md5 = Digest::MD5->new;
open(FH, $file) or die $!;
binmode(FH);
$md5->addfile(*FH) or die $1;
close(FH);
$filelistref->{$file}->{'type'} = 'file';
$filelistref->{$file}->{'md5'} = $md5->hexdigest;
if ((defined $cache->{$file}->{'md5'}) and ($cache->{$file}->{'md5'} eq $filelistref->{$file}->{'md5'})) {
print "S: " . $file . "\n";
}
else {
if($attempt_file ne $file) {
$attempt_file = $file;
$attempt = 1;
}
else {
$attempt++;
}
my ($fname, $fpath) = fileparse($file);
$fpath =~ s|$dir/|$dir_replace/|;
my $seconds = 20 + (-s $file)/40000;
print "copy " . $file . " -> " . $fpath . $fname . " (" . $seconds . "s)\n";
$ftp->mkdir($fpath, 1) or die "unable to create directory '$fpath', stopped at $!"; # 1 = recursive
eval {
local $SIG{ALRM} = sub { die "timeout" };
alarm $seconds;
$ftp->put($file, "$fpath/$fname");
alarm 0;
};
if($@) {
if($@ !~ /timeout/) {
die $@;
}
undef $@;
if($attempt < 3) {
print "timed out (" . $seconds . "s)... retry (attempt " . ($attempt+1) . ")\n";
undef $ftp;
$ftp = Net::FTP->new($host) or die "ftp connection failed, stopped at $!";
$ftp->login($username, $password) or die $!;
$ftp->binary;
redo;
}
else {
die "timed out (" . $seconds . "s)... failed after " . $attempt . " attempts";
}
}
$cache->{$file} = {
'type' => 'file',
'md5' => $filelistref->{$file}->{'md5'}
};
}
# write cache file
open(FH, ">" . $cachefile) or die $!;
print FH "# generated by $0\n";
print FH "# " . localtime() . "\n";
print FH Dumper $cache;
close FH;
}
}
$ftp->quit;