Perl supports various tests for file and directory states. Most are identical to their bash test siblings, but some additional are supported, like -M, -A and -C.
Perl is great. I'm working with it for 16 years - but still discover something new from time to time. Today, I stumbled into the MAC tests while browsing the perlvar documentation page for something completly different. I wanted to quick check $^T before using it (yes, sometime I also look up basic default variables before using them and I was right to do so, because I mixed up $^S (which might have been start time, but isn't) with $^T which is the (unix)Timestamp recoded at the start of the script).
I suddenly noticed, that $^T was referring to three one-letter-tests I didn't know. But as long as perlfunc is available, help is not far away:
-M Script start time minus file modification time, in days.
-A Same for access time.
-C Same for inode change time (Unix, may differ for other platforms)
I did some (persistent) scripts lately which are checking for updated modules they're using, but I
a) didn't have the idea to simply check their modification time against $^T
and
b) didn't ever think that special Perl tests might exist for this usage case.
But Perl is TIMTOWTDI and now I know at least three of them to check if a - for example - Gearman worker process should restart itself to reload changed modules. The shortest might be:
exit if grep { -M $_ < 0 } values %INC;
(Which doesn't cover the script itself, but all loaded modules.)
Here is a commented version of the same line:
exit if # Exit the currently running Perl script if the following condition matches...
grep { # Run the code between { and } for each item of the array given at the end
# returning those who are true
-M $_ # Compare the modification time of the filename in $_ to the start time of
# the current script and return the difference
< 0 # Return true if the -M comparison returned a value lower than zero
# (= file has been modified since script start)
}
values %INC; # Loop through the %INC hash and return all values = filenames of loaded
# modules
Any questions left?
2 Kommentare. Schreib was dazu-
reneeb
15.10.2013 13:16
Antworten
-
Sebastian
15.10.2013 14:48
Antworten
Especially when %INC can become very big, you might better use "first" from List::Util. And you might be interested in Module::Refresh that is designed for such use cases mentioned in your blogpost.
I thought about using List::Util, because I didn't want to introduce another dependeny, but you're right, it's better than grep.
Refreshing modules is dangerous, I saw many problems in various projects. Restarting the process may avoid a lot of trouble - unless you restart every second.