Line 1... |
Line 1... |
1 |
#! /usr/bin/env perl
|
1 |
#! /usr/bin/env perl
|
2 |
|
2 |
|
3 |
# archvieProjects.pl
|
3 |
# archiveDirectorys.pl
|
4 |
# Author: R. W. Rodolico
|
4 |
# Author: R. W. Rodolico
|
5 |
# Date: 20180603
|
5 |
# Date: 20180603
|
6 |
# Copyright: 2018, Vanduzen Enterprises, Dallas TX
|
6 |
# Copyright: 2018, Vanduzen Enterprises, Dallas TX
|
7 |
|
7 |
|
8 |
# Script designed to be run from a cron job, which checks if any projects
|
8 |
# Script designed to be run from a cron job, which checks if any directorys
|
9 |
# are ready to be archived. A project is defined as a directory under
|
9 |
# are ready to be archived. A directory is defined as a directory under
|
10 |
# the root of $localProjectDirectory.
|
10 |
# the root of $localDirectoryDirectory.
|
11 |
|
11 |
|
12 |
# If found, all directories are moved into the staging area and
|
12 |
# If found, all directories are moved into the staging area and
|
13 |
# an md5 checksum is calculated for the entire tree.
|
13 |
# an md5 checksum is calculated for the entire tree.
|
14 |
# After all projects are moved, a second process looks in the staging
|
14 |
# After all directorys are moved, a second process looks in the staging
|
15 |
# area and copies the files (using rsync for reliability) into the staging
|
15 |
# area and copies the files (using rsync for reliability) into the staging
|
16 |
# area of $targetServer. When a project has been copied, a checksum is
|
16 |
# area of $targetServer. When a directory has been copied, a checksum is
|
17 |
# calculated on the remote copy and compared to the checksum calculated
|
17 |
# calculated on the remote copy and compared to the checksum calculated
|
18 |
# in the first stage and, if it passes, the project is then moved to the
|
18 |
# in the first stage and, if it passes, the directory is then moved to the
|
19 |
# $targetProjectDirectory.
|
19 |
# $targetDirectoryDirectory.
|
20 |
# After the copy and move, the project and its MD5 sum file are moved
|
20 |
# After the copy and move, the directory and its MD5 sum file are moved
|
21 |
# to the $trashDirectory (which is cleaned on the next invocation of
|
21 |
# to the $trashDirectory (which is cleaned on the next invocation of
|
22 |
# the script).
|
22 |
# the script).
|
23 |
|
23 |
|
24 |
# Script does NOT handle the situation where projects are being moved
|
24 |
# Script does NOT handle the situation where directorys are being moved
|
25 |
# while the script is running, so the script should be run at a time
|
25 |
# while the script is running, so the script should be run at a time
|
26 |
# when there is no other activity on the server.
|
26 |
# when there is no other activity on the server.
|
27 |
#
|
27 |
#
|
28 |
# Version: 1.0
|
28 |
# Version: 1.0
|
29 |
|
29 |
|
Line 31... |
Line 31... |
31 |
use strict;
|
31 |
use strict;
|
32 |
use Cwd qw();
|
32 |
use Cwd qw();
|
33 |
use File::Copy qw(move);
|
33 |
use File::Copy qw(move);
|
34 |
use File::Basename;
|
34 |
use File::Basename;
|
35 |
|
35 |
|
- |
|
36 |
# location where directorys are put by end users
|
36 |
my $localProjectDirectory = '/home/samba/transfers/denver_to_dallas/Archive_to_DaVinci';
|
37 |
my $localDirectoryDirectory = '/home/samba/transfers/denver_to_dallas/Archive_to_DaVinci';
|
- |
|
38 |
# location where directories are moved while processing
|
37 |
my $trashDirectory = "$localProjectDirectory/.Trash";
|
39 |
my $rootWorkDirectory = '/home/transfer_work_area';
|
- |
|
40 |
# location where directories are moved when job is completed
|
38 |
my $stagingArea = "$localProjectDirectory/.Staging";
|
41 |
my $trashDirectory = "$localDirectoryDirectory/.Trash";
|
39 |
my $targetProjectDirectory = '/home/samba/archives/fromDenver/';
|
42 |
# location where directories are moved while being transferred
|
40 |
my $targetStagingArea = '/home/samba/archives/fromDenver/.Staging/';
|
43 |
my $stagingArea = "$localDirectoryDirectory/.Staging";
|
- |
|
44 |
# target server name/ip. Must be accessible via ssh with no password
|
41 |
my $targetServer = 'davinci';
|
45 |
my $targetServer = 'davinci';
|
- |
|
46 |
# location on target server where directories are placed while copying
|
- |
|
47 |
my $targetStagingArea = '/home/samba/archives/fromDenver/.Staging/';
|
- |
|
48 |
# location on target server where directories are finally put
|
- |
|
49 |
my $targetDirectoryDirectory = '/home/samba/archives/fromDenver/';
|
- |
|
50 |
# suffix of md5 of directories
|
42 |
my $md5suffix = '.md5sum';
|
51 |
my $md5suffix = '.md5sum';
|
43 |
|
52 |
|
44 |
my @ProjectsToMove;
|
53 |
my @DirectorysToMove;
|
45 |
|
54 |
|
46 |
# look in the projects to move directory and see if there is anything
|
55 |
# look in the directorys to move directory and see if there is anything
|
47 |
# new in there.
|
56 |
# new in there.
|
48 |
sub getProjects {
|
57 |
sub getDirectorys {
|
49 |
my $rootDir = shift;
|
58 |
my $rootDir = shift;
|
50 |
opendir( my $dh, $rootDir ) or die "Could not open directory $rootDir: $!\n";
|
59 |
opendir( my $dh, $rootDir ) or die "Could not open directory $rootDir: $!\n";
|
51 |
my @dirs = grep { ! /^\./ && -d "$rootDir/$_" } readdir( $dh );
|
60 |
my @dirs = grep { ! /^\./ && -d "$rootDir/$_" } readdir( $dh );
|
52 |
return @dirs;
|
61 |
return @dirs;
|
53 |
}
|
62 |
}
|
Line 66... |
Line 75... |
66 |
my $md5 = `find '$directory' -type f -exec md5sum \\{\\} \\; | cut -d' ' -f1 | sort | md5sum | cut -d' ' -f1`;
|
75 |
my $md5 = `find '$directory' -type f -exec md5sum \\{\\} \\; | cut -d' ' -f1 | sort | md5sum | cut -d' ' -f1`;
|
67 |
chomp $md5;
|
76 |
chomp $md5;
|
68 |
return $md5;
|
77 |
return $md5;
|
69 |
}
|
78 |
}
|
70 |
|
79 |
|
71 |
# moves project to staging area and puts the md5 sum into a file
|
80 |
# moves directory to staging area and puts the md5 sum into a file
|
72 |
# with the same name, but a .md5sum suffix
|
81 |
# with the same name, but a .md5sum suffix
|
73 |
sub moveToStaging {
|
82 |
sub moveToStaging {
|
74 |
my ( $project, $stagingArea, $md5 ) = @_;
|
83 |
my ( $directory, $stagingArea, $md5 ) = @_;
|
75 |
mkdir $stagingArea unless -d $stagingArea;
|
84 |
mkdir $stagingArea unless -d $stagingArea;
|
76 |
move( "$localProjectDirectory/$project", "$stagingArea/$project" );
|
85 |
move( "$localDirectoryDirectory/$directory", "$stagingArea/$directory" );
|
77 |
my $md5File = "$stagingArea/$project" . $md5suffix;
|
86 |
my $md5File = "$stagingArea/$directory" . $md5suffix;
|
78 |
open DATA,">$md5File" or die "Could not create md5sum file [$md5File]: $!\n";
|
87 |
open DATA,">$md5File" or die "Could not create md5sum file [$md5File]: $!\n";
|
79 |
print DATA "$md5\n";
|
88 |
print DATA "$md5\n";
|
80 |
close DATA;
|
89 |
close DATA;
|
81 |
return;
|
90 |
return;
|
82 |
}
|
91 |
}
|
83 |
|
92 |
|
84 |
# verifies the project is correct on the server by comparing the checksums
|
93 |
# verifies the directory is correct on the server by comparing the checksums
|
85 |
# calculated locally and remote server. If valid, moves it into the final
|
94 |
# calculated locally and remote server. If valid, moves it into the final
|
86 |
# location on the remote server
|
95 |
# location on the remote server
|
87 |
sub validateTarget {
|
96 |
sub validateTarget {
|
88 |
my ( $remoteServer, $remoteStaging, $remoteTarget, $project, $checksum ) = @_;
|
97 |
my ( $remoteServer, $remoteStaging, $remoteTarget, $directory, $checksum ) = @_;
|
89 |
my $md5sum = `ssh $remoteServer "find '$remoteStaging/$project' -type f -exec md5sum \\{\\} \\; | cut -d' ' -f1 | sort | md5sum | cut -d' ' -f1"`;
|
98 |
my $md5sum = `ssh $remoteServer "find '$remoteStaging/$directory' -type f -exec md5sum \\{\\} \\; | cut -d' ' -f1 | sort | md5sum | cut -d' ' -f1"`;
|
90 |
chomp $md5sum;
|
99 |
chomp $md5sum;
|
91 |
if ( $checksum eq $md5sum ) {
|
100 |
if ( $checksum eq $md5sum ) {
|
92 |
my $command = "ssh $remoteServer \"mv '$remoteStaging/$project' '$remoteTarget'\"";
|
101 |
my $command = "ssh $remoteServer \"mv '$remoteStaging/$directory' '$remoteTarget'\"";
|
93 |
if ( system( $command ) == 0 ) {
|
102 |
if ( system( $command ) == 0 ) {
|
94 |
return 1;
|
103 |
return 1;
|
95 |
} else {
|
104 |
} else {
|
96 |
&logit( "Unable to move $project to $remoteServer:$remoteTarget" );
|
105 |
&logit( "Unable to move $directory to $remoteServer:$remoteTarget" );
|
97 |
return 0;
|
106 |
return 0;
|
98 |
}
|
107 |
}
|
99 |
} else {
|
108 |
} else {
|
100 |
&logit( "Invalid checksum moving project $project" );
|
109 |
&logit( "Invalid checksum moving directory $directory" );
|
101 |
return 0;
|
110 |
return 0;
|
102 |
}
|
111 |
}
|
103 |
}
|
112 |
}
|
104 |
|
113 |
|
105 |
# reads the checksum file
|
114 |
# reads the checksum file
|
106 |
sub getCheckSum {
|
115 |
sub getCheckSum {
|
107 |
my ( $project, $staging ) = @_;
|
116 |
my ( $directory, $staging ) = @_;
|
108 |
$project .= $md5suffix;
|
117 |
$directory .= $md5suffix;
|
109 |
if ( open DATA, "<$staging/$project" ) {
|
118 |
if ( open DATA, "<$staging/$directory" ) {
|
110 |
my $cksum = <DATA>;
|
119 |
my $cksum = <DATA>;
|
111 |
chomp $cksum;
|
120 |
chomp $cksum;
|
112 |
close DATA;
|
121 |
close DATA;
|
113 |
return $cksum;
|
122 |
return $cksum;
|
114 |
}
|
123 |
}
|
115 |
&logit( "Could not open $staging/$project: $!" );
|
124 |
&logit( "Could not open $staging/$directory: $!" );
|
116 |
return '';
|
125 |
return '';
|
117 |
}
|
126 |
}
|
118 |
|
127 |
|
119 |
# simple little logger that records some information
|
128 |
# simple little logger that records some information
|
120 |
sub logit {
|
129 |
sub logit {
|
121 |
my $message = shift;
|
130 |
my $message = shift;
|
122 |
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
|
131 |
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
|
123 |
my $now = sprintf( "%04d-%02d-%02d %02d:%-2d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec );
|
132 |
my $now = sprintf( "%04d-%02d-%02d %02d:%-2d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec );
|
124 |
open LOG, ">>/tmp/archiveProjects.log" or die "could not write to archiveProjects.log: $!\n";
|
133 |
open LOG, ">>/tmp/archiveDirectorys.log" or die "could not write to archiveDirectorys.log: $!\n";
|
125 |
print LOG "$now\t$message\n";
|
134 |
print LOG "$now\t$message\n";
|
126 |
close LOG;
|
135 |
close LOG;
|
127 |
}
|
136 |
}
|
128 |
|
137 |
|
129 |
# simply remove everything from the trash directory
|
138 |
# simply remove everything from the trash directory
|
Line 131... |
Line 140... |
131 |
my $trashDir = shift;
|
140 |
my $trashDir = shift;
|
132 |
`rm -fR $trashDir/*`;
|
141 |
`rm -fR $trashDir/*`;
|
133 |
}
|
142 |
}
|
134 |
|
143 |
|
135 |
|
144 |
|
136 |
#&cleanTrash( $trashDirectory ) if &getProjectsToMove( $trashDirectory );
|
145 |
#&cleanTrash( $trashDirectory ) if &getDirectorysToMove( $trashDirectory );
|
137 |
|
146 |
|
138 |
|
147 |
|
139 |
# first, check and see if we have any projects we need to move
|
148 |
# first, check and see if we have any directorys we need to move
|
140 |
@ProjectsToMove = &getProjects( $localProjectDirectory );
|
149 |
@DirectorysToMove = &getDirectorys( $localDirectoryDirectory );
|
141 |
|
150 |
|
142 |
foreach my $project ( @ProjectsToMove ) {
|
151 |
foreach my $directory ( @DirectorysToMove ) {
|
143 |
my $md5 = &calcMD5( "$localProjectDirectory/$project" );
|
152 |
my $md5 = &calcMD5( "$localDirectoryDirectory/$directory" );
|
144 |
&logit( "New Project $md5\t$project" );
|
153 |
&logit( "New Directory $md5\t$directory" );
|
145 |
&moveToStaging( $project, $stagingArea, $md5 );
|
154 |
&moveToStaging( $directory, $stagingArea, $md5 );
|
146 |
}
|
155 |
}
|
147 |
|
156 |
|
148 |
# done with that, now we need to see if there is anything in the staging area
|
157 |
# done with that, now we need to see if there is anything in the staging area
|
149 |
# that needs to be sent to the remote server
|
158 |
# that needs to be sent to the remote server
|
150 |
opendir( my $dh, $stagingArea ) or die "Could not read $stagingArea: $!\n";
|
159 |
opendir( my $dh, $stagingArea ) or die "Could not read $stagingArea: $!\n";
|
151 |
my @directories;
|
160 |
my @directories;
|
152 |
my @toMove = grep { /$md5suffix$/ } readdir( $dh );
|
161 |
my @toMove = grep { /$md5suffix$/ } readdir( $dh );
|
153 |
foreach my $project ( @toMove ) {
|
162 |
foreach my $directory ( @toMove ) {
|
154 |
$project =~ m/^(.*)\.md5sum/;
|
163 |
$directory =~ m/^(.*)\.md5sum/;
|
155 |
$project = $1;
|
164 |
$directory = $1;
|
156 |
my $md5sum = &getCheckSum( $project, $stagingArea );
|
165 |
my $md5sum = &getCheckSum( $directory, $stagingArea );
|
157 |
next unless $md5sum;
|
166 |
next unless $md5sum;
|
158 |
my $rsync = "rsync -av '$stagingArea/$project' $targetServer:$targetStagingArea/ > /tmp/lastrsync.log";
|
167 |
my $rsync = "rsync -av '$stagingArea/$directory' $targetServer:$targetStagingArea/ > /tmp/lastrsync.log";
|
159 |
&logit( $rsync );
|
168 |
&logit( $rsync );
|
160 |
if ( system ( $rsync ) == 0 ) { # we succeeded
|
169 |
if ( system ( $rsync ) == 0 ) { # we succeeded
|
161 |
if ( &validateTarget( $targetServer, $targetStagingArea, $targetProjectDirectory, $project, $md5sum ) ) {
|
170 |
if ( &validateTarget( $targetServer, $targetStagingArea, $targetDirectoryDirectory, $directory, $md5sum ) ) {
|
162 |
`mkdir -p $trashDirectory` unless -d $trashDirectory;
|
171 |
`mkdir -p $trashDirectory` unless -d $trashDirectory;
|
163 |
move( "$stagingArea/$project", "$trashDirectory/$project" );
|
172 |
move( "$stagingArea/$directory", "$trashDirectory/$directory" );
|
164 |
$project .= $md5suffix;
|
173 |
$directory .= $md5suffix;
|
165 |
move( "$stagingArea/$project", "$trashDirectory/$project" );
|
174 |
move( "$stagingArea/$directory", "$trashDirectory/$directory" );
|
166 |
&logit( "Successfully moved project $project to $targetServer" );
|
175 |
&logit( "Successfully moved directory $directory to $targetServer" );
|
167 |
} else {
|
176 |
} else {
|
168 |
&logit( "Unable to validate target for $project" );
|
177 |
&logit( "Unable to validate target for $directory" );
|
169 |
}
|
178 |
}
|
170 |
} else {
|
179 |
} else {
|
171 |
&logit( "Unknown error attempting to rsync $project" );
|
180 |
&logit( "Unknown error attempting to rsync $directory" );
|
172 |
}
|
181 |
}
|
173 |
}
|
182 |
}
|
174 |
|
183 |
|
175 |
|
184 |
|
176 |
1;
|
185 |
1;
|