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

I have to call a interactive command from a perl script.The command which I am calling asks user for the conformation and proceed only after user enters yes or no. Paralley I want to capture output of this executed command to a file. I know I can not use back tick (`) because, it won't be interactive then. I can't use system() because system will run the command in interactive mode, but I will not be able to capture the output of the command. I also tried IPC::Open3 but again it was not interactive. Plz let me know, if somebody has done similar kind of stuff earlier.
  • Comment on How to cpture output of interactive command using perl.?

Replies are listed 'Best First'.
Re: How to cpture output of interactive command using perl.?
by moritz (Cardinal) on Dec 10, 2008 at 09:51 UTC
    On Unix-like systems you could try something like this:
    use File::Temp qw(tempfile); my ($fh, $filename) = tempfile(); close $fh; system("your_command | tee $filename"); # then open $filename for reading, it contains the output

    But since now the STDOUT of your program is connected to a pipe, it might do a bit more buffering, which is bad for the user experience on the interactive program.

      On Unix-like systems...

      For a portable, pure-perl approach, there is the Tee module.

      use Tee; use File::Temp qw(tempfile); my ($fh, $filename) = tempfile(); close $fh; tee("your_command", $filename);

      -xdg

      Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

      Could you not fix the buffering problem by turning on autoflush?
      ... $| = 1; #Autoflush on system("your_command | tee $filename"); $| = 0; #Autoflush off
      for(split(" ","tsuJ rehtonA lreP rekcaH")){print reverse . " "}print "\b.\n";
Re: How to cpture output of interactive command using perl.?
by BrowserUk (Patriarch) on Dec 10, 2008 at 13:54 UTC
    I know I can not use back tick (`) because, it won't be interactive then. I can't use system() because system will run the command in interactive mode, but I will not be able to capture the output of the command.

    You're going to have to elaborate on exactly what you are trying to do.

    • Do you want the command to interact with your script? Or the user?
    • If the latter, are you hoping to capture just the final output, or the entire interaction including user inputs and intermediate command outputs (eg. prompts)?

    Reading between the lines, it sounds like you might be looking for an Expect type of thing. (Be warned: As far as I know, noone has got this to work on windows.)


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      * Do you want the command to interact with your script? Or the user? Rapunzel: Command will interact with user. * If the latter, are you hoping to capture just the final output, or the entire interaction including user inputs and intermediate command outputs (eg. prompts)? Rapunzel: It is fine even if script is able to capture the final output. Also note that my script supports both windows and *nix operating system.
Re: How to cpture output of interactive command using perl.?
by JavaFan (Canon) on Dec 10, 2008 at 10:16 UTC
    Have you tried:
    open my $fh, "interactive_command |" or die; # I can never remember t +he mode for the 3-arg form of this while (<$fh>) { ... } close $fh or die;
      Thanks for looking to it. By using this I am able to run the command in interactive mode , but still i am not able to capture the output of the executed command. Please elaborate more on how to cature the output.
        Well, you read the output from the handle. And by output, I mean whatever the program writes to STDOUT. If the program "outputs" by driving the terminal and printing to the terminal, it becomes something different.
        open my $fh, "cat |" or die; while (<$fh>) { print "Got: $_"; } close $fh or die; __END__ foo Got: foo bar Got: bar baz Got: baz ^D