-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdirectory_monitor.pl
More file actions
148 lines (130 loc) · 4.6 KB
/
Copy pathdirectory_monitor.pl
File metadata and controls
148 lines (130 loc) · 4.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/perl
# Monitors a directory for file changes.
#
# Usage: directory_monitor.pl <directory>
#
# -- http://www.nooblet.org/blog
# -------------------------------------------------------------------------------------------------------------
## Default directory to be monitored.
my $directory = "/tmp/";
## How long to sleep between checks, in seconds
my $sleeptime = 1;
# -------------------------------------------------------------------------------------------------------------
use POSIX qw(ceil floor);
$| = 1;
# Directory on command-line
if ($#ARGV >= 0) { $directory = join(' ', @ARGV); }
# Directories need to have a trailing slash
if (substr($directory,-1) ne "/") { $directory .= "/"; }
# Check if the directory exists
if (!-e $directory) {
print STDERR "'$directory' does not exist.\n";
exit(-1);
}
# Store file info here
my %data;
# individual file statistics placed in this global array
my @gstat;
# begin
print "\nMonitoring directory: ".$directory."\n";
print "\t(ctrl+c to halt)\n\n";
# loop forever
while (true) {
my $first = 0;
# Get directory handle
opendir(DIR, $directory) or die "Unable to open directory, $directory : $!";
# And loop through the contents
while (defined(my $filename = readdir(DIR))) {
# We only want files, not sub-directories
if (-d $directory.$filename) { next; }
# Get inode statistics
@gstat = &getstat($filename);
# If this is the first time it is being run, don't want to spam that every file is new, just add it to the hash
if (!scalar(%data)) { $first = 1; &update($filename); }
# subsequent files are added on first run
elsif ($first == 1) { &update($filename); }
# Not first run, and new file found
elsif (!scalar($data{$filename})) { &doPrint($filename, "Created. [".&printBytes($gstat[7])."]"); &update($filename); }
# The size has changed
elsif ($data{$filename}{'size'} != $gstat[7]) {
my $increase = $gstat[7] - $data{$filename}{'size'};
my $text = "Size changed to ".&printBytes($gstat[7]);
if ($increase > 0) { $text .= " (up ".&printBytes($increase).")"; }
elsif ($increase < 0) { $text .= " (down ".&printBytes($increase * -1).")"; }
&doPrint($filename, $text);
&update($filename);
}
# The modified time has changed
elsif ($data{$filename}{'mtime'} != $gstat[9]) {
&doPrint($filename, "Modified, size unchanged");
&update($filename);
}
}
# Clean up the directory handle
closedir(DIR);
# Check for files in the hash which are no longer in the directory
foreach $key (keys %data) {
if (! -e $directory.$key) {
&doPrint($key, "Deleted. Last modified at ".readTime($data{$key}{'mtime'})." (".&duration(time() - $data{$key}{'mtime'}).") [".&printBytes($data{$key}{'size'})."]");
delete($data{$key});
}
}
# Sleep for a bit, else it eats up the CPU
sleep($sleeptime);
}
# returns the time in the format <year><month><day>.<hour><minute><second> .. hardly readable but concise
sub readTime {
my ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime(shift(@_));
my $time = (1900+ $yearOffset).sprintf("%02d", $month).sprintf("%02d", $dayOfMonth).".".sprintf("%02d", $hour).sprintf("%02d", $minute).sprintf("%02d", $second);
return $time;
}
# Print out a file change in a consistent format
sub doPrint {
my $fn = shift(@_);
my $t = shift(@_);
my $time = readTime(time());
print $time." : ".$fn."\t".$t."\n";
}
# Takes bytes are returns kilobytes, megabytes, gigabyte values instead based on set limits
sub printBytes {
my $bytes = shift(@_);
if ($bytes <= 4096) { return $bytes."b"; }
$bytes = sprintf("%.2f",$bytes / 1024);
if ($bytes <= 1024) { return $bytes."k"; }
$bytes = sprintf("%.2f",$bytes / 1024);
if ($bytes <= 1024) { return $bytes."m"; }
$bytes = sprintf("%.2f",$bytes / 1024);
return $bytes."g";
}
# Take number of seconds and return duration, ie. 2d 4h 5m 14s
sub duration {
my $time = shift(@_);
if ($time == 0) { return "just now"; }
my $string = "";
my $days = floor($time / 86400); $time = $time - ($days * 86400);
if ($days > 0) { $string .= $days."d "; }
my $hours = floor($time / 3600); $time = $time - ($hours * 3600);
if ($hours > 0) { $string .= $hours."h "; }
my $mins = floor($time / 60); $time = $time - ($mins * 60);
if ($mins > 0) { $string .= $mins."m "; }
my $secs = $time;
if ($secs > 0) { $string .= $secs."s "; }
$string .= "ago";
return $string;
}
# Populate array with inode statistics
sub getstat {
my $fn = $_[0];
open(FILE, $directory.$fn);
my @stat = stat(FILE);
close(FILE);
return @stat;
}
# update the has with file info
sub update {
my $fn = $_[0];
$data{$fn} = {
size => $gstat[7],
mtime => $gstat[9],
};
}