Greetings,
: > It doesn't die?
: >
: > Are you sure it runs? ie, does the root crontab have the proper path
elements for this to function?
: >
: > Check the return code from print. As in:
: >
: > sub writetemp {
: > open (NEWFILE, ">/tmp/$0.count") or die $!;
: > my $ok = print NEWFILE "$product{name}.value $product{value} $date";
: > if ( ! $ok ) {
: > print STDERR "error on print to file: $!\n";
: > }
: > close (NEWFILE);
: > }
: >
: > or print NEWFILE "$product{name}.value $product{value} $date" or warn "$!";
:
: As a test, I set it up under the ubuntu user. When run from the
: command line, the script runs and properly creates the expected
: output file in the /tmp directory.
:
: When I set up the crontab to run the script as ubuntu, I get an
: email saying:
:
: "No such file or directory at /home/ubuntu/bin/test line 99."
Try running your program on the command line with a fully qualified
path name:
perl /home/ubuntu/bin/test
You will probably see the same error.
: which is the 'open' in the script.
You are asking perl to open a file called:
/tmp/home/ubuntu/bin/test.count
When, in fact, I guess that you would like to create the file:
/tmp/test.count
A few notes and recommendations:
0. I would suggest renaming the script from 'test' to
'test-count-something'; there is a shell builtin called 'test'
and often a binary /usr/bin/test, as well.
1. To solve the fully qualified path issue from above, use 'basename'
from the perl module File::Basename:
use File::Basename;
sub writetemp {
my $fname = "/tmp/". basename($0) . ".count";
open (NEWFILE, ">$fname") or die $!;
print NEWFILE "$product{name}.value $product{value} $date";
close (NEWFILE);
}
2. If you are going to write a file with one program and read the
file with another program, get in the habit of creating the file
atomically. Imagine what happens when your data file creation
program is still writing a the data file when along comes the
data consuming program and starts to read it! Hilarity.
How do you do prevent this problem? Take advantage of
filesystem atomicity. In perl, you can use the perl function
rename:
use File::Basename;
sub writetemp {
my $fname = "/tmp/". basename($0) . ".count";
open (NEWFILE, ">${fname}.tmp") or die $!;
print NEWFILE "$product{name}.value $product{value} $date";
close (NEWFILE);
rename($fname . ".tmp", $fname) or die $!;
}
3. Consider making your 'or die' statements just ever so slightly
more informative:
use File::Basename;
sub writetemp {
my $fname = "/tmp/". basename($0) . ".count";
open (NEWFILE, ">${fname}.tmp")
or die "Could not open(NEWFILE, ${fname}.tmp): $!";
print NEWFILE "$product{name}.value $product{value} $date";
close (NEWFILE)
or die "Could not close(NEWFILE) [${fname}.tmp]: $!";
rename($fname . ".tmp", $fname)
or die "Could not rename(${fname}.tmp, $fname): $!";
}
You might be tricked into thinking that handling files safely is
really easy, given that it is such a basic thing that we do on
computer systems, however, there are well-beaten paths into the pits
of despair in file-handling. By the way, Russell--nice work with
calling close(). Sure, some languages will close the filehandle for
you when it goes out of scope, but not perl, so it is good that you
call close() explicitly.
I could probably fiddle indefinitely with this nicely functionized
'writetemp' you have created, but I'll leave you with one more
possible variant. I would use a scoped variable for the filehandle
(mostly so that perl will clean up the filehandle if I forget to
call close() on that filehandle).
use File::Basename;
sub writetemp {
my $fname = "/tmp/". basename($0) . ".count";
my $tmpf = $fname . ".tmp";
my $fh;
open ($fh, ">$tmpf")
or die "Could not open(\$fh, $tmpf): $!";
# -- put the data into the file ...
#
print $fh "$product{name}.value $product{value} $date";
# -- Good behaviour! Call close() on your filehandles!
#
close ($fh)
or die "Could not close(\$fh) [$tmpf]: $!";
# -- filesystem atomicity is a nice guarantee; use it
#
rename($tmpf, $fname)
or die "Could not rename($tmpf, $fname): $!";
}
Wow, you are still reading. OK, have a look at the perl module
called File::Temp, and also the Linux command strace. If you had
run strace on your initial program you would have seen exactly what
the error was. The good run:
$ strace -e file perl t0.pl
...
open("/tmp/t0.pl.count", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
OK, so here you got your file.
$ strace -e file perl /home/mabrown/tmp/t0.pl
...
open("/tmp//home/mabrown/tmp/t0.pl.count", O_WRONLY|O_CREAT|O_TRUNC, 0666) =
-1 ENOENT (No such file or directory)
Sometimes you have to dig around in the strace output a bit, but you
can get a very good idea of exactly what is going wrong.
Anyway, good luck!
-Martin
--
Martin A. Brown
http://linux-ip.net/
_______________________________________________
PLUG mailing list
[email protected]
http://lists.pdxlinux.org/mailman/listinfo/plug