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

Hello monks,
I have a bit of a quandry with Expect.pm 's logging function, for some reason when I declaire a location for logging it logs all the output previous to my declaration statement in the same place, which does not make sense. It seems as though Expect is anticipating the logfile, even though I clear the accumulated text...

Here is my code regarding this precognitive problem.
#!/usr/bin/perl -w use strict; use Expect; $| = 1; my $exp = new Expect; $exp->raw_pty(1); # treat this terminal as a raw file $exp->log_stdout(0); # do not show terminal output to STDOUT $exp->log_file("/dev/null"); # log all output to /dev/null $exp->spawn("/bin/sh"); $exp->expect(2, ['such file or directory', sub { print "ERROR: no shell\n"; die; } ], [timeout => sub { $exp->send("/usr/bin/last -5 $username\n"); $exp->log_file(undef); # should clear the log file +location $exp->clear_accum(); # should tell it to clear it +s buffer $exp->log_file(\&formatoutput); # log to function form +atoutput $exp->send("/bin/cat /etc/passwd\n"); } ], ); $exp->soft_close(); sub formatoutput { my $input = shift; chomp($input); $input =~ tr/\r//; print"$input \n"; }
all feedback is apprecated.
jcpunk

by the way thanks

20030622 Edit by Corion: Changed title from 'Logging, both where it should and should not be it is'

Replies are listed 'Best First'.
Re: Problems with Expect.pm's logging?
by graff (Chancellor) on Jun 20, 2003 at 05:51 UTC
    As posted, your code didn't have a declaration or assignment for "$username", but I think I got the idea...

    Having tried this out myself (putting in a suitable string for $username), I saw that the output from this instruction:

    $exp->send("/usr/bin/last -5 graff\n");
    showed up on STDOUT, and I gather from your post that you don't want this. Meanwhile, the output from this instruction:
    $exp->send("/bin/cat /etc/passwd\n");
    also showed up on STDOUT, and I gather you do want this. I realize that this is just some trimmed-down, debugging code to demonstrate the problem you want to solve, which is to control what does and does not end up on STDOUT.

    Thank you for a very clear and concise presentation -- it has led me to understand Expect.pm much better. Your problem is that you need to use the "expect()" method every time you send something to the process that will cause it to produce output; that's the only way to properly control where that output goes.

    Look closely at the part of the manpage that describes the "expect()" method, and note the difference between calling in scalar context vs. calling in array context. Structure your code to use the value(s) returned by this method.

    Maybe the following version will be closer to what you want for this example:

    #!/usr/bin/perl -w use strict; use Expect; $| = 1; my $exp = new Expect; $exp->raw_pty(1); # treat this terminal as a raw file $exp->log_stdout(undef); # do not show terminal output to STDOUT $exp->spawn("/bin/sh"); # typical regex pattern for end of /bin/sh prompt: my $shell_prompt = qr/[\$\#]\s*$/; my $result = $exp->expect(2, -re => $shell_prompt # pattern #1 ); die "Didn't get a shell prompt -- go figure" unless ( $result == 1 ); $exp->send("/usr/bin/last -5 nobody\n"); my @result = $exp->expect(2, -re => $shell_prompt); my $last_output = $result[3]; # element 3 is "before_match" text $exp->send("/bin/cat /etc/passwd\n"); @result = $exp->expect(2, -re => $shell_prompt); my $passwd_file = $result[3]; print "/etc/passwd contains:\n$passwd_file\n"; $exp->soft_close();
      wow

      thanks for that, i read the documentation 6 or 7 times and totally missed that. You are an absolute genius thanks so much.
      jcpunk

      by the way thanks for all the help that was, is, and will be