Reputation: 6350
I have a Perl daemon which runs 24 X 7 and It is running something like this
my_program.pl > /logs/user/data.out
my_program.pl will write only in data.out file only when there is an error in the application, otherwise it will not write in it .
Now I am application which does the cleanup and check if the file is under /logs/user/
is 2 days old it deletes the file and it is not getting any error while deleting .
But the consequence of this is files being deleted and left in an open state which is causing Disk Space issue on the server.
Now what I am trying to do is to check in my cleanup program if the file is open don't delete it but i am not able to identify it as the cleanup application i have only filename and it's path .
I tried the suggestion given in the below links but nothing is helping me in that .
How do you check if a file is open using Perl? How can I check if a filehandle is open in Perl?
Could you please suggest how we can handle this condition in Perl
Upvotes: 1
Views: 372
Reputation: 132802
Instead of redirecting to a file, I think you'd get better results of sending messages to syslogd (or whatever) and letting that take care of all of the details. Those things know how to cleanup and rotate files properly.
Upvotes: 2
Reputation: 13942
The problem is outside of Perl's control; you're using your shell's redirection to redirect STDOUT to a file, so from Perl's perspective writes are going to STDOUT; it didn't set up the redirection.
From within your Perl program you can ask if -t STDOUT
to see if STDOUT has been redirected to a file or if it is a terminal. But that doesn't really capture whether that file is opened.
One way that would work would be to test lsof /logs/user/data.out
. lsof
is a shell utility, not a Perl function, so you would need to run it with backticks, qx
, or similar. That will provide output of who has a claim on that file, including the PID. So with lsof
you can determine if a file is opened, and who has it opened. If multiple entities have it opened, you'll see that too (try lsof /dev/null
for example; lots of entities will have that opened).
If lsof
doesn't return output for a file, that's because nobody has it opened.
Keep in mind, though, that if the redirection is set up externally to the script itself, it would be fragile to assume that the redirection never changes, by hard-coding that filename. It may be better to lsof based on username where the user matches the user that ran the script, and then find a file that matches expectations.
The lsof -u [UID or USERNAME]
command would list only those files open by a specific user. You could combine that with $<
to run against the script-running user:
my $lsof_output = `lsof -u $< $path`;
Then examine the output for files opened by the same pid: $$
.
For completeness, I'll mention there's a Perl module on CPAN called Unix::Lsof which handles the details of parsing through lsof output for you.
Upvotes: 3