Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

-s test option returns differently in some cases

by frogsausage (Sexton)
on Oct 14, 2013 at 07:55 UTC ( #1058136=perlquestion: print w/replies, xml ) Need Help??
frogsausage has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks! Happy Monday everyone!

I am writing (or debugging now) a Perl script which at one point creates a file: creating an array, then printing it out through a filehandle. Therefore, I want to check if my file is present and not empty. For that I get the full path using rel2abs, which is working fine, then doing a

if (-s $myAbsPathToFile) {print "Good to go"} else {print "File is missing"};

Surprisingly, the same script behaved differently when running on these two configurations:

- SuSE 10 + Perl 5.8.5 (says "Good to go")

- SuSE 11 + Perl 5.14.1 (says "File is missing")

To test that, I wrote the following small script:

print "Matched" if (-s "/home/frogsausage/file");

Where "file" is a non-empty file in my ~ Output will be "Matched" on SuSE 10 (Perl 5.8.5) and... nothing on SuSE 11 (Perl 5.14.1) Actually it is "Matched on both with that small script, but when running my file it full script, it doesn't work :(. I ran it on my Mac at home (10.6.8 + Perl 5.8.8 / Perl 5.14.1 installed using macports) and it printed "Matched" for both Perl version. That was a debug before I could run it again on the SuSE machine. I also had a look at the perlport for 5.14.1 and couldn't find anything related to my issue.

-s and ! -z behave the same (not talking 'logically' here), meaning "File is missing" in the script. -e works fine.

Any ideas? Looking forward to some hints here.

Note that I cannot change the perl version by installing a new one. Also, I don't want the user to have to check anything prior running the script, meaning, it should run the same piece of script for both Perl 5.8.5 to Perl 5.14.1 (at least), as well as SuSE 10/11. Code is pretty simple and that is the only error I've found.

Update from the thread:

- on SuSE 11/Perl 5.14.1 error is 'No such file or directory' while it works on the SuSE 10 machine.

- file is located at the same place regarding the OS (NFS drive)

Update 2:

- Adding an extra empty system() statement before the file test made it work. No ideas why though. Hidden Perl variable messing up with it?

Last update and solution:

- The problem was caused by the filehandle for the file still being open. The file was created using the 'print' statement in my case.

- Thanks richardK, thanks all, for the useful hints and solution!

Replies are listed 'Best First'.
Re: -s test option returns differently in some cases
by RichardK (Parson) on Oct 14, 2013 at 11:26 UTC

    I wonder if you're suffering from NFS attribute caching?

    My guess is that it could be reading the local stale cache and has just not seen the update yet. If you sleep for more than the attribute cache timeout (set in the NFS mount) it should correct itself. You could try a loop that sleeps for one second and then tests the file and see if it ever recognises the change.

    Also, have you closed that file that you're writing to? I don't remember if this will flush the cache or not & I don't have a NFS server set up it test it on.

    Have you checked that the nfs mount options are the same on both machines & that the defaults didn't change between versions?

    You can set noac on the nfs mount but it does slow things down. Sadly, NFS is showing it's age and doesn't make a very good cluster file system.

      Aaaaaaaaaand, it is a problem with the file not being closed. Something might have changed somewhere in Perl or SuSE in between these two version (of each).

      Thank you very much for helping me out here! I'm short of 'vote' but I will come back later!

      Didn't think for a second about NFS actually. Lets see...

      My NFS has:


      which are default values apparently. Therefore, I set a sleep to '3' and it didn't work "Failed". It is also much longer than the system() statement which works.

      Now, I've looked at how I am writing my file: open, print and then... nothing. I added a close statement and it works like a charm. Let me double check on that though, I might have forgotten a switch somewhere that could affect that. I'll report back soon!

Re: -s test option returns differently in some cases
by hippo (Canon) on Oct 14, 2013 at 08:12 UTC

    I would increase the verbosity of the error message. eg:

    if (-s $myAbsPathToFile) {print "Good to go"} else {print "File $myAbsPathToFile may be empty or missing: $!"};

    That way you can see that you are testing the right file and you will also see the error condition, if one exists.

    It may also be that on your SuSE 11 box the file never gets created due to a permissions problem or somesuch. Do you check that it is opened correctly for writing and that the subsequent writes to it succeed?

      So this is the code I have:
      print "# File is located at: $myAbsPathToFile\n" if (-e $myAbsPathToFi +le); if (-s $myAbsPathToFile) { print "Good to go\n"; } else { print "# File $myAbsPathToFile is empty or missing: $!. Cannot con +tinue!\n"; exit; }
      And its output:
      # File is located at: /nfs/home/frogsausage/file # File /nfs/home/frogsausage/file is empty or missing: No such file or + directory. Cannot continue!

      Note how awkward it is: first test is saying "Can find it, it exists!", and the second says "Nope, no such file or directory". These lines are like that in the final code: no statements in between and it isn't part of a loop or anything like that.

      Edit: @hdb Indeed! I corrected typo after edit. I converted full path to variable again hence why. Thanks for the head up. Output is still the same after the typo edit.

        There is a $ missing in

        if (-s "myAbsPathToFile") {

      Thanks for the tip. Didn't thought of printing the error message.

      The error message returned on the SuSE 11/Perl 5.14.1 is "No such file or directory". At least it gives me why now. The sad thing is, if I stat the path of the file with 'ls' it gives me from your syntax (same terminal, without modifying anything) it says it can find it (correct rights, correct user and non-empty file).

      File is created in my home and my home is on nfs.

Re: -s test option returns differently in some cases
by parv (Priest) on Oct 14, 2013 at 11:25 UTC

    Could the problem be due to use of auto mount of a NFS directory (given auto mount is actually being used)? For whatever reason, perhaps use of ls is more forceful than size or emptiness test. Then again both -- ls & -X -- get the information via stat call, no? Seems like something might have changed in perl + Suse combination.

    Does calling stat() explicitly on file path (and not running system ls) before -[sz] make a difference?

      Thanks for thinking of the NFS too. It seems something changed either in Perl 5.14.1 or in SuSE 11 with either the 'print' statement, the way test works on a filehandle, how the system deals with an open file...

      Thanks for your input :) I'm short of 'vote' but I will come back later!

Re: -s test option returns differently in some cases
by hdb (Monsignor) on Oct 14, 2013 at 08:07 UTC

    Just guessing: did you check that file permissions are the same on both machines?

      Hi hdb, Actually, it is exactly the same file since it is located on a nfs directory. In the full script, I am now printing the value if a -e test returns true before going to the test that breaks and the path is exactly the same (which is expected).
        ...and the accounts on both machines have identical permissions and the NFS mounts are made in identical fashion i.e. with identical options, on the same mount point - each of which has identical permissions down to the mount point ?

        A user level that continues to overstate my experience :-))
Re: -s test option returns differently in some cases
by frogsausage (Sexton) on Oct 14, 2013 at 09:18 UTC

    You won't believe it but...

    print "# Command file is located at: $myAbsPathToFile\n" if (-e $myAbs +PathToFile); # system("ls -l $myAbsPathToFile"); if (-s $cmd_path) {# $myAbsPathToFile) { print "Good to go"; } else { print "Failed: $!"; }

    gives "Failed: No such file or directory"

    print "# Command file is located at: $myAbsPathToFile\n" if (-e $myAbs +PathToFile); system("ls -l $myAbsPathToFile"); if (-s $cmd_path) {# $myAbsPathToFile) { print "Good to go"; } else { print "Failed: $!"; }

    gives "Good to go"

    Same file, same code, same everything except that extra statement in between. An empty system(""); call does the same (works). Is a hidden/builtin Perl variable messing up with it or something? Ideas?!

    Sorry for the double post, I just posted in the wrong hierarchy :(

      Also, the shell does its own interpolation ( see system, sh ), and instead try
      system 'ls', '-l', $myAbsPathToFile;

        I just tried it and it works the same (as assumed) as my former system() call. The test result is "Good to go".


      its right about halloween

      well, the extra system is commented out, but I imagine if a sleep(1) accomplishes the same thing, you have your answer (delay)

        Sleep gives me the error again.

        Halloween you said? No wonder why my comment to the empty system() statement is # trick or treat... fix for etc.

        Let me try your syntax for system. Since system is taking an array as argument, I'm providing an array of '1' with "ls -l ...".

      $! is only going to be meaningful if -s returned undef, not if it returned 0.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1058136]
Front-paged by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (8)
As of 2018-09-21 11:42 GMT
Find Nodes?
    Voting Booth?
    Eventually, "covfefe" will come to mean:

    Results (185 votes). Check out past polls.

    • (Sep 10, 2018 at 22:53 UTC) Welcome new users!