http://www.perlmonks.org?node_id=1012066

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

I have to capture STDOUT from a perl script created by someone long since gone at $work. This individual decided to open( STDOUT, ">/dev/tty" ), so no matter what I do, output goes to my terminal. I've tried subshells, su - -c, Perl wrappers with IPC::Open3...

I'm not allowed to touch the script. That's completely forbidden.

Is there some way to capture the output and get it to stop spewing its text to my terminal? I'm concurrently looking for ways to send the terminal's STDOUT somewhere else...

Tommy
"Perl follows the principle of least astonishment"

Replies are listed 'Best First'.
Re: capture STDOUT when some jerk opened STDOUT to /dev/tty
by Corion (Patriarch) on Jan 07, 2013 at 18:04 UTC

    Why not fake modifying the script by using do?

    select MYSTDOUT; # use *MYSTDOUT instead of STDOUT for output # so all his reopening manipulates the wrong filehandle # Run the original script in our interpreter do 'original_script.pl' or die;

    Update: Also, you should be able to combine this with davido's recommendation of Capture::Tiny to do the (re)capturing before the main script starts.

    Update 2: No, it's unlikely. The Capture::Tiny documentation says:

    Attempting to modify STDIN, STDOUT or STDERR during capture or tee is almost certainly going to cause problems. Don't do that.
Re: capture STDOUT when some jerk opened STDOUT to /dev/tty
by davido (Cardinal) on Jan 07, 2013 at 17:31 UTC

    Capture::Tiny seems to handle it fine.

    use Capture::Tiny qw( capture_stdout ); open STDOUT, '>/dev/tty' or die $!; my $output = capture_stdout { print "Hello world!\n"; }; print "<<<$output>>>\n";

    ...the output...

    <<<Hello world! >>>

    (as expected)

    Update: ww has kindly reminded me that this is probably not a solution when you need to capture output of an external script. Apologies... and good luck! ;)


    Dave

Re: capture STDOUT when some jerk opened STDOUT to /dev/tty
by salva (Canon) on Jan 07, 2013 at 21:09 UTC
    You can use screen(1) to capture the output sent to /dev/tty easily. For instance:
    $ screen -L ssh foo.bar.com

      Sure, rub it in that we don't get to have screen at $work ;_;

      You know I even tried ssh 0 cmd!! Using screen is a really cool idea though.

      Originally I was just wondering if there was an obvious Perl solution to the problem that I was just either overlooking or of which I was unaware.

      Tommy
      "Perl follows the principle of least astonishment"
        Well, you can write your own tty logger using IO::Pty. It shouldn't be too complex.

        Another option may be to run the program through strace logging the interesting events. Then post-process that information to obtain a clean log of the data written to /dev/tty

Re: capture STDOUT when some jerk opened STDOUT to /dev/tty
by eyepopslikeamosquito (Archbishop) on Jan 07, 2013 at 18:05 UTC
Re: capture STDOUT when some jerk opened STDOUT to /dev/tty
by BrowserUk (Patriarch) on Jan 07, 2013 at 18:13 UTC
    I'm not allowed to touch the script. That's completely forbidden.

    Make your own local copy of the script, tweak and run that. The original is untouched.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    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.

      It communicates with a remote server to get the data it must process, and the remote server won't communicate with the script unless it has the right crypto hash...

      I decided the rabbit hole was getting too deep, and I wrote my own version in 1 line of shell code (a very long line with lots of pipes and regexen). *sigh*... Sometimes to win, you just have to know when you're beaten.

      Tommy
      "Perl follows the principle of least astonishment"
Re: capture STDOUT when some jerk opened STDOUT to /dev/tty
by clueless newbie (Curate) on Jan 07, 2013 at 20:14 UTC

    Being just a clueless newbie, I'd create a simple module (call it MyOpen) that overrides CORE::open. Upon encountering a '/dev/tty' it can then substitute '/dev/null' or something more appropriate before calling CORE::open. Pack this into the invoking system / backticks using -MMyOpen. or set PERL5OPT.

Re: capture STDOUT when some jerk opened STDOUT to /dev/tty
by dbuckhal (Chaplain) on Jan 07, 2013 at 21:56 UTC
    How about using shell redirection?

    $ script.pl >> output.txt

    Otherwise, maybe you can present a case of your desired changes you would like to make to that file and seek approval. I can't imagine any piece of software being completely forbidden forever! heh

Re: capture STDOUT when some jerk opened STDOUT to /dev/tty
by bart (Canon) on Jan 09, 2013 at 14:49 UTC
    I'm not allowed to touch the script. That's completely forbidden.
    Are you sure the "jerk" is the guy who wrote the code?

    Fork the code of the script. That's the best I can recommend.

Re: capture STDOUT when some jerk opened STDOUT to /dev/tty
by pvaldes (Chaplain) on Jan 08, 2013 at 21:44 UTC

    I CAN'T touch the script

    Is there some way to capture the output and get it to stop spewing its text to my terminal?

    perl my_untouched_script 1>/dev/null

    One liner example

    perl -e 'print "Shut up!"' 1>/dev/null