views:

77

answers:

3

I feel stupid for asking this, but I've tried a couple things and I'm not sure where to go with it.

From the Expect.pm documentation:

$object->log_file("filename" | $filehandle | \&coderef | undef)

Log session to a file. All characters send to or received from the spawned process are written to the file.

I'd like to pass the $filehandle to log_file. However, when I tried this:

open (LOG, ">>" .$opt{l});
my $sess = Expect->spawn("telnet $ip");
$sess->log_file(LOG)

I get a file named 'LOG' in the directory that I'm running the script out of. After some investigation, I tried this:

open (LOG, ">>" .$opt{l});
my $sess = Expect->spawn("telnet $ip");
my $fh = *LOG;
$sess->log_file($fh)

Now, I get a file named *main::LOG in the directory. I do have another file as well, named whatever I specified on the -l option, but it only contains the lines that I send to print LOG.

I'm not sure if the filehandling functionality is hosed in the function, or if I'm doing something wrong.

+4  A: 

If you have a bareword filehandle named LOG, you can pass it to a function by saying \*LOG (you can read more about this in perldoc perldata), but don't do that. Bareword filehandles are a very old style and should no longer be used. Try using a lexical filehandle and the three argument version of open:

open my $log, ">>", $opt{l}
    or die "could not open $opt{l}: $!";

you can use $log anywhere you used LOG in the past.

You should also be using the strict and warnings pragmas.

Chas. Owens
Chas.- Thanks, that helps. Unfortunately, I'm working with a lot of old documentation. I learned Perl in the early 2000's, and am circling back around to it now, so I have a lot of 'old' habits.
coding_hero
Now I'm getting "Given logfile doesn't have a 'print' method".
coding_hero
It sounds like it wants a blessed filehandle. You can get a blessed filehandle by just adding `use IO::Handle;` to the top of your program. All lexical and bareword filehandles should be usable as objects (e.g. `$log->print("I am printing!\n")` is the same as `print $log "I am printing!\n"`).
Chas. Owens
If you are coming back into the fold, you should really read [Perl Best Practices](http://oreilly.com/catalog/9780596001735) by Conway.
Chas. Owens
Thanks for the book recommendation, I'll check it out. But IO::Handle didn't fix the issue, unless I need to call open a different way.
coding_hero
This has become a different issue, I went ahead and asked a new question here: http://stackoverflow.com/questions/3721148/blessed-filehandle-doesnt-return-true-with-can
coding_hero
+1  A: 

Try using a lexical filehandle (and the three-argument open, and die) to begin with:

open my $logfh, ">>", $opt{l} or die "Could not open log file $opt{l}: $!\n";
$sess->log_file( $logfh );

LOG is incredibly generic and could be getting trumped (or doing the trumping) of another filehandle somewhere in your code. Using a lexical filehandle helps to prevent confusion. And you should always check the return status of open() (or use autodie) in case you can't actually open the file.

CanSpice
Thanks, CanSpice. I am checking the output of 'open', just left that off in the sample code.
coding_hero
A: 

It might be a better idea to return a filehandle using log_file by passing it the filename instead.


From the Expect documentation:

$object->log_file("filename" | $filehandle | \&coderef | undef)

Log session to a file. All characters send to or received from the spawned process are written to the file. Normally appends to the logfile, but you can pass an additional mode of "w" to truncate the file upon open():

$object->log_file("filename", "w");

Returns the logfilehandle.

So you should be able to achieve the same functionality using the following:

my $sess = Expect->spawn("telnet $ip");
$sess->log_file($opt{l});               # Or my $fh = $sess->log_file...
                                        # if that filehandle is needed

Now all your session activity will be logged to the file. Append mode is the default.

Zaid