in reply to Re^2: Deleting a file after it runs?
in thread Deleting a file after it runs?

You're both right. Try a bit more in your sample.

#!/usr/bin/perl -w + # Strict use strict; use warnings; + # Main program print "Check file before unlink\n"; sleep 1; system("ls $0"); print "Unlinking the file $0\n"; sleep 1; unlink $0; print "Check file after unlink\n"; sleep 1; system("ls $0"); + print "File should be now be gone from disk (but still in memory)\n"; print "Try ^Z and check it with 'ls $0' ... (come back with 'fg')\n"; sleep 10; print while <DATA>; print "I'm still here, but the original file is long gone.\n"; __END__ foo
When you run this, even after the file is unlinked, the *DATA filehandle still works. That's because the file is still physically on the disk, even though it has been unlinked from the directory tree. Once the file is finally closed, the filesystem is allowed to reuse that diskspace. To prove this, I created a ram disk (thanks to a recent thread ;-}), and added a check using df to see the filesystem being used.
#!/usr/bin/perl -w + # Strict use strict; use warnings; use File::Basename; + # Main program print "Check file before unlink\n"; sleep 1; system("ls $0; df -k $0 +"); print "Unlinking the file $0\n"; sleep 1; unlink $0; print "Check file after unlink\n"; sleep 1; system("ls $0; df -k " +. dirname($0)); + print "File should be now be gone from disk (but still in memory)\n"; print "Try ^Z and check it with 'ls $0' ... (come back with 'fg')\n"; sleep 10; 1 while <DATA>; # ensure we use the *DATA filehandle in case perl opti +mises it away print "I'm still here, but the original file is long gone.\n"; __END__ foo
In this case I ram it and got output like this:
$ cp z.pl /ram; perl /ram/z.pl Check file before unlink /ram/z.pl Filesystem 1K-blocks Used Available Use% Mounted on none 100 4 96 4% /ram Unlinking the file /ram/z.pl Check file after unlink ls: /ram/z.pl: No such file or directory Filesystem 1K-blocks Used Available Use% Mounted on none 100 4 96 4% /ram File should be now be gone from disk (but still in memory) Try ^Z and check it with 'ls /ram/z.pl' ... (come back with 'fg') I'm still here, but the original file is long gone. $ df -k /ram Filesystem 1K-blocks Used Available Use% Mounted on none 100 0 100 0% /ram
Note how the file may have disappeared from /ram, but the disk usage wasn't actually freed up until I was done with the script.

I re-ran the script without the __END__ marker or the usage of *DATA, and found that the script is closed after compilation as the diskspace is freed immediately. Again, you're both right. :-)

Replies are listed 'Best First'.
Re^4: Deleting a file after it runs?
by liverpole (Monsignor) on Oct 07, 2005 at 16:34 UTC
    I still don't think that's right, at least for my system, running Linux.  It might be somehow different because you're using a ramdisk, but when I run this program:
    #!/usr/bin/perl -w + my $iam = $0; my $lscmd = "ls -lt $iam"; my $dfcmd = "df --block-size=1 ."; + printf "Before remove\n"; system($lscmd); system($dfcmd); sleep 1; unlink $0; printf " After remove\n"; system($lscmd); system($dfcmd); sleep 1; printf "Try ^Z to see for yourself (cmd: $dfcmd) ...\n"; sleep 5; printf "Now exiting the program\n";
    it clearly shows that the space is freed up *before* the program exits.  The free space goes from 44290686976 bytes to 44290691072 (a difference of 4096 bytes) and remains at that value until after the program completes.  
    [liverpole@golux ~/perl]% chmod +x rmtest2 [liverpole@golux ~/perl]% ls -lt rmtest2 -rwxrwxr-x 1 liverpole liverpole 352 Oct 7 12:25 rmtest2* [liverpole@golux ~/perl]% rmtest2 Before remove -rwxrwxr-x 1 liverpole liverpole 352 Oct 7 12:25 rmtest2 Filesystem 1-blocks Used Available Use% Mounted on /dev/hda2 77584592896 29352763392 44290686976 40% / After remove ls: rmtest2: No such file or directory Filesystem 1-blocks Used Available Use% Mounted on /dev/hda2 77584592896 29352759296 44290691072 40% / Try ^Z to see for yourself (cmd: df --block-size=1 .) ... Suspended [liverpole@golux ~/perl]% ls -lt rmtest2 ls: rmtest2: No such file or directory [liverpole@golux ~/perl]% df --block-size=1 . Filesystem 1-blocks Used Available Use% Mounted on /dev/hda2 77584592896 29352759296 44290691072 40% / [liverpole@golux ~/perl]% fg rmtest2 Now exiting the program [liverpole@golux ~/perl]% df --block-size=1 . Filesystem 1-blocks Used Available Use% Mounted on /dev/hda2 77584592896 29352759296 44290691072 40% /

      I bet that's because perl opens the file, reads it, closes it and then runs the code.

      $ cat > hw.pl #!/usr/bin/perl print "Hello, World!\n"; sleep 5; print "exiting...\n"; $ chmod 755 !$ chmod 755 hw.pl $ strace -o abc -tt -ff -s 500 !$ strace -o abc -tt -ff -s 500 hw.pl $ _ (stripped strace output) 21:33:16.679617 open("/home/hue/lang/perl/hw.pl", O_RDONLY|O_LARGEFILE +) = 3 21:33:16.681557 read(3, "#!/usr/bin/perl\nprint \"Hello, World!\\n\";\ +nsleep 5;\nprint \"exiting...\\n\";\n", 4096) = 72 21:33:16.681985 read(3, "", 4096) = 0 21:33:16.682080 close(3) = 0 21:33:16.682336 write(1, "Hello, World!\n", 14) = 14 21:33:16.683833 nanosleep({5, 0}, {5, 0}) = 0 21:33:21.663964 write(1, "exiting...\n", 11) = 11

      Doing an lsof -n|grep hw shows that no process (except hw.pl itself) has the file opened, so when one unlinks it, the operation performs immediatly.

      --
      David Serrano