Wiggins has asked for the wisdom of the Perl Monks concerning the following question:

Upon much inspection of the real world, and internal meditation; I find I fail at determining when a file I have open has been deleted/renamed. In attempting to use the:
seek(ML, 0, 1); # reset end-of-file error
technique to 'tail' a file, I need a test to determine when the file has been closed (during log rotation, for example) and need to close/reopen the file name.
require "stat.pl"; ... for(;;) { open ML, "</var/log/local2" || die $!; &Stat(ML); $old_ML_size = $st_size; #seek(ML, 0, 2); # to EOF - Not, process from beginning for (;;){ &Stat(ML); if ($old_ML_size > $st_size) { print "closing the file\n"; last; #file closed and new one started }else{ $old_ML_size = $st_size; } while (<ML>){ another_line(); } sleep 5; seek(ML, 0, 1); # reset end-of-file error } close(ML); }
Repeated 'Stat' has not worked for me.
Must I depend upon someone else to signal me that the world has changed?

Replies are listed 'Best First'.
Re: Reading from a deleted file is futile
by Corion (Patriarch) on Feb 10, 2008 at 14:27 UTC

    See (the code of) File::Tail - basically, I think you stat your filehandle and the file name, and if you find that the inode and device node fields are different, you are allowed to conclude that you don't have the filehandle for that file name anymore.

Re: Reading from a deleted file is futile
by jrtayloriv (Pilgrim) on Feb 10, 2008 at 14:42 UTC
    On Unix, as long as you have a filehandle open for the file, it will not actually be deleted. You will just remove the entry for it in the directory. That is, you should still be able to read from it, because the data doesn't get removed from the disk until the last open filehandle is closed.

    Update: Perhaps this node will be informative as well.
Re: Reading from a deleted file is futile
by ysth (Canon) on Feb 10, 2008 at 23:03 UTC
    open ML, "</var/log/local2" || die $!;
    You've got a precedence error there. Either always use or instead of || for flow control, or always use parans around your open (and other builtin) arguments.
Re: Reading from a deleted file is futile
by dynamo (Chaplain) on Feb 12, 2008 at 12:52 UTC
    To determine whether a file is deleted or not (i.e., as jrtayloriv pointed out, whether there is an entry for it in it's directory), I feel compelled to offer yet another possible solution.

    When I want to know if a file has been deleted or not (in a unix-like system,) I run ls, to list the directory's contents. If the entry has been removed, the file should be missing.. so this is one option (somewhat simplified):

    $filename = "openfile.yaml"; $directory = "/over/here/somewhere/i/think/"; $fileIsDeleted = (`ls $directory` !~ /$filename/gs); print "Your file has ".($fileIsDeleted ? "" : "not ")."been deleted.";
    This code has not been tested, but looks ok to me. It's really about the idea behind it anyway.